/* Makes a move_t from a supplied string (in long algebraic notation), or returns 0 if it's an invalid move. */ move_t move_from_text(const char* text, board_t* board) { int text_length = strlen(text); if (text_length != 4 && text_length != 5) return 0; move_t move = (((text[1]-'1')*8)+(tolower(text[0])-'a')) + ((((text[3]-'1')*8)+(tolower(text[2])-'a'))<<6); if (text_length == 5) if (board->to_move == WHITE) move |= piece_type_from_char(toupper(text[4]))<<23; else move |= piece_type_from_char(tolower(text[4]))<<23; move_t move_list[MAX_MOVES]; move_t* end_of_move_list = generate_pseudolegal_moves(board, move_list); for (int i = 0; &move_list[i] != end_of_move_list; i++) { if ((move_list[i]&0x7800FFF) == move) { if (IS_CASTLE(move_list[i]) && !is_legal_castle(board, move_list[i])) return 0; make_move(board, move_list[i]); if (!is_king_in_check(board, !board->to_move)) { undo_move(board, move_list[i]); return move_list[i]; } } } return 0; }
Move move_from_san(Position &pos, const std::string &movestr) { assert(pos.is_ok()); MovePicker mp = MovePicker(pos, false, MOVE_NONE, MOVE_NONE, MOVE_NONE, MOVE_NONE, OnePly); // Castling moves if(movestr == "O-O-O") { Move m; while((m = mp.get_next_move()) != MOVE_NONE) if(move_is_long_castle(m) && pos.move_is_legal(m)) return m; return MOVE_NONE; } else if(movestr == "O-O") { Move m; while((m = mp.get_next_move()) != MOVE_NONE) if(move_is_short_castle(m) && pos.move_is_legal(m)) return m; return MOVE_NONE; } // Normal moves const char *cstr = movestr.c_str(); const char *c; char *cc; char str[10]; int i; // Initialize str[] by making a copy of movestr with the characters // 'x', '=', '+' and '#' removed. cc = str; for(i=0, c=cstr; i<10 && *c!='\0' && *c!='\n' && *c!=' '; i++, c++) if(!strchr("x=+#", *c)) { *cc = strchr("nrq", *c)? toupper(*c) : *c; cc++; } *cc = '\0'; int left = 0, right = strlen(str) - 1; PieceType pt = NO_PIECE_TYPE, promotion; Square to; File fromFile = FILE_NONE; Rank fromRank = RANK_NONE; // Promotion? if(strchr("BNRQ", str[right])) { promotion = piece_type_from_char(str[right]); right--; } else promotion = NO_PIECE_TYPE; // Find the moving piece: if(left < right) { if(strchr("BNRQK", str[left])) { pt = piece_type_from_char(str[left]); left++; } else pt = PAWN; } // Find the to square: if(left < right) { if(str[right] < '1' || str[right] > '8' || str[right-1] < 'a' || str[right-1] > 'h') return MOVE_NONE; to = make_square(file_from_char(str[right-1]), rank_from_char(str[right])); right -= 2; } else return MOVE_NONE; // Find the file and/or rank of the from square: if(left <= right) { if(strchr("abcdefgh", str[left])) { fromFile = file_from_char(str[left]); left++; } if(strchr("12345678", str[left])) fromRank = rank_from_char(str[left]); } // Look for a matching move: Move m, move = MOVE_NONE; int matches = 0; while((m = mp.get_next_move()) != MOVE_NONE) { bool match = true; if(pos.type_of_piece_on(move_from(m)) != pt) match = false; else if(move_to(m) != to) match = false; else if(move_promotion(m) != promotion) match = false; else if(fromFile != FILE_NONE && fromFile != square_file(move_from(m))) match = false; else if(fromRank != RANK_NONE && fromRank != square_rank(move_from(m))) match = false; if(match) { move = m; matches++; } } if(matches == 1) return move; else return MOVE_NONE; }
/* Sets up a board to the position indicated by the FEN string. */ void set_board_from_fen_string(board_t* board, const char* fen_string) { int fen_index = 0, fen_length = strlen(fen_string), square; char current_char; for (square=A1; square <= H8; square++) board->pieces[square] = EMPTY; for (int i = 0; i < NUMBER_OF_PIECES-2; i++) board->piece_bitboard[i] = 0; board->color_bitboard[WHITE] = board->color_bitboard[BLACK] = 0; board->can_castle = 0; board->passed_square = 0; board->fifty_move_rule_counter = 0; board->material[WHITE] = board->material[BLACK] = 0; board->hash_key = 0; board->state_index = 0; // set pieces for (int rank = 7; rank >= 0; rank--) { int file = 0; do { if (file > 7) { fprintf(stderr, "FEN read error: too many files\n"); return; } current_char = fen_string[fen_index++]; if (current_char >= '1' && current_char <= '8') file += (current_char - '0'); else { board->pieces[rank*8+file] = piece_type_from_char(current_char); file++; } } while (fen_string[fen_index] != '/' && fen_string[fen_index] != ' '); fen_index++; } if (fen_string[fen_index-1] != ' ') { fprintf(stderr, "FEN read error: too many ranks\n"); return; } // set side to move if (fen_string[fen_index] == 'W' || fen_string[fen_index] == 'w') board->to_move = WHITE; else if (fen_string[fen_index] == 'B' || fen_string[fen_index] == 'b') { board->to_move = BLACK; board->hash_key ^= hash_keys.side; } else { fprintf(stderr, "FEN read error: invalid side to move\n"); return; } fen_index += 2; // set castling permissions if (fen_index < fen_length) { do { switch (fen_string[fen_index]) { case 'K': board->can_castle |= WHITE_CASTLE_OO; board->hash_key ^= hash_keys.white_king_side_castle; break; case 'Q': board->can_castle |= WHITE_CASTLE_OOO; board->hash_key ^= hash_keys.white_queen_side_castle; break; case 'k': board->can_castle |= BLACK_CASTLE_OO; board->hash_key ^= hash_keys.black_king_side_castle; break; case 'q': board->can_castle |= BLACK_CASTLE_OOO; board->hash_key ^= hash_keys.black_queen_side_castle; break; case '-': break; default: fprintf(stderr, "FEN read error: invalid castle permission\n"); return; } } while (fen_string[++fen_index] != ' ' && fen_index < fen_length); } // set en-passant square fen_index++; if (fen_index+1 < fen_length && fen_string[fen_index] != '-') { board->passed_square = (fen_string[fen_index]-'a'+1) + (fen_string[fen_index+1]-'0')*8 - 9; if (board->passed_square < A1 || board->passed_square > H8) { fprintf(stderr, "FEN read error: invalid en-passant square\n"); return; } board->hash_key ^= hash_keys.en_passant_targets[board->passed_square]; } // set up bitboards & material values for (square=A1; square <= H8; square++) { switch(board->pieces[square]) { case WHITE_KING: board->king_position[WHITE] = square; board->hash_key ^= hash_keys.keys[square][WHITE_KING]; break; case BLACK_KING: board->king_position[BLACK] = square; board->hash_key ^= hash_keys.keys[square][BLACK_KING]; break; default: board->piece_bitboard[board->pieces[square]] |= SQUARE_MASK[square]; board->material[COLOR_OF_PIECE(board->pieces[square])] += MATERIAL_VALUE[board->pieces[square]]; board->hash_key ^= hash_keys.keys[square][board->pieces[square]]; break; } } board->color_bitboard[WHITE] = board->piece_bitboard[WHITE_PAWN] | board->piece_bitboard[WHITE_ROOK] | board->piece_bitboard[WHITE_BISHOP] | board->piece_bitboard[WHITE_KNIGHT] | board->piece_bitboard[WHITE_QUEEN] | SQUARE_MASK[board->king_position[WHITE]]; board->color_bitboard[BLACK] = board->piece_bitboard[BLACK_PAWN] | board->piece_bitboard[BLACK_ROOK] | board->piece_bitboard[BLACK_BISHOP] | board->piece_bitboard[BLACK_KNIGHT] | board->piece_bitboard[BLACK_QUEEN] | SQUARE_MASK[board->king_position[BLACK]]; board->all_pieces_bitboard = board->color_bitboard[WHITE] | board->color_bitboard[BLACK]; }