void MovePicker::score_captures() { // Winning and equal captures in the main search are ordered by MVV/LVA. // Suprisingly, this appears to perform slightly better than SEE based // move ordering. The reason is probably that in a position with a winning // capture, capturing a more valuable (but sufficiently defended) piece // first usually doesn't hurt. The opponent will have to recapture, and // the hanging piece will still be hanging (except in the unusual cases // where it is possible to recapture with the hanging piece). Exchanging // big pieces before capturing a hanging piece probably helps to reduce // the subtree size. for(int i = 0; i < numOfMoves; i++) { int seeValue = pos->see(moves[i].move); if(seeValue >= 0) { if(move_promotion(moves[i].move)) moves[i].score = QueenValueMidgame; else moves[i].score = int(pos->midgame_value_of_piece_on(move_to(moves[i].move))) - int(pos->type_of_piece_on(move_from(moves[i].move))); } else moves[i].score = seeValue; } }
void MovePicker::score_qcaptures() { // Use MVV/LVA ordering. for(int i = 0; i < numOfMoves; i++) { Move m = moves[i].move; if(move_promotion(m)) moves[i].score = QueenValueMidgame; else moves[i].score = int(pos->midgame_value_of_piece_on(move_to(m))) - int(pos->midgame_value_of_piece_on(move_to(m))) / 64; } }
const std::string move_to_san(Position &pos, Move m) { std::string str; assert(pos.is_ok()); assert(move_is_ok(m)); Square from, to; Piece pc; from = move_from(m); to = move_to(m); pc = pos.piece_on(move_from(m)); if(m == MOVE_NONE) { str = "(none)"; return str; } else if(m == MOVE_NULL) { str = "(null)"; return str; } else if(move_is_long_castle(m) || (int(to - from) == -2 && type_of_piece(pc) == KING)) str = "O-O-O"; else if(move_is_short_castle(m) || (int(to - from) == 2 && type_of_piece(pc) == KING)) str = "O-O"; else { str = ""; if(type_of_piece(pc) == PAWN) { if(pos.move_is_capture(m)) str += file_to_char(square_file(move_from(m))); } else { str += piece_type_to_char(type_of_piece(pc), true); Ambiguity amb = move_ambiguity(pos, m); switch(amb) { case AMBIGUITY_NONE: break; case AMBIGUITY_FILE: str += file_to_char(square_file(from)); break; case AMBIGUITY_RANK: str += rank_to_char(square_rank(from)); break; case AMBIGUITY_BOTH: str += square_to_string(from); break; default: assert(false); } } if(pos.move_is_capture(m)) str += "x"; str += square_to_string(move_to(m)); if(move_promotion(m)) { str += "="; str += piece_type_to_char(move_promotion(m), true); } } // Is the move check? We don't use pos.move_is_check(m) here, because // Position::move_is_check doesn't detect all checks (not castling moves, // promotions and en passant captures). UndoInfo u; pos.do_move(m, u); if(pos.is_check()) str += pos.is_mate()? "#" : "+"; pos.undo_move(m, u); return str; }
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; }