piece_to_partner (#802)
authorBajusz Tamás <gbtami@users.noreply.github.com>
Mon, 8 Jul 2024 15:07:01 +0000 (17:07 +0200)
committerGitHub <noreply@github.com>
Mon, 8 Jul 2024 15:07:01 +0000 (17:07 +0200)
setup.py
src/position.h
src/pyffish.cpp
test.py

index fa72818..0c690e1 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -39,7 +39,7 @@ pyffish_module = Extension(
     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",
index adaeeb6..d023725 100644 (file)
@@ -279,6 +279,7 @@ public:
   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;
 }
index fb8094f..0fa355c 100644 (file)
@@ -280,6 +280,21 @@ extern "C" PyObject* pyffish_isCapture(PyObject* self, PyObject *args) {
 }
 
 // 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<StateInfo>(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) {
     PyObject *moveList;
@@ -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 7a5aa45..bef4e5f 100644 (file)
--- a/test.py
+++ b/test.py
@@ -974,6 +974,27 @@ class TestPyffish(unittest.TestCase):
         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)