for (unsigned i = 0; i < (1 << 16); ++i)
PopCnt16[i] = std::bitset<16>(i).count();
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
- SquareBB[s] = (1ULL << s);
-
- for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
- for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
- SquareDistance[s1][s2] = std::max(distance<File>(s1, s2), distance<Rank>(s1, s2));
-
- Direction RookDirections[] = { NORTH, EAST, SOUTH, WEST };
- Direction BishopDirections[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
-
- init_magics(RookTable, RookMagics, RookDirections);
- init_magics(BishopTable, BishopMagics, BishopDirections);
+ for (Square s = SQ_A1; s <= SQ_MAX; ++s)
+ SquareBB[s] = make_bitboard(s);
+
+ for (File f = FILE_A; f <= FILE_MAX; ++f)
+ for (Rank r = RANK_1; r <= RANK_MAX; ++r)
+ BoardSizeBB[f][r] = forward_file_bb(BLACK, make_square(f, r)) | SquareBB[make_square(f, r)] | (f > FILE_A ? BoardSizeBB[f - 1][r] : Bitboard(0));
+
+ for (Square s1 = SQ_A1; s1 <= SQ_MAX; ++s1)
+ for (Square s2 = SQ_A1; s2 <= SQ_MAX; ++s2)
+ SquareDistance[s1][s2] = std::max(distance<File>(s1, s2), distance<Rank>(s1, s2));
+
+#ifdef PRECOMPUTED_MAGICS
+ init_magics<RIDER>(RookTableH, RookMagicsH, RookDirectionsH, RookMagicHInit);
+ init_magics<RIDER>(RookTableV, RookMagicsV, RookDirectionsV, RookMagicVInit);
+ init_magics<RIDER>(BishopTable, BishopMagics, BishopDirections, BishopMagicInit);
+ init_magics<HOPPER>(CannonTableH, CannonMagicsH, RookDirectionsH, CannonMagicHInit);
+ init_magics<HOPPER>(CannonTableV, CannonMagicsV, RookDirectionsV, CannonMagicVInit);
+ init_magics<LAME_LEAPER>(HorseTable, HorseMagics, HorseDirections, HorseMagicInit);
+ init_magics<LAME_LEAPER>(ElephantTable, ElephantMagics, ElephantDirections, ElephantMagicInit);
+ init_magics<LAME_LEAPER>(JanggiElephantTable, JanggiElephantMagics, JanggiElephantDirections, JanggiElephantMagicInit);
+#else
+ init_magics<RIDER>(RookTableH, RookMagicsH, RookDirectionsH);
+ init_magics<RIDER>(RookTableV, RookMagicsV, RookDirectionsV);
+ init_magics<RIDER>(BishopTable, BishopMagics, BishopDirections);
+ init_magics<HOPPER>(CannonTableH, CannonMagicsH, RookDirectionsH);
+ init_magics<HOPPER>(CannonTableV, CannonMagicsV, RookDirectionsV);
+ init_magics<LAME_LEAPER>(HorseTable, HorseMagics, HorseDirections);
+ init_magics<LAME_LEAPER>(ElephantTable, ElephantMagics, ElephantDirections);
+ init_magics<LAME_LEAPER>(JanggiElephantTable, JanggiElephantMagics, JanggiElephantDirections);
+#endif
+ // Helper returning the target bitboard of a step from a square
+ auto landing_square_bb = [&](Square s, int step)
+ {
+ Square to = Square(s + step);
- return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0);
++ return is_ok(to) && distance(s, to) < 4 ? square_bb(to) : Bitboard(0);
+ };
+
- for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
+ for (Color c : { WHITE, BLACK })
+ for (PieceType pt = PAWN; pt <= KING; ++pt)
+ {
+ const PieceInfo* pi = pieceMap.find(pt)->second;
+
+ for (Square s = SQ_A1; s <= SQ_MAX; ++s)
+ {
+ for (Direction d : pi->stepsCapture)
+ {
- Square to = s + Direction(c == WHITE ? d : -d);
-
- if (is_ok(to) && distance(s, to) < 4)
- {
- PseudoAttacks[c][pt][s] |= to;
- if (!pi->lameLeaper)
- LeaperAttacks[c][pt][s] |= to;
- }
++ PseudoAttacks[c][pt][s] |= landing_square_bb(s, c == WHITE ? d : -d);
++ if (!pi->lameLeaper)
++ LeaperAttacks[c][pt][s] |= landing_square_bb(s, c == WHITE ? d : -d);
+ }
+ for (Direction d : pi->stepsQuiet)
+ {
- Square to = s + Direction(c == WHITE ? d : -d);
-
- if (is_ok(to) && distance(s, to) < 4)
- {
- PseudoMoves[c][pt][s] |= to;
- if (!pi->lameLeaper)
- LeaperMoves[c][pt][s] |= to;
- }
++ PseudoMoves[c][pt][s] |= landing_square_bb(s, c == WHITE ? d : -d);
++ if (!pi->lameLeaper)
++ LeaperMoves[c][pt][s] |= landing_square_bb(s, c == WHITE ? d : -d);
+ }
+ PseudoAttacks[c][pt][s] |= sliding_attack<RIDER>(pi->sliderCapture, s, 0, c);
+ PseudoAttacks[c][pt][s] |= sliding_attack<RIDER>(pi->hopperCapture, s, 0, c);
+ PseudoMoves[c][pt][s] |= sliding_attack<RIDER>(pi->sliderQuiet, s, 0, c);
+ PseudoMoves[c][pt][s] |= sliding_attack<RIDER>(pi->hopperQuiet, s, 0, c);
+ }
+ }
+
+ for (Square s1 = SQ_A1; s1 <= SQ_MAX; ++s1)
{
- PawnAttacks[WHITE][s1] = pawn_attacks_bb<WHITE>(square_bb(s1));
- PawnAttacks[BLACK][s1] = pawn_attacks_bb<BLACK>(square_bb(s1));
-
- for (int step : {-9, -8, -7, -1, 1, 7, 8, 9} )
- PseudoAttacks[KING][s1] |= landing_square_bb(s1, step);
-
- for (int step : {-17, -15, -10, -6, 6, 10, 15, 17} )
- PseudoAttacks[KNIGHT][s1] |= landing_square_bb(s1, step);
-
- PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb<BISHOP>(s1, 0);
- PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ ROOK][s1] = attacks_bb< ROOK>(s1, 0);
-
for (PieceType pt : { BISHOP, ROOK })
- for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
- if (PseudoAttacks[pt][s1] & s2)
- LineBB[s1][s2] = (attacks_bb(pt, s1, 0) & attacks_bb(pt, s2, 0)) | s1 | s2;
+ for (Square s2 = SQ_A1; s2 <= SQ_MAX; ++s2)
+ if (PseudoAttacks[WHITE][pt][s1] & s2)
+ LineBB[s1][s2] = (attacks_bb(WHITE, pt, s1, 0) & attacks_bb(WHITE, pt, s2, 0)) | s1 | s2;
}
}
// MobilityBonus[PieceType-2][attacked] contains bonuses for middle and end game,
// indexed by piece type and number of attacked squares in the mobility area.
- #ifdef LARGEBOARDS
- constexpr Score MobilityBonus[][38] = {
- #else
-- constexpr Score MobilityBonus[][32] = {
- #endif
- { S(-62,-81), S(-53,-56), S(-12,-30), S( -4,-14), S( 3, 8), S( 13, 15), // Knights
++ constexpr Score MobilityBonus[][4 * RANK_NB] = {
+ { S(-62,-81), S(-53,-56), S(-12,-30), S( -4,-14), S( 3, 8), S( 13, 15), // Knight
S( 22, 23), S( 28, 27), S( 33, 33) },
- { S(-48,-59), S(-20,-23), S( 16, -3), S( 26, 13), S( 38, 24), S( 51, 42), // Bishops
+ { S(-48,-59), S(-20,-23), S( 16, -3), S( 26, 13), S( 38, 24), S( 51, 42), // Bishop
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(-58,-76), S(-27,-18), S(-15, 28), S(-10, 55), S( -5, 69), S( -2, 82), // Rooks
+ { S(-58,-76), S(-27,-18), S(-15, 28), S(-10, 55), S( -5, 69), S( -2, 82), // Rook
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(-39,-36), S(-21,-15), S( 3, 8), S( 3, 18), S( 14, 34), S( 22, 54), // Queen
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( 79,140), S( 88,143), S( 88,148), S( 99,166), S(102,170), S(102,175),
template<Tracing T> template<Color Us>
void Evaluation<T>::initialize() {
- constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
+ constexpr Color Them = ~Us;
constexpr Direction Up = pawn_push(Us);
constexpr Direction Down = -Up;
- constexpr Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB : Rank7BB | Rank6BB);
+ Bitboard LowRanks = rank_bb(relative_rank(Us, RANK_2, pos.max_rank())) | rank_bb(relative_rank(Us, RANK_3, pos.max_rank()));
- const Square ksq = pos.square<KING>(Us);
+ const Square ksq = pos.count<KING>(Us) ? pos.square<KING>(Us) : SQ_NONE;
Bitboard dblAttackByPawn = pawn_double_attacks_bb<Us>(pos.pieces(Us, PAWN));
// Evaluation::pieces() scores pieces of a given color and type
- template<Tracing T> template<Color Us, PieceType Pt>
- Score Evaluation<T>::pieces() {
+ template<Tracing T> template<Color Us>
+ Score Evaluation<T>::pieces(PieceType Pt) {
- constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
+ constexpr Color Them = ~Us;
constexpr Direction Down = -pawn_push(Us);
constexpr Bitboard OutpostRanks = (Us == WHITE ? Rank4BB | Rank5BB | Rank6BB
: Rank5BB | Rank4BB | Rank3BB);
score += MinorBehindPawn;
// Penalty if the piece is far from the king
+ if (pos.count<KING>(Us))
- score -= KingProtector * distance(s, pos.square<KING>(Us));
+ score -= KingProtector * distance(pos.square<KING>(Us), s);
if (Pt == BISHOP)
{
return score;
}
+ // Evaluation::hand() scores pieces of a given color and type in hand
+ template<Tracing T> template<Color Us>
+ Score Evaluation<T>::hand(PieceType pt) {
+
- constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
++ constexpr Color Them = ~Us;
+
+ Score score = SCORE_ZERO;
+
+ if (pos.count_in_hand(Us, pt))
+ {
+ Bitboard b = pos.drop_region(Us, pt) & ~pos.pieces() & (~attackedBy2[Them] | attackedBy[Us][ALL_PIECES]);
+ if ((b & kingRing[Them]) && pt != SHOGI_PAWN)
+ {
+ kingAttackersCountInHand[Us] += pos.count_in_hand(Us, pt);
+ kingAttackersWeightInHand[Us] += KingAttackWeights[std::min(int(pt), QUEEN + 1)] * pos.count_in_hand(Us, pt);
+ kingAttacksCount[Us] += popcount(b & attackedBy[Them][KING]);
+ }
+ Bitboard theirHalf = pos.board_bb() & ~forward_ranks_bb(Them, relative_rank(Them, Rank((pos.max_rank() - 1) / 2), pos.max_rank()));
+ mobility[Us] += DropMobility * popcount(b & theirHalf & ~attackedBy[Them][ALL_PIECES]);
+ if (pos.promoted_piece_type(pt) != NO_PIECE_TYPE && pos.drop_promoted())
+ score += make_score(std::max(PieceValue[MG][pos.promoted_piece_type(pt)] - PieceValue[MG][pt], VALUE_ZERO),
+ std::max(PieceValue[EG][pos.promoted_piece_type(pt)] - PieceValue[EG][pt], VALUE_ZERO)) / 4 * pos.count_in_hand(Us, pt);
+ if (pos.enclosing_drop())
+ mobility[Us] += make_score(500, 500) * popcount(b);
+ }
+
+ return score;
+ }
// Evaluation::king() assigns bonuses and penalties to a king of a given color
template<Tracing T> template<Color Us>
Score Evaluation<T>::king() const {
- constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
+ constexpr Color Them = ~Us;
- constexpr Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB
- : AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB);
+ Rank r = relative_rank(Us, std::min(Rank((pos.max_rank() - 1) / 2 + 1), pos.max_rank()), pos.max_rank());
+ Bitboard Camp = pos.board_bb() & ~forward_ranks_bb(Us, r);
+
+ if (!pos.count<KING>(Us) || !pos.checking_permitted())
+ return SCORE_ZERO;
Bitboard weak, b1, b2, b3, safe, unsafeChecks = 0;
- Bitboard rookChecks, queenChecks, bishopChecks, knightChecks;
+ Bitboard queenChecks, knightChecks, pawnChecks, otherChecks;
int kingDanger = 0;
const Square ksq = pos.square<KING>(Us);
template<Tracing T> template<Color Us>
Score Evaluation<T>::space() const {
- if (pos.non_pawn_material() < SpaceThreshold)
+ bool pawnsOnly = !(pos.pieces(Us) ^ pos.pieces(Us, PAWN));
+
+ if (pos.non_pawn_material() < SpaceThreshold && !pos.captures_to_hand() && !pawnsOnly)
return SCORE_ZERO;
- constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
+ constexpr Color Them = ~Us;
constexpr Direction Down = -pawn_push(Us);
constexpr Bitboard SpaceMask =
Us == WHITE ? CenterFiles & (Rank2BB | Rank3BB | Rank4BB)