[gnome-games] chess: Fix detect checkmate



commit ce665f9b0fc8296ccf65da868c5d3bdfef61b579
Author: Robert Ancell <robert ancell canonical com>
Date:   Thu Jan 20 10:22:09 2011 +1100

    chess: Fix detect checkmate

 glchess/src/chess-game.vala      |   54 ++++++++++++++++++++++++--------------
 glchess/src/test-chess-game.vala |   35 +++++++++++++++++-------
 2 files changed, 59 insertions(+), 30 deletions(-)
---
diff --git a/glchess/src/chess-game.vala b/glchess/src/chess-game.vala
index 015aedf..ac5cd31 100644
--- a/glchess/src/chess-game.vala
+++ b/glchess/src/chess-game.vala
@@ -192,6 +192,13 @@ public class ChessMove
     }
 }
 
+public enum CheckState
+{
+    NONE,
+    CHECK,
+    CHECKMATE
+}
+
 public class ChessState
 {
     public int number = 0;
@@ -204,7 +211,7 @@ public class ChessState
     public bool can_castle_kingside[2];
     public bool can_castle_queenside[2];
     public int en_passant_index = -1;
-    public bool in_check;
+    public CheckState check_state;
 
     public ChessPiece board[64];
     public ChessMove? last_move = null;
@@ -300,7 +307,7 @@ public class ChessState
         if (current_player.color == Color.BLACK)
             number++;
 
-        in_check = is_in_check (current_player);
+        check_state = get_check_state (current_player);
     }
 
     public ChessState copy ()
@@ -316,7 +323,7 @@ public class ChessState
         state.can_castle_kingside[Color.BLACK] = can_castle_kingside[Color.BLACK];
         state.can_castle_queenside[Color.BLACK] = can_castle_queenside[Color.BLACK];
         state.en_passant_index = en_passant_index;
-        state.in_check = in_check;
+        state.check_state = check_state;
         if (last_move != null)
             state.last_move = last_move.copy();
         for (int i = 0; i < 64; i++)
@@ -517,7 +524,7 @@ public class ChessState
                     return false;
 
                 /* Can't castle when in check */
-                if (in_check)
+                if (check_state == CheckState.CHECK)
                     return false;
 
                 /* Square moved across can't be under attack */
@@ -569,7 +576,6 @@ public class ChessState
         var old_black_can_castle_kingside = can_castle_kingside[Color.BLACK];
         var old_black_can_castle_queenside = can_castle_queenside[Color.BLACK];
         var old_en_passant_index = en_passant_index;
-        var old_in_check = in_check;
 
         /* Update board */
         board[start] = null;
@@ -619,15 +625,11 @@ public class ChessState
 
         /* Test if this move would leave that player in check */
         bool result = true;
-        if (test_check)
-        {
-            in_check = is_in_check (player);
-            if (in_check)
-                result = false;
-        }
+        if (test_check && is_in_check (player))
+            result = false;
 
         /* Undo move */
-        if (!apply || in_check)
+        if (!apply || !result)
         {
             board[start] = piece;
             board[end] = null;
@@ -646,11 +648,9 @@ public class ChessState
             can_castle_kingside[Color.BLACK] = old_black_can_castle_kingside;
             can_castle_queenside[Color.BLACK] = old_black_can_castle_queenside;
             en_passant_index = old_en_passant_index;
-            in_check = old_in_check;
-        }
 
-        if (!apply || in_check)
             return result;
+        }
 
         current_player = color == Color.WHITE ? players[Color.BLACK] : players[Color.WHITE];
 
@@ -669,10 +669,24 @@ public class ChessState
         last_move.ambiguous_rank = ambiguous_rank;
         last_move.ambiguous_file = ambiguous_file;
 
+        check_state = get_check_state (current_player);
+
         return true;
     }
 
-    public bool is_in_check (ChessPlayer player)
+    private CheckState get_check_state (ChessPlayer player)
+    {
+        if (is_in_check (player))
+        {
+            if (is_in_checkmate (player))
+                return CheckState.CHECKMATE;
+            else
+                return CheckState.CHECK;
+        }
+        return CheckState.NONE;
+    }
+
+    private bool is_in_check (ChessPlayer player)
     {
         var opponent = player.color == Color.WHITE ? players[Color.BLACK] : players[Color.WHITE];
 
@@ -693,7 +707,7 @@ public class ChessState
         return false;
     }
 
