From 06b18d187bd6d1329e6af5e0dfb0bb6aa989aad0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bajusz=20Tam=C3=A1s?= Date: Mon, 8 Jul 2024 17:07:01 +0200 Subject: [PATCH] piece_to_partner (#802) --- setup.py | 2 +- src/position.h | 10 ++++++++++ src/pyffish.cpp | 16 ++++++++++++++++ test.py | 21 +++++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index fa72818d2..0c690e12d 100644 --- a/setup.py +++ b/setup.py @@ -39,7 +39,7 @@ sources=sources, extra_compile_args=args) -setup(name="pyffish", version="0.0.82", +setup(name="pyffish", version="0.0.83", description="Fairy-Stockfish Python wrapper", long_description=long_description, long_description_content_type="text/markdown", diff --git a/src/position.h b/src/position.h index adaeeb6ad..d02372567 100644 --- a/src/position.h +++ b/src/position.h @@ -279,6 +279,7 @@ class Position { bool gives_check(Move m) const; Piece moved_piece(Move m) const; Piece captured_piece() const; + const std::string piece_to_partner() const; // Piece specific bool pawn_passed(Color c, Square s) const; @@ -1410,6 +1411,15 @@ inline Piece Position::captured_piece() const { return st->capturedPiece; } +inline const std::string Position::piece_to_partner() const { + if (!st->capturedPiece) return std::string(); + Color color = color_of(st->capturedPiece); + Piece piece = st->capturedpromoted ? + (st->unpromotedCapturedPiece ? st->unpromotedCapturedPiece : make_piece(color, promotion_pawn_type(color))) : + st->capturedPiece; + return std::string(1, piece_to_char()[piece]); +} + inline Thread* Position::this_thread() const { return thisThread; } diff --git a/src/pyffish.cpp b/src/pyffish.cpp index fb8094f2f..0fa355c9f 100644 --- a/src/pyffish.cpp +++ b/src/pyffish.cpp @@ -279,6 +279,21 @@ extern "C" PyObject* pyffish_isCapture(PyObject* self, PyObject *args) { return Py_BuildValue("O", pos.capture(UCI::to_move(pos, moveStr)) ? Py_True : Py_False); } +// INPUT variant, fen, move list +extern "C" PyObject* pyffish_pieceToPartner(PyObject* self, PyObject *args) { + PyObject *moveList; + Position pos; + const char *fen, *variant; + int chess960 = false; + if (!PyArg_ParseTuple(args, "ssO!|p", &variant, &fen, &PyList_Type, &moveList, &chess960)) { + return NULL; + } + + StateListPtr states(new std::deque(1)); + buildPosition(pos, states, variant, fen, moveList, chess960); + return Py_BuildValue("s", pos.piece_to_partner().c_str()); +} + // INPUT variant, fen, move list // should only be called when the move list is empty extern "C" PyObject* pyffish_gameResult(PyObject* self, PyObject *args) { @@ -384,6 +399,7 @@ static PyMethodDef PyFFishMethods[] = { {"get_fen", (PyCFunction)pyffish_getFEN, METH_VARARGS, "Get resulting FEN from given FEN and movelist."}, {"gives_check", (PyCFunction)pyffish_givesCheck, METH_VARARGS, "Get check status from given FEN and movelist."}, {"is_capture", (PyCFunction)pyffish_isCapture, METH_VARARGS, "Get whether given move is a capture from given FEN and movelist."}, + {"piece_to_partner", (PyCFunction)pyffish_pieceToPartner, METH_VARARGS, "Get unpromoted captured piece from given FEN and movelist."}, {"game_result", (PyCFunction)pyffish_gameResult, METH_VARARGS, "Get result from given FEN, considering variant end, checkmate, and stalemate."}, {"is_immediate_game_end", (PyCFunction)pyffish_isImmediateGameEnd, METH_VARARGS, "Get result from given FEN if variant rules ends the game."}, {"is_optional_game_end", (PyCFunction)pyffish_isOptionalGameEnd, METH_VARARGS, "Get result from given FEN it rules enable game end by player."}, diff --git a/test.py b/test.py index 7a5aa456b..bef4e5f6e 100644 --- a/test.py +++ b/test.py @@ -974,6 +974,27 @@ def test_is_capture(self): result = sf.is_capture("sittuyin", "8/2k5/8/4P3/4P1N1/5K2/8/8[] w - - 0 1", [], "e5e5f") self.assertFalse(result) + def test_piece_to_partner(self): + # take the rook and promote to queen + result = sf.piece_to_partner("bughouse", "r2qkbnr/1Ppppppp/2n5/8/8/8/1PPPPPPP/RNBQKBNR[] w KQkq - 0 1", ["b7a8q"]) + self.assertEqual(result, "r") + + # take back the queen (promoted pawn) + result = sf.piece_to_partner("bughouse", "r2qkbnr/1Ppppppp/2n5/8/8/8/1PPPPPPP/RNBQKBNR[] w KQkq - 0 1", ["b7a8q", "d8a8"]) + self.assertEqual(result, "P") + + # just a simple move (no take) + result = sf.piece_to_partner("bughouse", "r2qkbnr/1Ppppppp/2n5/8/8/8/1PPPPPPP/RNBQKBNR[] w KQkq - 0 1", ["b7a8q", "d8b8"]) + self.assertEqual(result, "") + + # silver takes the pawn and promotes to gold + result = sf.piece_to_partner("shogi", "lnsgkgsnl/1r5b1/ppppppppp/S8/9/9/PPPPPPPPP/1B5R1/LNSGKG1NL[] w 0 1", ["a6a7+"]) + self.assertEqual(result, "p") + + # take back the gold (promoted silver) + result = sf.piece_to_partner("shogi", "lnsgkgsnl/1r5b1/ppppppppp/S8/9/9/PPPPPPPPP/1B5R1/LNSGKG1NL[] w 0 1", ["a6a7+", "a9a7"]) + self.assertEqual(result, "S") + def test_game_result(self): result = sf.game_result("chess", CHESS, ["f2f3", "e7e5", "g2g4", "d8h4"]) self.assertEqual(result, -sf.VALUE_MATE)