mirror of
https://github.com/sockspls/badfish
synced 2025-05-01 01:03:09 +00:00
commit
ae4db5ebfd
11 changed files with 177 additions and 134 deletions
|
@ -75,9 +75,6 @@ Currently, Stockfish has the following UCI options:
|
||||||
Assume a time delay of x ms due to network and GUI overheads. This is useful to
|
Assume a time delay of x ms due to network and GUI overheads. This is useful to
|
||||||
avoid losses on time in those cases.
|
avoid losses on time in those cases.
|
||||||
|
|
||||||
* #### Minimum Thinking Time
|
|
||||||
Search for at least x ms per move.
|
|
||||||
|
|
||||||
* #### Slow Mover
|
* #### Slow Mover
|
||||||
Lower values will make Stockfish take less time in games, higher values will
|
Lower values will make Stockfish take less time in games, higher values will
|
||||||
make it think longer.
|
make it think longer.
|
||||||
|
|
|
@ -88,7 +88,7 @@ const vector<string> Defaults = {
|
||||||
|
|
||||||
// Chess 960
|
// Chess 960
|
||||||
"setoption name UCI_Chess960 value true",
|
"setoption name UCI_Chess960 value true",
|
||||||
"bbqnnrkr/pppppppp/8/8/8/8/PPPPPPPP/BBQNNRKR w KQkq - 0 1 moves g2g3 d7d5 d2d4 c8h3 c1g5 e8d6 g5e7 f7f6",
|
"bbqnnrkr/pppppppp/8/8/8/8/PPPPPPPP/BBQNNRKR w HFhf - 0 1 moves g2g3 d7d5 d2d4 c8h3 c1g5 e8d6 g5e7 f7f6",
|
||||||
"setoption name UCI_Chess960 value false"
|
"setoption name UCI_Chess960 value false"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -124,12 +124,19 @@ inline Bitboard operator&(Square s, Bitboard b) { return b & s; }
|
||||||
inline Bitboard operator|(Square s, Bitboard b) { return b | s; }
|
inline Bitboard operator|(Square s, Bitboard b) { return b | s; }
|
||||||
inline Bitboard operator^(Square s, Bitboard b) { return b ^ s; }
|
inline Bitboard operator^(Square s, Bitboard b) { return b ^ s; }
|
||||||
|
|
||||||
inline Bitboard operator|(Square s, Square s2) { return square_bb(s) | s2; }
|
inline Bitboard operator|(Square s1, Square s2) { return square_bb(s1) | s2; }
|
||||||
|
|
||||||
constexpr bool more_than_one(Bitboard b) {
|
constexpr bool more_than_one(Bitboard b) {
|
||||||
return b & (b - 1);
|
return b & (b - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Counts the occupation of the bitboard depending on the occupation of SQ_A1
|
||||||
|
/// as in `b & (1ULL << SQ_A1) ? more_than_two(b) : more_than_one(b)`
|
||||||
|
|
||||||
|
constexpr bool conditional_more_than_two(Bitboard b) {
|
||||||
|
return b & (b - 1) & (b - 2);
|
||||||
|
}
|
||||||
|
|
||||||
constexpr bool opposite_colors(Square s1, Square s2) {
|
constexpr bool opposite_colors(Square s1, Square s2) {
|
||||||
return (s1 + rank_of(s1) + s2 + rank_of(s2)) & 1;
|
return (s1 + rank_of(s1) + s2 + rank_of(s2)) & 1;
|
||||||
}
|
}
|
||||||
|
@ -138,19 +145,19 @@ constexpr bool opposite_colors(Square s1, Square s2) {
|
||||||
/// rank_bb() and file_bb() return a bitboard representing all the squares on
|
/// rank_bb() and file_bb() return a bitboard representing all the squares on
|
||||||
/// the given file or rank.
|
/// the given file or rank.
|
||||||
|
|
||||||
inline Bitboard rank_bb(Rank r) {
|
constexpr Bitboard rank_bb(Rank r) {
|
||||||
return Rank1BB << (8 * r);
|
return Rank1BB << (8 * r);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Bitboard rank_bb(Square s) {
|
constexpr Bitboard rank_bb(Square s) {
|
||||||
return rank_bb(rank_of(s));
|
return rank_bb(rank_of(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Bitboard file_bb(File f) {
|
constexpr Bitboard file_bb(File f) {
|
||||||
return FileABB << f;
|
return FileABB << f;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Bitboard file_bb(Square s) {
|
constexpr Bitboard file_bb(Square s) {
|
||||||
return file_bb(file_of(s));
|
return file_bb(file_of(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,16 +202,16 @@ constexpr Bitboard pawn_double_attacks_bb(Bitboard b) {
|
||||||
|
|
||||||
|
|
||||||
/// adjacent_files_bb() returns a bitboard representing all the squares on the
|
/// adjacent_files_bb() returns a bitboard representing all the squares on the
|
||||||
/// adjacent files of the given one.
|
/// adjacent files of a given square.
|
||||||
|
|
||||||
inline Bitboard adjacent_files_bb(Square s) {
|
constexpr Bitboard adjacent_files_bb(Square s) {
|
||||||
return shift<EAST>(file_bb(s)) | shift<WEST>(file_bb(s));
|
return shift<EAST>(file_bb(s)) | shift<WEST>(file_bb(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// line_bb(Square, Square) returns a bitboard representing an entire line,
|
/// line_bb() returns a bitboard representing an entire line (from board edge
|
||||||
/// from board edge to board edge, that intersects the given squares. If the
|
/// to board edge) that intersects the two given squares. If the given squares
|
||||||
/// given squares are not on a same file/rank/diagonal, returns 0. For instance,
|
/// are not on a same file/rank/diagonal, the function returns 0. For instance,
|
||||||
/// line_bb(SQ_C4, SQ_F7) will return a bitboard with the A2-G8 diagonal.
|
/// line_bb(SQ_C4, SQ_F7) will return a bitboard with the A2-G8 diagonal.
|
||||||
|
|
||||||
inline Bitboard line_bb(Square s1, Square s2) {
|
inline Bitboard line_bb(Square s1, Square s2) {
|
||||||
|
@ -215,8 +222,8 @@ inline Bitboard line_bb(Square s1, Square s2) {
|
||||||
|
|
||||||
|
|
||||||
/// between_bb() returns a bitboard representing squares that are linearly
|
/// between_bb() returns a bitboard representing squares that are linearly
|
||||||
/// between the given squares (excluding the given squares). If the given
|
/// between the two given squares (excluding the given squares). If the given
|
||||||
/// squares are not on a same file/rank/diagonal, return 0. For instance,
|
/// squares are not on a same file/rank/diagonal, we return 0. For instance,
|
||||||
/// between_bb(SQ_C4, SQ_F7) will return a bitboard with squares D5 and E6.
|
/// between_bb(SQ_C4, SQ_F7) will return a bitboard with squares D5 and E6.
|
||||||
|
|
||||||
inline Bitboard between_bb(Square s1, Square s2) {
|
inline Bitboard between_bb(Square s1, Square s2) {
|
||||||
|
@ -229,7 +236,7 @@ inline Bitboard between_bb(Square s1, Square s2) {
|
||||||
/// in front of the given one, from the point of view of the given color. For instance,
|
/// in front of the given one, from the point of view of the given color. For instance,
|
||||||
/// forward_ranks_bb(BLACK, SQ_D3) will return the 16 squares on ranks 1 and 2.
|
/// forward_ranks_bb(BLACK, SQ_D3) will return the 16 squares on ranks 1 and 2.
|
||||||
|
|
||||||
inline Bitboard forward_ranks_bb(Color c, Square s) {
|
constexpr Bitboard forward_ranks_bb(Color c, Square s) {
|
||||||
return c == WHITE ? ~Rank1BB << 8 * relative_rank(WHITE, s)
|
return c == WHITE ? ~Rank1BB << 8 * relative_rank(WHITE, s)
|
||||||
: ~Rank8BB >> 8 * relative_rank(BLACK, s);
|
: ~Rank8BB >> 8 * relative_rank(BLACK, s);
|
||||||
}
|
}
|
||||||
|
@ -238,7 +245,7 @@ inline Bitboard forward_ranks_bb(Color c, Square s) {
|
||||||
/// forward_file_bb() returns a bitboard representing all the squares along the
|
/// forward_file_bb() returns a bitboard representing all the squares along the
|
||||||
/// line in front of the given one, from the point of view of the given color.
|
/// line in front of the given one, from the point of view of the given color.
|
||||||
|
|
||||||
inline Bitboard forward_file_bb(Color c, Square s) {
|
constexpr Bitboard forward_file_bb(Color c, Square s) {
|
||||||
return forward_ranks_bb(c, s) & file_bb(s);
|
return forward_ranks_bb(c, s) & file_bb(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +254,7 @@ inline Bitboard forward_file_bb(Color c, Square s) {
|
||||||
/// be attacked by a pawn of the given color when it moves along its file, starting
|
/// be attacked by a pawn of the given color when it moves along its file, starting
|
||||||
/// from the given square.
|
/// from the given square.
|
||||||
|
|
||||||
inline Bitboard pawn_attack_span(Color c, Square s) {
|
constexpr Bitboard pawn_attack_span(Color c, Square s) {
|
||||||
return forward_ranks_bb(c, s) & adjacent_files_bb(s);
|
return forward_ranks_bb(c, s) & adjacent_files_bb(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +262,7 @@ inline Bitboard pawn_attack_span(Color c, Square s) {
|
||||||
/// passed_pawn_span() returns a bitboard which can be used to test if a pawn of
|
/// passed_pawn_span() returns a bitboard which can be used to test if a pawn of
|
||||||
/// the given color and on the given square is a passed pawn.
|
/// the given color and on the given square is a passed pawn.
|
||||||
|
|
||||||
inline Bitboard passed_pawn_span(Color c, Square s) {
|
constexpr Bitboard passed_pawn_span(Color c, Square s) {
|
||||||
return pawn_attack_span(c, s) | forward_file_bb(c, s);
|
return pawn_attack_span(c, s) | forward_file_bb(c, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -181,15 +181,15 @@ Value Endgame<KRKP>::operator()(const Position& pos) const {
|
||||||
assert(verify_material(pos, strongSide, RookValueMg, 0));
|
assert(verify_material(pos, strongSide, RookValueMg, 0));
|
||||||
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
|
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
|
||||||
|
|
||||||
Square strongKing = relative_square(strongSide, pos.square<KING>(strongSide));
|
Square strongKing = pos.square<KING>(strongSide);
|
||||||
Square weakKing = relative_square(strongSide, pos.square<KING>(weakSide));
|
Square weakKing = pos.square<KING>(weakSide);
|
||||||
Square strongRook = relative_square(strongSide, pos.square<ROOK>(strongSide));
|
Square strongRook = pos.square<ROOK>(strongSide);
|
||||||
Square weakPawn = relative_square(strongSide, pos.square<PAWN>(weakSide));
|
Square weakPawn = pos.square<PAWN>(weakSide);
|
||||||
Square queeningSquare = make_square(file_of(weakPawn), RANK_1);
|
Square queeningSquare = make_square(file_of(weakPawn), relative_rank(weakSide, RANK_8));
|
||||||
Value result;
|
Value result;
|
||||||
|
|
||||||
// If the stronger side's king is in front of the pawn, it's a win
|
// If the stronger side's king is in front of the pawn, it's a win
|
||||||
if (forward_file_bb(WHITE, strongKing) & weakPawn)
|
if (forward_file_bb(strongSide, strongKing) & weakPawn)
|
||||||
result = RookValueEg - distance(strongKing, weakPawn);
|
result = RookValueEg - distance(strongKing, weakPawn);
|
||||||
|
|
||||||
// If the weaker side's king is too far from the pawn and the rook,
|
// If the weaker side's king is too far from the pawn and the rook,
|
||||||
|
@ -200,15 +200,15 @@ Value Endgame<KRKP>::operator()(const Position& pos) const {
|
||||||
|
|
||||||
// If the pawn is far advanced and supported by the defending king,
|
// If the pawn is far advanced and supported by the defending king,
|
||||||
// the position is drawish
|
// the position is drawish
|
||||||
else if ( rank_of(weakKing) <= RANK_3
|
else if ( relative_rank(strongSide, weakKing) <= RANK_3
|
||||||
&& distance(weakKing, weakPawn) == 1
|
&& distance(weakKing, weakPawn) == 1
|
||||||
&& rank_of(strongKing) >= RANK_4
|
&& relative_rank(strongSide, strongKing) >= RANK_4
|
||||||
&& distance(strongKing, weakPawn) > 2 + (pos.side_to_move() == strongSide))
|
&& distance(strongKing, weakPawn) > 2 + (pos.side_to_move() == strongSide))
|
||||||
result = Value(80) - 8 * distance(strongKing, weakPawn);
|
result = Value(80) - 8 * distance(strongKing, weakPawn);
|
||||||
|
|
||||||
else
|
else
|
||||||
result = Value(200) - 8 * ( distance(strongKing, weakPawn + SOUTH)
|
result = Value(200) - 8 * ( distance(strongKing, weakPawn + pawn_push(weakSide))
|
||||||
- distance(weakKing, weakPawn + SOUTH)
|
- distance(weakKing, weakPawn + pawn_push(weakSide))
|
||||||
- distance(weakPawn, queeningSquare));
|
- distance(weakPawn, queeningSquare));
|
||||||
|
|
||||||
return strongSide == pos.side_to_move() ? result : -result;
|
return strongSide == pos.side_to_move() ? result : -result;
|
||||||
|
|
|
@ -82,11 +82,11 @@ namespace {
|
||||||
// KingAttackWeights[PieceType] contains king attack weights by piece type
|
// KingAttackWeights[PieceType] contains king attack weights by piece type
|
||||||
constexpr int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 81, 52, 44, 10 };
|
constexpr int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 81, 52, 44, 10 };
|
||||||
|
|
||||||
// Penalties for enemy's safe checks
|
// SafeCheck[PieceType][single/multiple] contains safe check bonus by piece type,
|
||||||
constexpr int QueenSafeCheck = 772;
|
// higher if multiple safe checks are possible for that piece type.
|
||||||
constexpr int RookSafeCheck = 1084;
|
constexpr int SafeCheck[][2] = {
|
||||||
constexpr int BishopSafeCheck = 645;
|
{}, {}, {792, 1283}, {645, 967}, {1084, 1897}, {772, 1119}
|
||||||
constexpr int KnightSafeCheck = 792;
|
};
|
||||||
|
|
||||||
#define S(mg, eg) make_score(mg, eg)
|
#define S(mg, eg) make_score(mg, eg)
|
||||||
|
|
||||||
|
@ -108,6 +108,18 @@ namespace {
|
||||||
S(110,182), S(114,182), S(114,192), S(116,219) }
|
S(110,182), S(114,182), S(114,192), S(116,219) }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// KingProtector[knight/bishop] contains penalty for each distance unit to own king
|
||||||
|
constexpr Score KingProtector[] = { S(8, 9), S(6, 9) };
|
||||||
|
|
||||||
|
// Outpost[knight/bishop] contains bonuses for each knight or bishop occupying a
|
||||||
|
// pawn protected square on rank 4 to 6 which is also safe from a pawn attack.
|
||||||
|
constexpr Score Outpost[] = { S(56, 36), S(30, 23) };
|
||||||
|
|
||||||
|
// PassedRank[Rank] contains a bonus according to the rank of a passed pawn
|
||||||
|
constexpr Score PassedRank[RANK_NB] = {
|
||||||
|
S(0, 0), S(10, 28), S(17, 33), S(15, 41), S(62, 72), S(168, 177), S(276, 260)
|
||||||
|
};
|
||||||
|
|
||||||
// RookOnFile[semiopen/open] contains bonuses for each rook when there is
|
// RookOnFile[semiopen/open] contains bonuses for each rook when there is
|
||||||
// no (friendly) pawn on the rook file.
|
// no (friendly) pawn on the rook file.
|
||||||
constexpr Score RookOnFile[] = { S(19, 7), S(48, 29) };
|
constexpr Score RookOnFile[] = { S(19, 7), S(48, 29) };
|
||||||
|
@ -123,23 +135,15 @@ namespace {
|
||||||
S(0, 0), S(3, 46), S(37, 68), S(42, 60), S(0, 38), S(58, 41)
|
S(0, 0), S(3, 46), S(37, 68), S(42, 60), S(0, 38), S(58, 41)
|
||||||
};
|
};
|
||||||
|
|
||||||
// PassedRank[Rank] contains a bonus according to the rank of a passed pawn
|
|
||||||
constexpr Score PassedRank[RANK_NB] = {
|
|
||||||
S(0, 0), S(10, 28), S(17, 33), S(15, 41), S(62, 72), S(168, 177), S(276, 260)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Assorted bonuses and penalties
|
// Assorted bonuses and penalties
|
||||||
constexpr Score BishopKingProtector = S( 6, 9);
|
constexpr Score BadOutpost = S( -7, 36);
|
||||||
constexpr Score BishopOnKingRing = S( 24, 0);
|
constexpr Score BishopOnKingRing = S( 24, 0);
|
||||||
constexpr Score BishopOutpost = S( 30, 23);
|
|
||||||
constexpr Score BishopPawns = S( 3, 7);
|
constexpr Score BishopPawns = S( 3, 7);
|
||||||
constexpr Score BishopXRayPawns = S( 4, 5);
|
constexpr Score BishopXRayPawns = S( 4, 5);
|
||||||
constexpr Score CorneredBishop = S( 50, 50);
|
constexpr Score CorneredBishop = S( 50, 50);
|
||||||
constexpr Score FlankAttacks = S( 8, 0);
|
constexpr Score FlankAttacks = S( 8, 0);
|
||||||
constexpr Score Hanging = S( 69, 36);
|
constexpr Score Hanging = S( 69, 36);
|
||||||
constexpr Score KnightKingProtector = S( 8, 9);
|
|
||||||
constexpr Score KnightOnQueen = S( 16, 11);
|
constexpr Score KnightOnQueen = S( 16, 11);
|
||||||
constexpr Score KnightOutpost = S( 56, 36);
|
|
||||||
constexpr Score LongDiagonalBishop = S( 45, 0);
|
constexpr Score LongDiagonalBishop = S( 45, 0);
|
||||||
constexpr Score MinorBehindPawn = S( 18, 3);
|
constexpr Score MinorBehindPawn = S( 18, 3);
|
||||||
constexpr Score PassedFile = S( 11, 8);
|
constexpr Score PassedFile = S( 11, 8);
|
||||||
|
@ -309,8 +313,14 @@ namespace {
|
||||||
{
|
{
|
||||||
// Bonus if piece is on an outpost square or can reach one
|
// Bonus if piece is on an outpost square or can reach one
|
||||||
bb = OutpostRanks & attackedBy[Us][PAWN] & ~pe->pawn_attacks_span(Them);
|
bb = OutpostRanks & attackedBy[Us][PAWN] & ~pe->pawn_attacks_span(Them);
|
||||||
if (bb & s)
|
if ( Pt == KNIGHT
|
||||||
score += (Pt == KNIGHT) ? KnightOutpost : BishopOutpost;
|
&& bb & s & ~CenterFiles
|
||||||
|
&& !(b & pos.pieces(Them) & ~pos.pieces(PAWN))
|
||||||
|
&& !conditional_more_than_two(
|
||||||
|
pos.pieces(Them) & ~pos.pieces(PAWN) & (s & QueenSide ? QueenSide : KingSide)))
|
||||||
|
score += BadOutpost;
|
||||||
|
else if (bb & s)
|
||||||
|
score += Outpost[Pt == BISHOP];
|
||||||
else if (Pt == KNIGHT && bb & b & ~pos.pieces(Us))
|
else if (Pt == KNIGHT && bb & b & ~pos.pieces(Us))
|
||||||
score += ReachableOutpost;
|
score += ReachableOutpost;
|
||||||
|
|
||||||
|
@ -319,8 +329,7 @@ namespace {
|
||||||
score += MinorBehindPawn;
|
score += MinorBehindPawn;
|
||||||
|
|
||||||
// Penalty if the piece is far from the king
|
// Penalty if the piece is far from the king
|
||||||
score -= (Pt == KNIGHT ? KnightKingProtector
|
score -= KingProtector[Pt == BISHOP] * distance(pos.square<KING>(Us), s);
|
||||||
: BishopKingProtector) * distance(pos.square<KING>(Us), s);
|
|
||||||
|
|
||||||
if (Pt == BISHOP)
|
if (Pt == BISHOP)
|
||||||
{
|
{
|
||||||
|
@ -422,41 +431,33 @@ namespace {
|
||||||
b2 = attacks_bb<BISHOP>(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
|
b2 = attacks_bb<BISHOP>(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
|
||||||
|
|
||||||
// Enemy rooks checks
|
// Enemy rooks checks
|
||||||
rookChecks = b1 & safe & attackedBy[Them][ROOK];
|
rookChecks = b1 & attackedBy[Them][ROOK] & safe;
|
||||||
if (rookChecks)
|
if (rookChecks)
|
||||||
kingDanger += more_than_one(rookChecks) ? RookSafeCheck * 175/100
|
kingDanger += SafeCheck[ROOK][more_than_one(rookChecks)];
|
||||||
: RookSafeCheck;
|
|
||||||
else
|
else
|
||||||
unsafeChecks |= b1 & attackedBy[Them][ROOK];
|
unsafeChecks |= b1 & attackedBy[Them][ROOK];
|
||||||
|
|
||||||
// Enemy queen safe checks: we count them only if they are from squares from
|
// Enemy queen safe checks: count them only if the checks are from squares from
|
||||||
// which we can't give a rook check, because rook checks are more valuable.
|
// which opponent cannot give a rook check, because rook checks are more valuable.
|
||||||
queenChecks = (b1 | b2)
|
queenChecks = (b1 | b2) & attackedBy[Them][QUEEN] & safe
|
||||||
& attackedBy[Them][QUEEN]
|
& ~(attackedBy[Us][QUEEN] | rookChecks);
|
||||||
& safe
|
|
||||||
& ~attackedBy[Us][QUEEN]
|
|
||||||
& ~rookChecks;
|
|
||||||
if (queenChecks)
|
if (queenChecks)
|
||||||
kingDanger += more_than_one(queenChecks) ? QueenSafeCheck * 145/100
|
kingDanger += SafeCheck[QUEEN][more_than_one(queenChecks)];
|
||||||
: QueenSafeCheck;
|
|
||||||
|
|
||||||
// Enemy bishops checks: we count them only if they are from squares from
|
// Enemy bishops checks: count them only if they are from squares from which
|
||||||
// which we can't give a queen check, because queen checks are more valuable.
|
// opponent cannot give a queen check, because queen checks are more valuable.
|
||||||
bishopChecks = b2
|
bishopChecks = b2 & attackedBy[Them][BISHOP] & safe
|
||||||
& attackedBy[Them][BISHOP]
|
|
||||||
& safe
|
|
||||||
& ~queenChecks;
|
& ~queenChecks;
|
||||||
if (bishopChecks)
|
if (bishopChecks)
|
||||||
kingDanger += more_than_one(bishopChecks) ? BishopSafeCheck * 3/2
|
kingDanger += SafeCheck[BISHOP][more_than_one(bishopChecks)];
|
||||||
: BishopSafeCheck;
|
|
||||||
else
|
else
|
||||||
unsafeChecks |= b2 & attackedBy[Them][BISHOP];
|
unsafeChecks |= b2 & attackedBy[Them][BISHOP];
|
||||||
|
|
||||||
// Enemy knights checks
|
// Enemy knights checks
|
||||||
knightChecks = attacks_bb<KNIGHT>(ksq) & attackedBy[Them][KNIGHT];
|
knightChecks = attacks_bb<KNIGHT>(ksq) & attackedBy[Them][KNIGHT];
|
||||||
if (knightChecks & safe)
|
if (knightChecks & safe)
|
||||||
kingDanger += more_than_one(knightChecks & safe) ? KnightSafeCheck * 162/100
|
kingDanger += SafeCheck[KNIGHT][more_than_one(knightChecks & safe)];
|
||||||
: KnightSafeCheck;
|
|
||||||
else
|
else
|
||||||
unsafeChecks |= knightChecks;
|
unsafeChecks |= knightChecks;
|
||||||
|
|
||||||
|
@ -727,9 +728,9 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Evaluation::winnable() adjusts the mg and eg score components based on the
|
// Evaluation::winnable() adjusts the midgame and endgame score components, based on
|
||||||
// known attacking/defending status of the players. A single value is derived
|
// the known attacking/defending status of the players. The final value is derived
|
||||||
// by interpolation from the mg and eg values and returned.
|
// by interpolation from the midgame and endgame values.
|
||||||
|
|
||||||
template<Tracing T>
|
template<Tracing T>
|
||||||
Value Evaluation<T>::winnable(Score score) const {
|
Value Evaluation<T>::winnable(Score score) const {
|
||||||
|
@ -769,11 +770,10 @@ namespace {
|
||||||
eg += v;
|
eg += v;
|
||||||
|
|
||||||
// Compute the scale factor for the winning side
|
// Compute the scale factor for the winning side
|
||||||
|
|
||||||
Color strongSide = eg > VALUE_DRAW ? WHITE : BLACK;
|
Color strongSide = eg > VALUE_DRAW ? WHITE : BLACK;
|
||||||
int sf = me->scale_factor(pos, strongSide);
|
int sf = me->scale_factor(pos, strongSide);
|
||||||
|
|
||||||
// If scale is not already specific, scale down the endgame via general heuristics
|
// If scale factor is not already specific, scale down via general heuristics
|
||||||
if (sf == SCALE_FACTOR_NORMAL)
|
if (sf == SCALE_FACTOR_NORMAL)
|
||||||
{
|
{
|
||||||
if (pos.opposite_bishops())
|
if (pos.opposite_bishops())
|
||||||
|
@ -784,6 +784,15 @@ namespace {
|
||||||
else
|
else
|
||||||
sf = 22 + 3 * pos.count<ALL_PIECES>(strongSide);
|
sf = 22 + 3 * pos.count<ALL_PIECES>(strongSide);
|
||||||
}
|
}
|
||||||
|
else if ( pos.non_pawn_material(WHITE) == RookValueMg
|
||||||
|
&& pos.non_pawn_material(BLACK) == RookValueMg
|
||||||
|
&& pos.count<PAWN>(strongSide) - pos.count<PAWN>(~strongSide) <= 1
|
||||||
|
&& bool(KingSide & pos.pieces(strongSide, PAWN)) != bool(QueenSide & pos.pieces(strongSide, PAWN))
|
||||||
|
&& (attackedBy[~strongSide][KING] & pos.pieces(~strongSide, PAWN)))
|
||||||
|
sf = 36;
|
||||||
|
else if (pos.count<QUEEN>() == 1)
|
||||||
|
sf = 37 + 3 * (pos.count<QUEEN>(WHITE) == 1 ? pos.count<BISHOP>(BLACK) + pos.count<KNIGHT>(BLACK)
|
||||||
|
: pos.count<BISHOP>(WHITE) + pos.count<KNIGHT>(WHITE));
|
||||||
else
|
else
|
||||||
sf = std::min(sf, 36 + 7 * pos.count<PAWN>(strongSide));
|
sf = std::min(sf, 36 + 7 * pos.count<PAWN>(strongSide));
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,22 +29,20 @@ namespace {
|
||||||
ExtMove* make_promotions(ExtMove* moveList, Square to, Square ksq) {
|
ExtMove* make_promotions(ExtMove* moveList, Square to, Square ksq) {
|
||||||
|
|
||||||
if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
|
if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
|
||||||
|
{
|
||||||
*moveList++ = make<PROMOTION>(to - D, to, QUEEN);
|
*moveList++ = make<PROMOTION>(to - D, to, QUEEN);
|
||||||
|
if (attacks_bb<KNIGHT>(to) & ksq)
|
||||||
|
*moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
if (Type == QUIETS || Type == EVASIONS || Type == NON_EVASIONS)
|
if (Type == QUIETS || Type == EVASIONS || Type == NON_EVASIONS)
|
||||||
{
|
{
|
||||||
*moveList++ = make<PROMOTION>(to - D, to, ROOK);
|
*moveList++ = make<PROMOTION>(to - D, to, ROOK);
|
||||||
*moveList++ = make<PROMOTION>(to - D, to, BISHOP);
|
*moveList++ = make<PROMOTION>(to - D, to, BISHOP);
|
||||||
|
if (!(attacks_bb<KNIGHT>(to) & ksq))
|
||||||
*moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
|
*moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Knight promotion is the only promotion that can give a direct check
|
|
||||||
// that's not already included in the queen promotion.
|
|
||||||
if (Type == QUIET_CHECKS && (attacks_bb<KNIGHT>(to) & ksq))
|
|
||||||
*moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
|
|
||||||
else
|
|
||||||
(void)ksq; // Silence a warning under MSVC
|
|
||||||
|
|
||||||
return moveList;
|
return moveList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,8 +261,8 @@ namespace {
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
/// <CAPTURES> Generates all pseudo-legal captures and queen promotions
|
/// <CAPTURES> Generates all pseudo-legal captures plus queen and checking knight promotions
|
||||||
/// <QUIETS> Generates all pseudo-legal non-captures and underpromotions
|
/// <QUIETS> Generates all pseudo-legal non-captures and underpromotions(except checking knight)
|
||||||
/// <NON_EVASIONS> Generates all pseudo-legal captures and non-captures
|
/// <NON_EVASIONS> Generates all pseudo-legal captures and non-captures
|
||||||
///
|
///
|
||||||
/// Returns a pointer to the end of the move list.
|
/// Returns a pointer to the end of the move list.
|
||||||
|
@ -287,8 +285,8 @@ template ExtMove* generate<QUIETS>(const Position&, ExtMove*);
|
||||||
template ExtMove* generate<NON_EVASIONS>(const Position&, ExtMove*);
|
template ExtMove* generate<NON_EVASIONS>(const Position&, ExtMove*);
|
||||||
|
|
||||||
|
|
||||||
/// generate<QUIET_CHECKS> generates all pseudo-legal non-captures and knight
|
/// generate<QUIET_CHECKS> generates all pseudo-legal non-captures.
|
||||||
/// underpromotions that give check. Returns a pointer to the end of the move list.
|
/// Returns a pointer to the end of the move list.
|
||||||
template<>
|
template<>
|
||||||
ExtMove* generate<QUIET_CHECKS>(const Position& pos, ExtMove* moveList) {
|
ExtMove* generate<QUIET_CHECKS>(const Position& pos, ExtMove* moveList) {
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,12 @@ namespace {
|
||||||
constexpr Score WeakLever = S( 0, 56);
|
constexpr Score WeakLever = S( 0, 56);
|
||||||
constexpr Score WeakUnopposed = S(13, 27);
|
constexpr Score WeakUnopposed = S(13, 27);
|
||||||
|
|
||||||
constexpr Score BlockedStorm[RANK_NB] = {S( 0, 0), S( 0, 0), S( 76, 78), S(-10, 15), S(-7, 10), S(-4, 6), S(-1, 2)};
|
// Bonus for blocked pawns at 5th or 6th rank
|
||||||
|
constexpr Score BlockedPawn[2] = { S(-11, -4), S(-3, 4) };
|
||||||
|
|
||||||
|
constexpr Score BlockedStorm[RANK_NB] = {
|
||||||
|
S(0, 0), S(0, 0), S(76, 78), S(-10, 15), S(-7, 10), S(-4, 6), S(-1, 2)
|
||||||
|
};
|
||||||
|
|
||||||
// Connected pawn bonus
|
// Connected pawn bonus
|
||||||
constexpr int Connected[RANK_NB] = { 0, 7, 8, 12, 29, 48, 86 };
|
constexpr int Connected[RANK_NB] = { 0, 7, 8, 12, 29, 48, 86 };
|
||||||
|
@ -143,7 +148,7 @@ namespace {
|
||||||
// Score this pawn
|
// Score this pawn
|
||||||
if (support | phalanx)
|
if (support | phalanx)
|
||||||
{
|
{
|
||||||
int v = Connected[r] * (4 + 2 * bool(phalanx) - 2 * bool(opposed) - bool(blocked)) / 2
|
int v = Connected[r] * (2 + bool(phalanx) - bool(opposed))
|
||||||
+ 21 * popcount(support);
|
+ 21 * popcount(support);
|
||||||
|
|
||||||
score += make_score(v, v * (r - 2) / 4);
|
score += make_score(v, v * (r - 2) / 4);
|
||||||
|
@ -167,6 +172,9 @@ namespace {
|
||||||
if (!support)
|
if (!support)
|
||||||
score -= Doubled * doubled
|
score -= Doubled * doubled
|
||||||
+ WeakLever * more_than_one(lever);
|
+ WeakLever * more_than_one(lever);
|
||||||
|
|
||||||
|
if (blocked && r > RANK_4)
|
||||||
|
score += BlockedPawn[r-4];
|
||||||
}
|
}
|
||||||
|
|
||||||
return score;
|
return score;
|
||||||
|
|
|
@ -119,15 +119,7 @@ void Position::init() {
|
||||||
Zobrist::enpassant[f] = rng.rand<Key>();
|
Zobrist::enpassant[f] = rng.rand<Key>();
|
||||||
|
|
||||||
for (int cr = NO_CASTLING; cr <= ANY_CASTLING; ++cr)
|
for (int cr = NO_CASTLING; cr <= ANY_CASTLING; ++cr)
|
||||||
{
|
Zobrist::castling[cr] = rng.rand<Key>();
|
||||||
Zobrist::castling[cr] = 0;
|
|
||||||
Bitboard b = cr;
|
|
||||||
while (b)
|
|
||||||
{
|
|
||||||
Key k = Zobrist::castling[1ULL << pop_lsb(&b)];
|
|
||||||
Zobrist::castling[cr] ^= k ? k : rng.rand<Key>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Zobrist::side = rng.rand<Key>();
|
Zobrist::side = rng.rand<Key>();
|
||||||
Zobrist::noPawns = rng.rand<Key>();
|
Zobrist::noPawns = rng.rand<Key>();
|
||||||
|
@ -186,9 +178,9 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
|
||||||
|
|
||||||
4) En passant target square (in algebraic notation). If there's no en passant
|
4) En passant target square (in algebraic notation). If there's no en passant
|
||||||
target square, this is "-". If a pawn has just made a 2-square move, this
|
target square, this is "-". If a pawn has just made a 2-square move, this
|
||||||
is the position "behind" the pawn. This is recorded only if there is a pawn
|
is the position "behind" the pawn. Following X-FEN standard, this is recorded only
|
||||||
in position to make an en passant capture, and if there really is a pawn
|
if there is a pawn in position to make an en passant capture, and if there really
|
||||||
that might have advanced two squares.
|
is a pawn that might have advanced two squares.
|
||||||
|
|
||||||
5) Halfmove clock. This is the number of halfmoves since the last pawn advance
|
5) Halfmove clock. This is the number of halfmoves since the last pawn advance
|
||||||
or capture. This is used to determine if a draw can be claimed under the
|
or capture. This is used to determine if a draw can be claimed under the
|
||||||
|
@ -278,17 +270,25 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
|
||||||
set_castling_right(c, rsq);
|
set_castling_right(c, rsq);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. En passant square. Ignore if no pawn capture is possible
|
// 4. En passant square.
|
||||||
|
// Ignore if square is invalid or not on side to move relative rank 6.
|
||||||
|
bool enpassant = false;
|
||||||
|
|
||||||
if ( ((ss >> col) && (col >= 'a' && col <= 'h'))
|
if ( ((ss >> col) && (col >= 'a' && col <= 'h'))
|
||||||
&& ((ss >> row) && (row == '3' || row == '6')))
|
&& ((ss >> row) && (row == (sideToMove == WHITE ? '6' : '3'))))
|
||||||
{
|
{
|
||||||
st->epSquare = make_square(File(col - 'a'), Rank(row - '1'));
|
st->epSquare = make_square(File(col - 'a'), Rank(row - '1'));
|
||||||
|
|
||||||
if ( !(attackers_to(st->epSquare) & pieces(sideToMove, PAWN))
|
// En passant square will be considered only if
|
||||||
|| !(pieces(~sideToMove, PAWN) & (st->epSquare + pawn_push(~sideToMove))))
|
// a) side to move have a pawn threatening epSquare
|
||||||
st->epSquare = SQ_NONE;
|
// b) there is an enemy pawn in front of epSquare
|
||||||
|
// c) there is no piece on epSquare or behind epSquare
|
||||||
|
enpassant = pawn_attacks_bb(~sideToMove, st->epSquare) & pieces(sideToMove, PAWN)
|
||||||
|
&& (pieces(~sideToMove, PAWN) & (st->epSquare + pawn_push(~sideToMove)))
|
||||||
|
&& !(pieces() & (st->epSquare | (st->epSquare + pawn_push(sideToMove))));
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (!enpassant)
|
||||||
st->epSquare = SQ_NONE;
|
st->epSquare = SQ_NONE;
|
||||||
|
|
||||||
// 5-6. Halfmove clock and fullmove number
|
// 5-6. Halfmove clock and fullmove number
|
||||||
|
@ -851,9 +851,9 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
|
||||||
// Update castling rights if needed
|
// Update castling rights if needed
|
||||||
if (st->castlingRights && (castlingRightsMask[from] | castlingRightsMask[to]))
|
if (st->castlingRights && (castlingRightsMask[from] | castlingRightsMask[to]))
|
||||||
{
|
{
|
||||||
int cr = castlingRightsMask[from] | castlingRightsMask[to];
|
k ^= Zobrist::castling[st->castlingRights];
|
||||||
k ^= Zobrist::castling[st->castlingRights & cr];
|
st->castlingRights &= ~(castlingRightsMask[from] | castlingRightsMask[to]);
|
||||||
st->castlingRights &= ~cr;
|
k ^= Zobrist::castling[st->castlingRights];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the piece. The tricky Chess960 castling is handled earlier
|
// Move the piece. The tricky Chess960 castling is handled earlier
|
||||||
|
|
|
@ -92,7 +92,7 @@ constexpr Score PBonus[RANK_NB][FILE_NB] =
|
||||||
{ S( 3,-10), S( 3, -6), S( 10, 10), S( 19, 0), S( 16, 14), S( 19, 7), S( 7, -5), S( -5,-19) },
|
{ S( 3,-10), S( 3, -6), S( 10, 10), S( 19, 0), S( 16, 14), S( 19, 7), S( 7, -5), S( -5,-19) },
|
||||||
{ S( -9,-10), S(-15,-10), S( 11,-10), S( 15, 4), S( 32, 4), S( 22, 3), S( 5, -6), S(-22, -4) },
|
{ S( -9,-10), S(-15,-10), S( 11,-10), S( 15, 4), S( 32, 4), S( 22, 3), S( 5, -6), S(-22, -4) },
|
||||||
{ S( -4, 6), S(-23, -2), S( 6, -8), S( 20, -4), S( 40,-13), S( 17,-12), S( 4,-10), S( -8, -9) },
|
{ S( -4, 6), S(-23, -2), S( 6, -8), S( 20, -4), S( 40,-13), S( 17,-12), S( 4,-10), S( -8, -9) },
|
||||||
{ S( 13, 9), S( 0, 4), S(-13, 3), S( 1,-12), S( 11,-12), S( -2, -6), S(-13, 13), S( 5, 8) },
|
{ S( 13, 10), S( 0, 5), S(-13, 4), S( 1, -5), S( 11, -5), S( -2, -5), S(-13, 14), S( 5, 9) },
|
||||||
{ S( 5, 28), S(-12, 20), S( -7, 21), S( 22, 28), S( -8, 30), S( -5, 7), S(-15, 6), S( -8, 13) },
|
{ S( 5, 28), S(-12, 20), S( -7, 21), S( 22, 28), S( -8, 30), S( -5, 7), S(-15, 6), S( -8, 13) },
|
||||||
{ S( -7, 0), S( 7,-11), S( -3, 12), S(-13, 21), S( 5, 25), S(-16, 19), S( 10, 4), S( -8, 7) }
|
{ S( -7, 0), S( 7,-11), S( -3, 12), S(-13, 21), S( 5, 25), S(-16, 19), S( 10, 4), S( -8, 7) }
|
||||||
};
|
};
|
||||||
|
|
|
@ -263,10 +263,10 @@ void MainThread::search() {
|
||||||
|
|
||||||
Thread* bestThread = this;
|
Thread* bestThread = this;
|
||||||
|
|
||||||
if (int(Options["MultiPV"]) == 1 &&
|
if ( int(Options["MultiPV"]) == 1
|
||||||
!Limits.depth &&
|
&& !Limits.depth
|
||||||
!(Skill(Options["Skill Level"]).enabled() || int(Options["UCI_LimitStrength"])) &&
|
&& !(Skill(Options["Skill Level"]).enabled() || int(Options["UCI_LimitStrength"]))
|
||||||
rootMoves[0].pv[0] != MOVE_NONE)
|
&& rootMoves[0].pv[0] != MOVE_NONE)
|
||||||
bestThread = Threads.get_best_thread();
|
bestThread = Threads.get_best_thread();
|
||||||
|
|
||||||
bestPreviousScore = bestThread->rootMoves[0].score;
|
bestPreviousScore = bestThread->rootMoves[0].score;
|
||||||
|
@ -596,7 +596,7 @@ namespace {
|
||||||
Key posKey;
|
Key posKey;
|
||||||
Move ttMove, move, excludedMove, bestMove;
|
Move ttMove, move, excludedMove, bestMove;
|
||||||
Depth extension, newDepth;
|
Depth extension, newDepth;
|
||||||
Value bestValue, value, ttValue, eval, maxValue;
|
Value bestValue, value, ttValue, eval, maxValue, probcutBeta;
|
||||||
bool ttHit, ttPv, formerPv, givesCheck, improving, didLMR, priorCapture;
|
bool ttHit, ttPv, formerPv, givesCheck, improving, didLMR, priorCapture;
|
||||||
bool captureOrPromotion, doFullDepthSearch, moveCountPruning,
|
bool captureOrPromotion, doFullDepthSearch, moveCountPruning,
|
||||||
ttCapture, singularQuietLMR;
|
ttCapture, singularQuietLMR;
|
||||||
|
@ -662,7 +662,7 @@ namespace {
|
||||||
// search to overwrite a previous full search TT value, so we use a different
|
// search to overwrite a previous full search TT value, so we use a different
|
||||||
// position key in case of an excluded move.
|
// position key in case of an excluded move.
|
||||||
excludedMove = ss->excludedMove;
|
excludedMove = ss->excludedMove;
|
||||||
posKey = pos.key() ^ (Key(excludedMove) << 48); // Isn't a very good hash
|
posKey = excludedMove == MOVE_NONE ? pos.key() : pos.key() ^ make_key(excludedMove);
|
||||||
tte = TT.probe(posKey, ttHit);
|
tte = TT.probe(posKey, ttHit);
|
||||||
ttValue = ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE;
|
ttValue = ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE;
|
||||||
ttMove = rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0]
|
ttMove = rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0]
|
||||||
|
@ -670,7 +670,11 @@ namespace {
|
||||||
ttPv = PvNode || (ttHit && tte->is_pv());
|
ttPv = PvNode || (ttHit && tte->is_pv());
|
||||||
formerPv = ttPv && !PvNode;
|
formerPv = ttPv && !PvNode;
|
||||||
|
|
||||||
if (ttPv && depth > 12 && ss->ply - 1 < MAX_LPH && !priorCapture && is_ok((ss-1)->currentMove))
|
if ( ttPv
|
||||||
|
&& depth > 12
|
||||||
|
&& ss->ply - 1 < MAX_LPH
|
||||||
|
&& !priorCapture
|
||||||
|
&& is_ok((ss-1)->currentMove))
|
||||||
thisThread->lowPlyHistory[ss->ply - 1][from_to((ss-1)->currentMove)] << stat_bonus(depth - 5);
|
thisThread->lowPlyHistory[ss->ply - 1][from_to((ss-1)->currentMove)] << stat_bonus(depth - 5);
|
||||||
|
|
||||||
// thisThread->ttHitAverage can be used to approximate the running average of ttHit
|
// thisThread->ttHitAverage can be used to approximate the running average of ttHit
|
||||||
|
@ -867,23 +871,33 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
probcutBeta = beta + 176 - 49 * improving;
|
||||||
|
|
||||||
// Step 10. ProbCut (~10 Elo)
|
// Step 10. ProbCut (~10 Elo)
|
||||||
// If we have a good enough capture and a reduced search returns a value
|
// If we have a good enough capture and a reduced search returns a value
|
||||||
// much above beta, we can (almost) safely prune the previous move.
|
// much above beta, we can (almost) safely prune the previous move.
|
||||||
if ( !PvNode
|
if ( !PvNode
|
||||||
&& depth > 4
|
&& depth > 4
|
||||||
&& abs(beta) < VALUE_TB_WIN_IN_MAX_PLY)
|
&& abs(beta) < VALUE_TB_WIN_IN_MAX_PLY
|
||||||
|
&& !( ttHit
|
||||||
|
&& tte->depth() >= depth - 3
|
||||||
|
&& ttValue != VALUE_NONE
|
||||||
|
&& ttValue < probcutBeta))
|
||||||
{
|
{
|
||||||
Value raisedBeta = beta + 176 - 49 * improving;
|
if ( ttHit
|
||||||
assert(raisedBeta < VALUE_INFINITE);
|
&& tte->depth() >= depth - 3
|
||||||
MovePicker mp(pos, ttMove, raisedBeta - ss->staticEval, &captureHistory);
|
&& ttValue != VALUE_NONE
|
||||||
|
&& ttValue >= probcutBeta
|
||||||
|
&& ttMove
|
||||||
|
&& pos.capture_or_promotion(ttMove))
|
||||||
|
return probcutBeta;
|
||||||
|
|
||||||
|
assert(probcutBeta < VALUE_INFINITE);
|
||||||
|
MovePicker mp(pos, ttMove, probcutBeta - ss->staticEval, &captureHistory);
|
||||||
int probCutCount = 0;
|
int probCutCount = 0;
|
||||||
|
|
||||||
while ( (move = mp.next_move()) != MOVE_NONE
|
while ( (move = mp.next_move()) != MOVE_NONE
|
||||||
&& probCutCount < 2 + 2 * cutNode
|
&& probCutCount < 2 + 2 * cutNode)
|
||||||
&& !( move == ttMove
|
|
||||||
&& tte->depth() >= depth - 4
|
|
||||||
&& ttValue < raisedBeta))
|
|
||||||
if (move != excludedMove && pos.legal(move))
|
if (move != excludedMove && pos.legal(move))
|
||||||
{
|
{
|
||||||
assert(pos.capture_or_promotion(move));
|
assert(pos.capture_or_promotion(move));
|
||||||
|
@ -901,18 +915,23 @@ namespace {
|
||||||
pos.do_move(move, st);
|
pos.do_move(move, st);
|
||||||
|
|
||||||
// Perform a preliminary qsearch to verify that the move holds
|
// Perform a preliminary qsearch to verify that the move holds
|
||||||
value = -qsearch<NonPV>(pos, ss+1, -raisedBeta, -raisedBeta+1);
|
value = -qsearch<NonPV>(pos, ss+1, -probcutBeta, -probcutBeta+1);
|
||||||
|
|
||||||
// If the qsearch held, perform the regular search
|
// If the qsearch held, perform the regular search
|
||||||
if (value >= raisedBeta)
|
if (value >= probcutBeta)
|
||||||
value = -search<NonPV>(pos, ss+1, -raisedBeta, -raisedBeta+1, depth - 4, !cutNode);
|
value = -search<NonPV>(pos, ss+1, -probcutBeta, -probcutBeta+1, depth - 4, !cutNode);
|
||||||
|
|
||||||
pos.undo_move(move);
|
pos.undo_move(move);
|
||||||
|
|
||||||
if (value >= raisedBeta)
|
if (value >= probcutBeta)
|
||||||
|
{
|
||||||
|
tte->save(posKey, value_to_tt(value, ss->ply), ttPv,
|
||||||
|
BOUND_LOWER,
|
||||||
|
depth - 3, move, ss->staticEval);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Step 11. Internal iterative deepening (~1 Elo)
|
// Step 11. Internal iterative deepening (~1 Elo)
|
||||||
if (depth >= 7 && !ttMove)
|
if (depth >= 7 && !ttMove)
|
||||||
|
@ -1486,8 +1505,8 @@ moves_loop: // When in check, search starts from here
|
||||||
|
|
||||||
// Initialize a MovePicker object for the current position, and prepare
|
// Initialize a MovePicker object for the current position, and prepare
|
||||||
// to search the moves. Because the depth is <= 0 here, only captures,
|
// to search the moves. Because the depth is <= 0 here, only captures,
|
||||||
// queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will
|
// queen and checking knight promotions, and other checks(only if depth >= DEPTH_QS_CHECKS)
|
||||||
// be generated.
|
// will be generated.
|
||||||
MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory,
|
MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory,
|
||||||
&thisThread->captureHistory,
|
&thisThread->captureHistory,
|
||||||
contHist,
|
contHist,
|
||||||
|
|
|
@ -501,6 +501,11 @@ inline PieceNumber& operator--(PieceNumber& d) { return d = PieceNumber(int8_t(d
|
||||||
constexpr bool is_ok(PieceNumber pn) { return pn < PIECE_NUMBER_NB; }
|
constexpr bool is_ok(PieceNumber pn) { return pn < PIECE_NUMBER_NB; }
|
||||||
#endif // defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
#endif // defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
||||||
|
|
||||||
|
/// Based on a congruential pseudo random number generator
|
||||||
|
constexpr Key make_key(uint64_t seed) {
|
||||||
|
return seed * 6364136223846793005ULL + 1442695040888963407ULL;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // #ifndef TYPES_H_INCLUDED
|
#endif // #ifndef TYPES_H_INCLUDED
|
||||||
|
|
||||||
#include "tune.h" // Global visibility to tuning setup
|
#include "tune.h" // Global visibility to tuning setup
|
||||||
|
|
Loading…
Add table
Reference in a new issue