Closes #749.
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",
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);
}
}
- // 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())
{
}
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) {
v->enclosingDrop = ATAXX;
v->flipEnclosedPieces = ATAXX;
v->materialCounting = UNWEIGHTED_MATERIAL;
+ v->adjudicateFullBoard = true;
v->nMoveRule = 0;
v->freeDrops = true;
return v;
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
int connectNxN = 0;
Value connectValue = VALUE_MATE;
MaterialCounting materialCounting = NO_MATERIAL_COUNTING;
+ bool adjudicateFullBoard = false;
CountingRule countingRule = NO_COUNTING;
CastlingRights castlingWins = NO_CASTLING;
# 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: -)
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])
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])