X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fposition.cpp;h=ceface349ef375f3359b91531cfc041e87c8389e;hb=21fc66c2466f86a7ee12221e197b6e6708f4512b;hp=e3bf4aee3e17863c55ca862ff15607443d395512;hpb=54f1c383d36f461a740eeaa93856b408e8d3faa3;p=stockfish diff --git a/src/position.cpp b/src/position.cpp index e3bf4aee..ceface34 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -29,6 +29,7 @@ #include "position.h" #include "psqtab.h" #include "rkiss.h" +#include "thread.h" #include "tt.h" #include "ucioption.h" @@ -569,10 +570,6 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const { assert(move_is_ok(m)); assert(pinned == pinned_pieces(side_to_move())); - // Castling moves are checked for legality during move generation. - if (move_is_castle(m)) - return true; - // En passant captures are a tricky special case. Because they are // rather uncommon, we do it simply by testing whether the king is attacked // after the move is made @@ -606,9 +603,10 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const { assert(piece_on(king_square(us)) == make_piece(us, KING)); // If the moving piece is a king, check whether the destination - // square is attacked by the opponent. + // square is attacked by the opponent. Castling moves are checked + // for legality during move generation. if (type_of_piece_on(from) == KING) - return !(attackers_to(move_to(m)) & pieces_of_color(opposite_color(us))); + 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 // is moving along the ray towards or away from the king. @@ -622,7 +620,7 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const { bool Position::pl_move_is_evasion(Move m, Bitboard pinned) const { - assert(is_check()); + assert(in_check()); Color us = side_to_move(); Square from = move_from(m); @@ -649,7 +647,7 @@ bool Position::pl_move_is_evasion(Move m, Bitboard pinned) const bool Position::move_is_legal(const Move m) const { - MoveStack mlist[MOVES_MAX]; + MoveStack mlist[MAX_MOVES]; MoveStack *cur, *last = generate(*this, mlist); for (cur = mlist; cur != last; cur++) @@ -678,9 +676,13 @@ bool Position::move_is_legal(const Move m, Bitboard pinned) const { if (move_is_special(m)) return move_is_legal(m); + // Is not a promotion, so promotion piece must be empty + if (move_promotion_piece(m) - 2 != PIECE_TYPE_NONE) + return false; + // If the from square is not occupied by a piece belonging to the side to // move, the move is obviously not legal. - if (color_of_piece(pc) != us) + if (pc == PIECE_NONE || color_of_piece(pc) != us) return false; // The destination square cannot be occupied by a friendly piece @@ -710,16 +712,20 @@ bool Position::move_is_legal(const Move m, Bitboard pinned) 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) - return false; - break; + if (color_of_piece_on(to) != them) + return false; + + // From and to files must be one file apart, avoids a7h5 + if (abs(square_file(from) - square_file(to)) != 1) + return false; + break; case DELTA_N: case DELTA_S: // Pawn push. The destination square must be empty. - if (!square_is_empty(to)) - return false; - break; + if (!square_is_empty(to)) + return false; + break; case DELTA_NN: // Double white pawn push. The destination square must be on the fourth @@ -729,17 +735,17 @@ bool Position::move_is_legal(const Move m, Bitboard pinned) const { || !square_is_empty(to) || !square_is_empty(from + DELTA_N)) return false; - break; + break; case DELTA_SS: // Double black pawn push. The destination square must be on the fifth // rank, and both the destination square and the square between the // source and destination squares must be empty. - if ( square_rank(to) != RANK_5 - || !square_is_empty(to) - || !square_is_empty(from + DELTA_S)) - return false; - break; + if ( square_rank(to) != RANK_5 + || !square_is_empty(to) + || !square_is_empty(from + DELTA_S)) + return false; + break; default: return false; @@ -749,18 +755,18 @@ bool Position::move_is_legal(const Move m, Bitboard pinned) const { return false; // The move is pseudo-legal, check if it is also legal - return is_check() ? pl_move_is_evasion(m, pinned) : pl_move_is_legal(m, pinned); + return in_check() ? pl_move_is_evasion(m, pinned) : pl_move_is_legal(m, pinned); } -/// Position::move_is_check() tests whether a pseudo-legal move is a check +/// Position::move_gives_check() tests whether a pseudo-legal move is a check -bool Position::move_is_check(Move m) const { +bool Position::move_gives_check(Move m) const { - return move_is_check(m, CheckInfo(*this)); + return move_gives_check(m, CheckInfo(*this)); } -bool Position::move_is_check(Move m, const CheckInfo& ci) const { +bool Position::move_gives_check(Move m, const CheckInfo& ci) const { assert(is_ok()); assert(move_is_ok(m)); @@ -852,9 +858,8 @@ bool Position::move_is_check(Move m, const CheckInfo& ci) const { } -/// Position::do_setup_move() makes a permanent move on the board. -/// It should be used when setting up a position on board. -/// You can't undo the move. +/// Position::do_setup_move() makes a permanent move on the board. It should +/// be used when setting up a position on board. You can't undo the move. void Position::do_setup_move(Move m) { @@ -871,18 +876,19 @@ void Position::do_setup_move(Move m) { startPosPlyCounter++; // Our StateInfo newSt is about going out of scope so copy - // its content inside pos before it disappears. + // its content before it disappears. detach(); } + /// Position::do_move() makes a move, and saves all information necessary -/// to a StateInfo object. The move is assumed to be legal. -/// Pseudo-legal moves should be filtered out before this function is called. +/// to a StateInfo object. The move is assumed to be legal. Pseudo-legal +/// moves should be filtered out before this function is called. void Position::do_move(Move m, StateInfo& newSt) { CheckInfo ci(*this); - do_move(m, newSt, ci, move_is_check(m, ci)); + do_move(m, newSt, ci, move_gives_check(m, ci)); } void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveIsCheck) { @@ -1047,7 +1053,8 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI } // Prefetch pawn and material hash tables - prefetchTables(st->pawnKey, st->materialKey, threadID); + Threads[threadID].pawnTable.prefetch(st->pawnKey); + Threads[threadID].materialTable.prefetch(st->materialKey); // Update incremental scores st->value += pst_delta(piece, from, to); @@ -1428,7 +1435,7 @@ void Position::undo_castle_move(Move m) { void Position::do_null_move(StateInfo& backupSt) { assert(is_ok()); - assert(!is_check()); + assert(!in_check()); // Back up the information necessary to undo the null move to the supplied // StateInfo object. @@ -1465,7 +1472,7 @@ void Position::do_null_move(StateInfo& backupSt) { void Position::undo_null_move() { assert(is_ok()); - assert(!is_check()); + assert(!in_check()); // Restore information from the our backup StateInfo object StateInfo* backupSt = st->previous; @@ -1488,12 +1495,6 @@ void Position::undo_null_move() { /// move, and one which takes a 'from' and a 'to' square. The function does /// not yet understand promotions captures. -int Position::see(Move m) const { - - assert(move_is_ok(m)); - return see(move_from(m), move_to(m)); -} - int Position::see_sign(Move m) const { assert(move_is_ok(m)); @@ -1507,25 +1508,28 @@ int Position::see_sign(Move m) const { if (midgame_value_of_piece_on(to) >= midgame_value_of_piece_on(from)) return 1; - return see(from, to); + return see(m); } -int Position::see(Square from, Square to) const { +int Position::see(Move m) const { + Square from, to; Bitboard occupied, attackers, stmAttackers, b; int swapList[32], slIndex = 1; PieceType capturedType, pt; Color stm; - assert(square_is_ok(from)); - assert(square_is_ok(to)); - - capturedType = type_of_piece_on(to); + assert(move_is_ok(m)); - // King cannot be recaptured - if (capturedType == KING) - return seeValues[capturedType]; + // As castle moves are implemented as capturing the rook, they have + // SEE == RookValueMidgame most of the times (unless the rook is under + // attack). + if (move_is_castle(m)) + return 0; + from = move_from(m); + to = move_to(m); + capturedType = type_of_piece_on(to); occupied = occupied_squares(); // Handle en passant moves @@ -1795,8 +1799,8 @@ bool Position::is_draw() const { bool Position::is_mate() const { - MoveStack moves[MOVES_MAX]; - return is_check() && generate(*this, moves) == moves; + MoveStack moves[MAX_MOVES]; + return in_check() && generate(*this, moves) == moves; } @@ -1840,13 +1844,15 @@ void Position::init_piece_square_tables() { } -/// Position::flipped_copy() makes a copy of the input position, but with -/// the white and black sides reversed. This is only useful for debugging, -/// especially for finding evaluation symmetry bugs. +/// Position::flip() flips position with the white and black sides reversed. This +/// is only useful for debugging especially for finding evaluation symmetry bugs. -void Position::flipped_copy(const Position& pos) { +void Position::flip() { + + assert(is_ok()); - assert(pos.is_ok()); + // Make a copy of current position before to start changing + const Position pos(*this, threadID); clear(); threadID = pos.thread();