From: H.G.Muller Date: Sat, 3 Jan 2026 19:07:19 +0000 (+0100) Subject: Allow encoding of non-contiguous slider ranges X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=22b88407fee5056cfb0a2bb505028853c776f4a4;p=fairystockfish.git Allow encoding of non-contiguous slider ranges The range of sliders as encoded in the steps/slidrs/hoppers maps that are passed from the Betza parser to the attack bitboard generators are no longer encoded as a number that indicates the range, but as the set of squares along the ray. Each of the lower 16 bits in this parameter corresponds to such a square, and setting the bit would deny access to that by keeping it out of the pseudoMoves/Attacks bitboards. So a range-3 slider would need code 0xFFF8, range 4 0xFFF0 etc. This opens the possibility to encode lame ski-sliders by passing a 1, excluding the first square on the ray as destination. (But keeping it as a potential blocking square of the entire slide. Or lame riders like the Dabbabarider (0x5555) or lame Panda (0xAAAAA), in combination with the Rook magics. This does not affect leapers, which keep using a 1 code for encoding lameness. Note that although non-contiguous destinations can currently break FSF's check detection, leading to crashes. This occurs with sliders that can deliver check by moving radially away from the King, such as lame ski-sliders. Lame elemntary riders (DD, AA, HH) should be OK. --- diff --git a/src/bitboard.cpp b/src/bitboard.cpp index b590265..da2f98d 100644 --- a/src/bitboard.cpp +++ b/src/bitboard.cpp @@ -122,27 +122,24 @@ namespace { #endif template - Bitboard sliding_attack(std::map directions, Square sq, Bitboard occupied, Color c = WHITE) { - assert(MT != LAME_LEAPER); - - Bitboard attack = 0; + Bitboard one_ride(DirectionCode v, int limit, Square sq, Bitboard occupied, Color c) { - for (auto const& [v, limit] : directions) - { - int count = 0; bool hurdle = false; Direction d = board_step(v); - for (Square s = sq + (c == WHITE ? d : -d); - is_ok(s) && distance(s, s - (c == WHITE ? d : -d)) <= 2; - s += (c == WHITE ? d : -d)) + int lim = limit; + Bitboard attack = 0; + + if(c != WHITE) d = -d; + if(MT == HOPPER_RANGE && limit == 0xFFFE) lim = 0; // give grasshopper unlimited total range + + for (Square s = sq + d; + is_ok(s) && distance(s, s - d) <= 2; + s += d) { if (MT != HOPPER || hurdle) { - attack |= s; - // For hoppers we consider limit == 1 as a grasshopper, - // but limit > 1 as a limited distance hopper - if (limit && !(MT == HOPPER_RANGE && limit == 1) && ++count >= limit) - break; + if(!(lim & 1)) attack |= s; + lim >>= 1; } if (occupied & s) @@ -153,8 +150,20 @@ namespace { break; } } - } + return attack; + } + + template + Bitboard sliding_attack(std::map directions, Square sq, Bitboard occupied, Color c = WHITE) { + assert(MT != LAME_LEAPER); + + Bitboard attack = 0; + + for (auto const& [v, limit] : directions) + { + attack |= one_ride(v, limit & 0xFFFF, sq, occupied, c); + } return attack; } diff --git a/src/piece.cpp b/src/piece.cpp index cd6660e..f6ad675 100644 --- a/src/piece.cpp +++ b/src/piece.cpp @@ -77,7 +77,7 @@ namespace { hopper = true; // Grasshopper if (c == 'g') - distance = 1; + distance = 0xFFFE; // range 1 } // Lame leaper else if (c == 'n') @@ -123,7 +123,7 @@ namespace { if (isdigit(betza[i])) { int range = betza[i] - '0'; if(range) - distance = range; + distance |= (0xFFFF << range & 0xFFFF); } } else i--; } diff --git a/src/psqt.cpp b/src/psqt.cpp index 0732c4d..827bf9c 100644 --- a/src/psqt.cpp +++ b/src/psqt.cpp @@ -157,7 +157,8 @@ constexpr Score PBonus[RANK_NB][FILE_NB] = int slider_fraction(std::map slider) { int s = 0; for (auto const& [_, limit] : slider) { - s += limit == 0 ? 100 : 200 * std::min(limit + 1, 8) / 16; + int targets = popcount(~limit & 0xFFFF); // in reality non-reachable squares should be weighted by distance + s += limit == 0 ? 100 : 200 * std::min(targets + 1, 8) / 16; } return s; }