Support new fivefold repetition and 75 move draw conditions

On July 1, 2014 the FIDE Laws of Chess were updated to add two new
automatic draw conditions. These are the same as the threefold
repetition and 50 move rules, except they take effect automatically
rather than optionally.

http://www.fide.com/component/handbook/?id=171&view=article

https://bugzilla.gnome.org/show_bug.cgi?id=766005
This commit is contained in:
Michael Catanzaro 2016-05-04 15:18:13 -05:00
parent b7acfb40a5
commit 19a65b04e6
2 changed files with 45 additions and 7 deletions

View file

@ -25,8 +25,10 @@ public enum ChessRule
CHECKMATE,
STALEMATE,
FIFTY_MOVES,
SEVENTY_FIVE_MOVES,
TIMEOUT,
THREE_FOLD_REPETITION,
FIVE_FOLD_REPETITION,
INSUFFICIENT_MATERIAL,
RESIGN,
ABANDONMENT,
@ -183,13 +185,25 @@ public class ChessGame : Object
if (result != ChessResult.IN_PROGRESS)
{
stop (result, rule);
return;
}
else
if (is_five_fold_repeat ())
{
if (_clock != null)
_clock.active_color = current_player.color;
turn_started (current_player);
stop (ChessResult.DRAW, ChessRule.FIVE_FOLD_REPETITION);
return;
}
/* Note this test must occur after the test for checkmate in current_state.get_result (). */
if (is_seventy_five_move_rule_fulfilled ())
{
stop (ChessResult.DRAW, ChessRule.SEVENTY_FIVE_MOVES);
return;
}
if (_clock != null)
_clock.active_color = current_player.color;
turn_started (current_player);
}
private void undo_cb (ChessPlayer player)
@ -233,23 +247,39 @@ public class ChessGame : Object
return count;
}
public bool is_three_fold_repeat ()
private bool is_n_fold_repeat (int n)
{
foreach (var state in move_stack)
{
if (state_repeated_times (state) >= 3)
if (state_repeated_times (state) >= n)
return true;
}
return false;
}
public bool is_three_fold_repeat ()
{
return is_n_fold_repeat (3);
}
public bool is_five_fold_repeat ()
{
return is_n_fold_repeat (5);
}
public bool is_fifty_move_rule_fulfilled ()
{
/* Fifty moves per player without capture or pawn advancement */
/* Fifty moves *per player* without capture or pawn advancement */
return current_state.halfmove_clock >= 100;
}
public bool is_seventy_five_move_rule_fulfilled ()
{
/* 75 moves *per player* without capture or pawn advancement */
return current_state.halfmove_clock >= 150;
}
public bool can_claim_draw ()
{
return is_fifty_move_rule_fulfilled () || is_three_fold_repeat ();

View file

@ -1314,6 +1314,10 @@ Copyright © 20152016 Sahil Sareen""";
/* Window subtitle when the game is drawn due to the fifty move rule */
reason = _("No piece was taken or pawn moved in fifty moves.");
break;
case ChessRule.SEVENTY_FIVE_MOVES:
/* Window subtitle when the game is drawn due to the 75 move rule */
reason = _("No piece was taken or pawn moved in 75 moves.");
break;
case ChessRule.TIMEOUT:
if (game.result == ChessResult.WHITE_WON)
/* Window subtitle when the game ends due to Black's clock stopping */
@ -1328,6 +1332,10 @@ Copyright © 20152016 Sahil Sareen""";
/* Window subtitle when the game is drawn due to the three-fold-repetition rule */
reason = _("The same board state has occurred three times.");
break;
case ChessRule.FIVE_FOLD_REPETITION:
/* Window subtitle when the game is drawn due to the five-fold-repetition rule */
reason = _("The same board state has occurred five times.");
break;
case ChessRule.INSUFFICIENT_MATERIAL:
/* Window subtitle when the game is drawn due to the insufficient material rule */
reason = _("Neither player can checkmate.");