From 15268d82d4d3f59d9b81751321d4511489932001 Mon Sep 17 00:00:00 2001 From: H.G.Muller Date: Sat, 3 Jan 2026 22:46:41 +0100 Subject: [PATCH] Implement Griffon piece type Four new RiderTypes are added, using 'tableless magics'. Thai is, they use the attacks tables of the Rook, but shifted by one file or rank. The Betza parser in extended to recognize two-leg moves of teh type yafs..., where yafsF is recognized as the Griffon. It then generates the (fake) large leap that is used to indicate these type of bent slides, omitting moves to the first square of the ride. (Because this is what yafsF means). Unbent moves of the type yaf... are recognized as lame ski-sliders. --- src/bitboard.cpp | 40 ++++++++++++++++++++++++++++++++++++++-- src/piece.cpp | 17 +++++++++++++++++ src/piece.h | 2 ++ src/types.h | 11 ++++++++++- 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/bitboard.cpp b/src/bitboard.cpp index 970fe3b..c85dd04 100644 --- a/src/bitboard.cpp +++ b/src/bitboard.cpp @@ -54,11 +54,16 @@ Magic NightriderMagics[SQUARE_NB]; Magic GrasshopperMagicsH[SQUARE_NB]; Magic GrasshopperMagicsV[SQUARE_NB]; Magic GrasshopperMagicsD[SQUARE_NB]; +Magic RookMagicsHT[SQUARE_NB]; +Magic RookMagicsHB[SQUARE_NB]; +Magic RookMagicsVL[SQUARE_NB]; +Magic RookMagicsVR[SQUARE_NB]; Magic CustomMagics[MAX_RIDE - CUSTOM_RIDES][SQUARE_NB]; Magic* magics[MAX_RIDE] = {BishopMagics, RookMagicsH, RookMagicsV, CannonMagicsH, CannonMagicsV, LameDabbabaMagics, HorseMagics, ElephantMagics, JanggiElephantMagics, CannonDiagMagics, NightriderMagics, - GrasshopperMagicsH, GrasshopperMagicsV, GrasshopperMagicsD}; + GrasshopperMagicsH, GrasshopperMagicsV, GrasshopperMagicsD, + RookMagicsHT, RookMagicsHB, RookMagicsVL, RookMagicsVR }; int nrOfRides; int riderBaseType[MAX_RIDE]; @@ -116,6 +121,10 @@ namespace { const std::map GrasshopperDirectionsH { {step(0, 1), 0xFFFE}, {step(0, -1), 0xFFFE} }; const std::map GrasshopperDirectionsD { {step(1, 1), 0xFFFE}, {step(-1, 1), 0xFFFE}, {step(-1, -1), 0xFFFE}, {step(1, -1), 0xFFFE} }; + const std::map RookDirectionsHT { {step(1, -BENT), 0}, {step(1, BENT), 0} }; + const std::map RookDirectionsHB { {step(-1, -BENT), 0}, {step(-1, BENT), 0} }; + const std::map RookDirectionsVL { {step(-BENT, -1), 0}, {step(BENT, -1), 0} }; + const std::map RookDirectionsVR { {step(-BENT, 1), 0}, {step(BENT, 1), 0} }; const std::map allDirections[] { BishopDirections, RookDirectionsH, RookDirectionsV }; @@ -133,13 +142,23 @@ namespace { bool hurdle = false; Direction d = board_step(v); + Direction x = h_step(v); + Direction y = v_step(v); int lim = limit; + Square ss = sq; 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; + if(std::abs(x) == BENT) { // bent slider + d = x/BENT; ss += y*FILE_NB; + } else + if(std::abs(y) == BENT) { // bent slider + d = y*FILE_NB/BENT; ss += x; + } + + for (Square s = ss + d; is_ok(s) && distance(s, s - d) <= 2; s += d) { @@ -322,6 +341,14 @@ void Bitboards::init_pieces() { riderTypes |= assign_magic(RIDER_ROOK_V, limit); if (HorseDirections.find(d) != HorseDirections.end()) riderTypes |= RIDER_NIGHTRIDER; + if (RookDirectionsHT.find(d) != RookDirectionsHT.end()) + riderTypes |= RIDER_ROOK_HT; + if (RookDirectionsVR.find(d) != RookDirectionsVR.end()) + riderTypes |= RIDER_ROOK_VR; + if (RookDirectionsHB.find(d) != RookDirectionsHB.end()) + riderTypes |= RIDER_ROOK_HB; + if (RookDirectionsVL.find(d) != RookDirectionsVL.end()) + riderTypes |= RIDER_ROOK_VL; } for (auto const& [d, limit] : pi->hopper[initial][modality]) { @@ -420,6 +447,15 @@ void Bitboards::init() { nrOfRides = CUSTOM_RIDES; for(int i = 0; i < CUSTOM_RIDES; i++) riderBaseType[i] = i; ++ + // Magics that can use attacks tables from others + for(Square s = SQ_A1; s <= SQ_MAX; ++s) + { + RookMagicsHT[s] = RookMagicsH[rank_of(s) < RANK_NB - 1 ? s + FILE_NB : s - FILE_NB]; + RookMagicsHB[s] = RookMagicsH[rank_of(s) > 0 ? s - FILE_NB : s + FILE_NB]; + RookMagicsVR[s] = RookMagicsV[file_of(s) < FILE_NB - 1 ? s + 1 : s - 1]; + RookMagicsVL[s] = RookMagicsV[file_of(s) > 0 ? s - 1 : s + 1]; + } init_pieces(); diff --git a/src/piece.cpp b/src/piece.cpp index 82a4117..851bbc8 100644 --- a/src/piece.cpp +++ b/src/piece.cpp @@ -64,6 +64,7 @@ namespace { int distance = 0; int fExtension = 0; int fsExtension = 0; + BentType bent = SINGLE_LEG; std::vector prelimDirections = {}; for (std::string::size_type i = 0; i < betza.size(); i++) { @@ -103,6 +104,17 @@ namespace { } prelimDirections.push_back(std::string(2, c)); } + // Multi-leg + else if(betza.size() > i + 3 && (c == 'a' || (c == 'y' && betza[++i] == 'a'))) // detect yaf(s) + { + if(betza[i+1] == 'f' && c == 'y') + { + if(betza[i+2] == 's') { i++; bent = BENT_SLIDER; } + else bent = SKI_SLIDER; + i++; distance |= 1; // suppress 1-step moves + moveModalities.clear(); + } + } // Move atom else if (leaperAtoms.find(c) != leaperAtoms.end() || riderAtoms.find(c) != riderAtoms.end()) { @@ -141,6 +153,10 @@ namespace { int y = atom.first + 3*fExtension + 2*fsExtension; int x = atom.second + 2*fsExtension; std::vector directions = {}; + if(bent != SINGLE_LEG) { + if(bent == BENT_SLIDER && c == 'F') y = BENT; // yafsF = griffon + rider = true; + } if(rider && y > 1 && (x == 0 || x == y)) { // radial true rider for(int n = distance; ~n & 1; n >>= 1) distance <<= y - 1; // adapt range to larger stride distance &= 0xFFFF; @@ -197,6 +213,7 @@ namespace { distance = 0; fExtension = 0; fsExtension = 0; + bent = SINGLE_LEG; } } return p; diff --git a/src/piece.h b/src/piece.h index 38fdcc9..d83e5d3 100644 --- a/src/piece.h +++ b/src/piece.h @@ -27,6 +27,8 @@ namespace Stockfish { +const int BENT = 9; // kludge for indicating bent slider as leap + enum MoveModality {MODALITY_QUIET, MODALITY_CAPTURE, MOVE_MODALITY_NB}; /// PieceInfo struct stores information about the piece movements. diff --git a/src/types.h b/src/types.h index aac1085..620e99b 100644 --- a/src/types.h +++ b/src/types.h @@ -450,6 +450,10 @@ enum PieceSet : uint64_t { COMMON_STEP_PIECES = (1ULL << COMMONER) | (1ULL << FERS) | (1ULL << WAZIR) | (1ULL << BREAKTHROUGH_PIECE), }; +enum BentType : int { + SINGLE_LEG, SKI_SLIDER, BENT_SLIDER, HOOK_MOVER +}; + enum RiderType : int { NO_RIDER = 0, RIDER_BISHOP = 1 << 0, @@ -466,10 +470,15 @@ enum RiderType : int { RIDER_GRASSHOPPER_H = 1 << 11, RIDER_GRASSHOPPER_V = 1 << 12, RIDER_GRASSHOPPER_D = 1 << 13, + RIDER_ROOK_HT = 1 << 14, + RIDER_ROOK_HB = 1 << 15, + RIDER_ROOK_VL = 1 << 16, + RIDER_ROOK_VR = 1 << 17, + RIDER_GRIFFON = RIDER_ROOK_HT | RIDER_ROOK_HB | RIDER_ROOK_VL | RIDER_ROOK_VR, HOPPING_RIDERS = RIDER_CANNON_H | RIDER_CANNON_V | RIDER_CANNON_DIAG | RIDER_GRASSHOPPER_H | RIDER_GRASSHOPPER_V | RIDER_GRASSHOPPER_D, LAME_LEAPERS = RIDER_LAME_DABBABA | RIDER_HORSE | RIDER_ELEPHANT | RIDER_JANGGI_ELEPHANT, - ASYMMETRICAL_RIDERS = RIDER_HORSE | RIDER_JANGGI_ELEPHANT + ASYMMETRICAL_RIDERS = RIDER_HORSE | RIDER_JANGGI_ELEPHANT | GRIFFON | RIDER_GRASSHOPPER_H | RIDER_GRASSHOPPER_V | RIDER_GRASSHOPPER_D, NON_SLIDING_RIDERS = HOPPING_RIDERS | LAME_LEAPERS | RIDER_NIGHTRIDER, CUSTOM_RIDES = 20, -- 1.7.0.4