X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fposition.cpp;h=42fdd62da8bfc3c121c61916164449682a2ed630;hb=93059830181b7167525ef4adad7d4ca3115b0701;hp=91fe7ab4506d9b11c85f626412dbf2be38ae77a0;hpb=89ec224cb92f49a6edc3d8b03a43d1c4418c285a;p=stockfish diff --git a/src/position.cpp b/src/position.cpp index 91fe7ab4..42fdd62d 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -45,7 +45,7 @@ Key Position::zobExclusion; Score Position::PieceSquareTable[16][64]; // Material values arrays, indexed by Piece -const Value Position::PieceValueMidgame[17] = { +const Value PieceValueMidgame[17] = { VALUE_ZERO, PawnValueMidgame, KnightValueMidgame, BishopValueMidgame, RookValueMidgame, QueenValueMidgame, VALUE_ZERO, @@ -54,7 +54,7 @@ const Value Position::PieceValueMidgame[17] = { RookValueMidgame, QueenValueMidgame }; -const Value Position::PieceValueEndgame[17] = { +const Value PieceValueEndgame[17] = { VALUE_ZERO, PawnValueEndgame, KnightValueEndgame, BishopValueEndgame, RookValueEndgame, QueenValueEndgame, VALUE_ZERO, @@ -63,13 +63,6 @@ const Value Position::PieceValueEndgame[17] = { RookValueEndgame, QueenValueEndgame }; -// Material values array used by SEE, indexed by PieceType -const Value Position::seeValues[] = { - VALUE_ZERO, - PawnValueMidgame, KnightValueMidgame, BishopValueMidgame, - RookValueMidgame, QueenValueMidgame, QueenValueMidgame*10 -}; - namespace { @@ -87,16 +80,17 @@ CheckInfo::CheckInfo(const Position& pos) { Color us = pos.side_to_move(); Color them = opposite_color(us); + Square ksq = pos.king_square(them); - ksq = pos.king_square(them); dcCandidates = pos.discovered_check_candidates(us); + pinned = pos.pinned_pieces(us); - checkSq[PAWN] = pos.attacks_from(ksq, them); + checkSq[PAWN] = pos.attacks_from(ksq, them); checkSq[KNIGHT] = pos.attacks_from(ksq); checkSq[BISHOP] = pos.attacks_from(ksq); - checkSq[ROOK] = pos.attacks_from(ksq); - checkSq[QUEEN] = checkSq[BISHOP] | checkSq[ROOK]; - checkSq[KING] = EmptyBoardBB; + checkSq[ROOK] = pos.attacks_from(ksq); + checkSq[QUEEN] = checkSq[BISHOP] | checkSq[ROOK]; + checkSq[KING] = EmptyBoardBB; } @@ -372,7 +366,7 @@ void Position::print(Move move) const { if (move) { Position p(*this, thread()); - string dd = (color_of_piece_on(move_from(move)) == BLACK ? ".." : ""); + string dd = (piece_color(piece_on(move_from(move))) == BLACK ? ".." : ""); cout << "\nMove is: " << dd << move_to_san(p, move); } @@ -387,7 +381,7 @@ void Position::print(Move move) const { if (piece == PIECE_NONE && square_color(sq) == DARK) piece = PIECE_NONE_DARK_SQ; - char c = (color_of_piece_on(sq) == BLACK ? '=' : ' '); + char c = (piece_color(piece_on(sq)) == BLACK ? '=' : ' '); cout << c << PieceToChar[piece] << c << '|'; } } @@ -526,7 +520,7 @@ bool Position::move_attacks_square(Move m, Square s) const { do_move_bb(&occ, make_move_bb(f, t)); xray = ( (rook_attacks_bb(s, occ) & pieces(ROOK, QUEEN)) |(bishop_attacks_bb(s, occ) & pieces(BISHOP, QUEEN))) - & pieces_of_color(color_of_piece_on(f)); + & pieces_of_color(piece_color(piece_on(f))); // If we have attacks we need to verify that are caused by our move // and are not already existent ones. @@ -558,7 +552,7 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const { Color us = side_to_move(); Square from = move_from(m); - assert(color_of_piece_on(from) == us); + assert(piece_color(piece_on(from)) == us); assert(piece_on(king_square(us)) == make_piece(us, KING)); // En passant captures are a tricky special case. Because they are @@ -588,7 +582,7 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const { // If the moving piece is a king, check whether the destination // square is attacked by the opponent. Castling moves are checked // for legality during move generation. - if (type_of_piece_on(from) == KING) + if (piece_type(piece_on(from)) == KING) return move_is_castle(m) || !(attackers_to(move_to(m)) & pieces_of_color(opposite_color(us))); // A non-king move is legal if and only if it is not pinned or it @@ -642,15 +636,15 @@ bool Position::move_is_pl(const Move m) const { // If the from square is not occupied by a piece belonging to the side to // move, the move is obviously not legal. - if (pc == PIECE_NONE || color_of_piece(pc) != us) + if (pc == PIECE_NONE || piece_color(pc) != us) return false; // The destination square cannot be occupied by a friendly piece - if (color_of_piece_on(to) == us) + if (piece_color(piece_on(to)) == us) return false; // Handle the special case of a pawn move - if (type_of_piece(pc) == PAWN) + if (piece_type(pc) == PAWN) { // Move direction must be compatible with pawn color int direction = to - from; @@ -672,7 +666,7 @@ bool Position::move_is_pl(const Move m) const { case DELTA_SE: // Capture. The destination square must be occupied by an enemy // piece (en passant captures was handled earlier). - if (color_of_piece_on(to) != them) + if (piece_color(piece_on(to)) != them) return false; // From and to files must be one file apart, avoids a7h5 @@ -718,7 +712,7 @@ bool Position::move_is_pl(const Move m) const { { // In case of king moves under check we have to remove king so to catch // as invalid moves like b1a1 when opposite queen is on c1. - if (type_of_piece_on(from) == KING) + if (piece_type(piece_on(from)) == KING) { Bitboard b = occupied_squares(); clear_bit(&b, from); @@ -746,22 +740,16 @@ bool Position::move_is_pl(const Move m) const { /// Position::move_gives_check() tests whether a pseudo-legal move is a check -bool Position::move_gives_check(Move m) const { - - return move_gives_check(m, CheckInfo(*this)); -} - bool Position::move_gives_check(Move m, const CheckInfo& ci) const { assert(is_ok()); assert(move_is_ok(m)); assert(ci.dcCandidates == discovered_check_candidates(side_to_move())); - assert(color_of_piece_on(move_from(m)) == side_to_move()); - assert(piece_on(ci.ksq) == make_piece(opposite_color(side_to_move()), KING)); + assert(piece_color(piece_on(move_from(m))) == side_to_move()); Square from = move_from(m); Square to = move_to(m); - PieceType pt = type_of_piece_on(from); + PieceType pt = piece_type(piece_on(from)); // Direct check ? if (bit_is_set(ci.checkSq[pt], to)) @@ -772,7 +760,7 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const { { // For pawn and king moves we need to verify also direction if ( (pt != PAWN && pt != KING) - || !squares_aligned(from, to, ci.ksq)) + || !squares_aligned(from, to, king_square(opposite_color(side_to_move())))) return true; } @@ -782,6 +770,7 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const { Color us = side_to_move(); Bitboard b = occupied_squares(); + Square ksq = king_square(opposite_color(us)); // Promotion with check ? if (move_is_promotion(m)) @@ -791,13 +780,13 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const { switch (promotion_piece_type(m)) { case KNIGHT: - return bit_is_set(attacks_from(to), ci.ksq); + return bit_is_set(attacks_from(to), ksq); case BISHOP: - return bit_is_set(bishop_attacks_bb(to, b), ci.ksq); + return bit_is_set(bishop_attacks_bb(to, b), ksq); case ROOK: - return bit_is_set(rook_attacks_bb(to, b), ci.ksq); + return bit_is_set(rook_attacks_bb(to, b), ksq); case QUEEN: - return bit_is_set(queen_attacks_bb(to, b), ci.ksq); + return bit_is_set(queen_attacks_bb(to, b), ksq); default: assert(false); } @@ -813,8 +802,8 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const { clear_bit(&b, from); clear_bit(&b, capsq); set_bit(&b, to); - return (rook_attacks_bb(ci.ksq, b) & pieces(ROOK, QUEEN, us)) - ||(bishop_attacks_bb(ci.ksq, b) & pieces(BISHOP, QUEEN, us)); + return (rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, us)) + ||(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, us)); } // Castling with check ? @@ -836,7 +825,7 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const { clear_bit(&b, rfrom); set_bit(&b, rto); set_bit(&b, kto); - return bit_is_set(rook_attacks_bb(rto, b), ci.ksq); + return bit_is_set(rook_attacks_bb(rto, b), ksq); } return false; @@ -928,11 +917,11 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI bool pm = move_is_promotion(m); Piece piece = piece_on(from); - PieceType pt = type_of_piece(piece); - PieceType capture = ep ? PAWN : type_of_piece_on(to); + PieceType pt = piece_type(piece); + PieceType capture = ep ? PAWN : piece_type(piece_on(to)); - assert(color_of_piece_on(from) == us); - assert(color_of_piece_on(to) == them || square_is_empty(to)); + assert(piece_color(piece_on(from)) == us); + assert(piece_color(piece_on(to)) == them || square_is_empty(to)); assert(!(ep || pm) || piece == make_piece(us, PAWN)); assert(!pm || relative_rank(us, to) == RANK_8); @@ -1066,10 +1055,10 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI if (ci.dcCandidates && bit_is_set(ci.dcCandidates, from)) { if (pt != ROOK) - st->checkersBB |= (attacks_from(ci.ksq) & pieces(ROOK, QUEEN, us)); + st->checkersBB |= (attacks_from(king_square(them)) & pieces(ROOK, QUEEN, us)); if (pt != BISHOP) - st->checkersBB |= (attacks_from(ci.ksq) & pieces(BISHOP, QUEEN, us)); + st->checkersBB |= (attacks_from(king_square(them)) & pieces(BISHOP, QUEEN, us)); } } } @@ -1266,10 +1255,10 @@ void Position::undo_move(Move m) { bool ep = move_is_ep(m); bool pm = move_is_promotion(m); - PieceType pt = type_of_piece_on(to); + PieceType pt = piece_type(piece_on(to)); assert(square_is_empty(from)); - assert(color_of_piece_on(to) == us); + assert(piece_color(piece_on(to)) == us); assert(!pm || relative_rank(us, to) == RANK_8); assert(!ep || to == st->previous->epSquare); assert(!ep || relative_rank(us, to) == RANK_6); @@ -1489,7 +1478,7 @@ int Position::see_sign(Move m) const { // 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 (midgame_value_of_piece_on(to) >= midgame_value_of_piece_on(from)) + if (piece_value_midgame(piece_on(to)) >= piece_value_midgame(piece_on(from))) return 1; return see(m); @@ -1513,16 +1502,16 @@ int Position::see(Move m) const { from = move_from(m); to = move_to(m); - capturedType = type_of_piece_on(to); + capturedType = piece_type(piece_on(to)); occupied = occupied_squares(); // Handle en passant moves - if (st->epSquare == to && type_of_piece_on(from) == PAWN) + if (st->epSquare == to && piece_type(piece_on(from)) == PAWN) { Square capQq = (side_to_move() == WHITE ? to - DELTA_N : to - DELTA_S); assert(capturedType == PIECE_TYPE_NONE); - assert(type_of_piece_on(capQq) == PAWN); + assert(piece_type(piece_on(capQq)) == PAWN); // Remove the captured pawn clear_bit(&occupied, capQq); @@ -1535,10 +1524,10 @@ int Position::see(Move m) const { attackers = attackers_to(to, occupied); // If the opponent has no attackers we are finished - stm = opposite_color(color_of_piece_on(from)); + stm = opposite_color(piece_color(piece_on(from))); stmAttackers = attackers & pieces_of_color(stm); if (!stmAttackers) - return seeValues[capturedType]; + 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 @@ -1546,8 +1535,8 @@ int Position::see(Move m) const { // 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] = seeValues[capturedType]; - capturedType = type_of_piece_on(from); + swapList[0] = PieceValueMidgame[capturedType]; + capturedType = piece_type(piece_on(from)); do { // Locate the least valuable attacker for the side to move. The loop @@ -1567,7 +1556,7 @@ int Position::see(Move m) const { // Add the new entry to the swap list assert(slIndex < 32); - swapList[slIndex] = -swapList[slIndex - 1] + seeValues[capturedType]; + swapList[slIndex] = -swapList[slIndex - 1] + PieceValueMidgame[capturedType]; slIndex++; // Remember the value of the capturing piece, and change the side to @@ -1632,8 +1621,8 @@ void Position::clear() { void Position::put_piece(Piece p, Square s) { - Color c = color_of_piece(p); - PieceType pt = type_of_piece(p); + Color c = piece_color(p); + PieceType pt = piece_type(p); board[s] = p; index[s] = pieceCount[c][pt]++; @@ -1656,7 +1645,7 @@ Key Position::compute_key() const { for (Square s = SQ_A1; s <= SQ_H8; s++) if (square_is_occupied(s)) - result ^= zobrist[color_of_piece_on(s)][type_of_piece_on(s)][s]; + result ^= zobrist[piece_color(piece_on(s))][piece_type(piece_on(s))][s]; if (ep_square() != SQ_NONE) result ^= zobEp[ep_square()]; @@ -1788,35 +1777,30 @@ bool Position::is_mate() const { } -/// Position::init_zobrist() is a static member function which initializes at -/// startup the various arrays used to compute hash keys. +/// Position::init() is a static member function which initializes at +/// startup the various arrays used to compute hash keys and the piece +/// square tables. The latter is a two-step operation: First, the white +/// halves of the tables are copied from the MgPST[][] and EgPST[][] arrays. +/// Second, the black halves of the tables are initialized by mirroring +/// and changing the sign of the corresponding white scores. -void Position::init_zobrist() { +void Position::init() { - int i,j, k; RKISS rk; - for (i = 0; i < 2; i++) for (j = 0; j < 8; j++) for (k = 0; k < 64; k++) - zobrist[i][j][k] = rk.rand(); + for (Color c = WHITE; c <= BLACK; c++) + for (PieceType pt = PAWN; pt <= KING; pt++) + for (Square s = SQ_A1; s <= SQ_H8; s++) + zobrist[c][pt][s] = rk.rand(); - for (i = 0; i < 64; i++) - zobEp[i] = rk.rand(); + for (Square s = SQ_A1; s <= SQ_H8; s++) + zobEp[s] = rk.rand(); - for (i = 0; i < 16; i++) + for (int i = 0; i < 16; i++) zobCastle[i] = rk.rand(); zobSideToMove = rk.rand(); zobExclusion = rk.rand(); -} - - -/// Position::init_piece_square_tables() initializes the piece square tables. -/// This is a two-step operation: First, the white halves of the tables are -/// copied from the MgPST[][] and EgPST[][] arrays. Second, the black halves -/// of the tables are initialized by mirroring and changing the sign of the -/// corresponding white scores. - -void Position::init_piece_square_tables() { for (Square s = SQ_A1; s <= SQ_H8; s++) for (Piece p = WP; p <= WK; p++) @@ -1939,8 +1923,8 @@ bool Position::is_ok(int* failedStep) const { { int kingCount[2] = {0, 0}; for (Square s = SQ_A1; s <= SQ_H8; s++) - if (type_of_piece_on(s) == KING) - kingCount[color_of_piece_on(s)]++; + if (piece_type(piece_on(s)) == KING) + kingCount[piece_color(piece_on(s))]++; if (kingCount[0] != 1 || kingCount[1] != 1) return false; @@ -2055,14 +2039,19 @@ bool Position::is_ok(int* failedStep) const { if (can_castle_queenside(c) && piece_on(initial_qr_square(c)) != make_piece(c, ROOK)) return false; } - if (castleRightsMask[initial_kr_square(WHITE)] != (ALL_CASTLES ^ WHITE_OO)) - return false; - if (castleRightsMask[initial_qr_square(WHITE)] != (ALL_CASTLES ^ WHITE_OOO)) - return false; - if (castleRightsMask[initial_kr_square(BLACK)] != (ALL_CASTLES ^ BLACK_OO)) - return false; - if (castleRightsMask[initial_qr_square(BLACK)] != (ALL_CASTLES ^ BLACK_OOO)) - return false; + // If we cannot castle castleRightsMask[] could be not valid, for instance when + // king initial file is FILE_A as queen rook. + if (can_castle(WHITE) || can_castle(BLACK)) + { + if (castleRightsMask[initial_kr_square(WHITE)] != (ALL_CASTLES ^ WHITE_OO)) + return false; + if (castleRightsMask[initial_qr_square(WHITE)] != (ALL_CASTLES ^ WHITE_OOO)) + return false; + if (castleRightsMask[initial_kr_square(BLACK)] != (ALL_CASTLES ^ BLACK_OO)) + return false; + if (castleRightsMask[initial_qr_square(BLACK)] != (ALL_CASTLES ^ BLACK_OOO)) + return false; + } } if (failedStep) *failedStep = 0;