Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement fog_fen() #840

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
sources=sources,
extra_compile_args=args)

setup(name="pyffish", version="0.0.84",
setup(name="pyffish", version="0.0.85",
description="Fairy-Stockfish Python wrapper",
long_description=long_description,
long_description_content_type="text/markdown",
Expand Down
6 changes: 3 additions & 3 deletions src/position.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ Position& Position::set(const string& code, Color c, StateInfo* si) {
/// Position::fen() returns a FEN representation of the position. In case of
/// Chess960 the Shredder-FEN notation is used. This is mainly a debugging function.

string Position::fen(bool sfen, bool showPromoted, int countStarted, std::string holdings) const {
string Position::fen(bool sfen, bool showPromoted, int countStarted, std::string holdings, Bitboard fogArea) const {

int emptyCnt;
std::ostringstream ss;
Expand All @@ -690,15 +690,15 @@ string Position::fen(bool sfen, bool showPromoted, int countStarted, std::string
{
for (File f = FILE_A; f <= max_file(); ++f)
{
for (emptyCnt = 0; f <= max_file() && !(pieces() & make_square(f, r)); ++f)
for (emptyCnt = 0; f <= max_file() && !(pieces() & make_square(f, r)) && !(fogArea & make_square(f, r)); ++f)
++emptyCnt;

if (emptyCnt)
ss << emptyCnt;

if (f <= max_file())
{
if (empty(make_square(f, r)))
if (empty(make_square(f, r)) || fogArea & make_square(f, r))
// Wall square
ss << "*";
else if (unpromoted_piece_on(make_square(f, r)))
Expand Down
17 changes: 16 additions & 1 deletion src/position.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class Position {
// FEN string input/output
Position& set(const Variant* v, const std::string& fenStr, bool isChess960, StateInfo* si, Thread* th, bool sfen = false);
Position& set(const std::string& code, Color c, StateInfo* si);
std::string fen(bool sfen = false, bool showPromoted = false, int countStarted = 0, std::string holdings = "-") const;
std::string fen(bool sfen = false, bool showPromoted = false, int countStarted = 0, std::string holdings = "-", Bitboard fogArea = 0) const;

// Variant rule properties
const Variant* variant() const;
Expand Down Expand Up @@ -328,6 +328,7 @@ class Position {
Score psq_score() const;
Value non_pawn_material(Color c) const;
Value non_pawn_material() const;
Bitboard fog_area() const;

// Position consistency check, for debugging
bool pos_is_ok() const;
Expand Down Expand Up @@ -1407,6 +1408,20 @@ inline Piece Position::captured_piece() const {
return st->capturedPiece;
}

inline Bitboard Position::fog_area() const {
Bitboard b = board_bb();
// Our own pieces are visible
Bitboard visible = pieces(sideToMove);
// Squares where we can move to are visible as well
for (const auto& m : MoveList<LEGAL>(*this))
{
Square to = to_sq(m);
visible |= to;
}
// Everything else is invisible
return ~visible & b;
}

inline const std::string Position::piece_to_partner() const {
if (!st->capturedPiece) return std::string();
Color color = color_of(st->capturedPiece);
Expand Down
19 changes: 18 additions & 1 deletion src/pyffish.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ void buildPosition(Position& pos, StateListPtr& states, const char *variant, con
}

extern "C" PyObject* pyffish_version(PyObject* self) {
return Py_BuildValue("(iii)", 0, 0, 84);
return Py_BuildValue("(iii)", 0, 0, 85);
}

extern "C" PyObject* pyffish_info(PyObject* self) {
Expand Down Expand Up @@ -383,6 +383,22 @@ extern "C" PyObject* pyffish_validateFen(PyObject* self, PyObject *args) {
return Py_BuildValue("i", FEN::validate_fen(std::string(fen), variants.find(std::string(variant))->second, chess960));
}

// INPUT variant, fen
extern "C" PyObject* pyffish_getFogFEN(PyObject* self, PyObject *args) {
PyObject* moveList = PyList_New(0);
Position pos;
const char *fen, *variant;

int chess960 = false, sfen = false, showPromoted = false, countStarted = 0;
if (!PyArg_ParseTuple(args, "ss|p", &fen, &variant, &chess960)) {
return NULL;
}
StateListPtr states(new std::deque<StateInfo>(1));
buildPosition(pos, states, variant, fen, moveList, chess960);

Py_XDECREF(moveList);
return Py_BuildValue("s", pos.fen(sfen, showPromoted, countStarted, "-", pos.fog_area()).c_str());
}

static PyMethodDef PyFFishMethods[] = {
{"version", (PyCFunction)pyffish_version, METH_NOARGS, "Get package version."},
Expand All @@ -405,6 +421,7 @@ static PyMethodDef PyFFishMethods[] = {
{"is_optional_game_end", (PyCFunction)pyffish_isOptionalGameEnd, METH_VARARGS, "Get result from given FEN it rules enable game end by player."},
{"has_insufficient_material", (PyCFunction)pyffish_hasInsufficientMaterial, METH_VARARGS, "Checks for insufficient material."},
{"validate_fen", (PyCFunction)pyffish_validateFen, METH_VARARGS, "Validate an input FEN."},
{"get_fog_fen", (PyCFunction)pyffish_getFogFEN, METH_VARARGS, "Get Fog of War FEN from given FEN."},
{NULL, NULL, 0, NULL}, // sentinel
};

Expand Down
17 changes: 17 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@
customPiece5 = f:mBpBmWpR2
promotedPieceType = u:w a:w c:f i:f
startFen = lnsgkgsnl/1rci1uab1/p1p1p1p1p/9/9/9/P1P1P1P1P/1BAU1ICR1/LNSGKGSNL[-] w 0 1

[fogofwar:chess]
king = -
commoner = k
castlingKingPiece = k
extinctionValue = loss
extinctionPieceTypes = k
"""

sf.load_variant_config(ini_text)
Expand Down Expand Up @@ -1151,5 +1158,15 @@ def test_validate_fen(self):
fen = sf.start_fen(variant)
self.assertEqual(sf.validate_fen(fen, variant), sf.FEN_OK)

def test_get_fog_fen(self):
fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" # startpos
result = sf.get_fog_fen(fen, "fogofwar")
self.assertEqual(result, "********/********/********/********/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")

fen = "rnbqkbnr/p1p2ppp/8/Pp1pp3/4P3/8/1PPP1PPP/RNBQKBNR w KQkq b6 0 1"
result = sf.get_fog_fen(fen, "fogofwar")
self.assertEqual(result, "********/********/2******/Pp*p***1/4P3/4*3/1PPP1PPP/RNBQKBNR w KQkq b6 0 1")


if __name__ == '__main__':
unittest.main(verbosity=2)
Loading