mirror of
https://github.com/sockspls/badfish
synced 2025-05-01 09:13:08 +00:00
Space inflate evaluate_king()
This is the most complex piece of software so far. Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
parent
2e3faae067
commit
b00abed181
1 changed files with 118 additions and 86 deletions
204
src/evaluate.cpp
204
src/evaluate.cpp
|
@ -697,6 +697,10 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Bitboard shiftRowsDown(const Bitboard& b, int num) {
|
||||||
|
|
||||||
|
return b >> (num << 3);
|
||||||
|
}
|
||||||
|
|
||||||
// evaluate_king() assigns bonuses and penalties to a king of a given
|
// evaluate_king() assigns bonuses and penalties to a king of a given
|
||||||
// color on a given square.
|
// color on a given square.
|
||||||
|
@ -705,32 +709,37 @@ namespace {
|
||||||
|
|
||||||
int shelter = 0, sign = Sign[us];
|
int shelter = 0, sign = Sign[us];
|
||||||
|
|
||||||
// King shelter.
|
// King shelter
|
||||||
if(relative_rank(us, s) <= RANK_4) {
|
if (relative_rank(us, s) <= RANK_4)
|
||||||
Bitboard pawns = p.pawns(us) & this_and_neighboring_files_bb(s);
|
{
|
||||||
Rank r = square_rank(s);
|
Bitboard pawns = p.pawns(us) & this_and_neighboring_files_bb(s);
|
||||||
for(int i = 0; i < 3; i++)
|
Rank r = square_rank(s);
|
||||||
shelter += count_1s_8bit(pawns >> ((r+(i+1)*sign) * 8)) * (64>>i);
|
for (int i = 1; i < 4; i++)
|
||||||
ei.mgValue += sign * Value(shelter);
|
shelter += count_1s_8bit(shiftRowsDown(pawns, r+i*sign)) * (128>>i);
|
||||||
|
|
||||||
|
ei.mgValue += sign * Value(shelter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// King safety. This is quite complicated, and is almost certainly far
|
// King safety. This is quite complicated, and is almost certainly far
|
||||||
// from optimally tuned.
|
// from optimally tuned.
|
||||||
Color them = opposite_color(us);
|
Color them = opposite_color(us);
|
||||||
if(p.queen_count(them) >= 1 && ei.kingAttackersCount[them] >= 2
|
|
||||||
&& p.non_pawn_material(them) >= QueenValueMidgame + RookValueMidgame
|
|
||||||
&& ei.kingAdjacentZoneAttacksCount[them]) {
|
|
||||||
|
|
||||||
|
if ( p.queen_count(them) >= 1
|
||||||
|
&& ei.kingAttackersCount[them] >= 2
|
||||||
|
&& p.non_pawn_material(them) >= QueenValueMidgame + RookValueMidgame
|
||||||
|
&& ei.kingAdjacentZoneAttacksCount[them])
|
||||||
|
{
|
||||||
// Is it the attackers turn to move?
|
// Is it the attackers turn to move?
|
||||||
bool sente = (them == p.side_to_move());
|
bool sente = (them == p.side_to_move());
|
||||||
|
|
||||||
// Find the attacked squares around the king which has no defenders
|
// Find the attacked squares around the king which has no defenders
|
||||||
// apart from the king itself:
|
// apart from the king itself
|
||||||
Bitboard undefended =
|
Bitboard undefended =
|
||||||
ei.attacked_by(them) & ~ei.attacked_by(us, PAWN)
|
ei.attacked_by(them) & ~ei.attacked_by(us, PAWN)
|
||||||
& ~ei.attacked_by(us, KNIGHT) & ~ei.attacked_by(us, BISHOP)
|
& ~ei.attacked_by(us, KNIGHT) & ~ei.attacked_by(us, BISHOP)
|
||||||
& ~ei.attacked_by(us, ROOK) & ~ei.attacked_by(us, QUEEN)
|
& ~ei.attacked_by(us, ROOK) & ~ei.attacked_by(us, QUEEN)
|
||||||
& ei.attacked_by(us, KING);
|
& ei.attacked_by(us, KING);
|
||||||
|
|
||||||
Bitboard occ = p.occupied_squares(), b, b2;
|
Bitboard occ = p.occupied_squares(), b, b2;
|
||||||
|
|
||||||
// Initialize the 'attackUnits' variable, which is used later on as an
|
// Initialize the 'attackUnits' variable, which is used later on as an
|
||||||
|
@ -739,113 +748,134 @@ namespace {
|
||||||
// undefended squares around the king, the square of the king, and the
|
// undefended squares around the king, the square of the king, and the
|
||||||
// quality of the pawn shelter.
|
// quality of the pawn shelter.
|
||||||
int attackUnits =
|
int attackUnits =
|
||||||
Min((ei.kingAttackersCount[them] * ei.kingAttackersWeight[them]) / 2, 25)
|
Min((ei.kingAttackersCount[them] * ei.kingAttackersWeight[them]) / 2, 25)
|
||||||
+ (ei.kingAdjacentZoneAttacksCount[them] + count_1s_max_15(undefended)) * 3
|
+ (ei.kingAdjacentZoneAttacksCount[them] + count_1s_max_15(undefended)) * 3
|
||||||
+ InitKingDanger[relative_square(us, s)] - shelter / 32;
|
+ InitKingDanger[relative_square(us, s)] - shelter / 32;
|
||||||
|
|
||||||
// Analyse safe queen contact checks:
|
// Analyse safe queen contact checks
|
||||||
b = undefended & ei.attacked_by(them, QUEEN) & ~p.pieces_of_color(them);
|
b = undefended & ei.attacked_by(them, QUEEN) & ~p.pieces_of_color(them);
|
||||||
if(b) {
|
if (b)
|
||||||
|
{
|
||||||
Bitboard attackedByOthers =
|
Bitboard attackedByOthers =
|
||||||
ei.attacked_by(them, PAWN) | ei.attacked_by(them, KNIGHT)
|
ei.attacked_by(them, PAWN) | ei.attacked_by(them, KNIGHT)
|
||||||
| ei.attacked_by(them, BISHOP) | ei.attacked_by(them, ROOK);
|
| ei.attacked_by(them, BISHOP) | ei.attacked_by(them, ROOK);
|
||||||
|
|
||||||
b &= attackedByOthers;
|
b &= attackedByOthers;
|
||||||
if(b) {
|
if (b)
|
||||||
|
{
|
||||||
// The bitboard b now contains the squares available for safe queen
|
// The bitboard b now contains the squares available for safe queen
|
||||||
// contact checks.
|
// contact checks.
|
||||||
int count = count_1s_max_15(b);
|
int count = count_1s_max_15(b);
|
||||||
attackUnits += QueenContactCheckBonus * count * (sente? 2 : 1);
|
attackUnits += QueenContactCheckBonus * count * (sente ? 2 : 1);
|
||||||
|
|
||||||
// Is there a mate threat?
|
// Is there a mate threat?
|
||||||
if(QueenContactMates && !p.is_check()) {
|
if (QueenContactMates && !p.is_check())
|
||||||
|
{
|
||||||
Bitboard escapeSquares =
|
Bitboard escapeSquares =
|
||||||
p.king_attacks(s) & ~p.pieces_of_color(us) & ~attackedByOthers;
|
p.king_attacks(s) & ~p.pieces_of_color(us) & ~attackedByOthers;
|
||||||
while(b) {
|
|
||||||
Square from, to = pop_1st_bit(&b);
|
while (b)
|
||||||
if(!(escapeSquares
|
{
|
||||||
& ~queen_attacks_bb(to, occ & clear_mask_bb(s)))) {
|
Square from, to = pop_1st_bit(&b);
|
||||||
// We have a mate, unless the queen is pinned or there
|
if (!(escapeSquares & ~queen_attacks_bb(to, occ & clear_mask_bb(s))))
|
||||||
// is an X-ray attack through the queen.
|
{
|
||||||
for(int i = 0; i < p.queen_count(them); i++) {
|
// We have a mate, unless the queen is pinned or there
|
||||||
from = p.queen_list(them, i);
|
// is an X-ray attack through the queen.
|
||||||
if(bit_is_set(p.queen_attacks(from), to)
|
for (int i = 0; i < p.queen_count(them); i++)
|
||||||
&& !bit_is_set(p.pinned_pieces(them), from)
|
{
|
||||||
&& !(rook_attacks_bb(to, occ & clear_mask_bb(from))
|
from = p.queen_list(them, i);
|
||||||
& p.rooks_and_queens(us))
|
if ( bit_is_set(p.queen_attacks(from), to)
|
||||||
&& !(rook_attacks_bb(to, occ & clear_mask_bb(from))
|
&& !bit_is_set(p.pinned_pieces(them), from)
|
||||||
& p.rooks_and_queens(us)))
|
&& !(rook_attacks_bb(to, occ & clear_mask_bb(from)) & p.rooks_and_queens(us))
|
||||||
ei.mateThreat[them] = make_move(from, to);
|
&& !(rook_attacks_bb(to, occ & clear_mask_bb(from)) & p.rooks_and_queens(us)))
|
||||||
|
|
||||||
|
ei.mateThreat[them] = make_move(from, to);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analyse safe rook contact checks:
|
// Analyse safe rook contact checks:
|
||||||
if(RookContactCheckBonus) {
|
if (RookContactCheckBonus)
|
||||||
b = undefended & ei.attacked_by(them, ROOK) & ~p.pieces_of_color(them);
|
{
|
||||||
if(b) {
|
b = undefended & ei.attacked_by(them, ROOK) & ~p.pieces_of_color(them);
|
||||||
Bitboard attackedByOthers =
|
if (b)
|
||||||
ei.attacked_by(them, PAWN) | ei.attacked_by(them, KNIGHT)
|
{
|
||||||
| ei.attacked_by(them, BISHOP) | ei.attacked_by(them, QUEEN);
|
Bitboard attackedByOthers =
|
||||||
b &= attackedByOthers;
|
ei.attacked_by(them, PAWN) | ei.attacked_by(them, KNIGHT)
|
||||||
if(b) {
|
| ei.attacked_by(them, BISHOP) | ei.attacked_by(them, QUEEN);
|
||||||
int count = count_1s_max_15(b);
|
|
||||||
attackUnits += (RookContactCheckBonus * count * (sente? 2 : 1));
|
b &= attackedByOthers;
|
||||||
|
if (b)
|
||||||
|
{
|
||||||
|
int count = count_1s_max_15(b);
|
||||||
|
attackUnits += (RookContactCheckBonus * count * (sente? 2 : 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analyse safe distance checks:
|
// Analyse safe distance checks:
|
||||||
if(QueenCheckBonus > 0 || RookCheckBonus > 0) {
|
if (QueenCheckBonus > 0 || RookCheckBonus > 0)
|
||||||
b = p.rook_attacks(s) & ~p.pieces_of_color(them) & ~ei.attacked_by(us);
|
{
|
||||||
|
b = p.rook_attacks(s) & ~p.pieces_of_color(them) & ~ei.attacked_by(us);
|
||||||
|
|
||||||
// Queen checks
|
// Queen checks
|
||||||
b2 = b & ei.attacked_by(them, QUEEN);
|
b2 = b & ei.attacked_by(them, QUEEN);
|
||||||
if(b2) attackUnits += QueenCheckBonus * count_1s_max_15(b2);
|
if( b2)
|
||||||
|
attackUnits += QueenCheckBonus * count_1s_max_15(b2);
|
||||||
|
|
||||||
// Rook checks
|
// Rook checks
|
||||||
b2 = b & ei.attacked_by(them, ROOK);
|
b2 = b & ei.attacked_by(them, ROOK);
|
||||||
if(b2) attackUnits += RookCheckBonus * count_1s_max_15(b2);
|
if (b2)
|
||||||
|
attackUnits += RookCheckBonus * count_1s_max_15(b2);
|
||||||
}
|
}
|
||||||
if(QueenCheckBonus > 0 || BishopCheckBonus > 0) {
|
if (QueenCheckBonus > 0 || BishopCheckBonus > 0)
|
||||||
b = p.bishop_attacks(s) & ~p.pieces_of_color(them) & ~ei.attacked_by(us);
|
{
|
||||||
// Queen checks
|
b = p.bishop_attacks(s) & ~p.pieces_of_color(them) & ~ei.attacked_by(us);
|
||||||
b2 = b & ei.attacked_by(them, QUEEN);
|
|
||||||
if(b2) attackUnits += QueenCheckBonus * count_1s_max_15(b2);
|
|
||||||
|
|
||||||
// Bishop checks
|
// Queen checks
|
||||||
b2 = b & ei.attacked_by(them, BISHOP);
|
b2 = b & ei.attacked_by(them, QUEEN);
|
||||||
if(b2) attackUnits += BishopCheckBonus * count_1s_max_15(b2);
|
if (b2)
|
||||||
|
attackUnits += QueenCheckBonus * count_1s_max_15(b2);
|
||||||
|
|
||||||
|
// Bishop checks
|
||||||
|
b2 = b & ei.attacked_by(them, BISHOP);
|
||||||
|
if (b2)
|
||||||
|
attackUnits += BishopCheckBonus * count_1s_max_15(b2);
|
||||||
}
|
}
|
||||||
if(KnightCheckBonus > 0) {
|
if (KnightCheckBonus > 0)
|
||||||
b = p.knight_attacks(s) & ~p.pieces_of_color(them) & ~ei.attacked_by(us);
|
{
|
||||||
// Knight checks
|
b = p.knight_attacks(s) & ~p.pieces_of_color(them) & ~ei.attacked_by(us);
|
||||||
b2 = b & ei.attacked_by(them, KNIGHT);
|
|
||||||
if(b2) attackUnits += KnightCheckBonus * count_1s_max_15(b2);
|
// Knight checks
|
||||||
|
b2 = b & ei.attacked_by(them, KNIGHT);
|
||||||
|
if (b2)
|
||||||
|
attackUnits += KnightCheckBonus * count_1s_max_15(b2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analyse discovered checks (only for non-pawns right now, consider
|
// Analyse discovered checks (only for non-pawns right now, consider
|
||||||
// adding pawns later).
|
// adding pawns later).
|
||||||
if(DiscoveredCheckBonus) {
|
if (DiscoveredCheckBonus)
|
||||||
|
{
|
||||||
b = p.discovered_check_candidates(them) & ~p.pawns();
|
b = p.discovered_check_candidates(them) & ~p.pawns();
|
||||||
if(b)
|
if (b)
|
||||||
attackUnits +=
|
attackUnits += DiscoveredCheckBonus * count_1s_max_15(b) * (sente? 2 : 1);
|
||||||
DiscoveredCheckBonus * count_1s_max_15(b) * (sente? 2 : 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has a mate threat been found? We don't do anything here if the
|
// Has a mate threat been found? We don't do anything here if the
|
||||||
// side with the mating move is the side to move, because in that
|
// side with the mating move is the side to move, because in that
|
||||||
// case the mating side will get a huge bonus at the end of the main
|
// case the mating side will get a huge bonus at the end of the main
|
||||||
// evaluation function instead.
|
// evaluation function instead.
|
||||||
if(ei.mateThreat[them] != MOVE_NONE)
|
if (ei.mateThreat[them] != MOVE_NONE)
|
||||||
attackUnits += MateThreatBonus;
|
attackUnits += MateThreatBonus;
|
||||||
|
|
||||||
// Ensure that attackUnits is between 0 and 99, in order to avoid array
|
// Ensure that attackUnits is between 0 and 99, in order to avoid array
|
||||||
// out of bounds errors:
|
// out of bounds errors:
|
||||||
if(attackUnits < 0) attackUnits = 0;
|
if (attackUnits < 0)
|
||||||
if(attackUnits >= 100) attackUnits = 99;
|
attackUnits = 0;
|
||||||
|
|
||||||
|
if (attackUnits >= 100)
|
||||||
|
attackUnits = 99;
|
||||||
|
|
||||||
// Finally, extract the king safety score from the SafetyTable[] array.
|
// Finally, extract the king safety score from the SafetyTable[] array.
|
||||||
// Add the score to the evaluation, and also to ei.futilityMargin. The
|
// Add the score to the evaluation, and also to ei.futilityMargin. The
|
||||||
|
@ -854,9 +884,11 @@ namespace {
|
||||||
// capturing a single attacking piece can therefore result in a score
|
// capturing a single attacking piece can therefore result in a score
|
||||||
// change far bigger than the value of the captured piece.
|
// change far bigger than the value of the captured piece.
|
||||||
Value v = apply_weight(SafetyTable[attackUnits], WeightKingSafety[us]);
|
Value v = apply_weight(SafetyTable[attackUnits], WeightKingSafety[us]);
|
||||||
|
|
||||||
ei.mgValue -= sign * v;
|
ei.mgValue -= sign * v;
|
||||||
if(us == p.side_to_move())
|
|
||||||
ei.futilityMargin += v;
|
if (us == p.side_to_move())
|
||||||
|
ei.futilityMargin += v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue