Magic GrasshopperMagicsH[SQUARE_NB];
Magic GrasshopperMagicsV[SQUARE_NB];
Magic GrasshopperMagicsD[SQUARE_NB];
+Magic CustomMagics[MAX_RIDE - CUSTOM_RIDES][SQUARE_NB];
-Magic* magics[] = {BishopMagics, RookMagicsH, RookMagicsV, CannonMagicsH, CannonMagicsV,
+Magic* magics[MAX_RIDE] = {BishopMagics, RookMagicsH, RookMagicsV, CannonMagicsH, CannonMagicsV,
LameDabbabaMagics, HorseMagics, ElephantMagics, JanggiElephantMagics, CannonDiagMagics, NightriderMagics,
GrasshopperMagicsH, GrasshopperMagicsV, GrasshopperMagicsD};
+int nrOfRides;
+int riderBaseType[MAX_RIDE];
+int riderRangeMask[MAX_RIDE];
+
namespace {
// Some magics need to be split in order to reduce memory consumption.
const std::map<DirectionCode, int> GrasshopperDirectionsD { {step(1, 1), 0xFFFE}, {step(-1, 1), 0xFFFE},
{step(-1, -1), 0xFFFE}, {step(1, -1), 0xFFFE} };
+ const std::map<DirectionCode, int> allDirections[] { BishopDirections, RookDirectionsH, RookDirectionsV };
+
enum MovementType { RIDER, HOPPER, LAME_LEAPER, HOPPER_RANGE };
template <MovementType MT>
return s;
}
+/// Derive a new RiderType from a sliding one, (if it did not exist yet)
+/// by removing squares to be skipped from the masks of the latter
+
+RiderType assign_magic(RiderType r, int limit) {
+
+ int n = lsb(r);
+ int i;
+ limit >>= 16;
+
+ for(i = 0; i < nrOfRides; i++)
+ if(riderBaseType[i] == n && riderRangeMask[i] == limit) return RiderType(1 << i);
+
+ if(nrOfRides == MAX_RIDE) return r; // use standard mask if capacity exceeded
+
+ i = nrOfRides++; // allocate new magic
+ riderBaseType[i] = n;
+ riderRangeMask[i] = limit;
+ Magic* m = CustomMagics[i - CUSTOM_RIDES];
+ magics[i] = m;
+
+ for(Square s = SQ_A1; s < SQUARE_NB; ++s)
+ {
+ Bitboard b = 0;
+ m[s] = magics[n][s];
+
+ for (auto const& [v, limit2] : allDirections[n]) {
+ b |= one_ride<RIDER>(v, limit, s, 0, WHITE);
+ }
+ m[s].mask &= b; // restrict mask according to high bits of limit
+ }
+
+ return RiderType(1 << i);
+}
+
/// Bitboards::init_pieces() initializes piece move/attack bitboards and rider types
void Bitboards::init_pieces() {
for (auto const& [d, limit] : pi->slider[initial][modality])
{
if (BishopDirections.find(d) != BishopDirections.end())
- riderTypes |= RIDER_BISHOP;
+ riderTypes |= assign_magic(RIDER_BISHOP, limit);
if (RookDirectionsH.find(d) != RookDirectionsH.end())
- riderTypes |= RIDER_ROOK_H;
+ riderTypes |= assign_magic(RIDER_ROOK_H, limit);
if (RookDirectionsV.find(d) != RookDirectionsV.end())
- riderTypes |= RIDER_ROOK_V;
+ riderTypes |= assign_magic(RIDER_ROOK_V, limit);
if (HorseDirections.find(d) != HorseDirections.end())
riderTypes |= RIDER_NIGHTRIDER;
}
init_magics<HOPPER>(GrasshopperTableD, GrasshopperMagicsD, GrasshopperDirectionsD);
#endif
+ nrOfRides = CUSTOM_RIDES;
+ for(int i = 0; i < CUSTOM_RIDES; i++) riderBaseType[i] = i;
+
init_pieces();
for (Square s1 = SQ_A1; s1 <= SQ_MAX; ++s1)