From: Ada Joule Date: Sat, 17 Sep 2022 13:59:48 +0000 (+0700) Subject: Implement correct Cambodian opening moves (#514) X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=685a446cec57e050998fb429a0f788513957cb9d;p=fairystockfish.git Implement correct Cambodian opening moves (#514) Article 5, Items 3 and 4 https://docs.google.com/document/d/1adppJ66vonM27UYwC-KyldXl7oZ_5Pb0/edit?usp=sharing&ouid=116281580550740302191&rtpof=true&sd=true - The king now loses the ability to leap if an enemy rook moves into the same rank or file - The ferz can no longer capture with its leap --- diff --git a/src/movegen.cpp b/src/movegen.cpp index ee9039a..b8e1d1a 100644 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@ -356,13 +356,13 @@ namespace { } // Special moves - if (pos.cambodian_moves() && pos.gates(Us)) + if (pos.cambodian_moves() && pos.gates(Us) && Type != CAPTURES) { - if (Type != CAPTURES && Type != EVASIONS && (pos.pieces(Us, KING) & pos.gates(Us))) + if (Type != EVASIONS && (pos.pieces(Us, KING) & pos.gates(Us))) { Square from = pos.square(Us); Bitboard b = PseudoAttacks[WHITE][KNIGHT][from] & rank_bb(rank_of(from + (Us == WHITE ? NORTH : SOUTH))) - & target & ~pos.pieces(); + & target & ~pos.pieces(); while (b) moveList = make_move_and_gating(pos, moveList, Us, from, pop_lsb(b)); } @@ -372,7 +372,7 @@ namespace { { Square from = pop_lsb(b); Square to = from + 2 * (Us == WHITE ? NORTH : SOUTH); - if (is_ok(to) && (target & to)) + if (is_ok(to) && (target & to & ~pos.pieces())) moveList = make_move_and_gating(pos, moveList, Us, from, to); } } diff --git a/src/position.cpp b/src/position.cpp index 966766e..1135563 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -911,14 +911,6 @@ Bitboard Position::attackers_to(Square s, Bitboard occupied, Color c, Bitboard j b |= attacks_bb(~c, move_pt, s, occupied) & pieces(c, pt); } - // Consider special move of neang in cambodian chess - if (cambodian_moves()) - { - Square fers_sq = s + 2 * (c == WHITE ? SOUTH : NORTH); - if (is_ok(fers_sq)) - b |= pieces(c, FERS) & gates(c) & fers_sq; - } - // Janggi palace moves if (diagonal_lines() & s) { @@ -1772,6 +1764,10 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) { st->gatesBB[us] = 0; } + // Remove king leaping right when aimed by a rook + if (cambodian_moves() && type_of(pc) == ROOK && (square(them) & gates(them) & attacks_bb(to))) + st->gatesBB[them] ^= square(them); + // Remove the blast pieces if (captured && blast_on_capture()) { diff --git a/test.py b/test.py index 8ea4620..f56635d 100644 --- a/test.py +++ b/test.py @@ -12,6 +12,7 @@ CAPA = "rnabqkbcnr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNABQKBCNR w KQkq - 0 1" CAPAHOUSE = "rnabqkbcnr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNABQKBCNR[] w KQkq - 0 1" SITTUYIN = "8/8/4pppp/pppp4/4PPPP/PPPP4/8/8[KFRRSSNNkfrrssnn] w - - 0 1" MAKRUK = "rnsmksnr/8/pppppppp/8/8/PPPPPPPP/8/RNSKMSNR w - - 0 1" +CAMBODIAN = "rnsmksnr/8/pppppppp/8/8/PPPPPPPP/8/RNSKMSNR w DEde - 0 1" SHOGI = "lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL[-] w - - 0 1" SHOGI_SFEN = "lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1" SEIRAWAN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR[EHeh] w KQBCDFGkqbcdfg - 0 1" @@ -289,6 +290,13 @@ class TestPyffish(unittest.TestCase): result = sf.legal_moves("shogun", SHOGUN, ["c2c4", "b8c6", "b2b4", "b7b5", "c4b5", "c6b8"]) self.assertIn("b5b6+", result) + # Cambodian queen cannot capture with its leap + # Cambodian king cannot leap to escape check + result = sf.legal_moves("cambodian", CAMBODIAN, ["b1d2", "g8e7", "d2e4", "d6d5", "e4d6"]) + self.assertNotIn("d8d6", result) + self.assertNotIn("e8g7", result) + self.assertNotIn("e8c7", result) + # In Janggi stalemate position pass move (in place king move) is possible fen = "4k4/c7R/9/3R1R3/9/9/9/9/9/3K5 b - - 0 1" result = sf.legal_moves("janggi", fen, []) @@ -522,6 +530,22 @@ class TestPyffish(unittest.TestCase): result = sf.get_fen("asean", fen, moves, False, False, False) self.assertEqual(result, "3QQ3/8/4K3/3Q4/1k6/8/8/8 b - - 0 1") + # Cambodian king loses its leap ability when it is "aimed" by a rook + fen = "rnsmk1nr/4s3/pppppppp/8/8/PPPPPPPP/R7/1NSKMSNR w DEde - 2 2" + moves = ["a2e2"] + result = sf.get_fen("cambodian", fen, moves, False, False, True) + self.assertEqual(result, "rnsmk1nr/4s3/pppppppp/8/8/PPPPPPPP/4R3/1NSKMSNR b DEd - 3 2") + + fen = "1nsmksnr/r7/pppppppp/8/8/PPPPPPPP/2SN4/R2KMSNR b DEde - 3 2" + moves = ["a7d7"] + result = sf.get_fen("cambodian", fen, moves, False, False, True) + self.assertEqual(result, "1nsmksnr/3r4/pppppppp/8/8/PPPPPPPP/2SN4/R2KMSNR w Ede - 4 3") + + fen = "rnsmksnr/8/1ppppppp/8/8/1PPPPPPP/8/RNSKMSNR w DEde - 0 1" + moves = ["a1a8"] + result = sf.get_fen("cambodian", fen, moves, False, False, True) + self.assertEqual(result, "Rnsmksnr/8/1ppppppp/8/8/1PPPPPPP/8/1NSKMSNR b DEd - 0 1") + def test_get_san(self): fen = "4k3/8/3R4/8/1R3R2/8/3R4/4K3 w - - 0 1" result = sf.get_san("chess", fen, "b4d4") diff --git a/tests/perft.sh b/tests/perft.sh index 9f00fa7..a34d052 100755 --- a/tests/perft.sh +++ b/tests/perft.sh @@ -40,9 +40,9 @@ if [[ $1 == "all" || $1 == "variant" ]]; then expect perft.exp losalamos "fen 6/2P3/6/1K1k2/6/6 w - - 0 1" 6 187431 > /dev/null # fairy expect perft.exp makruk startpos 4 273026 > /dev/null - expect perft.exp cambodian startpos 4 361793 > /dev/null + expect perft.exp cambodian startpos 4 361719 > /dev/null expect perft.exp cambodian "fen r1s1ks1r/3nm3/pppNpppp/3n4/5P2/PPPPPNPP/8/R1SKMS1R b DEe 0 0 5" 2 72 > /dev/null - expect perft.exp karouk "fen rn1mksnr/3s4/pppppppp/8/4N3/PPPPPPPP/8/R1SKMSNR b DEde - 3 2" 4 358535 > /dev/null + expect perft.exp karouk "fen rn1mksnr/3s4/pppppppp/8/4N3/PPPPPPPP/8/R1SKMSNR b DEde - 3 2" 4 358460 > /dev/null expect perft.exp makpong "fen 3mk3/r3s1R1/1psppnp1/p1pn4/1P2NP2/P1PPP1P1/4NS2/R1SKM3 w - - 0 1" 4 593103 > /dev/null expect perft.exp asean startpos 4 273026 > /dev/null expect perft.exp ai-wok startpos 4 485045 > /dev/null