@@ -955,102 +955,83 @@ Key Position::key_after(Move m) const {
955955}
956956
957957
958- // / Position::see() is a static exchange evaluator: It tries to estimate the
959- // / material gain or loss resulting from a move.
958+ // / Position::see_ge (Static Exchange Evaluation Greater or Equal) tests if the
959+ // / SEE value of move is greater or equal to the given value. We'll use an
960+ // / algorithm similar to alpha-beta pruning with a null window.
960961
961- Value Position::see_sign (Move m) const {
962+ bool Position::see_ge (Move m, Value v ) const {
962963
963964 assert (is_ok (m));
964965
965- // Early return if SEE cannot be negative because captured piece value
966- // is not less then capturing one. Note that king moves always return
967- // here because king midgame value is set to 0.
968- if (PieceValue[MG][moved_piece (m)] <= PieceValue[MG][piece_on (to_sq (m))])
969- return VALUE_KNOWN_WIN;
970-
971- return see (m);
972- }
973-
974- Value Position::see (Move m) const {
975-
976- Square from, to;
977- Bitboard occupied, attackers, stmAttackers;
978- Value swapList[32 ];
979- int slIndex = 1 ;
980- PieceType nextVictim;
981- Color stm;
982-
983- assert (is_ok (m));
984-
985- from = from_sq (m);
986- to = to_sq (m);
987- swapList[0 ] = PieceValue[MG][piece_on (to)];
988- stm = color_of (piece_on (from));
989- occupied = pieces () ^ from;
990-
991- // Castling moves are implemented as king capturing the rook so cannot
992- // be handled correctly. Simply return VALUE_ZERO that is always correct
993- // unless in the rare case the rook ends up under attack.
966+ // Castling moves are implemented as king capturing the rook so cannot be
967+ // handled correctly. Simply assume the SEE value is VALUE_ZERO that is always
968+ // correct unless in the rare case the rook ends up under attack.
994969 if (type_of (m) == CASTLING)
995- return VALUE_ZERO;
970+ return VALUE_ZERO >= v;
971+
972+ Square from = from_sq (m), to = to_sq (m);
973+ PieceType nextVictim = type_of (piece_on (from));
974+ Color stm = ~color_of (piece_on(from)); // First consider opponent's move
975+ Value balance; // Values of the pieces taken by us minus opponent's ones
976+ Bitboard occupied, stmAttackers;
996977
997978 if (type_of (m) == ENPASSANT)
998979 {
999- occupied ^= to - pawn_push (stm); // Remove the captured pawn
1000- swapList[0 ] = PieceValue[MG][PAWN];
980+ occupied = SquareBB[to - pawn_push (~stm)]; // Remove the captured pawn
981+ balance = PieceValue[MG][PAWN];
982+ }
983+ else
984+ {
985+ balance = PieceValue[MG][piece_on (to)];
986+ occupied = 0 ;
1001987 }
1002988
1003- // Find all attackers to the destination square, with the moving piece
1004- // removed, but possibly an X-ray attacker added behind it.
1005- attackers = attackers_to (to, occupied) & occupied;
989+ if (balance < v)
990+ return false ;
1006991
1007- // If the opponent has no attackers we are finished
1008- stm = ~stm;
1009- stmAttackers = attackers & pieces (stm);
1010- occupied ^= to; // For the case when captured piece is a pinner
992+ if (nextVictim == KING)
993+ return true ;
994+
995+ balance -= PieceValue[MG][nextVictim];
996+
997+ if (balance >= v)
998+ return true ;
1011999
1012- // Don't allow pinned pieces to attack pieces except the king as long all
1013- // pinners are on their original square.
1014- if (!(st->pinnersForKing [stm] & ~occupied))
1015- stmAttackers &= ~st->blockersForKing [stm];
1000+ bool relativeStm = true ; // True if the opponent is to move
1001+ occupied ^= pieces () ^ from ^ to;
10161002
1017- if (!stmAttackers)
1018- return swapList[0 ];
1003+ // Find all attackers to the destination square, with the moving piece removed,
1004+ // but possibly an X-ray attacker added behind it.
1005+ Bitboard attackers = attackers_to (to, occupied) & occupied;
10191006
1020- // The destination square is defended, which makes things rather more
1021- // difficult to compute. We proceed by building up a "swap list" containing
1022- // the material gain or loss at each stop in a sequence of captures to the
1023- // destination square, where the sides alternately capture, and always
1024- // capture with the least valuable piece. After each capture, we look for
1025- // new X-ray attacks from behind the capturing piece.
1026- nextVictim = type_of (piece_on (from));
1007+ while (true )
1008+ {
1009+ stmAttackers = attackers & pieces (stm);
10271010
1028- do {
1029- assert (slIndex < 32 );
1011+ // Don't allow pinned pieces to attack pieces except the king as long all
1012+ // pinners are on their original square.
1013+ if (!(st->pinnersForKing [stm] & ~occupied))
1014+ stmAttackers &= ~st->blockersForKing [stm];
10301015
1031- // Add the new entry to the swap list
1032- swapList[slIndex] = -swapList[slIndex - 1 ] + PieceValue[MG][nextVictim] ;
1016+ if (!stmAttackers)
1017+ return relativeStm ;
10331018
10341019 // Locate and remove the next least valuable attacker
10351020 nextVictim = min_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers);
1036- stm = ~stm;
1037- stmAttackers = attackers & pieces (stm);
10381021
1039- // Don't allow pinned pieces to attack pieces except the king
1040- if ( nextVictim != KING
1041- && !(st->pinnersForKing [stm] & ~occupied))
1042- stmAttackers &= ~st->blockersForKing [stm];
1022+ if (nextVictim == KING)
1023+ return relativeStm == bool (attackers & pieces (~stm));
10431024
1044- ++slIndex;
1025+ balance += relativeStm ? PieceValue[MG][nextVictim]
1026+ : -PieceValue[MG][nextVictim];
10451027
1046- } while (stmAttackers && (nextVictim != KING || (--slIndex, false ))); // Stop before a king capture
1028+ relativeStm = !relativeStm;
10471029
1048- // Having built the swap list, we negamax through it to find the best
1049- // achievable score from the point of view of the side to move.
1050- while (--slIndex)
1051- swapList[slIndex - 1 ] = std::min (-swapList[slIndex], swapList[slIndex - 1 ]);
1030+ if (relativeStm == (balance >= v))
1031+ return relativeStm;
10521032
1053- return swapList[0 ];
1033+ stm = ~stm;
1034+ }
10541035}
10551036
10561037
0 commit comments