From 8d83080d2a389b15140449b182d15eb80f3ee967 Mon Sep 17 00:00:00 2001 From: H.G.Muller Date: Fri, 9 Jan 2026 11:59:42 +0100 Subject: [PATCH] Remove squares that do not block any moves from magic masks The old code was removing edge squares from the Magic masks, but that is only sufficient for sliders. Pieces like Nightriders can already fall off the board when they are two files / ranks away from the edge. The proper procedure is to remove the fore-last square of any ride from the mask. The routine sliding_attack has been adapted to do that, when an additional argument asks it to do so. As a result, the attacks table for Nightriders can now be much smaller: it shrinks from more than 7MB to only 840KB. --- src/bitboard.cpp | 17 ++++++++--------- 1 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/bitboard.cpp b/src/bitboard.cpp index 9eeb16c..d1a9628 100644 --- a/src/bitboard.cpp +++ b/src/bitboard.cpp @@ -84,7 +84,7 @@ namespace { Bitboard ElephantTable[0x400]; // To store elephant attacks Bitboard JanggiElephantTable[0x1C000]; // To store janggi elephant attacks Bitboard CannonDiagTable[0x33C00]; // To store diagonal cannon attacks - Bitboard NightriderTable[0x70200]; // To store nightrider attacks + Bitboard NightriderTable[0xD200]; // To store nightrider attacks Bitboard GrasshopperTableH[0x11800]; // To store horizontal grasshopper attacks Bitboard GrasshopperTableV[0x4800]; // To store vertical grasshopper attacks Bitboard GrasshopperTableD[0x33C00]; // To store diagonal grasshopper attacks @@ -99,7 +99,7 @@ namespace { Bitboard ElephantTable[0x1A0]; // To store elephant attacks Bitboard JanggiElephantTable[0x5C00]; // To store janggi elephant attacks Bitboard CannonDiagTable[0x1480]; // To store diagonal cannon attacks - Bitboard NightriderTable[0x1840]; // To store nightrider attacks + Bitboard NightriderTable[0x500]; // To store nightrider attacks Bitboard GrasshopperTableH[0xA00]; // To store horizontal grasshopper attacks Bitboard GrasshopperTableV[0xA00]; // To store vertical grasshopper attacks Bitboard GrasshopperTableD[0x1480]; // To store diagonal grasshopper attacks @@ -138,7 +138,7 @@ namespace { #endif template - Bitboard one_ride(DirectionCode v, int limit, Square sq, Bitboard occupied, Color c) { + Bitboard one_ride(DirectionCode v, int limit, Square sq, Bitboard occupied, Color c, bool mask) { bool hurdle = false; Direction d = board_step(v); @@ -162,6 +162,8 @@ namespace { is_ok(s) && distance(s, s - d) <= 2; s += d) { + if(mask && (!is_ok(s + d) || distance(s, s + d) > 2)) break; // forelast square is not blocker + if (MT != HOPPER || hurdle) { if(!(lim & 1)) attack |= s; @@ -181,14 +183,14 @@ namespace { } template - Bitboard sliding_attack(std::map directions, Square sq, Bitboard occupied, Color c = WHITE) { + Bitboard sliding_attack(std::map directions, Square sq, Bitboard occupied, Color c = WHITE, bool mask = false) { assert(MT != LAME_LEAPER); Bitboard attack = 0; for (auto const& [v, limit] : directions) { - attack |= one_ride(v, limit & 0xFFFF, sq, occupied, c); + attack |= one_ride(v, limit & 0xFFFF, sq, occupied, c, mask); } return attack; } @@ -532,9 +534,6 @@ Bitboard puzzle(Bitboard key, Bitboard maskBitsToMap, Bitboard magic, int keySta for (Square s = SQ_A1; s <= SQ_MAX; ++s) { - // Board edges are not considered in the relevant occupancies - edges = ((Rank1BB | rank_bb(RANK_MAX)) & ~rank_bb(s)) | ((FileABB | file_bb(FILE_MAX)) & ~file_bb(s)); - // Given a square 's', the mask is the bitboard of sliding attacks from // 's' computed on an empty board. The index must be big enough to contain // all the attacks for each possible subset of the mask and so is 2 power @@ -542,7 +541,7 @@ Bitboard puzzle(Bitboard key, Bitboard maskBitsToMap, Bitboard magic, int keySta // apply to the 64 or 32 bits word to get the index. Magic& m = magics[s]; // The mask for hoppers is unlimited distance, even if the hopper is limited distance (e.g., grasshopper) - m.mask = (MT == LAME_LEAPER ? lame_leaper_path(directions, s) : sliding_attack(directions, s, 0)) & ~edges; + m.mask = (MT == LAME_LEAPER ? lame_leaper_path(directions, s) : sliding_attack(directions, s, 0, WHITE, true)); #ifdef LARGEBOARDS m.shift = 128 - popcount(m.mask); #else -- 1.7.0.4