public static void MovePicker.score() { // Try good captures ordered by MVV/LVA, then non-captures if destination square // is not under attack, ordered by history value, then bad-captures and quiet // moves with a negative SEE. This last group is ordered by the SEE value. Move m; Value see; for (ExtMove *it = moves; it != end; ++it) { m = it.move; if ((see = pos.see_sign(m)) < Value.VALUE_ZERO) { it.value = see - Stats <false, Value> .Max; // At the bottom } else if (pos.capture(m)) { it.value = GlobalMembersPosition.PieceValue[(int)Phase.MG, pos.piece_on(GlobalMembersTypes.to_sq(m))] - Value(GlobalMembersTypes.type_of(pos.moved_piece(m))) + Stats <false, Value> .Max; } else { it.value = history[pos.moved_piece(m)][(int)GlobalMembersTypes.to_sq(m)]; } } }
/// score() assign a numerical value to each move in a move list. The moves with /// highest values will be picked first. public static void MovePicker.score() { // 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. // In main search we want to push captures with negative SEE values to the // badCaptures[] array, but instead of doing it now we delay until the move // has been picked up in pick_move_from_list(). This way we save some SEE // calls in case we get a cutoff. Move m; for (ExtMove *it = moves; it != end; ++it) { m = it.move; it.value = GlobalMembersPosition.PieceValue[(int)Phase.MG, pos.piece_on(GlobalMembersTypes.to_sq(m))] - Value(GlobalMembersTypes.type_of(pos.moved_piece(m))); if (GlobalMembersTypes.type_of(m) == MoveType.ENPASSANT) { it.value += GlobalMembersPosition.PieceValue[(int)Phase.MG, (int)PieceType.PAWN]; } else if (GlobalMembersTypes.type_of(m) == MoveType.PROMOTION) { it.value += GlobalMembersPosition.PieceValue[(int)Phase.MG, (int)GlobalMembersTypes.promotion_type(m)] - GlobalMembersPosition.PieceValue[(int)Phase.MG, (int)PieceType.PAWN]; } } }
public static void MovePicker.score() { Move m; for (ExtMove *it = moves; it != end; ++it) { m = it.move; it.value = history[pos.moved_piece(m)][(int)GlobalMembersTypes.to_sq(m)]; } }