S( 37, 28), S( 42, 31), S(44, 33) },
{ S(-22,-27), S( -8,-13), S( 6, 1), S(20, 15), S(34, 29), S(48, 43), // Bishops
S( 60, 55), S( 68, 63), S(74, 68), S(77, 72), S(80, 75), S(82, 77),
- S( 84, 79), S( 86, 81), S(87, 82), S(87, 82) },
+ S( 84, 79), S( 86, 81) },
{ S(-17,-33), S(-11,-16), S(-5, 0), S( 1, 16), S( 7, 32), S(13, 48), // Rooks
S( 18, 64), S( 22, 80), S(26, 96), S(29,109), S(31,115), S(33,119),
- S( 35,122), S( 36,123), S(37,124), S(38,124) },
+ S( 35,122), S( 36,123), S(37,124) },
{ S(-12,-20), S( -8,-13), S(-5, -7), S(-2, -1), S( 1, 5), S( 4, 11), // Queens
S( 7, 17), S( 10, 23), S(13, 29), S(16, 34), S(18, 38), S(20, 40),
S( 22, 41), S( 23, 41), S(24, 41), S(25, 41), S(25, 41), S(25, 41),
S( 25, 41), S( 25, 41), S(25, 41), S(25, 41), S(25, 41), S(25, 41),
- S( 25, 41), S( 25, 41), S(25, 41), S(25, 41), S(25, 41), S(25, 41),
- S( 25, 41), S( 25, 41) }
+ S( 25, 41), S( 25, 41), S(25, 41), S(25, 41) }
};
// Outpost[PieceType][Square] contains bonuses of knights and bishops, indexed
// based on how many squares inside this area are safe and available for
// friendly minor pieces.
const Bitboard SpaceMask[] = {
- (1ULL << SQ_C2) | (1ULL << SQ_D2) | (1ULL << SQ_E2) | (1ULL << SQ_F2) |
- (1ULL << SQ_C3) | (1ULL << SQ_D3) | (1ULL << SQ_E3) | (1ULL << SQ_F3) |
- (1ULL << SQ_C4) | (1ULL << SQ_D4) | (1ULL << SQ_E4) | (1ULL << SQ_F4),
- (1ULL << SQ_C7) | (1ULL << SQ_D7) | (1ULL << SQ_E7) | (1ULL << SQ_F7) |
- (1ULL << SQ_C6) | (1ULL << SQ_D6) | (1ULL << SQ_E6) | (1ULL << SQ_F6) |
- (1ULL << SQ_C5) | (1ULL << SQ_D5) | (1ULL << SQ_E5) | (1ULL << SQ_F5)
+ (FileCBB | FileDBB | FileEBB | FileFBB) & (Rank2BB | Rank3BB | Rank4BB),
+ (FileCBB | FileDBB | FileEBB | FileFBB) & (Rank7BB | Rank6BB | Rank5BB)
};
// King danger constants and variables. The king danger scores are taken
const int MaxSlope = 30;
const int Peak = 1280;
- for (int t = 0, i = 1; i < 100; i++)
+ for (int t = 0, i = 1; i < 100; ++i)
{
t = std::min(Peak, std::min(int(0.4 * i * i), t + MaxSlope));
// type of attacking piece, from knights to queens. Kings are not
// considered because are already handled in king evaluation.
if (weakEnemies)
- for (PieceType pt1 = KNIGHT; pt1 < KING; pt1++)
+ for (PieceType pt1 = KNIGHT; pt1 < KING; ++pt1)
{
b = ei.attackedBy[Us][pt1] & weakEnemies;
if (b)
- for (PieceType pt2 = PAWN; pt2 < KING; pt2++)
+ for (PieceType pt2 = PAWN; pt2 < KING; ++pt2)
if (b & pos.pieces(pt2))
score += Threat[pt1][pt2];
}
ebonus -= Value(square_distance(pos.king_square(Us), blockSq) * 2 * rr);
// If blockSq is not the queening square then consider also a second push
- if (rank_of(blockSq) != (Us == WHITE ? RANK_8 : RANK_1))
+ if (relative_rank(Us, blockSq) != RANK_8)
ebonus -= Value(square_distance(pos.king_square(Us), blockSq + pawn_push(Us)) * rr);
// If the pawn is free to advance, increase bonus
{
if (pos.non_pawn_material(Them) <= KnightValueMg)
ebonus += ebonus / 4;
+
else if (pos.pieces(Them, ROOK, QUEEN))
ebonus -= ebonus / 4;
}
+
+ // Increase the bonus if we have more non-pawn pieces
+ if (pos.count<ALL_PIECES>( Us) - pos.count<PAWN>( Us) >
+ pos.count<ALL_PIECES>(Them) - pos.count<PAWN>(Them))
+ ebonus += ebonus / 4;
+
score += make_score(mbonus, ebonus);
}
// Step 1. Hunt for unstoppable passed pawns. If we find at least one,
// record how many plies are required for promotion.
- for (c = WHITE; c <= BLACK; c++)
+ for (c = WHITE; c <= BLACK; ++c)
{
// Skip if other side has non-pawn pieces
if (pos.non_pawn_material(~c))
{
b2 = supporters & in_front_bb(winnerSide, rank_of(blockSq + pawn_push(winnerSide)));
- while (b2) // This while-loop could be replaced with LSB/MSB (depending on color)
+ if (b2)
{
- d = square_distance(blockSq, pop_lsb(&b2)) - 2;
+ d = square_distance(blockSq, backmost_sq(winnerSide, b2)) - 2;
movesToGo = std::min(movesToGo, d);
}
}
// Check pawns that can be sacrificed against the blocking pawn
- b2 = pawn_attack_span(winnerSide, blockSq) & candidates & ~(1ULL << s);
+ b2 = pawn_attack_span(winnerSide, blockSq) & candidates & ~SquareBB[s];
- while (b2) // This while-loop could be replaced with LSB/MSB (depending on color)
+ if (b2)
{
- d = square_distance(blockSq, pop_lsb(&b2)) - 2;
+ d = square_distance(blockSq, backmost_sq(winnerSide, b2)) - 2;
movesToGo = std::min(movesToGo, d);
}
kingptg = (minKingDist + blockersCount) * 2;
}
- // Check if pawn sacrifice plan _may_ save the day
- if (pliesToQueen[winnerSide] + 3 > pliesToGo + sacptg)
- return SCORE_ZERO;
-
- // Check if king capture plan _may_ save the day (contains some false positives)
- if (pliesToQueen[winnerSide] + 3 > pliesToGo + kingptg)
+ // Check if pawn sacrifice or king capture plan _may_ save the day
+ if (pliesToQueen[winnerSide] + 3 > pliesToGo + std::min(kingptg, sacptg))
return SCORE_ZERO;
}