145 case PAWN: |
145 case PAWN: |
146 result = result && pawn_chkrules(board, move); |
146 result = result && pawn_chkrules(board, move); |
147 result = result && !pawn_isblocked(board, move); |
147 result = result && !pawn_isblocked(board, move); |
148 break; |
148 break; |
149 case ROOK: |
149 case ROOK: |
150 result = result && rook_chkrules(board, move); |
150 result = result && rook_chkrules(move); |
151 result = result && !rook_isblocked(board, move); |
151 result = result && !rook_isblocked(board, move); |
152 break; |
152 break; |
153 case KNIGHT: |
153 case KNIGHT: |
154 result = result && knight_chkrules(board, move); |
154 result = result && knight_chkrules(move); |
155 result = result && !knight_isblocked(board, move); |
155 result = result && !knight_isblocked(board, move); |
156 break; |
156 break; |
157 case BISHOP: |
157 case BISHOP: |
158 result = result && bishop_chkrules(board, move); |
158 result = result && bishop_chkrules(move); |
159 result = result && !bishop_isblocked(board, move); |
159 result = result && !bishop_isblocked(board, move); |
160 break; |
160 break; |
161 case QUEEN: |
161 case QUEEN: |
162 result = result && queen_chkrules(board, move); |
162 result = result && queen_chkrules(move); |
163 result = result && !queen_isblocked(board, move); |
163 result = result && !queen_isblocked(board, move); |
164 break; |
164 break; |
165 case KING: |
165 case KING: |
166 result = result && king_chkrules(board, move); |
166 result = result && king_chkrules(board, move); |
167 result = result && !king_isblocked(board, move); |
167 result = result && !king_isblocked(board, move); |
201 /** |
201 /** |
202 * Guesses the location of a piece for short algebraic notation. |
202 * Guesses the location of a piece for short algebraic notation. |
203 * |
203 * |
204 * @param board the current state of the board |
204 * @param board the current state of the board |
205 * @param move the move date to operate on |
205 * @param move the move date to operate on |
206 * @return TRUE if the location could be retrieved, FALSE if the location is |
206 * @return status code (see rules/rules.h for the codes) |
207 * ambiguous |
|
208 */ |
207 */ |
209 static _Bool getlocation(Board board, Move *move) { |
208 static int getlocation(Board board, Move *move) { |
210 uint8_t piece = move->piece & PIECE_MASK; |
209 uint8_t piece = move->piece & PIECE_MASK; |
211 switch (piece) { |
210 switch (piece) { |
212 case PAWN: return pawn_getlocation(board, move); |
211 case PAWN: return pawn_getlocation(board, move); |
213 case ROOK: return rook_getlocation(board, move); |
212 case ROOK: return rook_getlocation(board, move); |
214 case KNIGHT: return knight_getlocation(board, move); |
213 case KNIGHT: return knight_getlocation(board, move); |
215 case BISHOP: return bishop_getlocation(board, move); |
214 case BISHOP: return bishop_getlocation(board, move); |
216 case QUEEN: return queen_getlocation(board, move); |
215 case QUEEN: return queen_getlocation(board, move); |
217 case KING: return king_getlocation(board, move); |
216 case KING: return king_getlocation(board, move); |
218 default: return FALSE; |
217 default: return INVALID_MOVE_SYNTAX; |
219 } |
218 } |
220 } |
219 } |
221 |
220 |
222 /** |
221 /** |
223 * Evaluates a move syntactically and stores the move data in the specified |
222 * Evaluates a move syntactically and stores the move data in the specified |
225 * |
224 * |
226 * @param board the current state of the board |
225 * @param board the current state of the board |
227 * @param mycolor the color of the current player |
226 * @param mycolor the color of the current player |
228 * @param mstr the input string to parse |
227 * @param mstr the input string to parse |
229 * @param move a pointer to object where the move data shall be stored |
228 * @param move a pointer to object where the move data shall be stored |
230 * @return TRUE, if the move is syntactically valid, FALSE otherwise |
229 * @return status code (see rules/rules.h for the list of codes) |
231 */ |
230 */ |
232 static _Bool eval_move(Board board, uint8_t mycolor, char *mstr, Move *move) { |
231 static int eval_move(Board board, uint8_t mycolor, char *mstr, Move *move) { |
233 memset(move, 0, sizeof(Move)); |
232 memset(move, 0, sizeof(Move)); |
234 move->fromfile = POS_UNSPECIFIED; |
233 move->fromfile = POS_UNSPECIFIED; |
235 move->fromrow = POS_UNSPECIFIED; |
234 move->fromrow = POS_UNSPECIFIED; |
236 |
235 |
237 size_t len = strlen(mstr); |
236 size_t len = strlen(mstr); |
329 |
328 |
330 if (move->piece) { |
329 if (move->piece) { |
331 move->piece |= mycolor; |
330 move->piece |= mycolor; |
332 if (move->fromfile == POS_UNSPECIFIED |
331 if (move->fromfile == POS_UNSPECIFIED |
333 || move->fromrow == POS_UNSPECIFIED) { |
332 || move->fromrow == POS_UNSPECIFIED) { |
334 return getlocation(board, move) && chkidx(move); |
333 return getlocation(board, move); |
335 } else { |
334 } else { |
336 return chkidx(move); |
335 return chkidx(move) ? VALID_MOVE_SYNTAX : INVALID_POSITION; |
337 } |
336 } |
338 } else { |
337 } else { |
339 return FALSE; |
338 return INVALID_MOVE_SYNTAX; |
340 } |
339 } |
341 // TODO: return status code to indicate the error type |
|
342 } |
340 } |
343 |
341 |
344 static int sendmove(Board board, uint8_t mycolor, int opponent) { |
342 static int sendmove(Board board, uint8_t mycolor, int opponent) { |
345 const size_t buflen = 8; |
343 const size_t buflen = 8; |
346 char movestr[buflen]; |
344 char movestr[buflen]; |
364 refresh(); |
362 refresh(); |
365 getnstr(movestr, buflen); |
363 getnstr(movestr, buflen); |
366 |
364 |
367 if (strncmp(movestr, "surr", buflen) == 0) { |
365 if (strncmp(movestr, "surr", buflen) == 0) { |
368 printw("You surrendered!"); |
366 printw("You surrendered!"); |
|
367 clrtoeol(); |
369 refresh(); |
368 refresh(); |
370 net_send_code(opponent, NETCODE_SURRENDER); |
369 net_send_code(opponent, NETCODE_SURRENDER); |
371 return 1; |
370 return 1; |
372 } else if (strncmp(movestr, "remis", buflen) == 0) { |
371 } else if (strncmp(movestr, "remis", buflen) == 0) { |
373 if (!remisrejected) { |
372 if (!remisrejected) { |
383 remisrejected = TRUE; |
382 remisrejected = TRUE; |
384 } |
383 } |
385 } |
384 } |
386 } else { |
385 } else { |
387 Move move; |
386 Move move; |
388 if (eval_move(board, mycolor, movestr, &move)) { |
387 int eval_result = eval_move(board, mycolor, movestr, &move); |
389 net_send_code(opponent, NETCODE_MOVE); |
388 switch (eval_result) { |
390 net_send_data(opponent, &move, sizeof(Move)); |
389 case VALID_MOVE_SYNTAX: |
391 code = net_recieve_code(opponent); |
390 net_send_code(opponent, NETCODE_MOVE); |
392 move.check = code == NETCODE_CHECK; |
391 net_send_data(opponent, &move, sizeof(Move)); |
393 move.checkmate = code == NETCODE_CHECKMATE; |
392 code = net_recieve_code(opponent); |
394 // TODO: record move |
393 move.check = code == NETCODE_CHECK; |
395 if (code == NETCODE_DECLINE) { |
394 move.checkmate = code == NETCODE_CHECKMATE; |
396 printw("Invalid move."); |
395 // TODO: record move |
397 clrtoeol(); |
396 if (code == NETCODE_DECLINE) { |
398 } else { |
397 printw("Invalid move."); |
399 apply_move(board, &move); |
|
400 if (move.checkmate) { |
|
401 printw("Checkmate!"); |
|
402 return 1; |
|
403 } else { |
398 } else { |
404 return 0; |
399 apply_move(board, &move); |
|
400 if (move.checkmate) { |
|
401 printw("Checkmate!"); |
|
402 clrtoeol(); |
|
403 return 1; |
|
404 } else { |
|
405 return 0; |
|
406 } |
405 } |
407 } |
406 } |
408 break; |
407 } else { |
409 case AMBIGUOUS_MOVE: |
408 printw("Can't interpret move - please use algebraic notation."); |
410 printw("Ambiguous move - " |
|
411 "please specify the piece to move."); |
|
412 break; |
|
413 case INVALID_POSITION: |
|
414 printw("Cannot find the piece that shall be moved."); |
|
415 break; |
|
416 default: |
|
417 printw("Can't interpret move - " |
|
418 "please use algebraic notation."); |
409 } |
419 } |
|
420 clrtoeol(); |
410 } |
421 } |
411 } |
422 } |
412 } |
423 } |
413 |
424 |
414 static int recvmove(Board board, int opponent) { |
425 static int recvmove(Board board, int opponent) { |