[gnome-games] chess: Fix detect checkmate
- From: Robert Ancell <rancell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-games] chess: Fix detect checkmate
- Date: Wed, 19 Jan 2011 23:22:32 +0000 (UTC)
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]