-    public bool is_in_checkmate (ChessPlayer player)
+    private bool is_in_checkmate (ChessPlayer player)
     {
         for (int king_index = 0; king_index < 64; king_index++)
         {
@@ -703,10 +717,10 @@ public class ChessState
                 /* See if the king can move */
                 for (int i = 0; i < 64; i++)
                 {
-                    if (move_with_coords (opponent,
+                    if (move_with_coords (player,
                                           get_rank (king_index), get_file (king_index),
                                           get_rank (i), get_file (i),
-                                          PieceType.QUEEN, true, false))
+                                          PieceType.QUEEN, false, true))
                         return false;
                 }
             }
@@ -983,7 +997,7 @@ public class ChessGame
             state.last_move.moved_rook.moved ();
         moved (state.last_move);
 
-        if (state.is_in_check (current_player) && state.is_in_checkmate (current_player))
+        if (state.check_state == CheckState.CHECKMATE)
         {
             if (current_player.color == Color.WHITE)
                 stop (ChessResult.BLACK_WON, ChessRule.CHECKMATE);
diff --git a/glchess/src/test-chess-game.vala b/glchess/src/test-chess-game.vala
index b11df85..5ecf1f0 100644
--- a/glchess/src/test-chess-game.vala
+++ b/glchess/src/test-chess-game.vala
@@ -3,20 +3,32 @@ class GlChess
     static int test_count = 0;
     static int failure_count = 0;
 
-    private static void test_good_move (string fen, string move, string result_fen)
+    private static void test_good_move (string fen, string move, string result_fen, CheckState check_state)
     {
         ChessState state = new ChessState (fen);
         test_count++;
         if (!state.move (move))
         {
-            stderr.printf ("Not allowed to do valid move: %s : %s\n", fen, move);
+            stderr.printf ("%d. Not allowed to do valid move: %s : %s\n", test_count, fen, move);
             failure_count++;
+            return;
         }
-        else if (state.get_fen () != result_fen)
+
+        if (state.get_fen () != result_fen)
         {
-            stderr.printf ("Move led to invalid result: %s : %s -> %s, not %s\n", fen, move, state.get_fen (), result_fen);
+            stderr.printf ("%d. Move led to invalid state: %s : %s -> %s, not %s\n", test_count, fen, move, state.get_fen (), result_fen);
             failure_count++;
+            return;
         }
+
+        if (state.check_state != check_state)
+        {
+            stderr.printf ("%d. Move led to invalid check state: %s : %s -> %d, not %d\n", test_count, fen, move, state.check_state, check_state);
+            failure_count++;
+            return;
+        }
+
+        stderr.printf ("%d. %s + %s -> %s OK\n", test_count, fen, move, result_fen);
     }
 
     private static void test_bad_move (string fen, string move)
@@ -25,38 +37,41 @@ class GlChess
         test_count++;
         if (state.move (move, false))
         {
-            stderr.printf ("Allowed to do invalid move: %s : %s\n", fen, move);
+            stderr.printf ("%d. Allowed to do invalid move: %s : %s\n", test_count, fen, move);
             failure_count++;
+            return;
         }
+
+        stderr.printf ("%d. %s + %s -> invalid OK\n", test_count, fen, move);
     }
 
     public static int main (string[] args)
     {
         /* Pawn move */
         test_good_move ("8/8/8/8/8/8/P7/8 w - - 0 1", "a2a3",
-                        "8/8/8/8/8/P7/8/8 b - - 0 1");
+                        "8/8/8/8/8/P7/8/8 b - - 0 1", CheckState.NONE);
 
         /* Pawn march */
         test_good_move ("8/8/8/8/8/8/P7/8 w - - 0 1", "a2a4",
-                        "8/8/8/8/P7/8/8/8 b - a3 0 1");
+                        "8/8/8/8/P7/8/8/8 b - a3 0 1", CheckState.NONE);
 
         /* Pawn march only allowed from baseline */
         test_bad_move ("8/8/8/8/8/P7/8/8 w - - 0 1", "a2a5");
         
         /* En passant */
         test_good_move ("8/8/8/pP6/8/8/8/8 w - a6 0 1", "b5a6",
-                        "8/8/P7/8/8/8/8/8 b - - 0 1");
+                        "8/8/P7/8/8/8/8/8 b - - 0 1", CheckState.NONE);
 
         /* Can't en passant if wasn't allowed */
         test_bad_move ("8/8/8/pP6/8/8/8/8 w - - 0 1", "b5a6");
 
         /* Castle kingside */
         test_good_move ("8/8/8/8/8/8/8/4K2R w K - 0 1", "O-O",
-                        "8/8/8/8/8/8/8/5RK1 b - - 0 1");
+                        "8/8/8/8/8/8/8/5RK1 b - - 0 1", CheckState.NONE);
 
         /* Castle queenside */
         test_good_move ("8/8/8/8/8/8/8/R3K3 w Q - 0 1", "O-O-O",
-                        "8/8/8/8/8/8/8/2KR4 b - - 0 1");
+                        "8/8/8/8/8/8/8/2KR4 b - - 0 1", CheckState.NONE);
 
         /* Can't castle if pieces moved */
         test_bad_move ("8/8/8/8/8/8/8/4K2R w - - 0 1", "O-O");



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]