static ChessPiece promoted_piece(ChessMovePromote promote, ChessColor color) { switch (promote) { case CHESS_MOVE_PROMOTE_KNIGHT: return chess_piece_of_color(CHESS_PIECE_WHITE_KNIGHT, color); case CHESS_MOVE_PROMOTE_BISHOP: return chess_piece_of_color(CHESS_PIECE_WHITE_BISHOP, color); case CHESS_MOVE_PROMOTE_ROOK: return chess_piece_of_color(CHESS_PIECE_WHITE_ROOK, color); case CHESS_MOVE_PROMOTE_QUEEN: return chess_piece_of_color(CHESS_PIECE_WHITE_QUEEN, color); default: assert(0); return 0; } }
static ChessPiece captured_piece(ChessUnmoveCaptured captured, ChessColor color) { switch (captured) { case CHESS_UNMOVE_CAPTURED_NONE: return CHESS_PIECE_NONE; case CHESS_UNMOVE_CAPTURED_PAWN: return chess_piece_of_color(CHESS_PIECE_WHITE_PAWN, color); case CHESS_UNMOVE_CAPTURED_KNIGHT: return chess_piece_of_color(CHESS_PIECE_WHITE_KNIGHT, color); case CHESS_UNMOVE_CAPTURED_BISHOP: return chess_piece_of_color(CHESS_PIECE_WHITE_BISHOP, color); case CHESS_UNMOVE_CAPTURED_ROOK: return chess_piece_of_color(CHESS_PIECE_WHITE_ROOK, color); case CHESS_UNMOVE_CAPTURED_QUEEN: return chess_piece_of_color(CHESS_PIECE_WHITE_QUEEN, color); default: assert(0); return 0; } }
void chess_position_undo_move(ChessPosition* position, ChessUnmove unmove) { ChessSquare from = chess_unmove_from(unmove); ChessSquare to = chess_unmove_to(unmove); ChessUnmoveCaptured captured = chess_unmove_captured(unmove); ChessUnmoveEp ep = chess_unmove_ep(unmove); ChessPiece piece; ChessColor other = position->to_move; ChessColor color = chess_color_other(other); ChessFile file; if (from == 0 && to == 0) { /* Null move */ piece = CHESS_PIECE_NONE; } else { if (chess_unmove_promotion(unmove)) piece = chess_piece_of_color(CHESS_PIECE_WHITE_PAWN, color); else piece = position->piece[to]; assert(color == chess_piece_color(piece)); /* Unmove the piece */ position->piece[from] = piece; position->piece[to] = captured_piece(captured, other); /* Handle castling */ if (piece == CHESS_PIECE_WHITE_KING && from == CHESS_SQUARE_E1) { if (to == CHESS_SQUARE_G1) { position->piece[CHESS_SQUARE_F1] = CHESS_PIECE_NONE; position->piece[CHESS_SQUARE_H1] = CHESS_PIECE_WHITE_ROOK; } else if (to == CHESS_SQUARE_C1) { position->piece[CHESS_SQUARE_D1] = CHESS_PIECE_NONE; position->piece[CHESS_SQUARE_A1] = CHESS_PIECE_WHITE_ROOK; } } else if (piece == CHESS_PIECE_BLACK_KING && from == CHESS_SQUARE_E8) { if (to == CHESS_SQUARE_G8) { position->piece[CHESS_SQUARE_F8] = CHESS_PIECE_NONE; position->piece[CHESS_SQUARE_H8] = CHESS_PIECE_BLACK_ROOK; } else if (to == CHESS_SQUARE_C8) { position->piece[CHESS_SQUARE_D8] = CHESS_PIECE_NONE; position->piece[CHESS_SQUARE_A8] = CHESS_PIECE_BLACK_ROOK; } } position->castle = chess_unmove_castle(unmove); } /* Handle ep */ if (ep == CHESS_UNMOVE_EP_NONE) { position->ep = CHESS_FILE_INVALID; } else if (ep == CHESS_UNMOVE_EP_CAPTURE) { assert(piece == CHESS_PIECE_WHITE_PAWN || piece == CHESS_PIECE_BLACK_PAWN); /* Restore the captured pawn */ file = chess_square_file(to); if (color == CHESS_COLOR_WHITE) position->piece[chess_square_from_fr(file, CHESS_RANK_5)] = CHESS_PIECE_BLACK_PAWN; else position->piece[chess_square_from_fr(file, CHESS_RANK_4)] = CHESS_PIECE_WHITE_PAWN; position->ep = file; } else { position->ep = ep - CHESS_UNMOVE_EP_AVAILABLE; } /* Update king positions */ if (piece == CHESS_PIECE_WHITE_KING) position->wking = from; else if (piece == CHESS_PIECE_BLACK_KING) position->bking = from; /* Update move counters */ position->fifty = chess_unmove_fifty(unmove); position->to_move = color; if (position->to_move == CHESS_COLOR_BLACK) position->move_num--; }
ChessBoolean chess_generate_is_square_attacked(const ChessPosition* position, ChessSquare sq, ChessColor color) { ChessSquare from; ChessPiece piece; int dirs, dir, d, dist; /* Check for knight attacks */ dirs = jump_dirs[sq]; for (d = 0; d < 8; d++) { dir = dirs_array[d]; if ((dir & dirs) == 0) continue; from = sq + jumps_array[d]; piece = chess_position_piece(position, from); if (chess_position_piece(position, from) == chess_piece_of_color(CHESS_PIECE_WHITE_KNIGHT, color)) return CHESS_TRUE; } for (d = 0; d < 8; d++) { dir = dirs_array[d]; from = sq; dist = 1; do { dirs = slide_dirs[from]; if ((dir & dirs) == 0) break; from += slides_array[d]; piece = chess_position_piece(position, from); if (piece != CHESS_PIECE_NONE && chess_piece_color(piece) == color) { switch (piece) { case CHESS_PIECE_WHITE_QUEEN: case CHESS_PIECE_BLACK_QUEEN: return CHESS_TRUE; case CHESS_PIECE_WHITE_BISHOP: case CHESS_PIECE_BLACK_BISHOP: if (dir & bishop_dirs) return CHESS_TRUE; break; case CHESS_PIECE_WHITE_ROOK: case CHESS_PIECE_BLACK_ROOK: if (dir & rook_dirs) return CHESS_TRUE; break; case CHESS_PIECE_WHITE_KING: case CHESS_PIECE_BLACK_KING: if (dist == 1) return CHESS_TRUE; break; case CHESS_PIECE_WHITE_PAWN: if (dist == 1 && dir & (DIR_SE | DIR_SW)) return CHESS_TRUE; break; case CHESS_PIECE_BLACK_PAWN: if (dist == 1 && dir & (DIR_NE | DIR_NW)) return CHESS_TRUE; break; case CHESS_PIECE_WHITE_KNIGHT: case CHESS_PIECE_BLACK_KNIGHT: break; default: assert(CHESS_FALSE); break; } } dist++; } while (piece == CHESS_PIECE_NONE); } return CHESS_FALSE; }