[gnome-games/glchess-vala] Check FEN state is valid after move



commit ab6ac4b95abf773fb09e22b26034746430ee8871
Author: Robert Ancell <robert ancell canonical com>
Date:   Tue Dec 28 15:38:09 2010 +1100

    Check FEN state is valid after move

 glchess/src/chess-game.vala      |  117 ++++++++++++++++++++++++++++++++++---
 glchess/src/test-chess-game.vala |   28 ++++++---
 2 files changed, 126 insertions(+), 19 deletions(-)
---
diff --git a/glchess/src/chess-game.vala b/glchess/src/chess-game.vala
index 5bcbc8d..d7408c6 100644
--- a/glchess/src/chess-game.vala
+++ b/glchess/src/chess-game.vala
@@ -58,6 +58,38 @@ public class ChessPiece
     public signal void promoted ();
     public signal void died ();
 
+    public unichar symbol
+    {
+        get
+        {
+            unichar c = ' ';
+            switch (type)
+            {
+            case PieceType.PAWN:
+                c = 'p';
+                break;
+            case PieceType.ROOK:
+                c = 'r';
+                break;
+            case PieceType.KNIGHT:
+                c = 'k';
+                break;
+            case PieceType.BISHOP:
+                c = 'b';
+                break;
+            case PieceType.QUEEN:
+                c = 'q';
+                break;
+            case PieceType.KING:
+                c = 'k';
+                break;
+            }
+            if (player.color == Color.WHITE)
+                c = c.toupper ();
+            return c;
+        }
+    }
+
     public ChessPiece (ChessPlayer player, PieceType type)
     {
         this.player = player;
@@ -122,24 +154,24 @@ public class ChessState
     public int en_passant_index = -1;
     public bool in_check;
 
-    public ChessPiece[] board;
+    public ChessPiece board[64];
     public ChessMove? last_move = null;
 
     /* Bitmap of all the pieces */
     private int64 piece_masks[2];
 
-    public ChessState (string? state = null)
+    private ChessState.empty ()
+    {
+    }
+
+    public ChessState (string fen)
     {
         players[Color.WHITE] = new ChessPlayer (Color.WHITE);
         players[Color.BLACK] = new ChessPlayer (Color.BLACK);
-        board = new ChessPiece[64];
         for (int i = 0; i < 64; i++)
             board[i] = null;
 
-        if (state == null)
-            return;
-
-        string[] fields = state.split (" ");
+        string[] fields = fen.split (" ");
         //if (fields.length != 6)
         //    throw new Error ("Invalid FEN string");
 
@@ -221,7 +253,7 @@ public class ChessState
 
     public ChessState copy ()
     {
-        ChessState state = new ChessState ();
+        ChessState state = new ChessState.empty ();
 
         state.number = number;
         state.players[Color.WHITE] = players[Color.WHITE];
@@ -243,6 +275,71 @@ public class ChessState
         return state;
     }
 
+    public string get_fen ()
+    {
+        var value = new StringBuilder ();
+
+        for (int rank = 7; rank >= 0; rank--)
+        {
+            int skip_count = 0;
+            for (int file = 0; file < 8; file++)
+            {
+                ChessPiece? p = board[get_index (rank, file)];
+                if (p == null)
+                    skip_count++;
+                else
+                {
+                    if (skip_count > 0)
+                    {
+                        value.append_printf ("%d", skip_count);
+                        skip_count = 0;
+                    }
+                    value.append_printf ("%c", (int) p.symbol);
+                }
+            }
+            if (skip_count > 0)
+                value.append_printf ("%d", skip_count);
+            if (rank != 0)
+                value.append_c ('/');
+        }
+        
+        value.append_c (' ');
+        if (current_player.color == Color.WHITE)
+            value.append_c ('w');
+        else
+            value.append_c ('b');
+
+        value.append_c (' ');
+        if (can_castle_kingside[Color.WHITE])
+            value.append_c ('K');
+        if (can_castle_queenside[Color.WHITE])
+            value.append_c ('Q');
+        if (can_castle_kingside[Color.BLACK])
+            value.append_c ('k');
+        if (can_castle_queenside[Color.BLACK])
+            value.append_c ('q');
+        if (!(can_castle_kingside[Color.WHITE] | can_castle_queenside[Color.WHITE] | can_castle_kingside[Color.BLACK] | can_castle_queenside[Color.BLACK]))
+            value.append_c ('-');
+
+        value.append_c (' ');
+        if (en_passant_index >= 0)
+            value.append_printf ("%c%d", 'a' + get_file (en_passant_index), get_rank (en_passant_index) + 1);
+        else
+            value.append_c ('-');
+
+        // FIXME: Halfmove count
+        value.append_c (' ');
+        value.append_c ('0');
+
+        value.append_c (' ');
+        if (current_player.color == Color.WHITE)
+            value.append_printf ("%d", number / 2);
+        else
+            value.append_printf ("%d", number / 2 + 1);
+
+        return value.str;
+    }
+
     public int get_index (int rank, int file)
     {
         return rank * 8 + file;
@@ -712,10 +809,10 @@ public class ChessGame
         get { return move_stack.data.current_player; }
     }
 
-    public ChessGame (string state = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
+    public ChessGame (string fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
     {
         is_started = false;
-        move_stack.prepend (new ChessState (state));
+        move_stack.prepend (new ChessState (fen));
         result = ChessResult.IN_PROGRESS;
 
         white.do_move.connect (move_cb);
diff --git a/glchess/src/test-chess-game.vala b/glchess/src/test-chess-game.vala
index 0d969f0..b11df85 100644
--- a/glchess/src/test-chess-game.vala
+++ b/glchess/src/test-chess-game.vala
@@ -3,50 +3,60 @@ class GlChess
     static int test_count = 0;
     static int failure_count = 0;
 
-    private static void test_good_move (string fen, string move)
+    private static void test_good_move (string fen, string move, string result_fen)
     {
         ChessState state = new ChessState (fen);
-        if (!state.move (move, false))
+        test_count++;
+        if (!state.move (move))
         {
             stderr.printf ("Not allowed to do valid move: %s : %s\n", fen, move);
             failure_count++;
         }
-        test_count++;
+        else 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);
+            failure_count++;
+        }
     }
 
     private static void test_bad_move (string fen, string move)
     {
         ChessState state = new ChessState (fen);
+        test_count++;
         if (state.move (move, false))
         {
             stderr.printf ("Allowed to do invalid move: %s : %s\n", fen, move);
             failure_count++;
         }
-        test_count++;
     }
 
     public static int main (string[] args)
     {
         /* Pawn move */
-        test_good_move ("8/8/8/8/8/8/P7/8 w - - 0 1", "a2a3");
+        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");
 
         /* Pawn march */
-        test_good_move ("8/8/8/8/8/8/P7/8 w - - 0 1", "a2a4");
+        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");
 
         /* 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");
+        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");
 
         /* 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");
+        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");
 
         /* Castle queenside */
-        test_good_move ("8/8/8/8/8/8/8/R3K3 w Q - 0 1", "O-O-O");
+        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");
 
         /* 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]