55 CASTLE_QUEENSIDE ,
66 CASTLE_KINGSIDE ,
77 PAWN ,
8- BLACK
8+ BLACK ,
9+ GAME_COMPLETE
910} from './constants' ;
1011import FenParser from './fen-parser' ;
1112import Board from './board/board' ;
@@ -75,7 +76,13 @@ class Chess {
7576 return fenParser . stringify ( ) ;
7677 }
7778
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+ */
7884 moves ( piece = null ) {
85+ // If no piece, return all legal moves for current player
7986 if ( piece === null ) {
8087 return this . board . getAllLegalMoves (
8188 this . board . getBoard ( ) ,
@@ -85,6 +92,7 @@ class Chess {
8592 ) ;
8693 }
8794
95+ // If piece color is not current player, return empty array
8896 if ( getPieceColor ( piece ) !== this . activeColor ) {
8997 return [ ] ;
9098 }
@@ -97,10 +105,15 @@ class Chess {
97105 ) ;
98106 }
99107
108+ /**
109+ * Make a chess move
110+ * @param {String } piece - Piece to move
111+ * @param {String } to - Board position
112+ */
100113 move ( piece , to ) {
101114 const color = getPieceColor ( piece ) ;
102115 if ( color !== this . activeColor ) {
103- throw new Error ( `Not ${ color } turn` ) ;
116+ throw new Error ( `Wait for your turn` ) ;
104117 }
105118
106119 const board = this . getBoard ( ) ;
@@ -109,7 +122,7 @@ class Chess {
109122 . find ( move => move . to === to ) ;
110123
111124 if ( ! legalMove ) {
112- throw new Error ( 'Move not legal' ) ;
125+ throw new Error ( `You can't move ${ piece } to ${ to } ` ) ;
113126 }
114127
115128 // Move the piece
@@ -122,17 +135,18 @@ class Chess {
122135 this . deadPieces . push ( legalMove . capturedPiece ) ;
123136 }
124137
125- // Move castling rook
138+ // Move the rook if castling
126139 if ( legalMove . castle ) {
127140 const castleRookY = color === WHITE ? 7 : 0 ;
128-
129141 if ( legalMove . castle === CASTLE_QUEENSIDE ) {
142+ // Queen side castling
130143 const castleRookX = 0 ;
131144 const castleRook = getBoardPieceAt ( board , castleRookX , castleRookY ) ;
132145 const newRookPosition = stringifyBoardPosition ( castleRookX + 3 , castleRookY ) ;
133146 board [ castleRookY ] [ castleRookX ] = null ;
134147 board [ castleRookY ] [ castleRookX + 3 ] = updatePiecePosition ( castleRook , newRookPosition ) ;
135148 } else if ( legalMove . castle === CASTLE_KINGSIDE ) {
149+ // King side castling
136150 const castleRookX = 7 ;
137151 const castleRook = getBoardPieceAt ( board , 7 , castleRookY ) ;
138152 const newRookPosition = stringifyBoardPosition ( castleRookX - 2 , castleRookY ) ;
@@ -141,38 +155,62 @@ class Chess {
141155 }
142156 }
143157
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)
145159 if ( legalMove . piece === PAWN && Math . abs ( fromPos . y - toPos . y ) === 2 ) {
146160 const enPassantTargetY = color === WHITE ? fromPos . y - 1 : fromPos . y + 1 ;
147161 this . enPassantTarget = stringifyBoardPosition ( fromPos . x , enPassantTargetY ) ;
148162 } else {
149163 this . enPassantTarget = null ;
150164 }
151165
166+ // Update game state
152167 this . board = new Board ( board ) ;
153168 this . fullMoves += 1 ;
154169 this . halfMoves = Math . floor ( ( this . fullMoves + 1 ) / 2 ) ;
155170 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 ;
156175 }
157176
158- isCheck ( ) { }
177+ /**
178+ * Is game complete
179+ * @return {Boolean } isComplete
180+ */
181+ isComplete ( ) {
182+ return this . status === GAME_COMPLETE ;
183+ }
159184
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+ }
161194
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 ;
174201 }
175202
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+ */
176214 getBoard ( ) {
177215 return this . board . getBoard ( ) ;
178216 }
0 commit comments