// kingRing[color] is the zone around the king which is considered
// by the king safety evaluation. This consists of the squares directly
- // adjacent to the king, and the three (or two, for a king on an edge file)
+ // adjacent to the king, and (only for a king on its first rank) the
// squares two ranks in front of the king. For instance, if black's king
// is on g8, kingRing[BLACK] is a bitboard containing the squares f8, h8,
// f7, g7, h7, f6, g6 and h6.
{ S(-48,-59), S(-20,-23), S( 16, -3), S( 26, 13), S( 38, 24), S( 51, 42), // Bishops
S( 55, 54), S( 63, 57), S( 63, 65), S( 68, 73), S( 81, 78), S( 81, 86),
S( 91, 88), S( 98, 97) },
- { S(-60,-77), S(-26,-20), S(-11, 27), S( -6, 57), S( -3, 69), S( -1, 82), // Rooks
- S( 10,109), S( 16,121), S( 24,131), S( 25,143), S( 32,155), S( 32,163),
- S( 43,167), S( 48,171), S( 56,173) },
+ { S(-58,-76), S(-27,-18), S(-15, 28), S(-10, 55), S( -5, 69), S( -2, 82), // Rooks
+ S( 9,112), S( 16,118), S( 30,132), S( 29,142), S( 32,155), S( 38,165),
+ S( 46,166), S( 48,169), S( 58,171) },
{ S(-39,-36), S(-21,-15), S( 3, 8), S( 3, 18), S( 14, 34), S( 22, 54), // Queens
S( 28, 61), S( 41, 73), S( 43, 79), S( 48, 92), S( 56, 94), S( 60,104),
S( 60,113), S( 66,120), S( 67,123), S( 70,126), S( 71,133), S( 73,136),
S(-20,-12), S( 1, -8), S( 2, 10), S( 9, 10)
};
- // Protector[PieceType-2][distance] contains a protecting bonus for our king,
- // indexed by piece type and distance between the piece and the king.
- const Score Protector[][8] = {
- { S(0, 0), S( 7, 9), S( 7, 1), S( 1, 5), S(-10,-4), S( -1,-4), S( -7,-3), S(-16,-10) }, // Knight
- { S(0, 0), S(11, 8), S(-7,-1), S(-1,-2), S( -1,-7), S(-11,-3), S( -9,-1), S(-16, -1) }, // Bishop
- { S(0, 0), S(10, 0), S(-2, 2), S(-5, 4), S( -6, 2), S(-14,-3), S( -2,-9), S(-12, -7) }, // Rook
- { S(0, 0), S( 3,-5), S( 2,-5), S(-4, 0), S( -9,-6), S( -4, 7), S(-13,-7), S(-10, -7) } // Queen
- };
+ // KingProtector[PieceType-2] contains a bonus according to distance from king
+ const Score KingProtector[] = { S(-3, -5), S(-4, -3), S(-3, 0), S(-1, 1) };
// Assorted bonuses and penalties used by evaluation
const Score MinorBehindPawn = S( 16, 0);
const int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 78, 56, 45, 11 };
// Penalties for enemy's safe checks
- const int QueenCheck = 810;
- const int RookCheck = 888;
- const int BishopCheck = 400;
+ const int QueenCheck = 780;
+ const int RookCheck = 880;
+ const int BishopCheck = 435;
const int KnightCheck = 790;
// Threshold for lazy and space evaluation
ei.attackedBy[Us][ALL_PIECES] = b | ei.attackedBy[Us][PAWN];
// Init our king safety tables only if we are going to use them
- if (pos.non_pawn_material(Them) >= QueenValueMg)
+ if (pos.non_pawn_material(Them) >= RookValueMg + KnightValueMg)
{
- ei.kingRing[Us] = b | shift<Up>(b);
+ ei.kingRing[Us] = b;
+ if (relative_rank(Us, pos.square<KING>(Us)) == RANK_1)
+ ei.kingRing[Us] |= shift<Up>(b);
+
ei.kingAttackersCount[Them] = popcount(b & ei.pe->pawn_attacks(Them));
ei.kingAdjacentZoneAttacksCount[Them] = ei.kingAttackersWeight[Them] = 0;
}
int mob = popcount(b & ei.mobilityArea[Us]);
- mobility[Us] += MobilityBonus[Pt-2][mob];
+ mobility[Us] += MobilityBonus[Pt - 2][mob];
// Bonus for this piece as a king protector
- score += Protector[Pt-2][distance(s, pos.square<KING>(Us))];
+ score += KingProtector[Pt - 2] * distance(s, pos.square<KING>(Us));
if (Pt == BISHOP || Pt == KNIGHT)
{
Score score = ei.pe->king_safety<Us>(pos, ksq);
// Main king safety evaluation
- if (ei.kingAttackersCount[Them])
+ if (ei.kingAttackersCount[Them] > (1 - pos.count<QUEEN>(Them)))
{
// Find the attacked squares which are defended only by our king...
undefended = ei.attackedBy[Them][ALL_PIECES]
// attacked and undefended squares around our king and the quality of
// the pawn shelter (current 'score' value).
kingDanger = ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them]
- + 103 * ei.kingAdjacentZoneAttacksCount[Them]
- + 190 * popcount(undefended)
- + 142 * (popcount(b) + !!pos.pinned_pieces(Us))
- - 810 * !pos.count<QUEEN>(Them)
- - 6 * mg_value(score) / 5 - 5;
+ + 102 * ei.kingAdjacentZoneAttacksCount[Them]
+ + 201 * popcount(undefended)
+ + 143 * (popcount(b) + !!pos.pinned_pieces(Us))
+ - 848 * !pos.count<QUEEN>(Them)
+ - 9 * mg_value(score) / 8
+ + 40;
// Analyse the safe enemy's checks which are possible on next move
safe = ~pos.pieces(Them);
// Transform the kingDanger units into a Score, and substract it from the evaluation
if (kingDanger > 0)
- score -= make_score(kingDanger * kingDanger / 4096, 0);
+ score -= make_score(kingDanger * kingDanger / 4096, kingDanger / 16);
}
// King tropism: firstly, find squares that opponent attacks in our king flank
{
Square s = pop_lsb(&b);
- assert(!(pos.pieces(PAWN) & forward_bb(Us, s)));
+ assert(!(pos.pieces(Them, PAWN) & forward_bb(Us, s + pawn_push(Us))));
bb = forward_bb(Us, s) & (ei.attackedBy[Them][ALL_PIECES] | pos.pieces(Them));
score -= HinderPassedPawn * popcount(bb);
} // rr != 0
// Scale down bonus for candidate passers which need more than one
- // pawn push to become passed.
- if (!pos.pawn_passed(Us, s + pawn_push(Us)))
+ // pawn push to become passed or have a pawn in front of them.
+ if (!pos.pawn_passed(Us, s + pawn_push(Us)) || (pos.pieces(PAWN) & forward_bb(Us, s)))
mbonus /= 2, ebonus /= 2;
score += make_score(mbonus, ebonus) + PassedFile[file_of(s)];
<< " Imbalance | " << Term(IMBALANCE)
<< " Pawns | " << Term(PAWN)
<< " Knights | " << Term(KNIGHT)
- << " Bishop | " << Term(BISHOP)
+ << " Bishops | " << Term(BISHOP)
<< " Rooks | " << Term(ROOK)
<< " Queens | " << Term(QUEEN)
<< " Mobility | " << Term(MOBILITY)