ecattez / shahmat Goto Github PK
View Code? Open in Web Editor NEWA Chess implementation with the Domain Driven Design
Home Page: https://ecattez.github.io/shahmat/
License: GNU General Public License v3.0
A Chess implementation with the Domain Driven Design
Home Page: https://ecattez.github.io/shahmat/
License: GNU General Public License v3.0
Feature: Classical Chess
Scenario: a classical board game initialization
GIVEN a classical chess game
WHEN the board is initialized
THEN a white rook is in A1
AND a white knight is is B1
AND a white bishop is in C1
AND a white queen is in D1
AND a white king is in E1
AND a white bishop is in F1
AND a white knight is in G1
AND a white rook is in H1
AND a white pawn is in A2
AND a white pawn is in B2
AND a white pawn is in C2
AND a white pawn is in D2
AND a white pawn is in E2
AND a white pawn is in F2
AND a white pawn is in G2
AND a white pawn is in H2
AND a black rook is in A8
AND a black knight is is B8
AND a black bishop is in C8
AND a black queen is in D8
AND a black king is in E8
AND a black bishop is in F8
AND a black knight is in G8
AND a black rook is in H8
AND a black pawn is in A7
AND a black pawn is in B7
AND a black pawn is in C7
AND a black pawn is in D7
AND a black pawn is in E7
AND a black pawn is in F7
AND a black pawn is in G7
AND a black pawn is in H7
AND the board is ready to play with
Scenario: a board already initialized can not be initialized again
GIVEN a classical chess game
AND the board is already initialized
WHEN the board is initialized
THEN the initialization is refused
Feature: Queen
Scenario: A queen can move in any direction on a straight or diagonal path
GIVEN a <color> queen in <from>
AND the squares between <from> and <to> are vacant
WHEN the queen is moved <times> <direction>
THEN the queen is in <to>
Example:
| color | from | times | direction | to |
| WHITE | A1 | 4 | FORWARD | A5 |
| WHITE | A5 | 2 | SHIFT_RIGHT | C5 |
| WHITE | C5 | 2 | SHIFT_LEFT | A5 |
| WHITE | A5 | 4 | BACKWARD | A1 |
| WHITE | E5 | 3 | FORWARD_LEFT | B8 |
| WHITE | B8 | 2 | BACKWARD_RIGHT | D6 |
| WHITE | D6 | 1 | FORWARD_RIGHT | E7 |
| WHITE | E7 | 4 | BACKWARD_LEFT | A3 |
| BLACK | A8 | 4 | FORWARD | A4 |
| BLACK | A4 | 2 | SHIFT_LEFT | C4 |
| BLACK | C4 | 2 | SHIFT_RIGHT | A4 |
| BLACK | A4 | 4 | BACKWARD | A8 |
| BLACK | D5 | 3 | FORWARD_LEFT | G2 |
| BLACK | G2 | 2 | BACKWARD_RIGHT | E4 |
| BLACK | E4 | 2 | FORWARD_RIGHT | C2 |
| BLACK | C2 | 4 | BACKWARD_LEFT | G6 |
Scenario: A queen cannot move beyond an obstructed path
GIVEN a <color> queen in <from>
AND the square <obstructed> is not vacant
WHEN the queen is moved <time> <direction>
THEN the move is refused
Example:
| color | from | obstructed | times | direction |
| WHITE | A1 | C3 | 4 | FORWARD_RIGHT |
| WHITE | E6 | B3 | 4 | BACKWARD_LEFT |
| WHITE | C3 | B4 | 1 | FORWARD_LEFT |
| WHITE | B6 | C5 | 2 | BACKWARD_RIGHT |
| WHITE | A1 | A3 | 4 | FORWARD |
| WHITE | A5 | C5 | 2 | SHIFT_RIGHT |
| WHITE | E5 | C5 | 2 | SHIFT_LEFT |
| WHITE | A5 | A3 | 4 | BACKWARD |
| BLACK | E5 | C3 | 3 | FORWARD_RIGHT |
| BLACK | D5 | E6 | 2 | BACKWARD_LEFT |
| BLACK | E5 | G3 | 3 | FORWARD_LEFT |
| BLACK | D5 | B7 | 2 | BACKWARD_RIGHT |
| BLACK | A8 | A6 | 4 | FORWARD |
| BLACK | A4 | C4 | 2 | SHIFT_LEFT |
| BLACK | E4 | C4 | 2 | SHIFT_RIGHT |
| BLACK | A4 | A6 | 2 | BACKWARD |
Scenario: A queen can capture any opposing piece on the board that is within its bounds of movement
GIVEN a <color> queen in <from>
AND an opposing piece in <to>
WHEN the queen is moved to <to>
AND the queen captures the opposing piece
Example:
| color | from | to |
| WHITE | A1 | A3 |
| WHITE | A5 | C5 |
| WHITE | E5 | C5 |
| WHITE | A5 | A3 |
| WHITE | E5 | B2 |
| WHITE | C4 | D3 |
| WHITE | C6 | E8 |
| WHITE | H1 | A8 |
| BLACK | A8 | A6 |
| BLACK | A4 | C4 |
| BLACK | E4 | C4 |
| BLACK | A4 | A6 |
| BLACK | E5 | B2 |
| BLACK | C4 | D3 |
| BLACK | C6 | E8 |
| BLACK | H1 | A8 |
The idea is to create a visual chess board, available through the web browser.
Feature: Checkmate
Scenario: a king is checkmate after an opposing move
WHEN a king is put in check because of an opposing move
AND the king's player cannot make any legal move
THEN the king is checkmate
AND the game is over
WITH the player's opponent as winner
Scenario: a king is checkmate after an opposing promotion
WHEN a king is put in check because of an opposing promotion
AND the king's player cannot make any legal move
THEN the king is checkmate
AND the game is over
WITH the player's opponent as winner
Feature: En Passant
Scenario: a pawn can immediately capture an opposing pawn that moved forward two squares on a neighbouring file
GIVEN a <color> pawn in <from>
AND an opposing pawn that moved forward two squares on a neighbouring file <file>
WHEN the opposing pawn is immediately captured en passant
THEN the pawn is in <to>
AND the opposing pawn is removed from the game
Example:
| color | from | file | to |
| WHITE | C5 | B | B6 |
| WHITE | C5 | D | D6 |
| BLACK | C4 | D | B3 |
| BLACK | C4 | B | D3 |
Scenario: a pawn can not capture en passant if it is not immediately after the move of the opposing pawn
GIVEN a <color> pawn in <from>
AND an opposing pawn that moved forward two squares on a neighbouring file <file>
AND an other opposing piece as moved since
WHEN the opposing pawn is captured en passant
THEN the capture is refused
Example:
| color | from | file |
| WHITE | C5 | B |
| BLACK | C4 | D |
Feature: Turn of White and Black
The player controlling the white pieces is named "White"; the player controlling the black pieces is named "Black". White moves first, then players alternate moves. Making a move is required.
Scenario: White moves first
GIVEN an initialized board
WHEN a chess game starts
THEN it is the turn of White
Scenario: Turn changes after a move
GIVEN a ready to play chess game
AND <current_player> is playing
WHEN <current_player> moves one of its piece
THEN it is the turn of <next_player>
Example:
| current_player | next_player |
| WHITE | BLACK |
| BLACK | WHITE |
Scenario: A player can not move its opponent's piece
GIVEN a ready to play chess game
AND <color> is playing
WHEN <color> moves a <opponent_color> piece
THEN the move is refused
Example:
| color | opponent_color |
| WHITE | BLACK |
| BLACK | WHITE |
Scenario: Turn does not change when a promotion is proposed
GIVEN a <color> pawn in the other side of the chess board
AND <color> is playing
WHEN a promotion is proposed for the pawn
THEN turn stays for <color>
Example:
| color |
| WHITE |
| BLACK |
Scenario: Turn changes after promoting a pawn
GIVEN a <color> pawn in the other side of the chess board
AND <color> is playing
WHEN the pawn is promoted
THEN it is the turn of <opponent_color>
Example:
| color | opponent_color |
| WHITE | BLACK |
| BLACK | WHITE |
Feature: Promotion (rewritten)
Scenario: A pawn must be promoted when it reaches the other side of the chess board
GIVEN a <color> pawn in the penultimate rank (<penultimate-rank>)
WHEN the pawn reaches the other side of the chess board (<last-rank>)
AND the pawn's owner does not promote the pawn
THEN the move is refused because promotion must be done
Example:
| color | penultimate-rank | last-rank |
| WHITE | 7 | 8 |
| BLACK | 2 | 1 |
Scenario: A pawn can not be promoted for pawn nor a king
GIVEN a <color> pawn in the penultimate rank (<penultimate-rank>)
WHEN the pawn reaches the other side of the chess board (<last-rank>)
AND the pawn's owner has chosen to promote it with a <promotion-type>
THEN the promotion is refused because <promotion-type> can not promote
Example:
| color | penultimate-rank | last-rank | promotion-type |
| WHITE | 7 | 8 | KING |
| WHITE | 7 | 8 | PAWN |
| BLACK | 2 | 1 | KING |
| BLACK | 2 | 1 | PAWN |
Scenario: A pawn may be promoted for a queen, a rook, a bishop or a knight
GIVEN a <color> pawn in the penultimate rank (<penultimate-rank>)
WHEN the pawn reaches the other side of the chess board (<last-rank>)
AND the pawn's owner has chosen to promote it with a <promotion-type>
THEN a <promotion-type> of the same color replaces the pawn
Example:
| color | penultimate-rank | last-rank | promotion-type |
| WHITE | 7 | 8 | QUEEN |
| WHITE | 7 | 8 | ROOK |
| WHITE | 7 | 8 | BISHOP |
| WHITE | 7 | 8 | KNIGHT |
| BLACK | 2 | 1 | QUEEN |
| BLACK | 2 | 1 | ROOK |
| BLACK | 2 | 1 | BISHOP |
| BLACK | 2 | 1 | KNIGHT |
Scenario: A pawn is promoted when capturing an opposing piece
GIVEN a <color> pawn in <from>
AND an opposing piece in <opponent-location>
WHEN the pawn moves to <opponent-location>
AND the pawn's owner has chosen a valid promotion type
THEN the pawn captures the opposing piece
AND the promotion piece replaces the pawn
Example:
| color | from | opponent-location |
| WHITE | B7 | A8 |
| BLACK | E2 | F1 |
Scenario: Only a pawn can be promoted
WHEN a <type> is promoted (<from> to <to>)
THEN the promotion is refused
WITH "Piece can not be promoted" as reason
Example:
| type | from | to |
| KING | B2 | A1 |
| QUEEN | A3 | A1 |
| ROOK | A3 | A1 |
| BISHOP | A3 | C1 |
| KNIGHT | D2 | F1 |
Feature: Rook
Scenario: A rook can move horizontally and vertically while it is not obstructed
GIVEN a <color> rook in <from>
AND the squares between <from> and <to> are vacant
WHEN the rook is moved <times> <direction>
THEN the rook is in <to>
Example:
| color | from | times | direction | to |
| WHITE | A1 | 4 | FORWARD | A5 |
| WHITE | A5 | 2 | SHIFT_RIGHT | C5 |
| WHITE | C5 | 2 | SHIFT_LEFT | A5 |
| WHITE | A5 | 4 | BACKWARD | A1 |
| BLACK | A8 | 4 | FORWARD | A4 |
| BLACK | A4 | 2 | SHIFT_LEFT | C4 |
| BLACK | C4 | 2 | SHIFT_RIGHT | A4 |
| BLACK | A4 | 4 | BACKWARD | A8 |
Scenario: Rook can not move beyond an obstructed path
GIVEN a <color> rook in <from>
AND the square <obstructed> is not vacant
WHEN the rook is moved <time> <direction>
THEN the move is refused
Example:
| color | from | obstructed | times | direction |
| WHITE | A1 | A3 | 4 | FORWARD |
| WHITE | A5 | C5 | 2 | SHIFT_RIGHT |
| WHITE | E5 | C5 | 2 | SHIFT_LEFT |
| WHITE | A5 | A3 | 4 | BACKWARD |
| BLACK | A8 | A6 | 4 | FORWARD |
| BLACK | A4 | C4 | 2 | SHIFT_LEFT |
| BLACK | E4 | C4 | 2 | SHIFT_RIGHT |
| BLACK | A4 | A6 | 2 | BACKWARD |
Scenario: Rook can capture an opposing piece that obstruct its way
GIVEN a <color> rook in <from>
AND an opposing piece in <to>
WHEN the rook is moved to <to>
THEN the rook captures the opposing piece
Example:
| color | from | to |
| WHITE | A1 | A3 |
| WHITE | A5 | C5 |
| WHITE | E5 | C5 |
| WHITE | A5 | A3 |
| BLACK | A8 | A6 |
| BLACK | A4 | C4 |
| BLACK | E4 | C4 |
| BLACK | A4 | A6 |
Feature: Knight
Scenario: A knight can move forward, backward, left or right two squares and must then move one square in either perpendicular direction
GIVEN a <color> knight in <from>
WHEN the knight is moved to <direction> two times
AND then moved <perpendicular> one square
THEN the knight is in <to>
Example:
| color | from | direction | perpendicular | to |
| WHITE | D5 | FORWARD | SHIFT_LEFT | C7 |
| WHITE | D5 | FORWARD | SHIFT_RIGHT | E7 |
| WHITE | D5 | SHIFT_LEFT | FORWARD | B6 |
| WHITE | D5 | SHIFT_RIGHT | FORWARD | F6 |
| WHITE | D5 | SHIFT_LEFT | BACKWARD | B4 |
| WHITE | D5 | SHIFT_RIGHT | BACKWARD | F4 |
| WHITE | D5 | BACKWARD | SHIFT_LEFT | C3 |
| WHITE | D5 | BACKWARD | SHIFT_RIGHT | E3 |
| BLACK | E4 | BACKWARD | SHIFT_LEFT | F2 |
| BLACK | E4 | BACKWARD | SHIFT_RIGHT | D2 |
| BLACK | E4 | SHIFT_LEFT | FORWARD | G3 |
| BLACK | E4 | SHIFT_RIGHT | FORWARD | C3 |
| BLACK | E4 | SHIFT_LEFT | BACKWARD | G5 |
| BLACK | E4 | SHIFT_RIGHT | BACKWARD | C5 |
| BLACK | E4 | BACKWARD | SHIFT_LEFT | F6 |
| BLACK | E4 | BACKWARD | SHIFT_RIGHT | D6 |
Scenario: A knight can not take the place of any of its allies on the board that is within its bounds of movement
GIVEN a <color> knight in <from>
AND an allied piece in <to>
WHEN the knight is moved to <to>
THEN the move is refused
Example:
| color | from | to |
| WHITE | D5 | C7 |
| WHITE | D5 | E7 |
| WHITE | D5 | B6 |
| WHITE | D5 | F6 |
| WHITE | D5 | B4 |
| WHITE | D5 | F4 |
| WHITE | D5 | C3 |
| WHITE | D5 | E3 |
| BLACK | E4 | D6 |
| BLACK | E4 | F6 |
| BLACK | E4 | C5 |
| BLACK | E4 | G5 |
| BLACK | E4 | C3 |
| BLACK | E4 | G3 |
| BLACK | E4 | D2 |
| BLACK | E4 | F2 |
Scenario: A knight can take any opposing piece on the board that is within its bounds of movement
GIVEN a <color> knight in <from>
AND an opposing piece in <to>
WHEN the knight is moved to <to>
THEN the knight captures the opposing piece
Example:
| color | from | to |
| WHITE | D5 | C7 |
| WHITE | D5 | E7 |
| WHITE | D5 | B6 |
| WHITE | D5 | F6 |
| WHITE | D5 | B4 |
| WHITE | D5 | F4 |
| WHITE | D5 | C3 |
| WHITE | D5 | E3 |
| BLACK | E4 | D6 |
| BLACK | E4 | F6 |
| BLACK | E4 | C5 |
| BLACK | E4 | G5 |
| BLACK | E4 | C3 |
| BLACK | E4 | G3 |
| BLACK | E4 | D2 |
| BLACK | E4 | F2 |
Scenario: A knight can skip over any other pieces to reach its destination position
GIVEN a <color> knight in <from>
AND the square <obstructed> is not vacant
WHEN the knight is moved to <to>
THEN the knight is in <to>
Example:
| color | from | obstructed | to |
| WHITE | D5 | D6 | C7 |
| WHITE | D5 | D7 | E7 |
| WHITE | D5 | C5 | B6 |
| WHITE | D5 | F5 | F6 |
| WHITE | D5 | B5 | B4 |
| WHITE | D5 | E5 | F4 |
| WHITE | D5 | D4 | C3 |
| WHITE | D5 | D3 | E3 |
| BLACK | E4 | E5 | D6 |
| BLACK | E4 | E6 | F6 |
| BLACK | E4 | D4 | C5 |
| BLACK | E4 | F4 | G5 |
| BLACK | E4 | D4 | C3 |
| BLACK | E4 | G4 | G3 |
| BLACK | E4 | E3 | D2 |
| BLACK | E4 | E2 | F2 |
Feature: King
Scenario: A king moves exactly one square horizontally, vertically, or diagonally.
GIVEN a <color> king in <from>
AND the one square <direction> is vacant
WHEN the king is moved <direction>
THEN the king is in <to>
Example:
| color | from | to | direction |
| WHITE | E4 | E5 | FORWARD |
| WHITE | E6 | D7 | FORWARD_LEFT |
| WHITE | C3 | D4 | FORWARD_RIGHT |
| WHITE | B6 | B5 | BACKWARD |
| WHITE | B5 | A4 | BACKWARD_LEFT |
| WHITE | A5 | B4 | BACKWARD_RIGHT |
| WHITE | E5 | D5 | SHIFT_LEFT |
| WHITE | F6 | G6 | SHIFT_RIGHT |
| BLACK | E5 | E4 | FORWARD |
| BLACK | D5 | E4 | FORWARD_LEFT |
| BLACK | E5 | D4 | FORWARD_RIGHT |
| BLACK | D5 | D6 | BACKWARD |
| BLACK | G6 | H7 | BACKWARD_LEFT |
| BLACK | G5 | F6 | BACKWARD_RIGHT |
| BLACK | E4 | F4 | SHIFT_LEFT |
| BLACK | G6 | F6 | SHIFT_RIGHT |
Scenario: A king cannot move beyond an obstructed path
GIVEN a <color> king in <from>
AND the one square <direction> is not vacant
WHEN the king is moved <direction>
THEN the move is refused
Example:
| color | from | direction |
| WHITE | E4 | FORWARD |
| WHITE | E6 | FORWARD_LEFT |
| WHITE | C3 | FORWARD_RIGHT |
| WHITE | B6 | BACKWARD |
| WHITE | B5 | BACKWARD_LEFT |
| WHITE | A5 | BACKWARD_RIGHT |
| WHITE | E5 | SHIFT_LEFT |
| WHITE | F6 | SHIFT_RIGHT |
| BLACK | E5 | FORWARD |
| BLACK | D5 | FORWARD_LEFT |
| BLACK | E5 | FORWARD_RIGHT |
| BLACK | D5 | BACKWARD |
| BLACK | G6 | BACKWARD_LEFT |
| BLACK | G5 | BACKWARD_RIGHT |
| BLACK | E4 | SHIFT_LEFT |
| BLACK | F6 | SHIFT_RIGHT |
Scenario: A king can capture any opposing piece on the board that is within its bounds of movement
GIVEN a <color> king in <from>
AND an opposing piece in <to>
WHEN the king is moved to <to>
THEN the king captures the opposing piece
Example:
| color | from | to |
| WHITE | E4 | D3 |
| WHITE | E4 | D4 |
| WHITE | E4 | D5 |
| WHITE | E4 | E3 |
| WHITE | E4 | E5 |
| WHITE | E4 | F3 |
| WHITE | E4 | F4 |
| WHITE | E4 | F5 |
| BLACK | D5 | E6 |
| BLACK | D5 | E5 |
| BLACK | D5 | E4 |
| BLACK | D5 | D6 |
| BLACK | D5 | D4 |
| BLACK | D5 | C6 |
| BLACK | D5 | C5 |
| BLACK | D5 | C4 |
For HTTP Clients, we should send a representation such as below (preferred hal-forms
format).
{
"turnOf": "WHITE",
"number-of-living-black-pieces": 0,
"number-of-living-white-pieces": 0,
"_embedded": {
"squares": [
{
"location": "a1",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/a1"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "a2",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/a2"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "a3",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/a3"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "a4",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/a4"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "a5",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/a5"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "a6",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/a6"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "a7",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/a7"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "a8",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/a8"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "b1",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/b1"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "b2",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/b2"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "b3",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/b3"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "b4",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/b4"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "b5",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/b5"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "b6",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/b6"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "b7",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/b7"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "b8",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/b8"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "c1",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/c1"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "c2",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/c2"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "c3",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/c3"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "c4",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/c4"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "c5",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/c5"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "c6",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/c6"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "c7",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/c7"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "c8",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/c8"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "d1",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/d1"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "d2",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/d2"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "d3",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/d3"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "d4",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/d4"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "d5",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/d5"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "d6",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/d6"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "d7",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/d7"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "d8",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/d8"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "e1",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/e1"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "e2",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/e2"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "e3",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/e3"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "e4",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/e4"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "e5",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/e5"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "e6",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/e6"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "e7",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/e7"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "e8",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/e8"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "f1",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/f1"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "f2",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/f2"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "f3",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/f3"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "f4",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/f4"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "f5",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/f5"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "f6",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/f6"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "f7",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/f7"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "f8",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/f8"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "g1",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/g1"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "g2",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/g2"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "g3",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/g3"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "g4",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/g4"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "g5",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/g5"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "g6",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/g6"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "g7",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/g7"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "g8",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/g8"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "h1",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/h1"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "h2",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/h2"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "h3",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/h3"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "h4",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/h4"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "h5",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/h5"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "h6",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/h6"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "h7",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/h7"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
},
{
"location": "h8",
"vacant": true,
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c/squares/h8"
}
},
{
"related": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
}
]
},
"_links": [
{
"self": {
"href": "http://localhost:8080/boards/3feeafdf02b4c76c"
}
}
]
}
Feature: Promotion
Scenario: Promotion is proposed when a pawn reaches the other side of the chess board
GIVEN a <color> pawn in <from>
WHEN the pawn is moved forward
THEN a promotion is proposed in <to>
Example:
| color | from | to |
| WHITE | A7 | A8 |
| WHITE | B7 | B8 |
| WHITE | C7 | C8 |
| WHITE | D7 | D8 |
| WHITE | E7 | E8 |
| WHITE | F7 | F8 |
| WHITE | G7 | G8 |
| WHITE | H7 | H8 |
| BLACK | A2 | A1 |
| BLACK | B2 | B1 |
| BLACK | C2 | C1 |
| BLACK | D2 | D1 |
| BLACK | E2 | E1 |
| BLACK | F2 | F1 |
| BLACK | G2 | G1 |
| BLACK | H2 | H1 |
Scenario: Pawn can not be promoted for pawn nor a king
GIVEN a pawn in the other side of the chess board
WHEN the pawn is promoted to a <promotion-type>
THEN the promotion is refused
WITH "Piece can not promote" as reason
Example:
| promotion-type |
| PAWN |
| KING |
Scenario: Pawn may be promoted for a non king piece
GIVEN a pawn in the other side of the chess board
WHEN the pawn is promoted to a <promotion-type>
THEN a <promotion-type> replaces the pawn
Example:
| promotion-type |
| QUEEN |
| KNIGHT |
| ROOK |
| BISHOP |
Scenario: Pawn can not be promoted if it has not been offered to it
GIVEN a pawn not in the other side of the chess board
WHEN the pawn is promoted to a valid piece
THEN the promotion is refused
WITH "Piece can not be promoted" as reason
Scenario: No piece can be moved while a pawn is promoted
GIVEN a pawn in the other side of the chess board
AND the promotion is proposed
WHEN an other piece is moved
THEN the move is refused
Feature: Bishop
Scenario: A bishop can move in any direction diagonally, so long as it is not obstructed by another piece
GIVEN a <color> bishop in <from>
AND the diagonal squares between <from> and <to> are vacant
WHEN the bishop is moved <times> <direction>
THEN the bishop is in <to>
Example:
| color | from | times | direction | to |
| WHITE | E5 | 3 | FORWARD_LEFT | B8 |
| WHITE | B8 | 2 | BACKWARD_RIGHT | D6 |
| WHITE | D6 | 1 | FORWARD_RIGHT | E7 |
| WHITE | E7 | 4 | BACKWARD_LEFT | A3 |
| BLACK | D5 | 3 | FORWARD_LEFT | G2 |
| BLACK | G2 | 2 | BACKWARD_RIGHT | E4 |
| BLACK | E4 | 2 | FORWARD_RIGHT | C2 |
| BLACK | C2 | 4 | BACKWARD_LEFT | G6 |
Scenario: A bishop cannot move beyond an obstructed path
GIVEN a <color> bishop in <from>
AND the square <obstructed> is not vacant
WHEN the bishop is moved <time> <direction>
THEN the move is refused
Example:
| color | from | obstructed | times | direction |
| WHITE | A1 | C3 | 4 | FORWARD_RIGHT |
| WHITE | E6 | B3 | 4 | BACKWARD_LEFT |
| WHITE | C3 | B4 | 1 | FORWARD_LEFT |
| WHITE | B6 | C5 | 2 | BACKWARD_RIGHT |
| BLACK | E5 | C3 | 3 | FORWARD_RIGHT |
| BLACK | D5 | E6 | 2 | BACKWARD_LEFT |
| BLACK | E5 | G3 | 3 | FORWARD_LEFT |
| BLACK | D5 | B7 | 2 | BACKWARD_RIGHT |
Scenario: A bishop can capture any opposing piece on the board that is within its bounds of movement
GIVEN a <color> bishop in <from>
AND an opposing piece in <to>
WHEN the bishop is moved to <to>
THEN the bishop captures the opposing piece
Example:
| color | from | to |
| WHITE | E5 | B2 |
| WHITE | C4 | D3 |
| WHITE | C6 | E8 |
| WHITE | H1 | A8 |
| BLACK | E5 | B2 |
| BLACK | C4 | D3 |
| BLACK | C6 | E8 |
| BLACK | H1 | A8 |
Feature: Stalemate
Stalemate is a situation in the game of chess where the player whose turn it is to move is not in check but has no legal move. The rules of chess provide that when stalemate occurs, the game ends as a draw.
Scenario: a player is stalemate
WHEN a king is not in check
AND the king's player cannot make any legal move
THEN the player is stalemate
AND the game ends as a draw
Spring has an Event Publisher and allow to create custom events. There is no need to use Guava.
Domain events should be mapped as published events (infra) with stream id, timestamp etc..
Published events can then be added to EventStore and handled by Event Handlers.
Current behavior:
TurnChanged{color=WHITE}
a3
TurnChanged{color=BLACK}
b6
TurnChanged{color=WHITE}
Expected behavior:
Turn is implicit because of move series. See https://en.wikipedia.org/wiki/Algebraic_notation_(chess)#Notation_for_a_series_of_moves
In fact, a game or series of moves is generally written in n two columns, as White/Black pairs, preceded by the move number and a period:
Whoever has to play can be deducted from this series.
White play first. It moves. Black move, White move, etc. Turn is implicit.
TurnChanged{color=WHITE}
a3
TurnChanged{color=BLACK}
b6
TurnChanged{color=WHITE}
should be
a3
b6
Current behavior:
a2
...
a1
PromotionProposed{location=a8}
a1=Q
Expected behavior:
Promotion is the move of a pawn from the penultimate rank (2 for black, 7 for white) to the last rank with a promotion type (queen, rook, bishop, knight).
For example, a white pawn can not move from rank 2 to 1 without specifying in witch piece it would be promoted.
So event flow would be as below :
a2 [...]
a1=Q [...]
PromotionProposed should be removed. Promotion feature should be reopened with a scenario about moving a pawn to the last rank without promoting it (should raise an error).
Promotion can also happen when capturing.
Feature: Check
A check is a condition that occurs when a player's king is under threat of capture on their opponent's next turn. A king so threatened is said to be in check. A player must get out of check, if possible, by interposing a piece between the threatening piece and the king, capturing the threatening piece, or moving the king to a square where it is no longer in check. Players cannot make any move that puts their own king in check.
If the king is in check and the checked player has no legal move to get out of check, the king is checkmated and the player loses. When the king is not in check and it is the last living piece of its color, if the player has no legal move to get out of check, the game results in Pat.
Scenario: a king becomes threatened
GIVEN a king in <king-location>
AND an opposing <opponent-type> in <opposing-location>
WHEN the opposing piece is moved to <to>
THEN the king is in the bounds of movement of the opposing piece
AND the king is in check
Example:
| king-location | opponent-type | opponent-location | to |
| G4 | QUEEN | D8 | D4 |
| F4 | BISHOP | F8 | D6 |
| E4 | ROOK | A8 | A4 |
| D5 | KNIGHT | G8 | F6 |
| D5 | PAWN | C7 | C6 |
Scenario: a king can not move to a square where it could be in check
GIVEN a king in <king-location>
AND an opposing <opponent-type> in <opposing-location>
WHEN the king is moved to <to>
THEN the move is refused
Example:
| king-location | opponent-type | opponent-location | to |
| D3 | QUEEN | D8 | D4 |
| D5 | BISHOP | F8 | D6 |
| B3 | ROOK | A8 | A4 |
| E7 | KNIGHT | G8 | F6 |
| D4 | PAWN | C6 | D5 |
Scenario: a king can move to a square where it could escape from check
GIVEN a king in check in <king-location>
AND an opposing <opponent-type> in <opposing-location>
WITH the square <to> not in its bounds of movement
WHEN the king is moved to <to>
THEN the king is no longer in check
Example:
| king-location | opponent-type | opponent-location | to |
| D3 | QUEEN | D8 | C3 |
| E6 | BISHOP | C4 | F6 |
| E3 | ROOK | B3 | E4 |
| E5 | KNIGHT | G6 | E6 |
| E3 | PAWN | D4 | D3 |
| D7 | QUEEN | D8 | D8 |
| B4 | BISHOP | C4 | C4 |
| B2 | ROOK | B3 | B3 |
| E3 | PAWN | D4 | D4 |
Scenario: king's allies can move to help the king escaping from check
GIVEN a king in check in <king-location>
AND an opposing <opponent-type> in <opposing-location>
AND a <ally-type>, ally of the king in <ally-location>
WHEN the ally is moved to <to>
THEN the king is no longer in check
Example:
| king-location | opponent-type | opponent-location | ally-type | ally-location | to |
| E1 | QUEEN | E8 | BISHOP | D3 | E4 |
| E1 | BISHOP | B4 | QUEEN | D1 | D2 |
| E1 | ROOK | E8 | KNIGHT | D2 | E4 |
| E1 | KNIGHT | D3 | ROOK | H3 | D3 |
| E2 | PAWN | F3 | PAWN | G2 | F3 |
| E1 | QUEEN | E8 | BISHOP | A4 | E8 |
| E1 | BISHOP | B4 | ROOK | B1 | B4 |
| E1 | ROOK | E8 | KNIGHT | D6 | E8 |
Scenario: king's ally can not move from a square that could make the king in check if vacant
GIVEN a king in <king-location>
AND an opposing <opponent-type> in <opposing-location>
AND a <ally-type>, ally of the king in <ally-location>
WHEN the ally is moved to <to>
THEN the move is refused
Scenario: a king can be put in check because of pawn promotion
GIVEN a king in <king-location>
AND an opposing pawn in the other side of the board
WHEN the opposing pawn is promoted to <promotion-type>
THEN the king is in check
Example:
| king-location | promotion-location | promotion-type |
| E1 | B1 | ROOK |
| E1 | B1 | QUEEN |
| E2 | F1 | BISHOP |
| E2 | G1 | KNIGHT |
Feature: Notation for moves
Each move of a piece is indicated by the piece's uppercase letter, plus the coordinate of the destination square. For example, Be5 (move a bishop to e5), Nf3 (move a knight to f3). For pawn moves, a letter indicating pawn is not used, only the destination square is given. For example, c5 (move a pawn to c5).
Captures
When a piece makes a capture, an "x" is inserted immediately before the destination square. For example, Bxe5 (bishop captures the piece on e5). When a pawn makes a capture, the ''file'' from which the pawn departed is used to identify the pawn. For example, exd5 (pawn on the e-file captures the piece on d5).
En passant captures are indicated by specifying the capturing pawn's file of departure, the "x", the destination square (not the square of the captured pawn), and (optionally) the suffix "e.p." indicating the capture was ''en passant''. For example, exd6e.p..
Disambiguating moves
When two (or more) identical pieces can move to the same square, the moving piece is uniquely identified by specifying the piece's letter, followed by (in descending order of preference):
For example, in the diagram, Bb8 would be ambiguous, as either of the bishops on a7 and d6 could legally move to b8. The move of the d6 bishop is therefore specified as Bdb8, indicating that it was the bishop on the d file which moved. Although they could also be differentiated by their ranks, the file letter takes precedence.
For the black rooks both on the 8th rank, both could potentially move to f8, so the move of the d8 rook to f8 is disambiguated as Rdf8. For the white rooks both on the a file which could both move to a3, it is necessary to provide the ''rank'' of the moving piece, i.e. R1a3.
In the case of the white queen on h4 moving to e1, neither the rank nor file alone are sufficient to disambiguate from the other white queens. As such, this move is written Qh4e1.
As above, an "x" can be inserted to indicate a capture, for example if the final case were a capture it would be written Qh4xe1.
Pawn promotion
When a pawn moves to the last rank and promotes, the piece promoted to is indicated at the end of the move notation, for example: e8Q (promoting to queen). Sometimes an equals sign or parentheses are used: '''e8=Q''' or '''e8(Q)''', but neither format is a [[FIDE]] standard. In [[Portable Game Notation]] (PGN), pawn promotion is always indicated using the equals sign format ('''e8=Q''').
In older books, pawn promotions can be found using a forward slash: '''e8/Q'''.
Draw offer
In FIDE Laws of Chess, an equals sign with parentheses, "(=)", is used to write the offer of a draw on the score next to a move, but this is not part of algebraic notation.
Castling
Castling is indicated by the special notations 0-0 (for kingside castling) and 0-0-0(queenside castling).
Check
A move that places the opponent's king in check usually has the symbol "+" appended.
Checkmate
Checkmate at the completion of moves can be represented by the symbol "#".
End of game
The notation '''1–0''' at the completion of moves indicates that White won, '''0–1''' indicates that Black won, and '''½–½''' indicates a draw.
Often there is no indication regarding how a player won or lost (other than checkmate, see above), so simply 1–0 or 0–1 may be written to show that one player resigned or lost due to time control. (Similarly, there is more than one way for a game to end in a draw.) Sometimes direct information is given by the words "White resigns" or "Black resigns", though this is not considered part of the notation but rather a return to the surrounding narrative text.
Feature: Pawn
Scenario: Pawn can only move directly forward one square
GIVEN a <color> pawn in <from>
AND <to> is vacant
WHEN the pawn is moved forward
THEN the pawn is in <to>
Example:
| color | from | to |
| WHITE | A2 | A3 |
| BLACK | A7 | A6
Scenario: Pawn is stuck when the square is not vacant
GIVEN a <color> pawn in <from>
AND <to> is not vacant
WHEN the pawn is moved forward
THEN the pawn stays in <from>
Example:
| color | from | to |
| WHITE | A2 | A3 |
| BLACK | A7 | A6
Scenario: Pawn can move directly forward two squares on their first move only
GIVEN a <color> pawn in <from>
AND <forward> is vacant
AND <to> is vacant
WHEN the pawn is moved forward two squares
THEN the pawn is in <to>
Example:
| color | from | forward | to |
| WHITE | A2 | A3 | A4 |
| WHITE | B2 | B3 | B4 |
| WHITE | C2 | C3 | C4 |
| WHITE | D2 | D3 | D4 |
| WHITE | E2 | E3 | E4 |
| WHITE | F2 | F3 | F4 |
| WHITE | G2 | G3 | G4 |
| WHITE | H2 | H3 | H4 |
| BLACK | A7 | A6 | A5 |
| BLACK | B7 | B6 | B5 |
| BLACK | C7 | C6 | C5 |
| BLACK | D7 | D6 | D5 |
| BLACK | E7 | E6 | E5 |
| BLACK | F7 | F6 | F5 |
| BLACK | G7 | G6 | G5 |
| BLACK | H7 | H6 | H5 |
Scenario: Pawn can move diagonally forward when capturing an opposing piece
GIVEN a <color> pawn in <from>
AND an opposing piece in <opponent-location>
WHEN the pawn is moved to <opponent-location>
THEN the pawn captures the opposing piece
Example:
| color | from | opponent-location |
| WHITE | B3 | A4 |
| WHITE | B3 | C4 |
| BLACK | B5 | C4 |
| BLACK | B5 | A4 |
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.