Skip to content

Commit a207488

Browse files
committed
Allow fifty-move claim ahead of a checkmating or stalemating move
can_claim_fifty_moves() pushed each non-zeroing legal move and tested the result with is_fifty_moves(), which is False when the resulting position has no legal moves. A move that completes the 100 halfmoves but also gives checkmate or stalemate was therefore rejected. Under FIDE 9.3 the claim is made ahead of the move: the player only declares a non-pawn, non-capture move that completes the count; it is not played, so its being game-ending does not invalidate the claim. With the clock at 99 any non-zeroing legal move completes the count, so the push/is_fifty_moves() test becomes a direct check. Positions that are already checkmate or stalemate still return False (no legal moves to iterate). Closes #1188.
1 parent 8330cfd commit a207488

2 files changed

Lines changed: 12 additions & 6 deletions

File tree

chess/__init__.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2297,14 +2297,11 @@ def can_claim_fifty_moves(self) -> bool:
22972297
return True
22982298

22992299
if self.halfmove_clock >= 99:
2300+
# The claim can also be made ahead of a move that would itself give
2301+
# checkmate or stalemate (FIDE 9.3): it is declared, not played.
23002302
for move in self.generate_legal_moves():
23012303
if not self.is_zeroing(move):
2302-
self.push(move)
2303-
try:
2304-
if self.is_fifty_moves():
2305-
return True
2306-
finally:
2307-
self.pop()
2304+
return True
23082305

23092306
return False
23102307

test.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,15 @@ def test_fifty_moves(self):
13761376
self.assertFalse(board.can_claim_fifty_moves())
13771377
self.assertFalse(board.can_claim_draw())
13781378

1379+
# Claiming ahead of a move that would itself give checkmate is valid
1380+
# (FIDE 9.3): the move is only declared, not played.
1381+
board = chess.Board("6rk/6pp/7N/5p2/6p1/8/2q5/K7 w - - 99 60")
1382+
self.assertFalse(board.is_game_over())
1383+
self.assertTrue(board.gives_checkmate(chess.Move.from_uci("h6f7")))
1384+
self.assertFalse(board.is_fifty_moves())
1385+
self.assertTrue(board.can_claim_fifty_moves())
1386+
self.assertTrue(board.can_claim_draw())
1387+
13791388
def test_promoted_comparison(self):
13801389
board = chess.Board()
13811390
board.set_fen("5R2/3P4/8/8/7r/7r/7k/K7 w - - 0 1")

0 commit comments

Comments
 (0)