//// Variables
////
+extern SearchStack EmptySearchStack;
+
int Position::castleRightsMask[64];
Key Position::zobrist[2][8][64];
Value Position::MgPieceSquareTable[16][64];
Value Position::EgPieceSquareTable[16][64];
+static bool RequestPending = false;
////
//// Functions
fen += (rank > RANK_1 ? '/' : ' ');
}
- fen += (sideToMove == WHITE ? 'w' : 'b') + ' ';
+ fen += (sideToMove == WHITE ? "w " : "b ");
if (castleRights != NO_CASTLES)
{
if (can_castle_kingside(WHITE)) fen += 'K';
static const std::string pieceLetters = " PNBRQK PNBRQK .";
+ // Check for reentrancy, as example when called from inside
+ // MovePicker that is used also here in move_to_san()
+ if (RequestPending)
+ return;
+
+ RequestPending = true;
+
std::cout << std::endl;
if (m != MOVE_NONE)
{
- Position p(*this);
- std::cout << "Move is: " << move_to_san(p, m) << std::endl;
+ std::string col = (color_of_piece_on(move_from(m)) == BLACK ? ".." : "");
+ std::cout << "Move is: " << col << move_to_san(*this, m) << std::endl;
}
for (Rank rank = RANK_8; rank >= RANK_1; rank--)
{
}
std::cout << '|' << std::endl;
}
- std::cout << "+---+---+---+---+---+---+---+---+" << std::endl;
- std::cout << "Fen is: " << to_fen() << std::endl;
- std::cout << key << std::endl;
+ std::cout << "+---+---+---+---+---+---+---+---+" << std::endl
+ << "Fen is: " << to_fen() << std::endl
+ << "Key is: " << key << std::endl;
+
+ RequestPending = false;
}
/// Position::move_is_capture() tests whether a move from the current
-/// position is a capture.
+/// position is a capture. Move must not be MOVE_NONE.
bool Position::move_is_capture(Move m) const {
+ assert(m != MOVE_NONE);
+
return ( !square_is_empty(move_to(m))
&& (color_of_piece_on(move_to(m)) == opposite_color(side_to_move()))
)
/// Position::see() is a static exchange evaluator: It tries to estimate the
-/// material gain or loss resulting from a move. There are two versions of
-/// this function: One which takes a move as input, and one which takes a
-/// 'from' and a 'to' square. The function does not yet understand promotions
-/// or en passant captures.
+/// material gain or loss resulting from a move. There are three versions of
+/// this function: One which takes a destination square as input, one takes a
+/// move, and one which takes a 'from' and a 'to' square. The function does
+/// not yet understand promotions or en passant captures.
+
+int Position::see(Square to) const {
+
+ assert(square_is_ok(to));
+ return see(SQ_NONE, to);
+}
int Position::see(Move m) const {
int Position::see(Square from, Square to) const {
- // Approximate material values, with pawn = 1
+ // Material values
static const int seeValues[18] = {
- 0, 1, 3, 3, 5, 10, 100, 0, 0, 1, 3, 3, 5, 10, 100, 0, 0, 0
+ 0, PawnValueMidgame, KnightValueMidgame, BishopValueMidgame,
+ RookValueMidgame, QueenValueMidgame, QueenValueMidgame*10, 0,
+ 0, PawnValueMidgame, KnightValueMidgame, BishopValueMidgame,
+ RookValueMidgame, QueenValueMidgame, QueenValueMidgame*10, 0,
+ 0, 0
};
Bitboard attackers, occ, b;
- assert(square_is_ok(from));
+ assert(square_is_ok(from) || from == SQ_NONE);
assert(square_is_ok(to));
// Initialize colors
- Color us = color_of_piece_on(from);
+ Color us = (from != SQ_NONE ? color_of_piece_on(from) : opposite_color(color_of_piece_on(to)));
Color them = opposite_color(us);
// Initialize pieces
// Find all attackers to the destination square, with the moving piece
// removed, but possibly an X-ray attacker added behind it.
occ = occupied_squares();
- clear_bit(&occ, from);
- attackers = (rook_attacks_bb(to, occ) & rooks_and_queens())
- | (bishop_attacks_bb(to, occ) & bishops_and_queens())
- | (piece_attacks<KNIGHT>(to) & knights())
- | (piece_attacks<KING>(to) & kings())
- | (pawn_attacks(WHITE, to) & pawns(BLACK))
- | (pawn_attacks(BLACK, to) & pawns(WHITE));
-
- // If the opponent has no attackers, we are finished
+
+ // Handle enpassant moves
+ if (ep_square() == to && type_of_piece_on(from) == PAWN)
+ {
+ assert(capture == EMPTY);
+
+ Square capQq = (side_to_move() == WHITE)? (to - DELTA_N) : (to - DELTA_S);
+ capture = piece_on(capQq);
+
+ assert(type_of_piece_on(capQq) == PAWN);
+
+ // Remove the captured pawn
+ clear_bit(&occ, capQq);
+ }
+
+ while (true)
+ {
+ clear_bit(&occ, from);
+ attackers = (rook_attacks_bb(to, occ) & rooks_and_queens())
+ | (bishop_attacks_bb(to, occ) & bishops_and_queens())
+ | (piece_attacks<KNIGHT>(to) & knights())
+ | (piece_attacks<KING>(to) & kings())
+ | (pawn_attacks(WHITE, to) & pawns(BLACK))
+ | (pawn_attacks(BLACK, to) & pawns(WHITE));
+
+ if (from != SQ_NONE)
+ break;
+
+ // If we don't have any attacker we are finished
+ if ((attackers & pieces_of_color(us)) == EmptyBoardBB)
+ return 0;
+
+ // Locate the least valuable attacker to the destination square
+ // and use it to initialize from square.
+ PieceType pt;
+ for (pt = PAWN; !(attackers & pieces_of_color_and_type(us, pt)); pt++)
+ assert(pt < KING);
+
+ from = first_1(attackers & pieces_of_color_and_type(us, pt));
+ piece = piece_on(from);
+ }
+
+ // If the opponent has no attackers we are finished
if ((attackers & pieces_of_color(them)) == EmptyBoardBB)
return seeValues[capture];
if (is_check())
{
- MovePicker mp = MovePicker(*this, false, MOVE_NONE, MOVE_NONE,
- MOVE_NONE, MOVE_NONE, Depth(0));
+ MovePicker mp = MovePicker(*this, false, MOVE_NONE, EmptySearchStack, Depth(0));
return mp.get_next_move() == MOVE_NONE;
}
return false;