S(0, 0), S(0, 0), S(80, 119), S(80, 119), S(117, 199), S(127, 218)
};
- // Hanging contains a bonus for each enemy hanging piece
- const Score Hanging = S(23, 20);
-
- #undef S
-
- const Score RookOnPawn = make_score(10, 28);
- const Score RookOpenFile = make_score(43, 21);
- const Score RookSemiopenFile = make_score(19, 10);
- const Score BishopPawns = make_score( 8, 12);
- const Score MinorBehindPawn = make_score(16, 0);
- const Score TrappedRook = make_score(90, 0);
- const Score Unstoppable = make_score( 0, 20);
+ // Assorted bonuses and penalties used by evaluation
+ const Score KingOnOne = S(2 , 58);
+ const Score KingOnMany = S(6 ,125);
+ const Score RookOnPawn = S(10, 28);
+ const Score RookOpenFile = S(43, 21);
+ const Score RookSemiOpenFile = S(19, 10);
+ const Score BishopPawns = S( 8, 12);
+ const Score MinorBehindPawn = S(16, 0);
+ const Score TrappedRook = S(92, 0);
+ const Score Unstoppable = S( 0, 20);
+ const Score Hanging = S(23, 20);
// Penalty for a bishop on a1/h1 (a8/h8 for black) which is trapped by
// a friendly pawn on b2/g2 (b7/g7 for black). This can obviously only
// happen in Chess960 games.
- const Score TrappedBishopA1H1 = make_score(50, 50);
+ const Score TrappedBishopA1H1 = S(50, 50);
+
+ #undef S
// SpaceMask[Color] contains the area of the board which is considered
// by the space evaluation. In the middlegame, each side is given a bonus
ei.attackedBy[Us][ALL_PIECES] = ei.attackedBy[Us][PAWN] = ei.pi->pawn_attacks(Us);
// Init king safety tables only if we are going to use them
- if (pos.count<QUEEN>(Us) && pos.non_pawn_material(Us) > QueenValueMg + PawnValueMg)
+ if (pos.non_pawn_material(Us) > QueenValueMg + PawnValueMg)
{
ei.kingRing[Them] = b | shift_bb<Down>(b);
b &= ei.attackedBy[Us][PAWN];
bonus += bonus / 2;
}
- return make_score(bonus, bonus);
+ return make_score(bonus * 2, bonus / 2);
}
// Give a bonus for a rook on a open or semi-open file
if (ei.pi->semiopen_file(Us, file_of(s)))
- score += ei.pi->semiopen_file(Them, file_of(s)) ? RookOpenFile : RookSemiopenFile;
+ score += ei.pi->semiopen_file(Them, file_of(s)) ? RookOpenFile : RookSemiOpenFile;
if (mob > 3 || ei.pi->semiopen_file(Us, file_of(s)))
continue;
if ( ((file_of(ksq) < FILE_E) == (file_of(s) < file_of(ksq)))
&& (rank_of(ksq) == rank_of(s) || relative_rank(Us, ksq) == RANK_1)
&& !ei.pi->semiopen_side(Us, file_of(ksq), file_of(s) < file_of(ksq)))
- score -= (TrappedRook - make_score(mob * 8, 0)) * (1 + !pos.can_castle(Us));
+ score -= (TrappedRook - make_score(mob * 22, 0)) * (1 + !pos.can_castle(Us));
}
// An important Chess960 pattern: A cornered bishop blocked by a friendly
attackUnits = std::min(20, (ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them]) / 2)
+ 3 * (ei.kingAdjacentZoneAttacksCount[Them] + popcount<Max15>(undefended))
+ 2 * (ei.pinnedPieces[Us] != 0)
- - mg_value(score) / 32;
+ - mg_value(score) / 32
+ - !pos.count<QUEEN>(Them) * 15;
// Analyse the enemy's safe queen contact checks. Firstly, find the
// undefended squares around the king that are attacked by the enemy's
const Color Them = (Us == WHITE ? BLACK : WHITE);
- Bitboard b, weakEnemies;
+ Bitboard b, weakEnemies, protectedEnemies;
Score score = SCORE_ZERO;
+ enum { Minor, Major };
+
+ // Protected enemies
+ protectedEnemies = (pos.pieces(Them) ^ pos.pieces(Them,PAWN))
+ & ei.attackedBy[Them][PAWN]
+ & (ei.attackedBy[Us][KNIGHT] | ei.attackedBy[Us][BISHOP]);
+
+ if (protectedEnemies)
+ score += Threat[Minor][type_of(pos.piece_on(lsb(protectedEnemies)))];
// Enemies not defended by a pawn and under our attack
weakEnemies = pos.pieces(Them)
{
b = weakEnemies & (ei.attackedBy[Us][KNIGHT] | ei.attackedBy[Us][BISHOP]);
if (b)
- score += Threat[0][type_of(pos.piece_on(lsb(b)))];
+ score += Threat[Minor][type_of(pos.piece_on(lsb(b)))];
b = weakEnemies & (ei.attackedBy[Us][ROOK] | ei.attackedBy[Us][QUEEN]);
if (b)
- score += Threat[1][type_of(pos.piece_on(lsb(b)))];
+ score += Threat[Major][type_of(pos.piece_on(lsb(b)))];
b = weakEnemies & ~ei.attackedBy[Them][ALL_PIECES];
if (b)
score += more_than_one(b) ? Hanging * popcount<Max15>(b) : Hanging;
+
+ b = weakEnemies & ei.attackedBy[Us][KING];
+ if (b)
+ score += more_than_one(b) ? KingOnMany : KingOnOne;
}
if (Trace)
// If the pawn is free to advance, then increase the bonus
if (pos.empty(blockSq))
{
- squaresToQueen = forward_bb(Us, s);
-
- // If there is an enemy rook or queen attacking the pawn from behind,
- // add all X-ray attacks by the rook or queen. Otherwise consider only
- // the squares in the pawn's path attacked or occupied by the enemy.
- if ( unlikely(forward_bb(Them, s) & pos.pieces(Them, ROOK, QUEEN))
- && (forward_bb(Them, s) & pos.pieces(Them, ROOK, QUEEN) & pos.attacks_from<ROOK>(s)))
- unsafeSquares = squaresToQueen;
- else
- unsafeSquares = squaresToQueen & (ei.attackedBy[Them][ALL_PIECES] | pos.pieces(Them));
-
- if ( unlikely(forward_bb(Them, s) & pos.pieces(Us, ROOK, QUEEN))
- && (forward_bb(Them, s) & pos.pieces(Us, ROOK, QUEEN) & pos.attacks_from<ROOK>(s)))
- defendedSquares = squaresToQueen;
- else
- defendedSquares = squaresToQueen & ei.attackedBy[Us][ALL_PIECES];
+ // If there is a rook or queen attacking/defending the pawn from behind,
+ // consider all the squaresToQueen. Otherwise consider only the squares
+ // in the pawn's path attacked or occupied by the enemy.
+ defendedSquares = unsafeSquares = squaresToQueen = forward_bb(Us, s);
+
+ Bitboard bb = forward_bb(Them, s) & pos.pieces(ROOK, QUEEN) & pos.attacks_from<ROOK>(s);
+
+ if (!(pos.pieces(Us) & bb))
+ defendedSquares &= ei.attackedBy[Us][ALL_PIECES];
+
+ if (!(pos.pieces(Them) & bb))
+ unsafeSquares &= ei.attackedBy[Them][ALL_PIECES] | pos.pieces(Them);
// If there aren't any enemy attacks, assign a big bonus. Otherwise
// assign a smaller bonus if the block square isn't attacked.
mbonus += k * rr, ebonus += k * rr;
}
+ else if (pos.pieces(Us) & blockSq)
+ mbonus += rr * 3 + r * 2 + 3, ebonus += rr + r * 2;
} // rr != 0
if (pos.count<PAWN>(Us) < pos.count<PAWN>(Them))
}
- // evaluate_unstoppable_pawns() scores the most advanced among the passed and
- // candidate pawns. In case both players have no pieces but pawns, this is
- // somewhat related to the possibility that pawns are unstoppable.
+ // evaluate_unstoppable_pawns() scores the most advanced passed pawn. In case
+ // both players have no pieces but pawns, this is somewhat related to the
+ // possibility that pawns are unstoppable.
Score evaluate_unstoppable_pawns(Color us, const EvalInfo& ei) {
- Bitboard b = ei.pi->passed_pawns(us) | ei.pi->candidate_pawns(us);
+ Bitboard b = ei.pi->passed_pawns(us);
return b ? Unstoppable * int(relative_rank(us, frontmost_sq(us, b))) : SCORE_ZERO;
}
// Endgame with opposite-colored bishops, but also other pieces. Still
// a bit drawish, but not as drawish as with only the two bishops.
sf = ScaleFactor(50 * sf / SCALE_FACTOR_NORMAL);
- } else if ( abs(eg_value(score)) <= BishopValueEg &&
- ei.pi->pawn_span(strongSide) <= 1 &&
- !pos.pawn_passed(~strongSide, pos.king_square(~strongSide))) {
+ } else if ( abs(eg_value(score)) <= BishopValueEg
+ && ei.pi->pawn_span(strongSide) <= 1
+ && !pos.pawn_passed(~strongSide, pos.king_square(~strongSide))) {
+ // Endings where weaker side can be place his king in front of the opponent's pawns are drawish.
sf = ScaleFactor(ScalePawnSpan[ei.pi->pawn_span(strongSide)]);
}
}