mirror of
https://github.com/opelly27/Stockfish.git
synced 2026-05-20 06:17:49 +00:00
Merge remote-tracking branch 'upstream/master' into clusterMergeMaster4
This commit is contained in:
+2
-25
@@ -24,19 +24,13 @@
|
|||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
uint8_t PopCnt16[1 << 16];
|
uint8_t PopCnt16[1 << 16];
|
||||||
int SquareDistance[SQUARE_NB][SQUARE_NB];
|
int8_t SquareDistance[SQUARE_NB][SQUARE_NB];
|
||||||
|
|
||||||
Bitboard SquareBB[SQUARE_NB];
|
Bitboard SquareBB[SQUARE_NB];
|
||||||
Bitboard FileBB[FILE_NB];
|
|
||||||
Bitboard RankBB[RANK_NB];
|
|
||||||
Bitboard AdjacentFilesBB[FILE_NB];
|
|
||||||
Bitboard ForwardRanksBB[COLOR_NB][RANK_NB];
|
Bitboard ForwardRanksBB[COLOR_NB][RANK_NB];
|
||||||
Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
|
Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
|
||||||
Bitboard LineBB[SQUARE_NB][SQUARE_NB];
|
Bitboard LineBB[SQUARE_NB][SQUARE_NB];
|
||||||
Bitboard DistanceRingBB[SQUARE_NB][8];
|
Bitboard DistanceRingBB[SQUARE_NB][8];
|
||||||
Bitboard ForwardFileBB[COLOR_NB][SQUARE_NB];
|
|
||||||
Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB];
|
|
||||||
Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB];
|
|
||||||
Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
|
Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
|
||||||
Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
|
Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
|
||||||
|
|
||||||
@@ -91,25 +85,8 @@ void Bitboards::init() {
|
|||||||
for (Square s = SQ_A1; s <= SQ_H8; ++s)
|
for (Square s = SQ_A1; s <= SQ_H8; ++s)
|
||||||
SquareBB[s] = (1ULL << s);
|
SquareBB[s] = (1ULL << s);
|
||||||
|
|
||||||
for (File f = FILE_A; f <= FILE_H; ++f)
|
|
||||||
FileBB[f] = f > FILE_A ? FileBB[f - 1] << 1 : FileABB;
|
|
||||||
|
|
||||||
for (Rank r = RANK_1; r <= RANK_8; ++r)
|
|
||||||
RankBB[r] = r > RANK_1 ? RankBB[r - 1] << 8 : Rank1BB;
|
|
||||||
|
|
||||||
for (File f = FILE_A; f <= FILE_H; ++f)
|
|
||||||
AdjacentFilesBB[f] = (f > FILE_A ? FileBB[f - 1] : 0) | (f < FILE_H ? FileBB[f + 1] : 0);
|
|
||||||
|
|
||||||
for (Rank r = RANK_1; r < RANK_8; ++r)
|
for (Rank r = RANK_1; r < RANK_8; ++r)
|
||||||
ForwardRanksBB[WHITE][r] = ~(ForwardRanksBB[BLACK][r + 1] = ForwardRanksBB[BLACK][r] | RankBB[r]);
|
ForwardRanksBB[WHITE][r] = ~(ForwardRanksBB[BLACK][r + 1] = ForwardRanksBB[BLACK][r] | rank_bb(r));
|
||||||
|
|
||||||
for (Color c = WHITE; c <= BLACK; ++c)
|
|
||||||
for (Square s = SQ_A1; s <= SQ_H8; ++s)
|
|
||||||
{
|
|
||||||
ForwardFileBB [c][s] = ForwardRanksBB[c][rank_of(s)] & FileBB[file_of(s)];
|
|
||||||
PawnAttackSpan[c][s] = ForwardRanksBB[c][rank_of(s)] & AdjacentFilesBB[file_of(s)];
|
|
||||||
PassedPawnMask[c][s] = ForwardFileBB [c][s] | PawnAttackSpan[c][s];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
|
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
|
||||||
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
|
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
|
||||||
|
|||||||
+15
-24
@@ -60,19 +60,13 @@ constexpr Bitboard Rank6BB = Rank1BB << (8 * 5);
|
|||||||
constexpr Bitboard Rank7BB = Rank1BB << (8 * 6);
|
constexpr Bitboard Rank7BB = Rank1BB << (8 * 6);
|
||||||
constexpr Bitboard Rank8BB = Rank1BB << (8 * 7);
|
constexpr Bitboard Rank8BB = Rank1BB << (8 * 7);
|
||||||
|
|
||||||
extern int SquareDistance[SQUARE_NB][SQUARE_NB];
|
extern int8_t SquareDistance[SQUARE_NB][SQUARE_NB];
|
||||||
|
|
||||||
extern Bitboard SquareBB[SQUARE_NB];
|
extern Bitboard SquareBB[SQUARE_NB];
|
||||||
extern Bitboard FileBB[FILE_NB];
|
|
||||||
extern Bitboard RankBB[RANK_NB];
|
|
||||||
extern Bitboard AdjacentFilesBB[FILE_NB];
|
|
||||||
extern Bitboard ForwardRanksBB[COLOR_NB][RANK_NB];
|
extern Bitboard ForwardRanksBB[COLOR_NB][RANK_NB];
|
||||||
extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
|
extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
|
||||||
extern Bitboard LineBB[SQUARE_NB][SQUARE_NB];
|
extern Bitboard LineBB[SQUARE_NB][SQUARE_NB];
|
||||||
extern Bitboard DistanceRingBB[SQUARE_NB][8];
|
extern Bitboard DistanceRingBB[SQUARE_NB][8];
|
||||||
extern Bitboard ForwardFileBB[COLOR_NB][SQUARE_NB];
|
|
||||||
extern Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB];
|
|
||||||
extern Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB];
|
|
||||||
extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
|
extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
|
||||||
extern Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
|
extern Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
|
||||||
|
|
||||||
@@ -143,23 +137,23 @@ inline bool opposite_colors(Square s1, Square s2) {
|
|||||||
/// the given file or rank.
|
/// the given file or rank.
|
||||||
|
|
||||||
inline Bitboard rank_bb(Rank r) {
|
inline Bitboard rank_bb(Rank r) {
|
||||||
return RankBB[r];
|
return Rank1BB << (8 * r);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Bitboard rank_bb(Square s) {
|
inline Bitboard rank_bb(Square s) {
|
||||||
return RankBB[rank_of(s)];
|
return rank_bb(rank_of(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Bitboard file_bb(File f) {
|
inline Bitboard file_bb(File f) {
|
||||||
return FileBB[f];
|
return FileABB << f;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Bitboard file_bb(Square s) {
|
inline Bitboard file_bb(Square s) {
|
||||||
return FileBB[file_of(s)];
|
return file_bb(file_of(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// shift() moves a bitboard one step along direction D (mainly for pawns)
|
/// shift() moves a bitboard one step along direction D
|
||||||
|
|
||||||
template<Direction D>
|
template<Direction D>
|
||||||
constexpr Bitboard shift(Bitboard b) {
|
constexpr Bitboard shift(Bitboard b) {
|
||||||
@@ -171,8 +165,8 @@ constexpr Bitboard shift(Bitboard b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// pawn_attacks_bb() returns the pawn attacks for the given color from the
|
/// pawn_attacks_bb() returns the squares attacked by pawns of the given color
|
||||||
/// squares in the given bitboard.
|
/// from the squares in the given bitboard.
|
||||||
|
|
||||||
template<Color C>
|
template<Color C>
|
||||||
constexpr Bitboard pawn_attacks_bb(Bitboard b) {
|
constexpr Bitboard pawn_attacks_bb(Bitboard b) {
|
||||||
@@ -181,11 +175,11 @@ constexpr Bitboard pawn_attacks_bb(Bitboard b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// double_pawn_attacks_bb() returns the pawn attacks for the given color
|
/// pawn_double_attacks_bb() returns the squares doubly attacked by pawns of the
|
||||||
/// from the squares in the given bitboard.
|
/// given color from the squares in the given bitboard.
|
||||||
|
|
||||||
template<Color C>
|
template<Color C>
|
||||||
constexpr Bitboard double_pawn_attacks_bb(Bitboard b) {
|
constexpr Bitboard pawn_double_attacks_bb(Bitboard b) {
|
||||||
return C == WHITE ? shift<NORTH_WEST>(b) & shift<NORTH_EAST>(b)
|
return C == WHITE ? shift<NORTH_WEST>(b) & shift<NORTH_EAST>(b)
|
||||||
: shift<SOUTH_WEST>(b) & shift<SOUTH_EAST>(b);
|
: shift<SOUTH_WEST>(b) & shift<SOUTH_EAST>(b);
|
||||||
}
|
}
|
||||||
@@ -195,10 +189,9 @@ constexpr Bitboard double_pawn_attacks_bb(Bitboard b) {
|
|||||||
/// adjacent files of the given one.
|
/// adjacent files of the given one.
|
||||||
|
|
||||||
inline Bitboard adjacent_files_bb(File f) {
|
inline Bitboard adjacent_files_bb(File f) {
|
||||||
return AdjacentFilesBB[f];
|
return shift<EAST>(file_bb(f)) | shift<WEST>(file_bb(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// between_bb() returns a bitboard representing all the squares between the two
|
/// between_bb() returns a bitboard representing all the squares between the two
|
||||||
/// given ones. For instance, between_bb(SQ_C4, SQ_F7) returns a bitboard with
|
/// given ones. For instance, between_bb(SQ_C4, SQ_F7) returns a bitboard with
|
||||||
/// the bits for square d5 and e6 set. If s1 and s2 are not on the same rank, file
|
/// the bits for square d5 and e6 set. If s1 and s2 are not on the same rank, file
|
||||||
@@ -223,26 +216,24 @@ inline Bitboard forward_ranks_bb(Color c, Square s) {
|
|||||||
/// ForwardFileBB[c][s] = forward_ranks_bb(c, s) & file_bb(s)
|
/// ForwardFileBB[c][s] = forward_ranks_bb(c, s) & file_bb(s)
|
||||||
|
|
||||||
inline Bitboard forward_file_bb(Color c, Square s) {
|
inline Bitboard forward_file_bb(Color c, Square s) {
|
||||||
return ForwardFileBB[c][s];
|
return ForwardRanksBB[c][rank_of(s)] & file_bb(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// pawn_attack_span() returns a bitboard representing all the squares that can be
|
/// pawn_attack_span() returns a bitboard representing all the squares that can be
|
||||||
/// attacked by a pawn of the given color when it moves along its file, starting
|
/// attacked by a pawn of the given color when it moves along its file, starting
|
||||||
/// from the given square:
|
/// from the given square:
|
||||||
/// PawnAttackSpan[c][s] = forward_ranks_bb(c, s) & adjacent_files_bb(file_of(s));
|
|
||||||
|
|
||||||
inline Bitboard pawn_attack_span(Color c, Square s) {
|
inline Bitboard pawn_attack_span(Color c, Square s) {
|
||||||
return PawnAttackSpan[c][s];
|
return forward_ranks_bb(c, s) & adjacent_files_bb(file_of(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// passed_pawn_mask() returns a bitboard mask which can be used to test if a
|
/// passed_pawn_mask() returns a bitboard mask which can be used to test if a
|
||||||
/// pawn of the given color and on the given square is a passed pawn:
|
/// pawn of the given color and on the given square is a passed pawn:
|
||||||
/// PassedPawnMask[c][s] = pawn_attack_span(c, s) | forward_file_bb(c, s)
|
|
||||||
|
|
||||||
inline Bitboard passed_pawn_mask(Color c, Square s) {
|
inline Bitboard passed_pawn_mask(Color c, Square s) {
|
||||||
return PassedPawnMask[c][s];
|
return pawn_attack_span(c, s) | forward_file_bb(c, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -356,7 +356,7 @@ void save(Thread* thread, TTEntry* tte,
|
|||||||
bool found;
|
bool found;
|
||||||
TTEntry* replace_tte;
|
TTEntry* replace_tte;
|
||||||
replace_tte = TT.probe(e.first, found);
|
replace_tte = TT.probe(e.first, found);
|
||||||
replace_tte->save(e.first, e.second.value(), e.second.pv_hit(), e.second.bound(), e.second.depth(),
|
replace_tte->save(e.first, e.second.value(), e.second.is_pv(), e.second.bound(), e.second.depth(),
|
||||||
e.second.move(), e.second.eval());
|
e.second.move(), e.second.eval());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+79
-68
@@ -93,8 +93,8 @@ namespace {
|
|||||||
|
|
||||||
// Penalties for enemy's safe checks
|
// Penalties for enemy's safe checks
|
||||||
constexpr int QueenSafeCheck = 780;
|
constexpr int QueenSafeCheck = 780;
|
||||||
constexpr int RookSafeCheck = 880;
|
constexpr int RookSafeCheck = 1080;
|
||||||
constexpr int BishopSafeCheck = 435;
|
constexpr int BishopSafeCheck = 635;
|
||||||
constexpr int KnightSafeCheck = 790;
|
constexpr int KnightSafeCheck = 790;
|
||||||
|
|
||||||
#define S(mg, eg) make_score(mg, eg)
|
#define S(mg, eg) make_score(mg, eg)
|
||||||
@@ -117,14 +117,6 @@ namespace {
|
|||||||
S(106,184), S(109,191), S(113,206), S(116,212) }
|
S(106,184), S(109,191), S(113,206), S(116,212) }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Outpost[knight/bishop][supported by pawn] contains bonuses for minor
|
|
||||||
// pieces if they occupy or can reach an outpost square, bigger if that
|
|
||||||
// square is supported by a pawn.
|
|
||||||
constexpr Score Outpost[][2] = {
|
|
||||||
{ S(22, 6), S(36,12) }, // Knight
|
|
||||||
{ S( 9, 2), S(15, 5) } // Bishop
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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(18, 7), S(44, 20) };
|
constexpr Score RookOnFile[] = { S(18, 7), S(44, 20) };
|
||||||
@@ -153,8 +145,8 @@ namespace {
|
|||||||
|
|
||||||
// Assorted bonuses and penalties
|
// Assorted bonuses and penalties
|
||||||
constexpr Score BishopPawns = S( 3, 7);
|
constexpr Score BishopPawns = S( 3, 7);
|
||||||
constexpr Score CloseEnemies = S( 8, 0);
|
|
||||||
constexpr Score CorneredBishop = S( 50, 50);
|
constexpr Score CorneredBishop = S( 50, 50);
|
||||||
|
constexpr Score FlankAttacks = S( 8, 0);
|
||||||
constexpr Score Hanging = S( 69, 36);
|
constexpr Score Hanging = S( 69, 36);
|
||||||
constexpr Score KingProtector = S( 7, 8);
|
constexpr Score KingProtector = S( 7, 8);
|
||||||
constexpr Score KnightOnQueen = S( 16, 12);
|
constexpr Score KnightOnQueen = S( 16, 12);
|
||||||
@@ -168,9 +160,10 @@ namespace {
|
|||||||
constexpr Score ThreatByPawnPush = S( 48, 39);
|
constexpr Score ThreatByPawnPush = S( 48, 39);
|
||||||
constexpr Score ThreatByRank = S( 13, 0);
|
constexpr Score ThreatByRank = S( 13, 0);
|
||||||
constexpr Score ThreatBySafePawn = S(173, 94);
|
constexpr Score ThreatBySafePawn = S(173, 94);
|
||||||
constexpr Score TrappedRook = S( 96, 4);
|
constexpr Score TrappedRook = S( 47, 4);
|
||||||
constexpr Score WeakQueen = S( 49, 15);
|
constexpr Score WeakQueen = S( 49, 15);
|
||||||
constexpr Score WeakUnopposedPawn = S( 12, 23);
|
constexpr Score WeakUnopposedPawn = S( 12, 23);
|
||||||
|
constexpr Score Outpost = S( 9, 3);
|
||||||
|
|
||||||
#undef S
|
#undef S
|
||||||
|
|
||||||
@@ -245,33 +238,37 @@ namespace {
|
|||||||
constexpr Direction Down = (Us == WHITE ? SOUTH : NORTH);
|
constexpr Direction Down = (Us == WHITE ? SOUTH : NORTH);
|
||||||
constexpr Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB: Rank7BB | Rank6BB);
|
constexpr Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB: Rank7BB | Rank6BB);
|
||||||
|
|
||||||
|
const Square ksq = pos.square<KING>(Us);
|
||||||
|
|
||||||
// Find our pawns that are blocked or on the first two ranks
|
// Find our pawns that are blocked or on the first two ranks
|
||||||
Bitboard b = pos.pieces(Us, PAWN) & (shift<Down>(pos.pieces()) | LowRanks);
|
Bitboard b = pos.pieces(Us, PAWN) & (shift<Down>(pos.pieces()) | LowRanks);
|
||||||
|
|
||||||
// Squares occupied by those pawns, by our king or queen, or controlled by enemy pawns
|
// Squares occupied by those pawns, by our king or queen or controlled by
|
||||||
// are excluded from the mobility area.
|
// enemy pawns are excluded from the mobility area.
|
||||||
mobilityArea[Us] = ~(b | pos.pieces(Us, KING, QUEEN) | pe->pawn_attacks(Them));
|
mobilityArea[Us] = ~(b | pos.pieces(Us, KING, QUEEN) | pe->pawn_attacks(Them));
|
||||||
|
|
||||||
// Initialise attackedBy bitboards for kings and pawns
|
// Initialize attackedBy[] for king and pawns
|
||||||
attackedBy[Us][KING] = pos.attacks_from<KING>(pos.square<KING>(Us));
|
attackedBy[Us][KING] = pos.attacks_from<KING>(ksq);
|
||||||
attackedBy[Us][PAWN] = pe->pawn_attacks(Us);
|
attackedBy[Us][PAWN] = pe->pawn_attacks(Us);
|
||||||
attackedBy[Us][ALL_PIECES] = attackedBy[Us][KING] | attackedBy[Us][PAWN];
|
attackedBy[Us][ALL_PIECES] = attackedBy[Us][KING] | attackedBy[Us][PAWN];
|
||||||
attackedBy2[Us] = attackedBy[Us][KING] & attackedBy[Us][PAWN];
|
attackedBy2[Us] = attackedBy[Us][KING] & attackedBy[Us][PAWN];
|
||||||
|
|
||||||
// Init our king safety tables
|
// Init our king safety tables
|
||||||
kingRing[Us] = attackedBy[Us][KING];
|
kingRing[Us] = attackedBy[Us][KING];
|
||||||
if (relative_rank(Us, pos.square<KING>(Us)) == RANK_1)
|
if (relative_rank(Us, ksq) == RANK_1)
|
||||||
kingRing[Us] |= shift<Up>(kingRing[Us]);
|
kingRing[Us] |= shift<Up>(kingRing[Us]);
|
||||||
|
|
||||||
if (file_of(pos.square<KING>(Us)) == FILE_H)
|
if (file_of(ksq) == FILE_H)
|
||||||
kingRing[Us] |= shift<WEST>(kingRing[Us]);
|
kingRing[Us] |= shift<WEST>(kingRing[Us]);
|
||||||
|
|
||||||
else if (file_of(pos.square<KING>(Us)) == FILE_A)
|
else if (file_of(ksq) == FILE_A)
|
||||||
kingRing[Us] |= shift<EAST>(kingRing[Us]);
|
kingRing[Us] |= shift<EAST>(kingRing[Us]);
|
||||||
|
|
||||||
kingAttackersCount[Them] = popcount(kingRing[Us] & pe->pawn_attacks(Them));
|
kingAttackersCount[Them] = popcount(kingRing[Us] & pe->pawn_attacks(Them));
|
||||||
kingRing[Us] &= ~double_pawn_attacks_bb<Us>(pos.pieces(Us, PAWN));
|
|
||||||
kingAttacksCount[Them] = kingAttackersWeight[Them] = 0;
|
kingAttacksCount[Them] = kingAttackersWeight[Them] = 0;
|
||||||
|
|
||||||
|
// Remove from kingRing[] the squares defended by two pawns
|
||||||
|
kingRing[Us] &= ~pawn_double_attacks_bb<Us>(pos.pieces(Us, PAWN));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -286,12 +283,11 @@ namespace {
|
|||||||
const Square* pl = pos.squares<Pt>(Us);
|
const Square* pl = pos.squares<Pt>(Us);
|
||||||
|
|
||||||
Bitboard b, bb;
|
Bitboard b, bb;
|
||||||
Square s;
|
|
||||||
Score score = SCORE_ZERO;
|
Score score = SCORE_ZERO;
|
||||||
|
|
||||||
attackedBy[Us][Pt] = 0;
|
attackedBy[Us][Pt] = 0;
|
||||||
|
|
||||||
while ((s = *pl++) != SQ_NONE)
|
for (Square s = *pl; s != SQ_NONE; s = *++pl)
|
||||||
{
|
{
|
||||||
// Find attacked squares, including x-ray attacks for bishops and rooks
|
// Find attacked squares, including x-ray attacks for bishops and rooks
|
||||||
b = Pt == BISHOP ? attacks_bb<BISHOP>(s, pos.pieces() ^ pos.pieces(QUEEN))
|
b = Pt == BISHOP ? attacks_bb<BISHOP>(s, pos.pieces() ^ pos.pieces(QUEEN))
|
||||||
@@ -321,10 +317,12 @@ 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 & ~pe->pawn_attacks_span(Them);
|
bb = OutpostRanks & ~pe->pawn_attacks_span(Them);
|
||||||
if (bb & s)
|
if (bb & s)
|
||||||
score += Outpost[Pt == BISHOP][bool(attackedBy[Us][PAWN] & s)] * 2;
|
score += Outpost * (Pt == KNIGHT ? 4 : 2)
|
||||||
|
* (1 + bool(attackedBy[Us][PAWN] & s));
|
||||||
|
|
||||||
else if (bb &= b & ~pos.pieces(Us))
|
else if (bb &= b & ~pos.pieces(Us))
|
||||||
score += Outpost[Pt == BISHOP][bool(attackedBy[Us][PAWN] & bb)];
|
score += Outpost * (Pt == KNIGHT ? 2 : 1)
|
||||||
|
* (1 + bool(attackedBy[Us][PAWN] & bb));
|
||||||
|
|
||||||
// Knight and Bishop bonus for being right behind a pawn
|
// Knight and Bishop bonus for being right behind a pawn
|
||||||
if (shift<Down>(pos.pieces(PAWN)) & s)
|
if (shift<Down>(pos.pieces(PAWN)) & s)
|
||||||
@@ -377,7 +375,7 @@ namespace {
|
|||||||
{
|
{
|
||||||
File kf = file_of(pos.square<KING>(Us));
|
File kf = file_of(pos.square<KING>(Us));
|
||||||
if ((kf < FILE_E) == (file_of(s) < kf))
|
if ((kf < FILE_E) == (file_of(s) < kf))
|
||||||
score -= (TrappedRook - make_score(mob * 22, 0)) * (1 + !pos.castling_rights(Us));
|
score -= TrappedRook * (1 + !pos.castling_rights(Us));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,23 +402,12 @@ namespace {
|
|||||||
constexpr Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB
|
constexpr Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB
|
||||||
: AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB);
|
: AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB);
|
||||||
|
|
||||||
const Square ksq = pos.square<KING>(Us);
|
Bitboard weak, b, b1, b2, safe, unsafeChecks = 0;
|
||||||
Bitboard kingFlank, weak, b, b1, b2, safe, unsafeChecks;
|
|
||||||
|
|
||||||
// King shelter and enemy pawns storm
|
|
||||||
Score score = pe->king_safety<Us>(pos);
|
|
||||||
|
|
||||||
// Find the squares that opponent attacks in our king flank, and the squares
|
|
||||||
// which are attacked twice in that flank.
|
|
||||||
kingFlank = KingFlank[file_of(ksq)];
|
|
||||||
b1 = attackedBy[Them][ALL_PIECES] & kingFlank & Camp;
|
|
||||||
b2 = b1 & attackedBy2[Them];
|
|
||||||
|
|
||||||
int tropism = popcount(b1) + popcount(b2);
|
|
||||||
|
|
||||||
// Main king safety evaluation
|
|
||||||
int kingDanger = 0;
|
int kingDanger = 0;
|
||||||
unsafeChecks = 0;
|
const Square ksq = pos.square<KING>(Us);
|
||||||
|
|
||||||
|
// Init the score with king shelter and enemy pawns storm
|
||||||
|
Score score = pe->king_safety<Us>(pos);
|
||||||
|
|
||||||
// Attacked squares defended at most once by our queen or king
|
// Attacked squares defended at most once by our queen or king
|
||||||
weak = attackedBy[Them][ALL_PIECES]
|
weak = attackedBy[Them][ALL_PIECES]
|
||||||
@@ -434,27 +421,42 @@ namespace {
|
|||||||
b1 = attacks_bb<ROOK >(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
|
b1 = attacks_bb<ROOK >(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
|
||||||
b2 = attacks_bb<BISHOP>(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
|
b2 = attacks_bb<BISHOP>(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
|
||||||
|
|
||||||
// Enemy queen safe checks
|
|
||||||
if ((b1 | b2) & attackedBy[Them][QUEEN] & safe & ~attackedBy[Us][QUEEN])
|
|
||||||
kingDanger += QueenSafeCheck;
|
|
||||||
|
|
||||||
b1 &= attackedBy[Them][ROOK];
|
|
||||||
b2 &= attackedBy[Them][BISHOP];
|
|
||||||
|
|
||||||
// Enemy rooks checks
|
// Enemy rooks checks
|
||||||
if (b1 & safe)
|
Bitboard RookCheck = b1
|
||||||
|
& safe
|
||||||
|
& attackedBy[Them][ROOK];
|
||||||
|
|
||||||
|
if (RookCheck)
|
||||||
kingDanger += RookSafeCheck;
|
kingDanger += RookSafeCheck;
|
||||||
else
|
else
|
||||||
unsafeChecks |= b1;
|
unsafeChecks |= b1 & attackedBy[Them][ROOK];
|
||||||
|
|
||||||
// Enemy bishops checks
|
// Enemy queen safe checks: we count them only if they are from squares from
|
||||||
if (b2 & safe)
|
// which we can't give a rook check, because rook checks are more valuable.
|
||||||
|
Bitboard QueenCheck = (b1 | b2)
|
||||||
|
& attackedBy[Them][QUEEN]
|
||||||
|
& safe
|
||||||
|
& ~attackedBy[Us][QUEEN]
|
||||||
|
& ~RookCheck;
|
||||||
|
|
||||||
|
if (QueenCheck)
|
||||||
|
kingDanger += QueenSafeCheck;
|
||||||
|
|
||||||
|
// Enemy bishops checks: we count them only if they are from squares from
|
||||||
|
// which we can't give a queen check, because queen checks are more valuable.
|
||||||
|
Bitboard BishopCheck = b2
|
||||||
|
& attackedBy[Them][BISHOP]
|
||||||
|
& safe
|
||||||
|
& ~QueenCheck;
|
||||||
|
|
||||||
|
if (BishopCheck)
|
||||||
kingDanger += BishopSafeCheck;
|
kingDanger += BishopSafeCheck;
|
||||||
else
|
else
|
||||||
unsafeChecks |= b2;
|
unsafeChecks |= b2 & attackedBy[Them][BISHOP];
|
||||||
|
|
||||||
// Enemy knights checks
|
// Enemy knights checks
|
||||||
b = pos.attacks_from<KNIGHT>(ksq) & attackedBy[Them][KNIGHT];
|
b = pos.attacks_from<KNIGHT>(ksq) & attackedBy[Them][KNIGHT];
|
||||||
|
|
||||||
if (b & safe)
|
if (b & safe)
|
||||||
kingDanger += KnightSafeCheck;
|
kingDanger += KnightSafeCheck;
|
||||||
else
|
else
|
||||||
@@ -464,26 +466,34 @@ namespace {
|
|||||||
// the square is in the attacker's mobility area.
|
// the square is in the attacker's mobility area.
|
||||||
unsafeChecks &= mobilityArea[Them];
|
unsafeChecks &= mobilityArea[Them];
|
||||||
|
|
||||||
|
// Find the squares that opponent attacks in our king flank, and the squares
|
||||||
|
// which are attacked twice in that flank.
|
||||||
|
b1 = attackedBy[Them][ALL_PIECES] & KingFlank[file_of(ksq)] & Camp;
|
||||||
|
b2 = b1 & attackedBy2[Them];
|
||||||
|
|
||||||
|
int kingFlankAttacks = popcount(b1) + popcount(b2);
|
||||||
|
|
||||||
kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them]
|
kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them]
|
||||||
+ 69 * kingAttacksCount[Them]
|
+ 69 * kingAttacksCount[Them]
|
||||||
+ 185 * popcount(kingRing[Us] & weak)
|
+ 185 * popcount(kingRing[Us] & weak)
|
||||||
|
- 100 * bool(attackedBy[Us][KNIGHT] & attackedBy[Us][KING])
|
||||||
+ 150 * popcount(pos.blockers_for_king(Us) | unsafeChecks)
|
+ 150 * popcount(pos.blockers_for_king(Us) | unsafeChecks)
|
||||||
+ tropism * tropism / 4
|
|
||||||
- 873 * !pos.count<QUEEN>(Them)
|
- 873 * !pos.count<QUEEN>(Them)
|
||||||
- 6 * mg_value(score) / 8
|
- 6 * mg_value(score) / 8
|
||||||
+ mg_value(mobility[Them] - mobility[Us])
|
+ mg_value(mobility[Them] - mobility[Us])
|
||||||
- 30;
|
+ 5 * kingFlankAttacks * kingFlankAttacks / 16
|
||||||
|
- 25;
|
||||||
|
|
||||||
// Transform the kingDanger units into a Score, and subtract it from the evaluation
|
// Transform the kingDanger units into a Score, and subtract it from the evaluation
|
||||||
if (kingDanger > 0)
|
if (kingDanger > 0)
|
||||||
score -= make_score(kingDanger * kingDanger / 4096, kingDanger / 16);
|
score -= make_score(kingDanger * kingDanger / 4096, kingDanger / 16);
|
||||||
|
|
||||||
// Penalty when our king is on a pawnless flank
|
// Penalty when our king is on a pawnless flank
|
||||||
if (!(pos.pieces(PAWN) & kingFlank))
|
if (!(pos.pieces(PAWN) & KingFlank[file_of(ksq)]))
|
||||||
score -= PawnlessFlank;
|
score -= PawnlessFlank;
|
||||||
|
|
||||||
// King tropism bonus, to anticipate slow motion attacks on our king
|
// Penalty if king flank is under attack, potentially moving toward the king
|
||||||
score -= CloseEnemies * tropism;
|
score -= FlankAttacks * kingFlankAttacks;
|
||||||
|
|
||||||
if (T)
|
if (T)
|
||||||
Trace::add(KING, Us, score);
|
Trace::add(KING, Us, score);
|
||||||
@@ -701,7 +711,8 @@ namespace {
|
|||||||
if (pos.non_pawn_material() < SpaceThreshold)
|
if (pos.non_pawn_material() < SpaceThreshold)
|
||||||
return SCORE_ZERO;
|
return SCORE_ZERO;
|
||||||
|
|
||||||
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
|
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
|
||||||
|
constexpr Direction Down = (Us == WHITE ? SOUTH : NORTH);
|
||||||
constexpr Bitboard SpaceMask =
|
constexpr Bitboard SpaceMask =
|
||||||
Us == WHITE ? CenterFiles & (Rank2BB | Rank3BB | Rank4BB)
|
Us == WHITE ? CenterFiles & (Rank2BB | Rank3BB | Rank4BB)
|
||||||
: CenterFiles & (Rank7BB | Rank6BB | Rank5BB);
|
: CenterFiles & (Rank7BB | Rank6BB | Rank5BB);
|
||||||
@@ -713,8 +724,8 @@ namespace {
|
|||||||
|
|
||||||
// Find all squares which are at most three squares behind some friendly pawn
|
// Find all squares which are at most three squares behind some friendly pawn
|
||||||
Bitboard behind = pos.pieces(Us, PAWN);
|
Bitboard behind = pos.pieces(Us, PAWN);
|
||||||
behind |= (Us == WHITE ? behind >> 8 : behind << 8);
|
behind |= shift<Down>(behind);
|
||||||
behind |= (Us == WHITE ? behind >> 16 : behind << 16);
|
behind |= shift<Down>(shift<Down>(behind));
|
||||||
|
|
||||||
int bonus = popcount(safe) + popcount(behind & safe);
|
int bonus = popcount(safe) + popcount(behind & safe);
|
||||||
int weight = pos.count<ALL_PIECES>(Us)
|
int weight = pos.count<ALL_PIECES>(Us)
|
||||||
@@ -743,12 +754,12 @@ namespace {
|
|||||||
&& (pos.pieces(PAWN) & KingSide);
|
&& (pos.pieces(PAWN) & KingSide);
|
||||||
|
|
||||||
// Compute the initiative bonus for the attacking side
|
// Compute the initiative bonus for the attacking side
|
||||||
int complexity = 8 * pe->pawn_asymmetry()
|
int complexity = 9 * pe->pawn_asymmetry()
|
||||||
+ 12 * pos.count<PAWN>()
|
+ 11 * pos.count<PAWN>()
|
||||||
+ 12 * outflanking
|
+ 9 * outflanking
|
||||||
+ 16 * pawnsOnBothFlanks
|
+ 18 * pawnsOnBothFlanks
|
||||||
+ 48 * !pos.non_pawn_material()
|
+ 49 * !pos.non_pawn_material()
|
||||||
-118 ;
|
-121 ;
|
||||||
|
|
||||||
// Now apply the bonus: note that we find the attacking side by extracting
|
// Now apply the bonus: note that we find the attacking side by extracting
|
||||||
// the sign of the endgame value, and that we carefully cap the bonus so
|
// the sign of the endgame value, and that we carefully cap the bonus so
|
||||||
@@ -842,7 +853,7 @@ namespace {
|
|||||||
v = mg_value(score) * int(me->game_phase())
|
v = mg_value(score) * int(me->game_phase())
|
||||||
+ eg_value(score) * int(PHASE_MIDGAME - me->game_phase()) * sf / SCALE_FACTOR_NORMAL;
|
+ eg_value(score) * int(PHASE_MIDGAME - me->game_phase()) * sf / SCALE_FACTOR_NORMAL;
|
||||||
|
|
||||||
v /= int(PHASE_MIDGAME);
|
v /= PHASE_MIDGAME;
|
||||||
|
|
||||||
// In case of tracing add all remaining individual evaluation terms
|
// In case of tracing add all remaining individual evaluation terms
|
||||||
if (T)
|
if (T)
|
||||||
|
|||||||
+3
-3
@@ -93,10 +93,10 @@ namespace {
|
|||||||
// if the pawn is not on the same file as the enemy king, because we
|
// if the pawn is not on the same file as the enemy king, because we
|
||||||
// don't generate captures. Note that a possible discovery check
|
// don't generate captures. Note that a possible discovery check
|
||||||
// promotion has been already generated amongst the captures.
|
// promotion has been already generated amongst the captures.
|
||||||
Bitboard dcCandidates = pos.blockers_for_king(Them);
|
Bitboard dcCandidateQuiets = pos.blockers_for_king(Them) & pawnsNotOn7;
|
||||||
if (pawnsNotOn7 & dcCandidates)
|
if (dcCandidateQuiets)
|
||||||
{
|
{
|
||||||
Bitboard dc1 = shift<Up>(pawnsNotOn7 & dcCandidates) & emptySquares & ~file_bb(ksq);
|
Bitboard dc1 = shift<Up>(dcCandidateQuiets) & emptySquares & ~file_bb(ksq);
|
||||||
Bitboard dc2 = shift<Up>(dc1 & TRank3BB) & emptySquares;
|
Bitboard dc2 = shift<Up>(dc1 & TRank3BB) & emptySquares;
|
||||||
|
|
||||||
b1 |= dc1;
|
b1 |= dc1;
|
||||||
|
|||||||
+4
-4
@@ -76,9 +76,9 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHist
|
|||||||
assert(d <= DEPTH_ZERO);
|
assert(d <= DEPTH_ZERO);
|
||||||
|
|
||||||
stage = pos.checkers() ? EVASION_TT : QSEARCH_TT;
|
stage = pos.checkers() ? EVASION_TT : QSEARCH_TT;
|
||||||
ttMove = ttm
|
ttMove = ttm
|
||||||
&& pos.pseudo_legal(ttm)
|
&& (depth > DEPTH_QS_RECAPTURES || to_sq(ttm) == recaptureSquare)
|
||||||
&& (depth > DEPTH_QS_RECAPTURES || to_sq(ttm) == recaptureSquare) ? ttm : MOVE_NONE;
|
&& pos.pseudo_legal(ttm) ? ttm : MOVE_NONE;
|
||||||
stage += (ttMove == MOVE_NONE);
|
stage += (ttMove == MOVE_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,8 +91,8 @@ MovePicker::MovePicker(const Position& p, Move ttm, Value th, const CapturePiece
|
|||||||
|
|
||||||
stage = PROBCUT_TT;
|
stage = PROBCUT_TT;
|
||||||
ttMove = ttm
|
ttMove = ttm
|
||||||
&& pos.pseudo_legal(ttm)
|
|
||||||
&& pos.capture(ttm)
|
&& pos.capture(ttm)
|
||||||
|
&& pos.pseudo_legal(ttm)
|
||||||
&& pos.see_ge(ttm, threshold) ? ttm : MOVE_NONE;
|
&& pos.see_ge(ttm, threshold) ? ttm : MOVE_NONE;
|
||||||
stage += (ttMove == MOVE_NONE);
|
stage += (ttMove == MOVE_NONE);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -498,14 +498,15 @@ Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners
|
|||||||
Bitboard blockers = 0;
|
Bitboard blockers = 0;
|
||||||
pinners = 0;
|
pinners = 0;
|
||||||
|
|
||||||
// Snipers are sliders that attack 's' when a piece is removed
|
// Snipers are sliders that attack 's' when a piece and other snipers are removed
|
||||||
Bitboard snipers = ( (PseudoAttacks[ ROOK][s] & pieces(QUEEN, ROOK))
|
Bitboard snipers = ( (PseudoAttacks[ ROOK][s] & pieces(QUEEN, ROOK))
|
||||||
| (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders;
|
| (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders;
|
||||||
|
Bitboard occupancy = pieces() & ~snipers;
|
||||||
|
|
||||||
while (snipers)
|
while (snipers)
|
||||||
{
|
{
|
||||||
Square sniperSq = pop_lsb(&snipers);
|
Square sniperSq = pop_lsb(&snipers);
|
||||||
Bitboard b = between_bb(s, sniperSq) & pieces();
|
Bitboard b = between_bb(s, sniperSq) & occupancy;
|
||||||
|
|
||||||
if (b && !more_than_one(b))
|
if (b && !more_than_one(b))
|
||||||
{
|
{
|
||||||
@@ -1076,8 +1077,8 @@ bool Position::see_ge(Move m, Value threshold) const {
|
|||||||
stmAttackers = attackers & pieces(stm);
|
stmAttackers = attackers & pieces(stm);
|
||||||
|
|
||||||
// Don't allow pinned pieces to attack (except the king) as long as
|
// Don't allow pinned pieces to attack (except the king) as long as
|
||||||
// all pinners are on their original square.
|
// any pinners are on their original square.
|
||||||
if (!(st->pinners[~stm] & ~occupied))
|
if (st->pinners[~stm] & occupied)
|
||||||
stmAttackers &= ~st->blockersForKing[stm];
|
stmAttackers &= ~st->blockersForKing[stm];
|
||||||
|
|
||||||
// If stm has no more attackers then give up: stm loses
|
// If stm has no more attackers then give up: stm loses
|
||||||
|
|||||||
+26
-26
@@ -59,46 +59,46 @@ constexpr Score Bonus[][RANK_NB][int(FILE_NB) / 2] = {
|
|||||||
{ S(-48,-51), S( -3,-40), S(-12,-39), S(-25,-20) }
|
{ S(-48,-51), S( -3,-40), S(-12,-39), S(-25,-20) }
|
||||||
},
|
},
|
||||||
{ // Rook
|
{ // Rook
|
||||||
{ S(-24, -2), S(-13,-6), S( -7, -3), S( 2,-2) },
|
{ S(-24, -2), S(-13,-6), S(-7, -3), S( 2,-2) },
|
||||||
{ S(-18,-10), S(-10,-7), S( -5, 1), S( 9, 0) },
|
{ S(-18,-10), S(-10,-7), S(-5, 1), S( 9, 0) },
|
||||||
{ S(-21, 10), S( -7,-4), S( 3, 2), S(-1,-2) },
|
{ S(-21, 10), S( -7,-4), S( 3, 2), S(-1,-2) },
|
||||||
{ S(-13, -5), S( -5, 2), S( -4, -8), S(-6, 8) },
|
{ S(-13, -5), S( -5, 2), S(-4, -8), S(-6, 8) },
|
||||||
{ S(-24, -8), S(-12, 5), S( -1, 4), S( 6,-9) },
|
{ S(-24, -8), S(-12, 5), S(-1, 4), S( 6,-9) },
|
||||||
{ S(-24, 3), S( -4,-2), S( 4,-10), S(10, 7) },
|
{ S(-24, 3), S( -4,-2), S( 4,-10), S(10, 7) },
|
||||||
{ S( -8, 1), S( 6, 2), S( 10, 17), S(12,-8) },
|
{ S( -8, 1), S( 6, 2), S(10, 17), S(12,-8) },
|
||||||
{ S(-22, 12), S(-24,-6), S( -6, 13), S( 4, 7) }
|
{ S(-22, 12), S(-24,-6), S(-6, 13), S( 4, 7) }
|
||||||
},
|
},
|
||||||
{ // Queen
|
{ // Queen
|
||||||
{ S( 3,-69), S(-5,-57), S(-5,-47), S( 4,-26) },
|
{ S( 3,-69), S(-5,-57), S(-5,-47), S( 4,-26) },
|
||||||
{ S( -3,-55), S( 5,-31), S( 8,-22), S(12, -4) },
|
{ S(-3,-55), S( 5,-31), S( 8,-22), S(12, -4) },
|
||||||
{ S( -3,-39), S( 6,-18), S(13, -9), S( 7, 3) },
|
{ S(-3,-39), S( 6,-18), S(13, -9), S( 7, 3) },
|
||||||
{ S( 4,-23), S( 5, -3), S( 9, 13), S( 8, 24) },
|
{ S( 4,-23), S( 5, -3), S( 9, 13), S( 8, 24) },
|
||||||
{ S( 0,-29), S(14, -6), S(12, 9), S( 5, 21) },
|
{ S( 0,-29), S(14, -6), S(12, 9), S( 5, 21) },
|
||||||
{ S( -4,-38), S(10,-18), S( 6,-12), S( 8, 1) },
|
{ S(-4,-38), S(10,-18), S( 6,-12), S( 8, 1) },
|
||||||
{ S( -5,-50), S( 6,-27), S(10,-24), S( 8, -8) },
|
{ S(-5,-50), S( 6,-27), S(10,-24), S( 8, -8) },
|
||||||
{ S( -2,-75), S(-2,-52), S( 1,-43), S(-2,-36) }
|
{ S(-2,-75), S(-2,-52), S( 1,-43), S(-2,-36) }
|
||||||
},
|
},
|
||||||
{ // King
|
{ // King
|
||||||
{ S(272, 0), S(325, 41), S(273, 80), S(190, 93) },
|
{ S(272, 0), S(325, 41), S(273, 80), S(190, 93) },
|
||||||
{ S(277, 57), S(305, 98), S(241,138), S(183,131) },
|
{ S(277, 57), S(305, 98), S(241,138), S(183,131) },
|
||||||
{ S(198, 86), S(253,138), S(168,165), S(120,173) },
|
{ S(198, 86), S(253,138), S(168,165), S(120,173) },
|
||||||
{ S(169,103), S(191,152), S(136,168), S(108,169) },
|
{ S(169,103), S(191,152), S(136,168), S(108,169) },
|
||||||
{ S(145, 98), S(176,166), S(112,197), S(69, 194) },
|
{ S(145, 98), S(176,166), S(112,197), S( 69,194) },
|
||||||
{ S(122, 87), S(159,164), S(85, 174), S(36, 189) },
|
{ S(122, 87), S(159,164), S( 85,174), S( 36,189) },
|
||||||
{ S(87, 40), S(120, 99), S(64, 128), S(25, 141) },
|
{ S( 87, 40), S(120, 99), S( 64,128), S( 25,141) },
|
||||||
{ S(64, 5), S(87, 60), S(49, 75), S(0, 75) }
|
{ S( 64, 5), S( 87, 60), S( 49, 75), S( 0, 75) }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr Score PBonus[RANK_NB][FILE_NB] =
|
constexpr Score PBonus[RANK_NB][FILE_NB] =
|
||||||
{ // Pawn (asymmetric distribution)
|
{ // Pawn (asymmetric distribution)
|
||||||
{ },
|
{ },
|
||||||
{ S( 0,-11), S( -3,-4), S(13, -1), S( 19, -4), S(16, 17), S(13, 7), S( 4, 4), S( -4,-13) },
|
{ S( 0,-10), S( -5,-3), S( 10, 7), S( 13,-1), S( 21, 7), S( 17, 6), S( 6, 1), S( -3,-20) },
|
||||||
{ S(-16, -8), S(-12,-6), S(20, -3), S( 21, 0), S(25,-11), S(29, 3), S( 0, 0), S(-27, -1) },
|
{ S(-11, -6), S(-10,-6), S( 15,-1), S( 22,-1), S( 26, -1), S( 28, 2), S( 4,-2), S(-24, -5) },
|
||||||
{ S(-11, 3), S(-17, 6), S(11,-10), S( 21, 1), S(32, -6), S(19,-11), S( -5, 0), S(-14, -2) },
|
{ S( -9, 4), S(-18,-5), S( 8,-4), S( 22,-5), S( 33, -6), S( 25,-13), S( -4,-3), S(-16, -7) },
|
||||||
{ S( 4, 13), S( 6, 7), S(-8, 3), S( 3, -5), S( 8,-15), S(-2, -1), S(-19, 9), S( -5, 13) },
|
{ S( 6, 18), S( -3, 2), S(-10, 2), S( 1,-9), S( 12,-13), S( 6, -8), S(-12,11), S( 1, 9) },
|
||||||
{ S( -5, 25), S(-19,20), S( 7, 16), S( 8, 12), S(-7, 21), S(-2, 3), S(-10, -4), S(-16, 15) },
|
{ S( -6, 25), S( -8,17), S( 5,19), S( 11,29), S(-14, 29), S( 0, 8), S(-12, 4), S(-14, 12) },
|
||||||
{ S(-10, 6), S( 9,-5), S(-7, 16), S(-12, 27), S(-7, 15), S(-8, 11), S( 16, -7), S( -8, 4) }
|
{ S(-10, -1), S( 6,-6), S( -5,18), S(-11,22), S( -2, 22), S(-14, 17), S( 12, 2), S( -1, 9) }
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef S
|
#undef S
|
||||||
|
|||||||
+30
-49
@@ -230,10 +230,9 @@ void MainThread::search() {
|
|||||||
// Threads.stop. However, if we are pondering or in an infinite search,
|
// Threads.stop. However, if we are pondering or in an infinite search,
|
||||||
// the UCI protocol states that we shouldn't print the best move before the
|
// the UCI protocol states that we shouldn't print the best move before the
|
||||||
// GUI sends a "stop" or "ponderhit" command. We therefore simply wait here
|
// GUI sends a "stop" or "ponderhit" command. We therefore simply wait here
|
||||||
// until the GUI sends one of those commands (which also raises Threads.stop).
|
// until the GUI sends one of those commands.
|
||||||
Threads.stopOnPonderhit = true;
|
|
||||||
|
|
||||||
while (!Threads.stop && (Threads.ponder || Limits.infinite))
|
while (!Threads.stop && (ponder || Limits.infinite))
|
||||||
{ Cluster::signals_poll(); } // Busy wait for a stop or a ponder reset
|
{ Cluster::signals_poll(); } // Busy wait for a stop or a ponder reset
|
||||||
|
|
||||||
// Stop the threads if not already stopped (also raise the stop if
|
// Stop the threads if not already stopped (also raise the stop if
|
||||||
@@ -265,27 +264,23 @@ void MainThread::search() {
|
|||||||
|
|
||||||
// Find out minimum score and reset votes for moves which can be voted
|
// Find out minimum score and reset votes for moves which can be voted
|
||||||
for (Thread* th: Threads)
|
for (Thread* th: Threads)
|
||||||
{
|
|
||||||
minScore = std::min(minScore, th->rootMoves[0].score);
|
minScore = std::min(minScore, th->rootMoves[0].score);
|
||||||
votes[th->rootMoves[0].pv[0]] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vote according to score and depth
|
// Vote according to score and depth
|
||||||
auto square = [](int64_t x) { return x * x; };
|
|
||||||
for (Thread* th : Threads)
|
|
||||||
votes[th->rootMoves[0].pv[0]] += 200 + (square(th->rootMoves[0].score - minScore + 1)
|
|
||||||
* int64_t(th->completedDepth));
|
|
||||||
|
|
||||||
// Select best thread
|
|
||||||
int64_t bestVote = votes[this->rootMoves[0].pv[0]];
|
|
||||||
for (Thread* th : Threads)
|
for (Thread* th : Threads)
|
||||||
{
|
{
|
||||||
|
int64_t s = th->rootMoves[0].score - minScore + 1;
|
||||||
|
votes[th->rootMoves[0].pv[0]] += 200 + s * s * int(th->completedDepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select best thread
|
||||||
|
auto bestVote = votes[this->rootMoves[0].pv[0]];
|
||||||
|
for (Thread* th : Threads)
|
||||||
if (votes[th->rootMoves[0].pv[0]] > bestVote)
|
if (votes[th->rootMoves[0].pv[0]] > bestVote)
|
||||||
{
|
{
|
||||||
bestVote = votes[th->rootMoves[0].pv[0]];
|
bestVote = votes[th->rootMoves[0].pv[0]];
|
||||||
bestThread = th;
|
bestThread = th;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -482,7 +477,7 @@ void Thread::search() {
|
|||||||
{
|
{
|
||||||
failedHighCnt = 0;
|
failedHighCnt = 0;
|
||||||
failedLow = true;
|
failedLow = true;
|
||||||
Threads.stopOnPonderhit = false;
|
mainThread->stopOnPonderhit = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (bestValue >= beta)
|
else if (bestValue >= beta)
|
||||||
@@ -534,16 +529,13 @@ void Thread::search() {
|
|||||||
// Do we have time for the next iteration? Can we stop searching now?
|
// Do we have time for the next iteration? Can we stop searching now?
|
||||||
if ( Limits.use_time_management()
|
if ( Limits.use_time_management()
|
||||||
&& !Threads.stop
|
&& !Threads.stop
|
||||||
&& !Threads.stopOnPonderhit)
|
&& !mainThread->stopOnPonderhit)
|
||||||
{
|
{
|
||||||
double fallingEval = (306 + 119 * failedLow + 6 * (mainThread->previousScore - bestValue)) / 581.0;
|
double fallingEval = (306 + 119 * failedLow + 6 * (mainThread->previousScore - bestValue)) / 581.0;
|
||||||
fallingEval = std::max(0.5, std::min(1.5, fallingEval));
|
fallingEval = std::max(0.5, std::min(1.5, fallingEval));
|
||||||
|
|
||||||
// If the bestMove is stable over several iterations, reduce time accordingly
|
// If the bestMove is stable over several iterations, reduce time accordingly
|
||||||
timeReduction = 1.0;
|
timeReduction = lastBestMoveDepth + 10 * ONE_PLY < completedDepth ? 1.95 : 1.0;
|
||||||
for (int i : {3, 4, 5})
|
|
||||||
if (lastBestMoveDepth * i < completedDepth)
|
|
||||||
timeReduction *= 1.25;
|
|
||||||
|
|
||||||
// Use part of the gained time from a previous stable move for the current move
|
// Use part of the gained time from a previous stable move for the current move
|
||||||
double bestMoveInstability = 1.0 + mainThread->bestMoveChanges;
|
double bestMoveInstability = 1.0 + mainThread->bestMoveChanges;
|
||||||
@@ -555,8 +547,8 @@ void Thread::search() {
|
|||||||
{
|
{
|
||||||
// If we are allowed to ponder do not stop the search now but
|
// If we are allowed to ponder do not stop the search now but
|
||||||
// keep pondering until the GUI sends "ponderhit" or "stop".
|
// keep pondering until the GUI sends "ponderhit" or "stop".
|
||||||
if (Threads.ponder)
|
if (mainThread->ponder)
|
||||||
Threads.stopOnPonderhit = true;
|
mainThread->stopOnPonderhit = true;
|
||||||
else
|
else
|
||||||
Threads.stop = true;
|
Threads.stop = true;
|
||||||
}
|
}
|
||||||
@@ -614,8 +606,8 @@ namespace {
|
|||||||
Move ttMove, move, excludedMove, bestMove;
|
Move ttMove, move, excludedMove, bestMove;
|
||||||
Depth extension, newDepth;
|
Depth extension, newDepth;
|
||||||
Value bestValue, value, ttValue, eval, maxValue, pureStaticEval;
|
Value bestValue, value, ttValue, eval, maxValue, pureStaticEval;
|
||||||
bool ttHit, pvHit, inCheck, givesCheck, improving;
|
bool ttHit, ttPv, inCheck, givesCheck, improving;
|
||||||
bool captureOrPromotion, doFullDepthSearch, moveCountPruning, skipQuiets, ttCapture, pvExact;
|
bool captureOrPromotion, doFullDepthSearch, moveCountPruning, skipQuiets, ttCapture;
|
||||||
Piece movedPiece;
|
Piece movedPiece;
|
||||||
int moveCount, captureCount, quietCount;
|
int moveCount, captureCount, quietCount;
|
||||||
|
|
||||||
@@ -680,7 +672,7 @@ namespace {
|
|||||||
ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
|
ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
|
||||||
ttMove = rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0]
|
ttMove = rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0]
|
||||||
: ttHit ? tte->move() : MOVE_NONE;
|
: ttHit ? tte->move() : MOVE_NONE;
|
||||||
pvHit = ttHit ? tte->pv_hit() : false;
|
ttPv = (ttHit && tte->is_pv()) || (PvNode && depth > 4 * ONE_PLY);
|
||||||
|
|
||||||
// At non-PV nodes we check for an early TT cutoff
|
// At non-PV nodes we check for an early TT cutoff
|
||||||
if ( !PvNode
|
if ( !PvNode
|
||||||
@@ -714,11 +706,6 @@ namespace {
|
|||||||
return ttValue;
|
return ttValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( depth > 6 * ONE_PLY
|
|
||||||
&& !excludedMove
|
|
||||||
&& PvNode)
|
|
||||||
pvHit = true;
|
|
||||||
|
|
||||||
// Step 5. Tablebases probe
|
// Step 5. Tablebases probe
|
||||||
if (!rootNode && TB::Cardinality)
|
if (!rootNode && TB::Cardinality)
|
||||||
{
|
{
|
||||||
@@ -753,7 +740,7 @@ namespace {
|
|||||||
|| (b == BOUND_LOWER ? value >= beta : value <= alpha))
|
|| (b == BOUND_LOWER ? value >= beta : value <= alpha))
|
||||||
{
|
{
|
||||||
Cluster::save(thisThread, tte,
|
Cluster::save(thisThread, tte,
|
||||||
posKey, value_to_tt(value, ss->ply), pvHit, b,
|
posKey, value_to_tt(value, ss->ply), ttPv, b,
|
||||||
std::min(DEPTH_MAX - ONE_PLY, depth + 6 * ONE_PLY),
|
std::min(DEPTH_MAX - ONE_PLY, depth + 6 * ONE_PLY),
|
||||||
MOVE_NONE, VALUE_NONE);
|
MOVE_NONE, VALUE_NONE);
|
||||||
|
|
||||||
@@ -794,9 +781,7 @@ namespace {
|
|||||||
{
|
{
|
||||||
if ((ss-1)->currentMove != MOVE_NULL)
|
if ((ss-1)->currentMove != MOVE_NULL)
|
||||||
{
|
{
|
||||||
int p = (ss-1)->statScore;
|
int bonus = -(ss-1)->statScore / 512;
|
||||||
int bonus = p > 0 ? (-p - 2500) / 512 :
|
|
||||||
p < 0 ? (-p + 2500) / 512 : 0;
|
|
||||||
|
|
||||||
pureStaticEval = evaluate(pos);
|
pureStaticEval = evaluate(pos);
|
||||||
ss->staticEval = eval = pureStaticEval + bonus;
|
ss->staticEval = eval = pureStaticEval + bonus;
|
||||||
@@ -805,7 +790,7 @@ namespace {
|
|||||||
ss->staticEval = eval = pureStaticEval = -(ss-1)->staticEval + 2 * Eval::Tempo;
|
ss->staticEval = eval = pureStaticEval = -(ss-1)->staticEval + 2 * Eval::Tempo;
|
||||||
|
|
||||||
Cluster::save(thisThread, tte,
|
Cluster::save(thisThread, tte,
|
||||||
posKey, VALUE_NONE, pvHit, BOUND_NONE, DEPTH_NONE, MOVE_NONE,
|
posKey, VALUE_NONE, ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE,
|
||||||
pureStaticEval);
|
pureStaticEval);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -921,7 +906,6 @@ namespace {
|
|||||||
tte = TT.probe(posKey, ttHit);
|
tte = TT.probe(posKey, ttHit);
|
||||||
ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
|
ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
|
||||||
ttMove = ttHit ? tte->move() : MOVE_NONE;
|
ttMove = ttHit ? tte->move() : MOVE_NONE;
|
||||||
pvHit = ttHit ? tte->pv_hit() : false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
moves_loop: // When in check, search starts from here
|
moves_loop: // When in check, search starts from here
|
||||||
@@ -938,7 +922,6 @@ moves_loop: // When in check, search starts from here
|
|||||||
|
|
||||||
skipQuiets = false;
|
skipQuiets = false;
|
||||||
ttCapture = ttMove && pos.capture_or_promotion(ttMove);
|
ttCapture = ttMove && pos.capture_or_promotion(ttMove);
|
||||||
pvExact = PvNode && ttHit && tte->bound() == BOUND_EXACT;
|
|
||||||
|
|
||||||
// Step 12. Loop through all pseudo-legal moves until no moves remain
|
// Step 12. Loop through all pseudo-legal moves until no moves remain
|
||||||
// or a beta cutoff occurs.
|
// or a beta cutoff occurs.
|
||||||
@@ -1006,11 +989,13 @@ moves_loop: // When in check, search starts from here
|
|||||||
else if (cutNode && singularBeta > beta)
|
else if (cutNode && singularBeta > beta)
|
||||||
return beta;
|
return beta;
|
||||||
}
|
}
|
||||||
else if ( givesCheck // Check extension (~2 Elo)
|
|
||||||
&& pos.see_ge(move))
|
// Check extension (~2 Elo)
|
||||||
|
else if ( givesCheck
|
||||||
|
&& (pos.blockers_for_king(~us) & from_sq(move) || pos.see_ge(move)))
|
||||||
extension = ONE_PLY;
|
extension = ONE_PLY;
|
||||||
|
|
||||||
// Extension if castling
|
// Castling extension
|
||||||
else if (type_of(move) == CASTLING)
|
else if (type_of(move) == CASTLING)
|
||||||
extension = ONE_PLY;
|
extension = ONE_PLY;
|
||||||
|
|
||||||
@@ -1083,7 +1068,7 @@ moves_loop: // When in check, search starts from here
|
|||||||
Depth r = reduction<PvNode>(improving, depth, moveCount);
|
Depth r = reduction<PvNode>(improving, depth, moveCount);
|
||||||
|
|
||||||
// Decrease reduction if position is or has been on the PV
|
// Decrease reduction if position is or has been on the PV
|
||||||
if (pvHit && !PvNode)
|
if (ttPv)
|
||||||
r -= ONE_PLY;
|
r -= ONE_PLY;
|
||||||
|
|
||||||
// Decrease reduction if opponent's move count is high (~10 Elo)
|
// Decrease reduction if opponent's move count is high (~10 Elo)
|
||||||
@@ -1092,10 +1077,6 @@ moves_loop: // When in check, search starts from here
|
|||||||
|
|
||||||
if (!captureOrPromotion)
|
if (!captureOrPromotion)
|
||||||
{
|
{
|
||||||
// Decrease reduction for exact PV nodes (~0 Elo)
|
|
||||||
if (pvExact)
|
|
||||||
r -= ONE_PLY;
|
|
||||||
|
|
||||||
// Increase reduction if ttMove is a capture (~0 Elo)
|
// Increase reduction if ttMove is a capture (~0 Elo)
|
||||||
if (ttCapture)
|
if (ttCapture)
|
||||||
r += ONE_PLY;
|
r += ONE_PLY;
|
||||||
@@ -1269,7 +1250,7 @@ moves_loop: // When in check, search starts from here
|
|||||||
|
|
||||||
if (!excludedMove)
|
if (!excludedMove)
|
||||||
Cluster::save(thisThread, tte,
|
Cluster::save(thisThread, tte,
|
||||||
posKey, value_to_tt(bestValue, ss->ply), pvHit,
|
posKey, value_to_tt(bestValue, ss->ply), ttPv,
|
||||||
bestValue >= beta ? BOUND_LOWER :
|
bestValue >= beta ? BOUND_LOWER :
|
||||||
PvNode && bestMove ? BOUND_EXACT : BOUND_UPPER,
|
PvNode && bestMove ? BOUND_EXACT : BOUND_UPPER,
|
||||||
depth, bestMove, pureStaticEval);
|
depth, bestMove, pureStaticEval);
|
||||||
@@ -1333,7 +1314,7 @@ moves_loop: // When in check, search starts from here
|
|||||||
tte = TT.probe(posKey, ttHit);
|
tte = TT.probe(posKey, ttHit);
|
||||||
ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
|
ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
|
||||||
ttMove = ttHit ? tte->move() : MOVE_NONE;
|
ttMove = ttHit ? tte->move() : MOVE_NONE;
|
||||||
pvHit = ttHit ? tte->pv_hit() : false;
|
pvHit = ttHit && tte->is_pv();
|
||||||
|
|
||||||
if ( !PvNode
|
if ( !PvNode
|
||||||
&& ttHit
|
&& ttHit
|
||||||
@@ -1654,10 +1635,10 @@ void MainThread::check_time() {
|
|||||||
Cluster::signals_poll();
|
Cluster::signals_poll();
|
||||||
|
|
||||||
// We should not stop pondering until told so by the GUI
|
// We should not stop pondering until told so by the GUI
|
||||||
if (Threads.ponder)
|
if (ponder)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( (Limits.use_time_management() && elapsed > Time.maximum() - 10)
|
if ( (Limits.use_time_management() && (elapsed > Time.maximum() - 10 || stopOnPonderhit))
|
||||||
|| (Limits.movetime && elapsed >= Limits.movetime)
|
|| (Limits.movetime && elapsed >= Limits.movetime)
|
||||||
|| (Limits.nodes && Cluster::nodes_searched() >= (uint64_t)Limits.nodes))
|
|| (Limits.nodes && Cluster::nodes_searched() >= (uint64_t)Limits.nodes))
|
||||||
Threads.stop = true;
|
Threads.stop = true;
|
||||||
|
|||||||
+2
-3
@@ -165,9 +165,8 @@ void ThreadPool::start_thinking(Position& pos, StateListPtr& states,
|
|||||||
|
|
||||||
main()->wait_for_search_finished();
|
main()->wait_for_search_finished();
|
||||||
|
|
||||||
stopOnPonderhit = stop = false;
|
main()->stopOnPonderhit = stop = false;
|
||||||
|
main()->ponder = ponderMode;
|
||||||
ponder = ponderMode;
|
|
||||||
Search::Limits = limits;
|
Search::Limits = limits;
|
||||||
Search::RootMoves rootMoves;
|
Search::RootMoves rootMoves;
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -96,6 +96,8 @@ struct MainThread : public Thread {
|
|||||||
double bestMoveChanges, previousTimeReduction;
|
double bestMoveChanges, previousTimeReduction;
|
||||||
Value previousScore;
|
Value previousScore;
|
||||||
int callsCnt;
|
int callsCnt;
|
||||||
|
bool stopOnPonderhit;
|
||||||
|
std::atomic_bool ponder;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -114,7 +116,7 @@ struct ThreadPool : public std::vector<Thread*> {
|
|||||||
uint64_t tb_hits() const { return accumulate(&Thread::tbHits); }
|
uint64_t tb_hits() const { return accumulate(&Thread::tbHits); }
|
||||||
uint64_t TT_saves() const { return accumulate(&Thread::TTsaves); }
|
uint64_t TT_saves() const { return accumulate(&Thread::TTsaves); }
|
||||||
|
|
||||||
std::atomic_bool stop, ponder, stopOnPonderhit;
|
std::atomic_bool stop;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StateListPtr setupStates;
|
StateListPtr setupStates;
|
||||||
|
|||||||
+9
-7
@@ -30,8 +30,10 @@
|
|||||||
|
|
||||||
TranspositionTable TT; // Our global transposition table
|
TranspositionTable TT; // Our global transposition table
|
||||||
|
|
||||||
/// TTEntry::save saves a TTEntry
|
/// TTEntry::save populates the TTEntry with a new node's data, possibly
|
||||||
void TTEntry::save(Key k, Value v, bool PvNode, Bound b, Depth d, Move m, Value ev) {
|
/// overwriting an old position. Update is not atomic and can be racy.
|
||||||
|
|
||||||
|
void TTEntry::save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev) {
|
||||||
|
|
||||||
assert(d / ONE_PLY * ONE_PLY == d);
|
assert(d / ONE_PLY * ONE_PLY == d);
|
||||||
|
|
||||||
@@ -47,7 +49,7 @@ void TTEntry::save(Key k, Value v, bool PvNode, Bound b, Depth d, Move m, Value
|
|||||||
key16 = (uint16_t)(k >> 48);
|
key16 = (uint16_t)(k >> 48);
|
||||||
value16 = (int16_t)v;
|
value16 = (int16_t)v;
|
||||||
eval16 = (int16_t)ev;
|
eval16 = (int16_t)ev;
|
||||||
genBound8 = (uint8_t)(TT.generation8 | PvNode << 2 | b);
|
genBound8 = (uint8_t)(TT.generation8 | uint8_t(pv) << 2 | b);
|
||||||
depth8 = (int8_t)(d / ONE_PLY);
|
depth8 = (int8_t)(d / ONE_PLY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,7 +124,7 @@ TTEntry* TranspositionTable::probe(const Key key, bool& found) const {
|
|||||||
for (int i = 0; i < ClusterSize; ++i)
|
for (int i = 0; i < ClusterSize; ++i)
|
||||||
if (!tte[i].key16 || tte[i].key16 == key16)
|
if (!tte[i].key16 || tte[i].key16 == key16)
|
||||||
{
|
{
|
||||||
tte[i].genBound8 = uint8_t(generation8 | tte[i].pv_hit() << 2 | tte[i].bound()); // Refresh
|
tte[i].genBound8 = uint8_t(generation8 | (tte[i].genBound8 & 0x7)); // Refresh
|
||||||
|
|
||||||
return found = (bool)tte[i].key16, &tte[i];
|
return found = (bool)tte[i].key16, &tte[i];
|
||||||
}
|
}
|
||||||
@@ -131,8 +133,8 @@ TTEntry* TranspositionTable::probe(const Key key, bool& found) const {
|
|||||||
TTEntry* replace = tte;
|
TTEntry* replace = tte;
|
||||||
for (int i = 1; i < ClusterSize; ++i)
|
for (int i = 1; i < ClusterSize; ++i)
|
||||||
// Due to our packed storage format for generation and its cyclic
|
// Due to our packed storage format for generation and its cyclic
|
||||||
// nature we add 263 (263 is the modulus plus 7 to keep the lowest
|
// nature we add 263 (256 is the modulus plus 7 to keep the unrelated
|
||||||
// two bound bits from affecting the result) to calculate the entry
|
// lowest three bits from affecting the result) to calculate the entry
|
||||||
// age correctly even after generation8 overflows into the next cycle.
|
// age correctly even after generation8 overflows into the next cycle.
|
||||||
if ( replace->depth8 - ((263 + generation8 - replace->genBound8) & 0xF8)
|
if ( replace->depth8 - ((263 + generation8 - replace->genBound8) & 0xF8)
|
||||||
> tte[i].depth8 - ((263 + generation8 - tte[i].genBound8) & 0xF8))
|
> tte[i].depth8 - ((263 + generation8 - tte[i].genBound8) & 0xF8))
|
||||||
@@ -150,7 +152,7 @@ int TranspositionTable::hashfull() const {
|
|||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
for (int i = 0; i < 1000 / ClusterSize; ++i)
|
for (int i = 0; i < 1000 / ClusterSize; ++i)
|
||||||
for (int j = 0; j < ClusterSize; ++j)
|
for (int j = 0; j < ClusterSize; ++j)
|
||||||
cnt += (table[i].entry[j].genBound8 & 0xFC) == generation8;
|
cnt += (table[i].entry[j].genBound8 & 0xF8) == generation8;
|
||||||
|
|
||||||
return cnt * 1000 / (ClusterSize * (1000 / ClusterSize));
|
return cnt * 1000 / (ClusterSize * (1000 / ClusterSize));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace Cluster {
|
|||||||
/// value 16 bit
|
/// value 16 bit
|
||||||
/// eval value 16 bit
|
/// eval value 16 bit
|
||||||
/// generation 5 bit
|
/// generation 5 bit
|
||||||
/// PvNode 1 bit
|
/// pv node 1 bit
|
||||||
/// bound type 2 bit
|
/// bound type 2 bit
|
||||||
/// depth 8 bit
|
/// depth 8 bit
|
||||||
|
|
||||||
@@ -46,9 +46,9 @@ struct TTEntry {
|
|||||||
Value value() const { return (Value)value16; }
|
Value value() const { return (Value)value16; }
|
||||||
Value eval() const { return (Value)eval16; }
|
Value eval() const { return (Value)eval16; }
|
||||||
Depth depth() const { return (Depth)(depth8 * int(ONE_PLY)); }
|
Depth depth() const { return (Depth)(depth8 * int(ONE_PLY)); }
|
||||||
bool pv_hit() const { return (bool)(genBound8 & 0x4); }
|
bool is_pv() const { return (bool)(genBound8 & 0x4); }
|
||||||
Bound bound() const { return (Bound)(genBound8 & 0x3); }
|
Bound bound() const { return (Bound)(genBound8 & 0x3); }
|
||||||
void save(Key k, Value v, bool PvNode, Bound b, Depth d, Move m, Value ev);
|
void save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class TranspositionTable;
|
friend class TranspositionTable;
|
||||||
|
|||||||
+3
-1
@@ -141,9 +141,11 @@ enum CastlingRight {
|
|||||||
WHITE_OOO = WHITE_OO << 1,
|
WHITE_OOO = WHITE_OO << 1,
|
||||||
BLACK_OO = WHITE_OO << 2,
|
BLACK_OO = WHITE_OO << 2,
|
||||||
BLACK_OOO = WHITE_OO << 3,
|
BLACK_OOO = WHITE_OO << 3,
|
||||||
|
|
||||||
WHITE_CASTLING = WHITE_OO | WHITE_OOO,
|
WHITE_CASTLING = WHITE_OO | WHITE_OOO,
|
||||||
BLACK_CASTLING = BLACK_OO | BLACK_OOO,
|
BLACK_CASTLING = BLACK_OO | BLACK_OOO,
|
||||||
ANY_CASTLING = WHITE_CASTLING | BLACK_CASTLING,
|
ANY_CASTLING = WHITE_CASTLING | BLACK_CASTLING,
|
||||||
|
|
||||||
CASTLING_RIGHT_NB = 16
|
CASTLING_RIGHT_NB = 16
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+6
-8
@@ -210,18 +210,16 @@ void UCI::loop(int argc, char* argv[]) {
|
|||||||
token.clear(); // Avoid a stale if getline() returns empty or blank line
|
token.clear(); // Avoid a stale if getline() returns empty or blank line
|
||||||
is >> skipws >> token;
|
is >> skipws >> token;
|
||||||
|
|
||||||
|
if ( token == "quit"
|
||||||
|
|| token == "stop")
|
||||||
|
Threads.stop = true;
|
||||||
|
|
||||||
// The GUI sends 'ponderhit' to tell us the user has played the expected move.
|
// The GUI sends 'ponderhit' to tell us the user has played the expected move.
|
||||||
// So 'ponderhit' will be sent if we were told to ponder on the same move the
|
// So 'ponderhit' will be sent if we were told to ponder on the same move the
|
||||||
// user has played. We should continue searching but switch from pondering to
|
// user has played. We should continue searching but switch from pondering to
|
||||||
// normal search. In case Threads.stopOnPonderhit is set we are waiting for
|
// normal search.
|
||||||
// 'ponderhit' to stop the search, for instance if max search depth is reached.
|
|
||||||
if ( token == "quit"
|
|
||||||
|| token == "stop"
|
|
||||||
|| (token == "ponderhit" && Threads.stopOnPonderhit))
|
|
||||||
Threads.stop = true;
|
|
||||||
|
|
||||||
else if (token == "ponderhit")
|
else if (token == "ponderhit")
|
||||||
Threads.ponder = false; // Switch to normal search
|
Threads.main()->ponder = false; // Switch to normal search
|
||||||
|
|
||||||
else if (token == "uci" && Cluster::is_root())
|
else if (token == "uci" && Cluster::is_root())
|
||||||
sync_cout << "id name " << engine_info(true)
|
sync_cout << "id name " << engine_info(true)
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ race:TTEntry::bound
|
|||||||
race:TTEntry::save
|
race:TTEntry::save
|
||||||
race:TTEntry::value
|
race:TTEntry::value
|
||||||
race:TTEntry::eval
|
race:TTEntry::eval
|
||||||
race:TTEntry::pv_hit
|
race:TTEntry::is_pv
|
||||||
|
|
||||||
race:TranspositionTable::probe
|
race:TranspositionTable::probe
|
||||||
race:TranspositionTable::hashfull
|
race:TranspositionTable::hashfull
|
||||||
|
|||||||
Reference in New Issue
Block a user