[gnome-games] chess: Detect stalemate



commit 2b8350ad9ae6912348d5b5124c02156239a0ec32
Author: Robert Ancell <robert ancell canonical com>
Date:   Tue Jan 25 15:15:08 2011 +1000

    chess: Detect stalemate

 glchess/src/chess-game.vala      |   58 ++++++++++++++++++++++++++++++++++----
 glchess/src/test-chess-game.vala |    4 ++
 2 files changed, 56 insertions(+), 6 deletions(-)
---
diff --git a/glchess/src/chess-game.vala b/glchess/src/chess-game.vala
index 9e286d2..ea739bd 100644
--- a/glchess/src/chess-game.vala
+++ b/glchess/src/chess-game.vala
@@ -196,7 +196,8 @@ public enum CheckState
 {
     NONE,
     CHECK,
-    CHECKMATE
+    CHECKMATE,
+    STALEMATE
 }
 
 public class ChessState
@@ -428,7 +429,10 @@ public class ChessState
         return true;
     }
 
-    public bool move_with_coords (ChessPlayer player, int r0, int f0, int r1, int f1, PieceType promotion_type = PieceType.QUEEN, bool apply = true, bool test_check = true)
+    public bool move_with_coords (ChessPlayer player,
+                                  int r0, int f0, int r1, int f1,
+                                  PieceType promotion_type = PieceType.QUEEN,
+                                  bool apply = true, bool test_check = true)
     {
         // FIXME: Make this use indexes to be faster
         var start = get_index (r0, f0);
@@ -691,6 +695,11 @@ public class ChessState
             else
                 return CheckState.CHECK;
         }
+        else
+        {
+            if (!can_move (player))
+                return CheckState.STALEMATE;
+        }
         return CheckState.NONE;
     }
 
@@ -704,9 +713,12 @@ public class ChessState
             if (p != null && p.player == player && p.type == PieceType.KING)
             {
                 /* See if any enemy pieces can take the king */
-                for (int i = 0; i < 64; i++)
+                for (int start = 0; start < 64; start++)
                 {
-                    if (move_with_coords (opponent, get_rank (i), get_file (i), get_rank (king_index), get_file (king_index), PieceType.QUEEN, false, false))
+                    if (move_with_coords (opponent,
+                                          get_rank (start), get_file (start),
+                                          get_rank (king_index), get_file (king_index),
+                                          PieceType.QUEEN, false, false))
                         return true;
                 }
             }
@@ -723,11 +735,11 @@ public class ChessState
             if (p != null && p.player == player && p.type == PieceType.KING)
             {
                 /* See if the king can move */
-                for (int i = 0; i < 64; i++)
+                for (int end = 0; end < 64; end++)
                 {
                     if (move_with_coords (player,
                                           get_rank (king_index), get_file (king_index),
-                                          get_rank (i), get_file (i),
+                                          get_rank (end), get_file (end),
                                           PieceType.QUEEN, false, true))
                         return false;
                 }
@@ -737,6 +749,36 @@ public class ChessState
         return true;
     }
 
+    private bool can_move (ChessPlayer player)
+    {
+        bool have_pieces = false;
+
+        for (int start = 0; start < 64; start++)
+        {
+            var p = board[start];
+            if (p != null && p.player == player)
+            {
+                have_pieces = true;
+
+                /* See if can move anywhere */
+                for (int end = 0; end < 64; end++)
+                {
+                    if (move_with_coords (player,
+                                          get_rank (start), get_file (start),
+                                          get_rank (end), get_file (end),
+                                          PieceType.QUEEN, false, true))
+                        return true;
+                }
+            }
+        }
+
+        /* Only mark as stalemate if have at least one piece */
+        if (have_pieces)
+            return false;
+        else
+            return true;
+    }
+
     private bool decode_piece_type (unichar c, out PieceType type)
     {
         switch (c)
@@ -1012,6 +1054,10 @@ public class ChessGame
             else
                 stop (ChessResult.WHITE_WON, ChessRule.CHECKMATE);
         }
+        else if (state.check_state == CheckState.STALEMATE)
+        {
+            stop (ChessResult.DRAW, ChessRule.STALEMATE);
+        }
         else
         {
             if (_clock != null)
diff --git a/glchess/src/test-chess-game.vala b/glchess/src/test-chess-game.vala
index 089d202..ae3283d 100644
--- a/glchess/src/test-chess-game.vala
+++ b/glchess/src/test-chess-game.vala
@@ -96,6 +96,10 @@ class GlChess
         test_good_move ("k7/8/8/8/8/8/1R6/1R6 w - - 0 1", "b1a1",
                         "k7/8/8/8/8/8/1R6/R7 b - - 1 1", CheckState.CHECKMATE);
 
+        /* Stalemate */
+        test_good_move ("k7/8/7R/8/8/8/8/1R6 w - - 0 1", "h6h7",
+                        "k7/7R/8/8/8/8/8/1R6 b - - 1 1", CheckState.STALEMATE);
+
         stdout.printf ("%d/%d tests successful\n", test_count - failure_count, test_count);
 
         return failure_count;



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