Skip to content

Commit

Permalink
Adjudicate when board is full
Browse files Browse the repository at this point in the history
Closes #749.
  • Loading branch information
ianfab committed Dec 23, 2023
1 parent ae72c8e commit aaf49a3
Show file tree
Hide file tree
Showing 8 changed files with 24 additions and 4 deletions.
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.78",
setup(name="pyffish", version="0.0.80",
description="Fairy-Stockfish Python wrapper",
long_description=long_description,
long_description_content_type="text/markdown",
Expand Down
1 change: 1 addition & 0 deletions src/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
parse_attribute("connectNxN", v->connectNxN);
parse_attribute("connectValue", v->connectValue);
parse_attribute("materialCounting", v->materialCounting);
parse_attribute("adjudicateFullBoard", v->adjudicateFullBoard);
parse_attribute("countingRule", v->countingRule);
parse_attribute("castlingWins", v->castlingWins);

Expand Down
7 changes: 5 additions & 2 deletions src/position.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2845,18 +2845,21 @@ bool Position::is_immediate_game_end(Value& result, int ply) const {
}
}

// Check for bikjang rule (Janggi) and double passing
if (st->pliesFromNull > 0 && ((st->bikjang && st->previous->bikjang) || (st->pass && st->previous->pass)))
// Check for bikjang rule (Janggi), double passing, or board running full
if ( (st->pliesFromNull > 0 && ((st->bikjang && st->previous->bikjang) || (st->pass && st->previous->pass)))
|| (var->adjudicateFullBoard && !(~pieces() & board_bb())))
{
result = var->materialCounting ? convert_mate_value(material_counting_result(), ply) : VALUE_DRAW;
return true;
}

// Tsume mode: Assume that side with king wins when not in check
if (tsumeMode && !count<KING>(~sideToMove) && count<KING>(sideToMove) && !checkers())
{
result = mate_in(ply);
return true;
}

// Failing to checkmate with virtual pieces is a loss
if (two_boards() && !checkers())
{
Expand Down
2 changes: 1 addition & 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, 78);
return Py_BuildValue("(iii)", 0, 0, 80);
}

extern "C" PyObject* pyffish_info(PyObject* self) {
Expand Down
2 changes: 2 additions & 0 deletions src/variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1141,6 +1141,7 @@ namespace {
v->enclosingDrop = ATAXX;
v->flipEnclosedPieces = ATAXX;
v->materialCounting = UNWEIGHTED_MATERIAL;
v->adjudicateFullBoard = true;
v->nMoveRule = 0;
v->freeDrops = true;
return v;
Expand All @@ -1167,6 +1168,7 @@ namespace {
v->enclosingDropStart = make_bitboard(SQ_D4, SQ_E4, SQ_D5, SQ_E5);
v->flipEnclosedPieces = REVERSI;
v->materialCounting = UNWEIGHTED_MATERIAL;
v->adjudicateFullBoard = true;
return v;
}
// Flipello
Expand Down
1 change: 1 addition & 0 deletions src/variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ struct Variant {
int connectNxN = 0;
Value connectValue = VALUE_MATE;
MaterialCounting materialCounting = NO_MATERIAL_COUNTING;
bool adjudicateFullBoard = false;
CountingRule countingRule = NO_COUNTING;
CastlingRights castlingWins = NO_CASTLING;

Expand Down
1 change: 1 addition & 0 deletions src/variants.ini
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@
# connectNxN: connect a tight NxN square for win [int] (default: 0)
# connectValue: result in case of connect [Value] (default: win)
# materialCounting: enable material counting rules [MaterialCounting] (default: none)
# adjudicateFullBoard: apply material counting immediately when board is full [bool] (default: false)
# countingRule: enable counting rules [CountingRule] (default: none)
# castlingWins: Specified castling moves are win conditions. Losing these rights is losing. [CastlingRights] (default: -)

Expand Down
12 changes: 12 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,13 @@ def test_game_result(self):
result = sf.game_result("royalduck", "rnbqk1nr/pppp1ppp/4p3/8/7P/5Pb1/PPPPP*P1/RNBQKBNR w KQkq - 1 4", [])
self.assertEqual(result, sf.VALUE_MATE)

def _check_immediate_game_end(self, variant, fen, moves, game_end, game_result=None):
with self.subTest(variant=variant, fen=fen, game_end=game_end, game_result=game_result):
result = sf.is_immediate_game_end(variant, fen, moves)
self.assertEqual(result[0], game_end)
if game_result is not None:
self.assertEqual(result[1], game_result)

def test_is_immediate_game_end(self):
result = sf.is_immediate_game_end("capablanca", CAPA, [])
self.assertFalse(result[0])
Expand All @@ -991,6 +998,11 @@ def test_is_immediate_game_end(self):
self.assertTrue(result[0])
self.assertEqual(result[1], -sf.VALUE_MATE)

# full board adjudication
self._check_immediate_game_end("flipello", "pppppppp/pppppppp/pppPpppp/pPpPpppp/pppppppp/pPpPPPPP/ppPpPPpp/pppppppp[PPpp] b - - 63 32", [], True, sf.VALUE_MATE)
self._check_immediate_game_end("ataxx", "PPPpppp/pppPPPp/pPPPPPP/PPPPPPp/ppPPPpp/pPPPPpP/pPPPPPP b - - 99 50", [], True, -sf.VALUE_MATE)
self._check_immediate_game_end("ataxx", "PPPpppp/pppPPPp/pPP*PPP/PP*P*Pp/ppP*Ppp/pPPPPpP/pPPPPPP b - - 99 50", [], True, -sf.VALUE_MATE)

def test_is_optional_game_end(self):
result = sf.is_optional_game_end("capablanca", CAPA, [])
self.assertFalse(result[0])
Expand Down

0 comments on commit aaf49a3

Please sign in to comment.