-int Position::see_sign(Move m) const {
-
- assert(is_ok(m));
-
- Square from = move_from(m);
- Square to = move_to(m);
-
- // Early return if SEE cannot be negative because captured piece value
- // is not less then capturing one. Note that king moves always return
- // here because king midgame value is set to 0.
- if (PieceValueMidgame[piece_on(to)] >= PieceValueMidgame[piece_on(from)])
- return 1;
-
- return see(m);
-}
-
-int Position::see(Move m) const {
-
- Square from, to;
- Bitboard occ, attackers, stmAttackers, b;
- int swapList[32], slIndex = 1;
- PieceType capturedType, pt;
- Color stm;
-
- assert(is_ok(m));
-
- // As castle moves are implemented as capturing the rook, they have
- // SEE == RookValueMidgame most of the times (unless the rook is under
- // attack).
- if (is_castle(m))
- return 0;
-
- from = move_from(m);
- to = move_to(m);
- capturedType = type_of(piece_on(to));
- occ = occupied_squares();
-
- // Handle en passant moves
- if (is_enpassant(m))
- {
- Square capQq = to - pawn_push(side_to_move());
-
- assert(capturedType == PIECE_TYPE_NONE);
- assert(type_of(piece_on(capQq)) == PAWN);
-
- // Remove the captured pawn
- clear_bit(&occ, capQq);
- capturedType = PAWN;
- }
-
- // Find all attackers to the destination square, with the moving piece
- // removed, but possibly an X-ray attacker added behind it.
- clear_bit(&occ, from);
- attackers = attackers_to(to, occ);
-
- // If the opponent has no attackers we are finished
- stm = flip(color_of(piece_on(from)));
- stmAttackers = attackers & pieces(stm);
- if (!stmAttackers)
- return PieceValueMidgame[capturedType];
-
- // The destination square is defended, which makes things rather more
- // difficult to compute. We proceed by building up a "swap list" containing
- // the material gain or loss at each stop in a sequence of captures to the
- // destination square, where the sides alternately capture, and always
- // capture with the least valuable piece. After each capture, we look for
- // new X-ray attacks from behind the capturing piece.
- swapList[0] = PieceValueMidgame[capturedType];
- capturedType = type_of(piece_on(from));
-
- do {
- // Locate the least valuable attacker for the side to move. The loop
- // below looks like it is potentially infinite, but it isn't. We know
- // that the side to move still has at least one attacker left.
- for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++)
- assert(pt < KING);
-
- // Remove the attacker we just found from the 'occupied' bitboard,
- // and scan for new X-ray attacks behind the attacker.
- b = stmAttackers & pieces(pt);
- occ ^= (b & (~b + 1));
- attackers |= (rook_attacks_bb(to, occ) & pieces(ROOK, QUEEN))
- | (bishop_attacks_bb(to, occ) & pieces(BISHOP, QUEEN));
-
- attackers &= occ; // Cut out pieces we've already done
-
- // Add the new entry to the swap list
- assert(slIndex < 32);
- swapList[slIndex] = -swapList[slIndex - 1] + PieceValueMidgame[capturedType];
- slIndex++;
-
- // Remember the value of the capturing piece, and change the side to
- // move before beginning the next iteration.
- capturedType = pt;
- stm = flip(stm);
- stmAttackers = attackers & pieces(stm);
-
- // Stop before processing a king capture
- if (capturedType == KING && stmAttackers)
- {
- assert(slIndex < 32);
- swapList[slIndex++] = QueenValueMidgame*10;
- break;
- }
- } while (stmAttackers);
-
- // Having built the swap list, we negamax through it to find the best
- // achievable score from the point of view of the side to move.
- while (--slIndex)
- swapList[slIndex-1] = std::min(-swapList[slIndex], swapList[slIndex-1]);
-
- return swapList[0];