5
5
CASTLE_QUEENSIDE ,
6
6
CASTLE_KINGSIDE ,
7
7
PAWN ,
8
- BLACK
8
+ BLACK ,
9
+ GAME_COMPLETE
9
10
} from './constants' ;
10
11
import FenParser from './fen-parser' ;
11
12
import Board from './board/board' ;
@@ -75,7 +76,13 @@ class Chess {
75
76
return fenParser . stringify ( ) ;
76
77
}
77
78
79
+ /**
80
+ * Gets an array of legal moves for current player
81
+ * @param {String } piece - Filter moves by piece
82
+ * @return {Array } moves - Array of moves
83
+ */
78
84
moves ( piece = null ) {
85
+ // If no piece, return all legal moves for current player
79
86
if ( piece === null ) {
80
87
return this . board . getAllLegalMoves (
81
88
this . board . getBoard ( ) ,
@@ -85,6 +92,7 @@ class Chess {
85
92
) ;
86
93
}
87
94
95
+ // If piece color is not current player, return empty array
88
96
if ( getPieceColor ( piece ) !== this . activeColor ) {
89
97
return [ ] ;
90
98
}
@@ -97,10 +105,15 @@ class Chess {
97
105
) ;
98
106
}
99
107
108
+ /**
109
+ * Make a chess move
110
+ * @param {String } piece - Piece to move
111
+ * @param {String } to - Board position
112
+ */
100
113
move ( piece , to ) {
101
114
const color = getPieceColor ( piece ) ;
102
115
if ( color !== this . activeColor ) {
103
- throw new Error ( `Not ${ color } turn` ) ;
116
+ throw new Error ( `Wait for your turn` ) ;
104
117
}
105
118
106
119
const board = this . getBoard ( ) ;
@@ -109,7 +122,7 @@ class Chess {
109
122
. find ( move => move . to === to ) ;
110
123
111
124
if ( ! legalMove ) {
112
- throw new Error ( 'Move not legal' ) ;
125
+ throw new Error ( `You can't move ${ piece } to ${ to } ` ) ;
113
126
}
114
127
115
128
// Move the piece
@@ -122,17 +135,18 @@ class Chess {
122
135
this . deadPieces . push ( legalMove . capturedPiece ) ;
123
136
}
124
137
125
- // Move castling rook
138
+ // Move the rook if castling
126
139
if ( legalMove . castle ) {
127
140
const castleRookY = color === WHITE ? 7 : 0 ;
128
-
129
141
if ( legalMove . castle === CASTLE_QUEENSIDE ) {
142
+ // Queen side castling
130
143
const castleRookX = 0 ;
131
144
const castleRook = getBoardPieceAt ( board , castleRookX , castleRookY ) ;
132
145
const newRookPosition = stringifyBoardPosition ( castleRookX + 3 , castleRookY ) ;
133
146
board [ castleRookY ] [ castleRookX ] = null ;
134
147
board [ castleRookY ] [ castleRookX + 3 ] = updatePiecePosition ( castleRook , newRookPosition ) ;
135
148
} else if ( legalMove . castle === CASTLE_KINGSIDE ) {
149
+ // King side castling
136
150
const castleRookX = 7 ;
137
151
const castleRook = getBoardPieceAt ( board , 7 , castleRookY ) ;
138
152
const newRookPosition = stringifyBoardPosition ( castleRookX - 2 , castleRookY ) ;
@@ -141,38 +155,62 @@ class Chess {
141
155
}
142
156
}
143
157
144
- // En passant target (if a pawn does a 2 step move)
158
+ // Set new en passant target (if a pawn does a 2 step move)
145
159
if ( legalMove . piece === PAWN && Math . abs ( fromPos . y - toPos . y ) === 2 ) {
146
160
const enPassantTargetY = color === WHITE ? fromPos . y - 1 : fromPos . y + 1 ;
147
161
this . enPassantTarget = stringifyBoardPosition ( fromPos . x , enPassantTargetY ) ;
148
162
} else {
149
163
this . enPassantTarget = null ;
150
164
}
151
165
166
+ // Update game state
152
167
this . board = new Board ( board ) ;
153
168
this . fullMoves += 1 ;
154
169
this . halfMoves = Math . floor ( ( this . fullMoves + 1 ) / 2 ) ;
155
170
this . activeColor = color === WHITE ? BLACK : WHITE ;
171
+ this . status =
172
+ this . board . getAllLegalMoves ( board , this . enPassantTarget , this . castling ) . length !== 0
173
+ ? GAME_ONGOING
174
+ : GAME_COMPLETE ;
156
175
}
157
176
158
- isCheck ( ) { }
177
+ /**
178
+ * Is game complete
179
+ * @return {Boolean } isComplete
180
+ */
181
+ isComplete ( ) {
182
+ return this . status === GAME_COMPLETE ;
183
+ }
159
184
160
- isCheckmate ( ) { }
185
+ /**
186
+ * Is check
187
+ * @param {String } color - player color
188
+ * @return {Boolean } isCheck
189
+ */
190
+ isCheck ( color = null ) {
191
+ const board = this . board . getBoard ( ) ;
192
+ return this . board . isCheck ( color === null ? this . activeColor : color , board ) ;
193
+ }
161
194
162
- isDone ( ) {
163
- const board = this . getBoard ( ) ;
164
- const legalMoves = this . board . getAllLegalMoves (
165
- board ,
166
- this . activeColor ,
167
- this . enPassantTarget ,
168
- this . castling
169
- ) ;
170
- if ( legalMoves . length === 0 ) {
171
- return true ;
172
- }
173
- return false ;
195
+ /**
196
+ * Is checkmate
197
+ * @return {Boolean } isCheckmate
198
+ */
199
+ isCheckmate ( ) {
200
+ return this . isCheck ( ) && this . moves ( ) . length === 0 ;
174
201
}
175
202
203
+ /**
204
+ * Is draw
205
+ * @return {Boolean } isDraw
206
+ */
207
+ isDraw ( ) {
208
+ return ! this . isCheck ( ) && this . moves ( ) . length === 0 ;
209
+ }
210
+
211
+ /**
212
+ * Get board matrix
213
+ */
176
214
getBoard ( ) {
177
215
return this . board . getBoard ( ) ;
178
216
}
0 commit comments