Rescales the king danger variables in evaluate_king() to
suppress the KingDanger[] array. This avoids the cost of
the memory accesses to the array and simplifies the non-linear
transformation used.
Full credits to "hxim" for the seminal idea and implementation,
see pull request #786.
https://github.com/official-stockfish/Stockfish/pull/786
Passed STC:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 9649 W: 1829 L: 1689 D: 6131
Passed LTC:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 53494 W: 7254 L: 7178 D: 39062
Bench:
6116200
- // King danger constants and variables. The king danger scores are looked-up
- // in KingDanger[]. Various little "meta-bonuses" measuring the strength
- // of the enemy attack are added up into an integer, which is used as an
- // index to KingDanger[].
- Score KingDanger[400];
-
// KingAttackWeights[PieceType] contains king attack weights by piece type
// KingAttackWeights[PieceType] contains king attack weights by piece type
- const int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 7, 5, 4, 1 };
+ const int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 78, 56, 45, 11 };
// Penalties for enemy's safe checks
// Penalties for enemy's safe checks
- const int QueenContactCheck = 89;
- const int QueenCheck = 62;
- const int RookCheck = 57;
- const int BishopCheck = 48;
- const int KnightCheck = 78;
+ const int QueenContactCheck = 997;
+ const int QueenCheck = 695;
+ const int RookCheck = 638;
+ const int BishopCheck = 538;
+ const int KnightCheck = 874;
// eval_init() initializes king and attack bitboards for a given color
// eval_init() initializes king and attack bitboards for a given color
const Square Up = (Us == WHITE ? DELTA_N : DELTA_S);
Bitboard undefended, b, b1, b2, safe, other;
const Square Up = (Us == WHITE ? DELTA_N : DELTA_S);
Bitboard undefended, b, b1, b2, safe, other;
const Square ksq = pos.square<KING>(Us);
// King shelter and enemy pawns storm
const Square ksq = pos.square<KING>(Us);
// King shelter and enemy pawns storm
b = ei.attackedBy[Them][ALL_PIECES] & ~ei.attackedBy[Us][ALL_PIECES]
& ei.kingRing[Us] & ~pos.pieces(Them);
b = ei.attackedBy[Them][ALL_PIECES] & ~ei.attackedBy[Us][ALL_PIECES]
& ei.kingRing[Us] & ~pos.pieces(Them);
- // Initialize the 'attackUnits' variable, which is used later on as an
- // index into the KingDanger[] array. The initial value is based on the
+ // Initialize the 'kingDanger' variable, which will be transformed
+ // later into a king danger score. The initial value is based on the
// number and types of the enemy's attacking pieces, the number of
// attacked and undefended squares around our king and the quality of
// the pawn shelter (current 'score' value).
// number and types of the enemy's attacking pieces, the number of
// attacked and undefended squares around our king and the quality of
// the pawn shelter (current 'score' value).
- attackUnits = std::min(72, ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them])
- + 9 * ei.kingAdjacentZoneAttacksCount[Them]
- + 21 * popcount(undefended)
- + 12 * (popcount(b) + !!ei.pinnedPieces[Us])
- - 64 * !pos.count<QUEEN>(Them)
- - mg_value(score) / 8;
+ kingDanger = std::min(807, ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them])
+ + 101 * ei.kingAdjacentZoneAttacksCount[Them]
+ + 235 * popcount(undefended)
+ + 134 * (popcount(b) + !!ei.pinnedPieces[Us])
+ - 717 * !pos.count<QUEEN>(Them)
+ - 7 * mg_value(score) / 5 - 5;
// Analyse the enemy's safe queen contact checks. Firstly, find the
// undefended squares around the king reachable by the enemy queen...
b = undefended & ei.attackedBy[Them][QUEEN] & ~pos.pieces(Them);
// ...and keep squares supported by another enemy piece
// Analyse the enemy's safe queen contact checks. Firstly, find the
// undefended squares around the king reachable by the enemy queen...
b = undefended & ei.attackedBy[Them][QUEEN] & ~pos.pieces(Them);
// ...and keep squares supported by another enemy piece
- attackUnits += QueenContactCheck * popcount(b & ei.attackedBy2[Them]);
+ kingDanger += QueenContactCheck * popcount(b & ei.attackedBy2[Them]);
// Analyse the safe enemy's checks which are possible on next move...
safe = ~(ei.attackedBy[Us][ALL_PIECES] | pos.pieces(Them));
// Analyse the safe enemy's checks which are possible on next move...
safe = ~(ei.attackedBy[Us][ALL_PIECES] | pos.pieces(Them));
// Enemy queen safe checks
if ((b1 | b2) & ei.attackedBy[Them][QUEEN] & safe)
// Enemy queen safe checks
if ((b1 | b2) & ei.attackedBy[Them][QUEEN] & safe)
- attackUnits += QueenCheck, score -= SafeCheck;
+ kingDanger += QueenCheck, score -= SafeCheck;
// For other pieces, also consider the square safe if attacked twice,
// and only defended by a queen.
// For other pieces, also consider the square safe if attacked twice,
// and only defended by a queen.
// Enemy rooks safe and other checks
if (b1 & ei.attackedBy[Them][ROOK] & safe)
// Enemy rooks safe and other checks
if (b1 & ei.attackedBy[Them][ROOK] & safe)
- attackUnits += RookCheck, score -= SafeCheck;
+ kingDanger += RookCheck, score -= SafeCheck;
else if (b1 & ei.attackedBy[Them][ROOK] & other)
score -= OtherCheck;
// Enemy bishops safe and other checks
if (b2 & ei.attackedBy[Them][BISHOP] & safe)
else if (b1 & ei.attackedBy[Them][ROOK] & other)
score -= OtherCheck;
// Enemy bishops safe and other checks
if (b2 & ei.attackedBy[Them][BISHOP] & safe)
- attackUnits += BishopCheck, score -= SafeCheck;
+ kingDanger += BishopCheck, score -= SafeCheck;
else if (b2 & ei.attackedBy[Them][BISHOP] & other)
score -= OtherCheck;
else if (b2 & ei.attackedBy[Them][BISHOP] & other)
score -= OtherCheck;
// Enemy knights safe and other checks
b = pos.attacks_from<KNIGHT>(ksq) & ei.attackedBy[Them][KNIGHT];
if (b & safe)
// Enemy knights safe and other checks
b = pos.attacks_from<KNIGHT>(ksq) & ei.attackedBy[Them][KNIGHT];
if (b & safe)
- attackUnits += KnightCheck, score -= SafeCheck;
+ kingDanger += KnightCheck, score -= SafeCheck;
else if (b & other)
score -= OtherCheck;
else if (b & other)
score -= OtherCheck;
- // Finally, extract the king danger score from the KingDanger[]
- // array and subtract the score from the evaluation.
- score -= KingDanger[std::max(std::min(attackUnits, 399), 0)];
+ // Compute the king danger score and subtract it from the evaluation
+ if (kingDanger > 0)
+ score -= make_score(std::min(kingDanger * kingDanger / 4096, 2 * int(BishopValueMg)), 0);
}
// King tropism: firstly, find squares that opponent attacks in our king flank
}
// King tropism: firstly, find squares that opponent attacks in our king flank
-
-
-/// init() computes evaluation weights, usually at startup
-
-void Eval::init() {
-
- const int MaxSlope = 322;
- const int Peak = 47410;
- int t = 0;
-
- for (int i = 0; i < 400; ++i)
- {
- t = std::min(Peak, std::min(i * i - 16, t + MaxSlope));
- KingDanger[i] = make_score(t * 268 / 7700, 0);
- }
-}
const Value Tempo = Value(20); // Must be visible to search
const Value Tempo = Value(20); // Must be visible to search
std::string trace(const Position& pos);
template<bool DoTrace = false>
std::string trace(const Position& pos);
template<bool DoTrace = false>
#include <iostream>
#include "bitboard.h"
#include <iostream>
#include "bitboard.h"
#include "position.h"
#include "search.h"
#include "thread.h"
#include "position.h"
#include "search.h"
#include "thread.h"
Position::init();
Bitbases::init();
Search::init();
Position::init();
Bitbases::init();
Search::init();
Pawns::init();
Threads.init();
Tablebases::init(Options["SyzygyPath"]);
Pawns::init();
Threads.init();
Tablebases::init(Options["SyzygyPath"]);
// Step 13. Pruning at shallow depth
if ( !rootNode
// Step 13. Pruning at shallow depth
if ( !rootNode
- && !inCheck
- && bestValue > VALUE_MATED_IN_MAX_PLY)
+ && !inCheck
+ && bestValue > VALUE_MATED_IN_MAX_PLY)
{
if ( !captureOrPromotion
&& !givesCheck
{
if ( !captureOrPromotion
&& !givesCheck