diff --git a/src/evaluate.cpp b/src/evaluate.cpp index c9b2d31b0d4..57bbfe09d87 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -494,16 +494,16 @@ Value do_evaluate(const Position& pos) { if (ei.attackedBy[Them][PAWN] & s) score -= ThreatenedByPawn[Pt]; - // Penalty for bishop with same coloured pawns - if (Pt == BISHOP) - score -= BishopPawns * ei.pi->pawns_on_same_color_squares(Us, s); - - // Penalty for knight when there are few enemy pawns - if (Pt == KNIGHT) - score -= KnightPawns * std::max(5 - pos.count(Them), 0); - if (Pt == BISHOP || Pt == KNIGHT) { + // Penalty for bishop with same colored pawns + if (Pt == BISHOP) + score -= BishopPawns * ei.pi->pawns_on_same_color_squares(Us, s); + + // Penalty for knight when there are few enemy pawns + if (Pt == KNIGHT) + score -= KnightPawns * std::max(5 - pos.count(Them), 0); + // Bishop and knight outposts squares if (!(pos.pieces(Them, PAWN) & pawn_attack_span(Us, s))) score += evaluate_outposts(pos, ei, s); diff --git a/src/movegen.cpp b/src/movegen.cpp index 2591473514a..39c372924a3 100644 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@ -31,23 +31,25 @@ (mlist++)->move = make_move(to - (d), to); } namespace { - template + template ExtMove* generate_castling(const Position& pos, ExtMove* mlist, Color us, const CheckInfo* ci) { - if (pos.castling_impeded(us, Side) || !pos.can_castle(make_castling_flag(us, Side))) + static const bool KingSide = (Cf == WHITE_OO || Cf == BLACK_OO); + + if (pos.castling_impeded(Cf) || !pos.can_castle(Cf)) return mlist; // After castling, the rook and king final positions are the same in Chess960 // as they would be in standard chess. Square kfrom = pos.king_square(us); - Square rfrom = pos.castling_rook_square(us, Side); - Square kto = relative_square(us, Side == KING_SIDE ? SQ_G1 : SQ_C1); + Square rfrom = pos.castling_rook_square(Cf); + Square kto = relative_square(us, KingSide ? SQ_G1 : SQ_C1); Bitboard enemies = pos.pieces(~us); assert(!pos.checkers()); - const Square K = Chess960 ? kto > kfrom ? DELTA_W : DELTA_E - : Side == KING_SIDE ? DELTA_W : DELTA_E; + const Square K = Chess960 ? kto > kfrom ? DELTA_W : DELTA_E + : KingSide ? DELTA_W : DELTA_E; for (Square s = kto; s != kfrom; s += K) if (pos.attackers_to(s) & enemies) @@ -262,13 +264,13 @@ namespace { { if (pos.is_chess960()) { - mlist = generate_castling< KING_SIDE, Checks, true>(pos, mlist, Us, ci); - mlist = generate_castling(pos, mlist, Us, ci); + mlist = generate_castling::flag, Checks, true>(pos, mlist, Us, ci); + mlist = generate_castling::flag, Checks, true>(pos, mlist, Us, ci); } else { - mlist = generate_castling< KING_SIDE, Checks, false>(pos, mlist, Us, ci); - mlist = generate_castling(pos, mlist, Us, ci); + mlist = generate_castling::flag, Checks, false>(pos, mlist, Us, ci); + mlist = generate_castling::flag, Checks, false>(pos, mlist, Us, ci); } } diff --git a/src/notation.cpp b/src/notation.cpp index a57072ef142..3ca43deb402 100644 --- a/src/notation.cpp +++ b/src/notation.cpp @@ -72,7 +72,7 @@ const string move_to_uci(Move m, bool chess960) { if (type_of(m) == CASTLING && !chess960) to = (to > from ? FILE_G : FILE_C) | rank_of(from); - string move = square_to_string(from) + square_to_string(to); + string move = to_string(from) + to_string(to); if (type_of(m) == PROMOTION) move += PieceToChar[BLACK][promotion_type(m)]; // Lower case @@ -140,22 +140,22 @@ const string move_to_san(Position& pos, Move m) { if (others) { if (!(others & file_bb(from))) - san += file_to_char(file_of(from)); + san += to_char(file_of(from)); else if (!(others & rank_bb(from))) - san += rank_to_char(rank_of(from)); + san += to_char(rank_of(from)); else - san += square_to_string(from); + san += to_string(from); } } else if (pos.capture(m)) - san = file_to_char(file_of(from)); + san = to_char(file_of(from)); if (pos.capture(m)) san += 'x'; - san += square_to_string(to); + san += to_string(to); if (type_of(m) == PROMOTION) san += string("=") + PieceToChar[WHITE][promotion_type(m)]; diff --git a/src/pawns.cpp b/src/pawns.cpp index f767f6dbcbf..5a5ebb5d1ff 100644 --- a/src/pawns.cpp +++ b/src/pawns.cpp @@ -291,10 +291,10 @@ Score Entry::update_safety(const Position& pos, Square ksq) { Value bonus = shelter_storm(pos, ksq); // If we can castle use the bonus after the castling if it is bigger - if (pos.can_castle(make_castling_flag(Us, KING_SIDE))) + if (pos.can_castle(MakeCastling::flag)) bonus = std::max(bonus, shelter_storm(pos, relative_square(Us, SQ_G1))); - if (pos.can_castle(make_castling_flag(Us, QUEEN_SIDE))) + if (pos.can_castle(MakeCastling::flag)) bonus = std::max(bonus, shelter_storm(pos, relative_square(Us, SQ_C1))); return kingSafety[Us] = make_score(bonus, -16 * minKPdistance[Us]); diff --git a/src/position.cpp b/src/position.cpp index 78fccbb2891..dcd3eb24853 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -304,23 +304,23 @@ void Position::set_castling_flag(Color c, Square rfrom) { Square kfrom = king_square(c); CastlingSide cs = kfrom < rfrom ? KING_SIDE : QUEEN_SIDE; - CastlingFlag cf = make_castling_flag(c, cs); + CastlingFlag cf = (c | cs); st->castlingFlags |= cf; castlingFlagsMask[kfrom] |= cf; castlingFlagsMask[rfrom] |= cf; - castlingRookSquare[c][cs] = rfrom; + castlingRookSquare[cf] = rfrom; Square kto = relative_square(c, cs == KING_SIDE ? SQ_G1 : SQ_C1); Square rto = relative_square(c, cs == KING_SIDE ? SQ_F1 : SQ_D1); for (Square s = std::min(rfrom, rto); s <= std::max(rfrom, rto); ++s) if (s != kfrom && s != rfrom) - castlingPath[c][cs] |= s; + castlingPath[cf] |= s; for (Square s = std::min(kfrom, kto); s <= std::max(kfrom, kto); ++s) if (s != kfrom && s != rfrom) - castlingPath[c][cs] |= s; + castlingPath[cf] |= s; } @@ -353,21 +353,21 @@ const string Position::fen() const { ss << (sideToMove == WHITE ? " w " : " b "); if (can_castle(WHITE_OO)) - ss << (chess960 ? file_to_char(file_of(castling_rook_square(WHITE, KING_SIDE)), false) : 'K'); + ss << (chess960 ? to_char(file_of(castling_rook_square(WHITE | KING_SIDE)), false) : 'K'); if (can_castle(WHITE_OOO)) - ss << (chess960 ? file_to_char(file_of(castling_rook_square(WHITE, QUEEN_SIDE)), false) : 'Q'); + ss << (chess960 ? to_char(file_of(castling_rook_square(WHITE | QUEEN_SIDE)), false) : 'Q'); if (can_castle(BLACK_OO)) - ss << (chess960 ? file_to_char(file_of(castling_rook_square(BLACK, KING_SIDE)), true) : 'k'); + ss << (chess960 ? to_char(file_of(castling_rook_square(BLACK | KING_SIDE)), true) : 'k'); if (can_castle(BLACK_OOO)) - ss << (chess960 ? file_to_char(file_of(castling_rook_square(BLACK, QUEEN_SIDE)), true) : 'q'); + ss << (chess960 ? to_char(file_of(castling_rook_square(BLACK | QUEEN_SIDE)), true) : 'q'); if (!can_castle(WHITE) && !can_castle(BLACK)) ss << '-'; - ss << (ep_square() == SQ_NONE ? " - " : " " + square_to_string(ep_square()) + " ") + ss << (ep_square() == SQ_NONE ? " - " : " " + to_string(ep_square()) + " ") << st->rule50 << " " << 1 + (gamePly - int(sideToMove == BLACK)) / 2; return ss.str(); @@ -401,7 +401,7 @@ const string Position::pretty(Move move) const { << std::setfill('0') << std::setw(16) << st->key << "\nCheckers: "; for (Bitboard b = checkers(); b; ) - ss << square_to_string(pop_lsb(&b)) << " "; + ss << to_string(pop_lsb(&b)) << " "; ss << "\nLegal moves: "; for (MoveList it(*this); *it; ++it) @@ -1393,14 +1393,12 @@ bool Position::pos_is_ok(int* failedStep) const { for (Color c = WHITE; c <= BLACK; ++c) for (CastlingSide s = KING_SIDE; s <= QUEEN_SIDE; s = CastlingSide(s + 1)) { - CastlingFlag cf = make_castling_flag(c, s); - - if (!can_castle(cf)) + if (!can_castle(c | s)) continue; - if ( (castlingFlagsMask[king_square(c)] & cf) != cf - || piece_on(castlingRookSquare[c][s]) != make_piece(c, ROOK) - || castlingFlagsMask[castlingRookSquare[c][s]] != cf) + if ( (castlingFlagsMask[king_square(c)] & (c | s)) != (c | s) + || piece_on(castlingRookSquare[c | s]) != make_piece(c, ROOK) + || castlingFlagsMask[castlingRookSquare[c | s]] != (c | s)) return false; } diff --git a/src/position.h b/src/position.h index 8d3393faaa1..527e66e8b62 100644 --- a/src/position.h +++ b/src/position.h @@ -100,10 +100,10 @@ class Position { template const Square* list(Color c) const; // Castling - int can_castle(CastlingFlag f) const; int can_castle(Color c) const; - bool castling_impeded(Color c, CastlingSide s) const; - Square castling_rook_square(Color c, CastlingSide s) const; + int can_castle(CastlingFlag f) const; + bool castling_impeded(CastlingFlag f) const; + Square castling_rook_square(CastlingFlag f) const; // Checking Bitboard checkers() const; @@ -198,8 +198,8 @@ class Position { // Other info int castlingFlagsMask[SQUARE_NB]; - Square castlingRookSquare[COLOR_NB][CASTLING_SIDE_NB]; - Bitboard castlingPath[COLOR_NB][CASTLING_SIDE_NB]; + Square castlingRookSquare[CASTLING_FLAG_NB]; + Bitboard castlingPath[CASTLING_FLAG_NB]; StateInfo startState; uint64_t nodes; int gamePly; @@ -281,12 +281,12 @@ inline int Position::can_castle(Color c) const { return st->castlingFlags & ((WHITE_OO | WHITE_OOO) << (2 * c)); } -inline bool Position::castling_impeded(Color c, CastlingSide s) const { - return byTypeBB[ALL_PIECES] & castlingPath[c][s]; +inline bool Position::castling_impeded(CastlingFlag f) const { + return byTypeBB[ALL_PIECES] & castlingPath[f]; } -inline Square Position::castling_rook_square(Color c, CastlingSide s) const { - return castlingRookSquare[c][s]; +inline Square Position::castling_rook_square(CastlingFlag f) const { + return castlingRookSquare[f]; } template diff --git a/src/search.cpp b/src/search.cpp index eb3fc82a408..d7a8379a14e 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -185,8 +185,7 @@ void Search::think() { RootColor = RootPos.side_to_move(); TimeMgr.init(Limits, RootPos.game_ply(), RootColor); - // Dynamic draw value: try to avoid repetition draws at early midgame - int cf = std::max(70 - RootPos.game_ply(), 0); + int cf = Options["Contempt Factor"] * PawnValueMg / 100; // From centipawns DrawValue[ RootColor] = VALUE_DRAW - Value(cf); DrawValue[~RootColor] = VALUE_DRAW + Value(cf); @@ -392,8 +391,6 @@ namespace { sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl; } - Time::point iterationTime = Time::now() - SearchTime; - // If skill levels are enabled and time is up, pick a sub-optimal best move if (skill.enabled() && skill.time_to_pick(depth)) skill.pick_move(); @@ -418,8 +415,6 @@ namespace { // Do we have time for the next iteration? Can we stop searching now? if (Limits.use_time_management() && !Signals.stop && !Signals.stopOnPonderhit) { - bool stop = false; // Local variable, not the volatile Signals.stop - // Take some extra time if the best move has changed if (depth > 4 && depth < 50 && MultiPV == 1) TimeMgr.pv_instability(BestMoveChanges); @@ -427,10 +422,7 @@ namespace { // Stop the search if only one legal move is available or all // of the available time has been used. if ( RootMoves.size() == 1 - || iterationTime > TimeMgr.available_time() ) - stop = true; - - if (stop) + || Time::now() - SearchTime > TimeMgr.available_time()) { // If we are allowed to ponder do not stop the search now but // keep pondering until the GUI sends "ponderhit" or "stop". @@ -664,7 +656,7 @@ namespace { && abs(beta) < VALUE_MATE_IN_MAX_PLY) { Value rbeta = std::min(beta + 200, VALUE_INFINITE); - Depth rdepth = depth - ONE_PLY - 3 * ONE_PLY; + Depth rdepth = depth - 4 * ONE_PLY; assert(rdepth >= ONE_PLY); assert((ss-1)->currentMove != MOVE_NONE); @@ -1017,7 +1009,7 @@ namespace { // case of Signals.stop or thread.cutoff_occurred() are set, but this is // harmless because return value is discarded anyhow in the parent nodes. // If we are in a singular extension search then return a fail low score. - // A split node has at least one move - the one tried before to be splitted. + // A split node has at least one move - the one tried before to be split. if (!moveCount) return excludedMove ? alpha : inCheck ? mated_in(ss->ply) : DrawValue[pos.side_to_move()]; diff --git a/src/thread.cpp b/src/thread.cpp index e5bcc64d430..9e96be6eb7f 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -59,7 +59,7 @@ namespace { } -// ThreadBase::notify_one() wakes up the thread when there is some work to do +// notify_one() wakes up the thread when there is some work to do void ThreadBase::notify_one() { @@ -69,7 +69,7 @@ void ThreadBase::notify_one() { } -// ThreadBase::wait_for() set the thread to sleep until condition 'b' turns true +// wait_for() set the thread to sleep until condition 'b' turns true void ThreadBase::wait_for(volatile const bool& b) { @@ -92,7 +92,7 @@ Thread::Thread() /* : splitPoints() */ { // Value-initialization bug in MSVC } -// Thread::cutoff_occurred() checks whether a beta cutoff has occurred in the +// cutoff_occurred() checks whether a beta cutoff has occurred in the // current active split point, or in some ancestor of the split point. bool Thread::cutoff_occurred() const { @@ -219,12 +219,9 @@ void ThreadPool::read_uci_options() { assert(requested > 0); - // Value 0 has a special meaning: We determine the optimal minimum split depth - // automatically. Anyhow the minimumSplitDepth should never be under 4 plies. + // If zero (default) then set best minimum split depth automatically if (!minimumSplitDepth) - minimumSplitDepth = (requested < 8 ? 4 : 7) * ONE_PLY; - else - minimumSplitDepth = std::max(4 * ONE_PLY, minimumSplitDepth); + minimumSplitDepth = requested < 8 ? 4 * ONE_PLY : 7 * ONE_PLY; while (size() < requested) push_back(new_thread()); @@ -237,7 +234,7 @@ void ThreadPool::read_uci_options() { } -// slave_available() tries to find an idle thread which is available as a slave +// available_slave() tries to find an idle thread which is available as a slave // for the thread 'master'. Thread* ThreadPool::available_slave(const Thread* master) const { diff --git a/src/tt.h b/src/tt.h index 9e8c0481eb0..05f6dfff5d7 100644 --- a/src/tt.h +++ b/src/tt.h @@ -32,7 +32,6 @@ /// value: 16 bit /// depth: 16 bit /// static value: 16 bit -/// static margin: 16 bit struct TTEntry { diff --git a/src/types.h b/src/types.h index 03053591f05..f041e29db51 100644 --- a/src/types.h +++ b/src/types.h @@ -116,6 +116,14 @@ enum MoveType { CASTLING = 3 << 14 }; +enum Color { + WHITE, BLACK, NO_COLOR, COLOR_NB = 2 +}; + +enum CastlingSide { + KING_SIDE, QUEEN_SIDE, CASTLING_SIDE_NB = 2 +}; + enum CastlingFlag { // Defined as in PolyGlot book hash key NO_CASTLING, WHITE_OO, @@ -126,10 +134,10 @@ enum CastlingFlag { // Defined as in PolyGlot book hash key CASTLING_FLAG_NB = 16 }; -enum CastlingSide { - KING_SIDE, - QUEEN_SIDE, - CASTLING_SIDE_NB = 2 +template struct MakeCastling { + static const CastlingFlag + flag = C == WHITE ? S == QUEEN_SIDE ? WHITE_OOO : WHITE_OO + : S == QUEEN_SIDE ? BLACK_OOO : BLACK_OO; }; enum Phase { @@ -187,10 +195,6 @@ enum Piece { PIECE_NB = 16 }; -enum Color { - WHITE, BLACK, NO_COLOR, COLOR_NB = 2 -}; - enum Depth { ONE_PLY = 2, @@ -337,6 +341,10 @@ inline Square operator|(File f, Rank r) { return Square((r << 3) | f); } +inline CastlingFlag operator|(Color c, CastlingSide s) { + return CastlingFlag(WHITE_OO << ((s == QUEEN_SIDE) + 2 * c)); +} + inline Value mate_in(int ply) { return VALUE_MATE - ply; } @@ -349,10 +357,6 @@ inline Piece make_piece(Color c, PieceType pt) { return Piece((c << 3) | pt); } -inline CastlingFlag make_castling_flag(Color c, CastlingSide s) { - return CastlingFlag(WHITE_OO << ((s == QUEEN_SIDE) + 2 * c)); -} - inline PieceType type_of(Piece p) { return PieceType(p & 7); } @@ -391,11 +395,11 @@ inline bool opposite_colors(Square s1, Square s2) { return ((s >> 3) ^ s) & 1; } -inline char file_to_char(File f, bool tolower = true) { +inline char to_char(File f, bool tolower = true) { return char(f - FILE_A + (tolower ? 'a' : 'A')); } -inline char rank_to_char(Rank r) { +inline char to_char(Rank r) { return char(r - RANK_1 + '1'); } @@ -434,8 +438,8 @@ inline bool is_ok(Move m) { #include -inline const std::string square_to_string(Square s) { - char ch[] = { file_to_char(file_of(s)), rank_to_char(rank_of(s)), 0 }; +inline const std::string to_string(Square s) { + char ch[] = { to_char(file_of(s)), to_char(rank_of(s)), 0 }; return ch; }