DistanceRingBB[s1][SquareDistance[s1][s2]] |= s2;
}
- int steps[][5] = { {}, { 7, 9 }, { 6, 10, 15, 17 }, {}, {}, {}, { 1, 7, 8, 9 } };
+ // Piece moves
+ Direction RookDirections[5] = { NORTH, EAST, SOUTH, WEST };
+ Direction BishopDirections[5] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
+
+#ifdef PRECOMPUTED_MAGICS
+ init_magics(RookTable, RookMagics, RookDirections, RookMagicInit);
+ init_magics(BishopTable, BishopMagics, BishopDirections, BishopMagicInit);
+#else
+ init_magics(RookTable, RookMagics, RookDirections);
+ init_magics(BishopTable, BishopMagics, BishopDirections);
+#endif
+
+ int stepsCapture[][13] = {
+ {}, // NO_PIECE_TYPE
+ { NORTH_WEST, NORTH_EAST }, // pawn
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // knight
+ {}, // bishop
+ {}, // rook
+ {}, // queen
+ { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // fers/met
+ { 2 * SOUTH_WEST, 2 * SOUTH_EAST, 2 * NORTH_WEST, 2 * NORTH_EAST }, // alfil
+ { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH, NORTH_EAST }, // silver/khon
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH_WEST, SOUTH_EAST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH_WEST, NORTH_EAST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // aiwok
+ { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // bers/dragon
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // archbishop
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // chancellor
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // amazon
+ {}, // knibis
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // biskni
+ { NORTH }, // shogi pawn
+ {}, // lance
+ { 2 * NORTH + WEST, 2 * NORTH + EAST }, // shogi knight
+ { WEST, EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // euroshogi knight
+ { SOUTH, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // gold
+ { SOUTH, WEST, EAST, NORTH }, // horse
+ { SOUTH, WEST, EAST, NORTH }, // clobber
+ { NORTH_WEST, NORTH_EAST }, // breakthrough
+ {}, // immobile
+ { SOUTH, WEST, EAST, NORTH }, // wazir
+ { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // commoner
+ { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST } // king
+ };
+ int stepsQuiet[][13] = {
+ {}, // NO_PIECE_TYPE
+ { NORTH }, // pawn
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // knight
+ {}, // bishop
+ {}, // rook
+ {}, // queen
+ { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // fers/met
+ { 2 * SOUTH_WEST, 2 * SOUTH_EAST, 2 * NORTH_WEST, 2 * NORTH_EAST }, // alfil
+ { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH, NORTH_EAST }, // silver/khon
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH_WEST, SOUTH_EAST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH_WEST, NORTH_EAST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // aiwok
+ { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // bers/dragon
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // archbishop
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // chancellor
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // amazon
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // knibis
+ {}, // biskni
+ { NORTH }, // shogi pawn
+ {}, // lance
+ { 2 * NORTH + WEST, 2 * NORTH + EAST }, // shogi knight
+ { WEST, EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // euroshogi knight
+ { SOUTH, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // gold
+ { SOUTH, WEST, EAST, NORTH }, // horse
+ {}, // clobber
+ { NORTH_WEST, NORTH, NORTH_EAST }, // breakthrough
+ {}, // immobile
+ { SOUTH, WEST, EAST, NORTH }, // wazir
+ { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // commoner
+ { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST } // king
+ };
+ Direction sliderCapture[][9] = {
+ {}, // NO_PIECE_TYPE
+ {}, // pawn
+ {}, // knight
+ { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // bishop
+ { NORTH, EAST, SOUTH, WEST }, // rook
+ { NORTH, EAST, SOUTH, WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // queen
+ {}, // fers/met
+ {}, // alfil
+ {}, // silver/khon
+ { NORTH, EAST, SOUTH, WEST }, // aiwok
+ { NORTH, EAST, SOUTH, WEST }, // bers/dragon
+ { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // archbishop
+ { NORTH, EAST, SOUTH, WEST }, // chancellor
+ { NORTH, EAST, SOUTH, WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // amazon
+ { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // knibis
+ {}, // biskni
+ {}, // shogi pawn
+ { NORTH }, // lance
+ {}, // shogi knight
+ {}, // euroshogi knight
+ {}, // gold
+ { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // horse
+ {}, // clobber
+ {}, // breakthrough
+ {}, // immobile
+ {}, // wazir
+ {}, // commoner
+ {} // king
+ };
+ Direction sliderQuiet[][9] = {
+ {}, // NO_PIECE_TYPE
+ {}, // pawn
+ {}, // knight
+ { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // bishop
+ { NORTH, EAST, SOUTH, WEST }, // rook
+ { NORTH, EAST, SOUTH, WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // queen
+ {}, // fers/met
+ {}, // alfil
+ {}, // silver/khon
+ { NORTH, EAST, SOUTH, WEST }, // aiwok
+ { NORTH, EAST, SOUTH, WEST }, // bers/dragon
+ { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // archbishop
+ { NORTH, EAST, SOUTH, WEST }, // chancellor
+ { NORTH, EAST, SOUTH, WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // amazon
+ {}, // knibis
+ { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // biskni
+ {}, // shogi pawn
+ { NORTH }, // lance
+ {}, // shogi knight
+ {}, // euroshogi knight
+ {}, // gold
+ { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // horse
+ {}, // clobber
+ {}, // breakthrough
+ {}, // immobile
+ {}, // wazir
+ {}, // commoner
+ {} // king
+ };
+ int sliderDistCapture[] = {
+ 0, // NO_PIECE_TYPE
+ 0, // pawn
+ 0, // knight
+ FILE_MAX, // bishop
+ FILE_MAX, // rook
+ FILE_MAX, // queen
+ 0, // fers/met
+ 0, // alfil
+ 0, // silver/khon
+ FILE_MAX, // aiwok
+ FILE_MAX, // bers/dragon
+ FILE_MAX, // archbishop
+ FILE_MAX, // chancellor
+ FILE_MAX, // amazon
+ FILE_MAX, // knibis
+ 0, // biskni
+ 0, // shogi pawn
+ FILE_MAX, // lance
+ 0, // shogi knight
+ 0, // euroshogi knight
+ 0, // gold
+ FILE_MAX, // horse
+ 0, // clobber
+ 0, // breakthrough
+ 0, // immobile
+ 0, // wazir
+ 0, // commoner
+ 0 // king
+ };
+ int sliderDistQuiet[] = {
+ 0, // NO_PIECE_TYPE
+ 0, // pawn
+ 0, // knight
+ FILE_MAX, // bishop
+ FILE_MAX, // rook
+ FILE_MAX, // queen
+ 0, // fers/met
+ 0, // alfil
+ 0, // silver/khon
+ FILE_MAX, // aiwok
+ FILE_MAX, // bers/dragon
+ FILE_MAX, // archbishop
+ FILE_MAX, // chancellor
+ FILE_MAX, // amazon
+ 0, // knibis
+ FILE_MAX, // biskni
+ 0, // shogi pawn
+ FILE_MAX, // lance
+ 0, // shogi knight
+ 0, // euroshogi knight
+ 0, // gold
+ FILE_MAX, // horse
+ 0, // clobber
+ 0, // breakthrough
+ 0, // immobile
+ 0, // wazir
+ 0, // commoner
+ 0 // king
+ };
for (Color c = WHITE; c <= BLACK; ++c)
- for (PieceType pt : { PAWN, KNIGHT, KING })
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
- for (int i = 0; steps[pt][i]; ++i)
+ for (PieceType pt = PAWN; pt <= KING; ++pt)
+ for (Square s = SQ_A1; s <= SQ_MAX; ++s)
+ {
+ for (int i = 0; stepsCapture[pt][i]; ++i)
{
- Square to = s + Direction(c == WHITE ? steps[pt][i] : -steps[pt][i]);
+ Square to = s + Direction(c == WHITE ? stepsCapture[pt][i] : -stepsCapture[pt][i]);
- if (is_ok(to) && distance(s, to) < 3)
+ if (is_ok(to) && distance(s, to) < 4)
{
- if (pt == PAWN)
- PawnAttacks[c][s] |= to;
- else
- PseudoAttacks[pt][s] |= to;
+ PseudoAttacks[c][pt][s] |= to;
+ LeaperAttacks[c][pt][s] |= to;
}
}
+ for (int i = 0; stepsQuiet[pt][i]; ++i)
+ {
+ Square to = s + Direction(c == WHITE ? stepsQuiet[pt][i] : -stepsQuiet[pt][i]);
- 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);
+ if (is_ok(to) && distance(s, to) < 4)
+ {
+ PseudoMoves[c][pt][s] |= to;
+ LeaperMoves[c][pt][s] |= to;
+ }
+ }
+ PseudoAttacks[c][pt][s] |= sliding_attack(sliderCapture[pt], s, 0, sliderDistCapture[pt], c);
+ PseudoMoves[c][pt][s] |= sliding_attack(sliderQuiet[pt], s, 0, sliderDistQuiet[pt], c);
+ }
- for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
+ for (Square s1 = SQ_A1; s1 <= SQ_MAX; ++s1)
{
- 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)
+ for (Square s2 = SQ_A1; s2 <= SQ_MAX; ++s2)
+ if (PseudoAttacks[WHITE][pt][s1] & s2)
{
- LineBB[s1][s2] = (attacks_bb(pt, s1, 0) & attacks_bb(pt, s2, 0)) | s1 | s2;
- BetweenBB[s1][s2] = attacks_bb(pt, s1, square_bb(s2)) & attacks_bb(pt, s2, square_bb(s1));
+ LineBB[s1][s2] = (attacks_bb(WHITE, pt, s1, 0) & attacks_bb(WHITE, pt, s2, 0)) | s1 | s2;
- BetweenBB[s1][s2] = attacks_bb(WHITE, pt, s1, SquareBB[s2]) & attacks_bb(WHITE, pt, s2, SquareBB[s1]);
++ BetweenBB[s1][s2] = attacks_bb(WHITE, pt, s1, square_bb(s2)) & attacks_bb(WHITE, pt, s2, square_bb(s1));
}
}
}
Value npm_w = pos.non_pawn_material(WHITE);
Value npm_b = pos.non_pawn_material(BLACK);
- Value npm = std::max(EndgameLimit, std::min(npm_w + npm_b, MidgameLimit));
+ Value npm = clamp(npm_w + npm_b, EndgameLimit, MidgameLimit);
// Map total non-pawn material into [PHASE_ENDGAME, PHASE_MIDGAME]
- e->gamePhase = Phase(((npm - EndgameLimit) * PHASE_MIDGAME) / (MidgameLimit - EndgameLimit));
-
- // Let's look if we have a specialized evaluation function for this particular
- // material configuration. Firstly we look for a fixed configuration one, then
- // for a generic one if the previous search failed.
- if ((e->evaluationFunction = pos.this_thread()->endgames.probe<Value>(key)) != nullptr)
- return e;
-
- for (Color c = WHITE; c <= BLACK; ++c)
- if (is_KXK(pos, c))
- {
- e->evaluationFunction = &EvaluateKXK[c];
- return e;
- }
-
- // OK, we didn't find any special evaluation function for the current material
- // configuration. Is there a suitable specialized scaling function?
- const EndgameBase<ScaleFactor>* sf;
-
- if ((sf = pos.this_thread()->endgames.probe<ScaleFactor>(key)) != nullptr)
+ if (pos.captures_to_hand())
{
- e->scalingFunction[sf->strongSide] = sf; // Only strong color assigned
- return e;
+ npm = VALUE_ZERO;
+ for (PieceType pt : pos.piece_types())
+ npm += (pos.count_in_hand(WHITE, pt) + pos.count_in_hand(BLACK, pt)) * PieceValue[MG][make_piece(WHITE, pt)];
+ e->gamePhase = Phase(PHASE_MIDGAME * (MidgameLimit - std::min(npm, MidgameLimit)) / MidgameLimit);
}
-
- // We didn't find any specialized scaling function, so fall back on generic
- // ones that refer to more than one material distribution. Note that in this
- // case we don't return after setting the function.
- for (Color c = WHITE; c <= BLACK; ++c)
+ else
+ e->gamePhase = Phase(((npm - EndgameLimit) * PHASE_MIDGAME) / (MidgameLimit - EndgameLimit));
+
+#ifdef LARGEBOARDS
+ // Disable endgame evaluation until it works independent of board size
+ if (false)
+#else
+ if (pos.endgame_eval())
+#endif
{
- if (is_KBPsK(pos, c))
- e->scalingFunction[c] = &ScaleKBPsK[c];
-
- else if (is_KQKRPs(pos, c))
- e->scalingFunction[c] = &ScaleKQKRPs[c];
- }
+ // Let's look if we have a specialized evaluation function for this particular
+ // material configuration. Firstly we look for a fixed configuration one, then
+ // for a generic one if the previous search failed.
+ if ((e->evaluationFunction = pos.this_thread()->endgames.probe<Value>(key)) != nullptr)
+ return e;
- if (npm_w + npm_b == VALUE_ZERO && pos.pieces(PAWN)) // Only pawns on the board
- {
- if (!pos.count<PAWN>(BLACK))
+ for (Color c = WHITE; c <= BLACK; ++c)
+ if (is_KFsPsK(pos, c))
+ {
+ e->evaluationFunction = &EvaluateKFsPsK[c];
+ return e;
+ }
+
+ for (Color c = WHITE; c <= BLACK; ++c)
+ if (is_KXK(pos, c))
+ {
+ e->evaluationFunction = &EvaluateKXK[c];
+ return e;
+ }
+
+ // OK, we didn't find any special evaluation function for the current material
+ // configuration. Is there a suitable specialized scaling function?
+ const EndgameBase<ScaleFactor>* sf;
+
+ if ((sf = pos.this_thread()->endgames.probe<ScaleFactor>(key)) != nullptr)
{
- assert(pos.count<PAWN>(WHITE) >= 2);
-
- e->scalingFunction[WHITE] = &ScaleKPsK[WHITE];
+ e->scalingFunction[sf->strongSide] = sf; // Only strong color assigned
+ return e;
}
- else if (!pos.count<PAWN>(WHITE))
+
+ // We didn't find any specialized scaling function, so fall back on generic
+ // ones that refer to more than one material distribution. Note that in this
+ // case we don't return after setting the function.
+ for (Color c = WHITE; c <= BLACK; ++c)
{
- assert(pos.count<PAWN>(BLACK) >= 2);
+ if (is_KBPsK(pos, c))
+ e->scalingFunction[c] = &ScaleKBPsK[c];
- e->scalingFunction[BLACK] = &ScaleKPsK[BLACK];
+ else if (is_KQKRPs(pos, c))
+ e->scalingFunction[c] = &ScaleKQKRPs[c];
}
- else if (pos.count<PAWN>(WHITE) == 1 && pos.count<PAWN>(BLACK) == 1)
+
+ if (npm_w + npm_b == VALUE_ZERO && pos.pieces(PAWN)) // Only pawns on the board
{
- // This is a special case because we set scaling functions
- // for both colors instead of only one.
- e->scalingFunction[WHITE] = &ScaleKPKP[WHITE];
- e->scalingFunction[BLACK] = &ScaleKPKP[BLACK];
+ if (!pos.count<PAWN>(BLACK))
+ {
+ assert(pos.count<PAWN>(WHITE) >= 2);
+
+ e->scalingFunction[WHITE] = &ScaleKPsK[WHITE];
+ }
+ else if (!pos.count<PAWN>(WHITE))
+ {
+ assert(pos.count<PAWN>(BLACK) >= 2);
+
+ e->scalingFunction[BLACK] = &ScaleKPsK[BLACK];
+ }
+ else if (pos.count<PAWN>(WHITE) == 1 && pos.count<PAWN>(BLACK) == 1)
+ {
+ // This is a special case because we set scaling functions
+ // for both colors instead of only one.
+ e->scalingFunction[WHITE] = &ScaleKPKP[WHITE];
+ e->scalingFunction[BLACK] = &ScaleKPKP[BLACK];
+ }
}
- }
- // Zero or just one pawn makes it difficult to win, even with a small material
- // advantage. This catches some trivial draws like KK, KBK and KNK and gives a
- // drawish scale factor for cases such as KRKBP and KmmKm (except for KBBKN).
- if (!pos.count<PAWN>(WHITE) && npm_w - npm_b <= BishopValueMg)
- e->factor[WHITE] = uint8_t(npm_w < RookValueMg ? SCALE_FACTOR_DRAW :
- npm_b <= BishopValueMg ? 4 : 14);
+ // Zero or just one pawn makes it difficult to win, even with a small material
+ // advantage. This catches some trivial draws like KK, KBK and KNK and gives a
+ // drawish scale factor for cases such as KRKBP and KmmKm (except for KBBKN).
+ if (!pos.count<PAWN>(WHITE) && npm_w - npm_b <= BishopValueMg)
+ e->factor[WHITE] = uint8_t(npm_w < RookValueMg ? SCALE_FACTOR_DRAW :
+ npm_b <= BishopValueMg ? 4 : 14);
- if (!pos.count<PAWN>(BLACK) && npm_b - npm_w <= BishopValueMg)
- e->factor[BLACK] = uint8_t(npm_b < RookValueMg ? SCALE_FACTOR_DRAW :
- npm_w <= BishopValueMg ? 4 : 14);
+ if (!pos.count<PAWN>(BLACK) && npm_b - npm_w <= BishopValueMg)
+ e->factor[BLACK] = uint8_t(npm_b < RookValueMg ? SCALE_FACTOR_DRAW :
+ npm_w <= BishopValueMg ? 4 : 14);
+ }
// Evaluate the material imbalance. We use PIECE_TYPE_NONE as a place holder
// for the bishop pair "extended piece", which allows us to be more flexible