// Returns the short algebraic chess notation and the new board of a castling // type move. Assume that the castling move is legal. Equivalent of // Game#apply_move but for a castling move. char* castling (Board *board, int castling_type, Board *new_board) { char *move; switch (castling_type) { case WHITE_SHORT_CASTLING: memcpy (new_board, board, sizeof (Board)); new_board->king[WHITE] ^= 0x50; new_board->rooks[WHITE] ^= 0xa0; new_board->placement[E1] = '\0'; new_board->placement[F1] = 'R'; new_board->placement[G1] = 'K'; new_board->placement[H1] = '\0'; new_board->castling ^= new_board->castling & 0x1100; move = (char *) malloc (5); strcpy (move, "O-O"); break; case WHITE_LONG_CASTLING: memcpy (new_board, board, sizeof (Board)); new_board->king[WHITE] ^= 0x14; new_board->rooks[WHITE] ^= 0x09; new_board->placement[E1] = '\0'; new_board->placement[D1] = 'R'; new_board->placement[C1] = 'K'; new_board->placement[A1] = '\0'; new_board->castling ^= new_board->castling & 0x1100; move = (char *) malloc (7); strcpy (move, "O-O-O"); break; case BLACK_SHORT_CASTLING: memcpy (new_board, board, sizeof (Board)); new_board->king[BLACK] ^= 0x5000000000000000; new_board->rooks[BLACK] ^= 0xa000000000000000; new_board->placement[E8] = '\0'; new_board->placement[F8] = 'r'; new_board->placement[G8] = 'k'; new_board->placement[H8] = '\0'; new_board->castling ^= new_board->castling & 0x0011; move = (char *) malloc (5); strcpy (move, "O-O"); break; case BLACK_LONG_CASTLING: memcpy (new_board, board, sizeof (Board)); new_board->king[BLACK] ^= 0x1400000000000000; new_board->rooks[BLACK] ^= 0x0900000000000000; new_board->placement[E8] = '\0'; new_board->placement[D8] = 'r'; new_board->placement[C8] = 'k'; new_board->placement[A8] = '\0'; new_board->castling ^= new_board->castling & 0x0011; move = (char *) malloc (7); strcpy (move, "O-O-O"); break; default: return NULL; } set_occupied (new_board); return move; }
/* A FEN string is composed of 6 parts separated by " " (space). 1. Piece placement (from white's perspective). 2. Active color. "w" means white moves next, "b" means black. 3. Castling availability. If neither side can castle, this is "-". 4. En passant target square in algebraic notation. If there's no en passant target square, this is "-". 5. Halfmove clock: this is the number of halfmoves since the last pawn advance or capture. 6. Fullmove number: the number of the full move. It starts at 1, and is incremented after black's move. */ void set_fen (Game *g, const char *fen) { Board *board = NEW_BOARD; int i = 0, j, k, square; char *pch; char *s = (char *) malloc (sizeof (char) * (strlen (fen) + 1)); strcpy (s, fen); // Init board memset (board->placement, '\0', 64); board->pawns[WHITE] = 0x0; board->pawns[BLACK] = 0x0; board->rooks[WHITE] = 0x0; board->rooks[BLACK] = 0x0; board->knights[WHITE] = 0x0; board->knights[BLACK] = 0x0; board->bishops[WHITE] = 0x0; board->bishops[BLACK] = 0x0; board->queens[WHITE] = 0x0; board->queens[BLACK] = 0x0; board->king[WHITE] = 0x0; board->king[BLACK] = 0x0; pch = strtok (s, " /"); while (pch != NULL) { if (i < 8) { for (j = 0, k = 0; j < (int) strlen (pch); j++) { if (pch[j] - 48 > 8) { square = (abs (i - 7) * 8) + k; switch (pch[j]) { case 'P': board->placement[square] = pch[j]; board->pawns[WHITE] ^= 1ULL << square; break; case 'p': board->placement[square] = pch[j]; board->pawns[BLACK] ^= 1ULL << square; break; case 'R': board->placement[square] = pch[j]; board->rooks[WHITE] ^= 1ULL << square; break; case 'r': board->placement[square] = pch[j]; board->rooks[BLACK] ^= 1ULL << square; break; case 'N': board->placement[square] = pch[j]; board->knights[WHITE] ^= 1ULL << square; break; case 'n': board->placement[square] = pch[j]; board->knights[BLACK] ^= 1ULL << square; break; case 'B': board->placement[square] = pch[j]; board->bishops[WHITE] ^= 1ULL << square; break; case 'b': board->placement[square] = pch[j]; board->bishops[BLACK] ^= 1ULL << square; break; case 'Q': board->placement[square] = pch[j]; board->queens[WHITE] ^= 1ULL << square; break; case 'q': board->placement[square] = pch[j]; board->queens[BLACK] ^= 1ULL << square; break; case 'K': board->placement[square] = pch[j]; board->king[WHITE] ^= 1ULL << square; break; case 'k': board->placement[square] = pch[j]; board->king[BLACK] ^= 1ULL << square; break; } k++; } else k += pch[j] - 48; } } else if (i == 8) { board->active_color = pch[0] == 'b'; } else if (i == 9) { board->castling = 0x0000; for (j = 0; j < (int) strlen (pch); j++) { switch (pch[j]) { case 'K': board->castling |= 0x1000; break; case 'Q': board->castling |= 0x0100; break; case 'k': board->castling |= 0x0010; break; case 'q': board->castling |= 0x0001; break; } } } else if (i == 10) { board->en_passant = coord_to_square (pch); } else if (i == 11) { board->halfmove_clock = atoi (pch); } else if (i == 12) { board->fullmove_number = atoi (pch); } i++; pch = strtok (NULL, " /"); } set_occupied (board); g->boards[g->current] = board; g->moves[g->current] = (char *) malloc (11); g->coord_moves[g->current] = (char *) malloc (11); strcpy (g->moves[g->current], "SET BY FEN"); strcpy (g->coord_moves[g->current], "SET BY FEN"); g->current++; // check result if (king_in_checkmate (board, board->active_color)) g->result = !board->active_color; else if (stalemate (board, board->active_color) || insufficient_material (board)) g->result = DRAW; free (s); }