[iagno] Introduce GameStateObject.
- From: Arnaud B. <arnaudb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [iagno] Introduce GameStateObject.
- Date: Wed, 22 May 2019 13:02:45 +0000 (UTC)
commit ddd0adb8c375ad359c4f9b6d84848f5eb5de9457
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date: Fri May 17 12:18:24 2019 +0200
Introduce GameStateObject.
src/computer-reversi.vala | 24 +++---
src/game-view.vala | 2 +-
src/game.vala | 212 ++++++++++++++++++++++++++++------------------
3 files changed, 142 insertions(+), 96 deletions(-)
---
diff --git a/src/computer-reversi.vala b/src/computer-reversi.vala
index bb00f79..7a30273 100644
--- a/src/computer-reversi.vala
+++ b/src/computer-reversi.vala
@@ -72,7 +72,7 @@ private class ComputerReversiEasy : ComputerReversi
* * AI
\*/
- protected override int16 calculate_heuristic (GameState g)
+ protected override int16 calculate_heuristic (GameStateStruct g)
{
/* Try to lose */
return (int16) g.n_opponent_tiles - (int16) g.n_current_tiles;
@@ -117,7 +117,7 @@ private class ComputerReversiHard : ComputerReversi
* * AI
\*/
- protected override int16 calculate_heuristic (GameState g)
+ protected override int16 calculate_heuristic (GameStateStruct g)
{
/* End of the game: just maximize the number of tokens */
if (g.n_tiles >= end_start)
@@ -127,7 +127,7 @@ private class ComputerReversiHard : ComputerReversi
return (int16) g.n_current_tiles - (int16) g.n_opponent_tiles + eval_heuristic (g, ref heuristic);
}
- private static int16 eval_heuristic (GameState g, ref int16 [,] heuristic)
+ private static int16 eval_heuristic (GameStateStruct g, ref int16 [,] heuristic)
{
uint8 size = g.size;
int16 count = 0;
@@ -246,7 +246,7 @@ private abstract class ComputerReversi : ComputerPlayer
/* Has been reached, once. So let's have a fallback. */
PossibleMove random_move;
- random_select (game.current_state, out random_move);
+ random_select (game.current_state.game_state_struct, out random_move);
if (!game.place_tile (random_move.x, random_move.y))
{
critical (@"Computer chose an invalid move for the second time:
$(random_move.x),$(random_move.y)\n$game");
@@ -255,7 +255,7 @@ private abstract class ComputerReversi : ComputerPlayer
}
}
- private static void random_select (GameState g, out PossibleMove random_move)
+ private static void random_select (GameStateStruct g, out PossibleMove random_move)
{
SList<PossibleMove?> moves;
g.get_possible_moves (out moves);
@@ -284,7 +284,7 @@ private abstract class ComputerReversi : ComputerPlayer
/* For the first/first two moves play randomly so the game is not always the same */
if (game.current_state.n_tiles < game.initial_number_of_tiles + (game.size < 6 ? 2 : 4))
{
- random_select (game.current_state, out best_move);
+ random_select (game.current_state.game_state_struct, out best_move);
return;
}
@@ -293,7 +293,7 @@ private abstract class ComputerReversi : ComputerPlayer
/* Choose a location to place by building the tree of possible moves and
* using the minimax algorithm to pick the best branch with the chosen
* strategy. */
- GameState g = game.current_state;
+ GameStateStruct g = game.current_state.game_state_struct;
/* The search sometimes returns NEGATIVE_INFINITY. */
int16 a = LESS_THAN_NEGATIVE_INFINITY;
@@ -307,7 +307,7 @@ private abstract class ComputerReversi : ComputerPlayer
// if (move == null)
// assert_not_reached ();
- GameState _g = new GameState.copy_and_move (g, (!) move);
+ GameStateStruct _g = GameStateStruct.copy_and_move (g, (!) move);
int16 a_new = -1 * search (_g, initial_depth, NEGATIVE_INFINITY, -a);
if (a_new > a)
@@ -323,7 +323,7 @@ private abstract class ComputerReversi : ComputerPlayer
}
}
- private int16 search (GameState g, uint8 depth, int16 a, int16 b)
+ private int16 search (GameStateStruct g, uint8 depth, int16 a, int16 b)
// requires (a <= b)
{
/* End of the game, return a near-infinite evaluation */
@@ -347,7 +347,7 @@ private abstract class ComputerReversi : ComputerPlayer
// if (move == null)
// assert_not_reached ();
- GameState _g = new GameState.copy_and_move (g, (!) move);
+ GameStateStruct _g = GameStateStruct.copy_and_move (g, (!) move);
int16 a_new = -1 * search (_g, depth - 1, -b, -a);
if (a_new > a)
@@ -360,7 +360,7 @@ private abstract class ComputerReversi : ComputerPlayer
}
else // pass
{
- GameState _g = new GameState.copy_and_pass (g);
+ GameStateStruct _g = GameStateStruct.copy_and_pass (g);
int16 a_new = -1 * search (_g, depth - 1, -b, -a);
if (a_new > a)
@@ -370,6 +370,6 @@ private abstract class ComputerReversi : ComputerPlayer
return a;
}
- protected abstract int16 calculate_heuristic (GameState g);
+ protected abstract int16 calculate_heuristic (GameStateStruct g);
protected abstract void sort_moves (ref SList<PossibleMove?> moves);
}
diff --git a/src/game-view.vala b/src/game-view.vala
index 7c709e9..2608021 100644
--- a/src/game-view.vala
+++ b/src/game-view.vala
@@ -456,7 +456,7 @@ private class GameView : Gtk.DrawingArea
\*/
private bool last_state_set = false;
- private GameState last_state;
+ private GameStateObject last_state;
private inline void update_highlight_after_undo ()
requires (last_state_set)
diff --git a/src/game.vala b/src/game.vala
index c8b99d0..008182a 100644
--- a/src/game.vala
+++ b/src/game.vala
@@ -20,22 +20,18 @@
along with GNOME Reversi. If not, see <https://www.gnu.org/licenses/>.
*/
-private class GameState : Object
+private struct GameStateStruct
{
- private struct GameStateStruct
- {
- public Player current_color;
- public uint8 size;
-
- public uint8 n_light_tiles;
- public uint8 n_dark_tiles;
+ public Player current_color;
+ public uint8 size;
- public bool current_player_can_move;
- public bool is_complete;
- }
- private GameStateStruct game_state_struct = GameStateStruct ();
+ public uint8 n_light_tiles;
+ public uint8 n_dark_tiles;
- [CCode (notify = false)] internal Player current_color { internal get { return
game_state_struct.current_color; }}
+ public bool current_player_can_move;
+ public bool is_complete;
+ private Player [,] tiles;
+ private unowned uint8 [,] neighbor_tiles;
internal string to_string ()
{
@@ -51,41 +47,34 @@ private class GameState : Object
return s;
}
- /*\
- * * board
- \*/
-
- [CCode (notify = false)] internal uint8 size { internal get { return game_state_struct.size; }}
-
- private Player [,] tiles;
- private unowned uint8 [,] neighbor_tiles;
-
- internal GameState.copy_and_pass (GameState game)
+ internal GameStateStruct.copy_and_pass (GameStateStruct game)
// requires (!game.current_player_can_move)
// requires (!game.is_complete)
{
- game_state_struct.size = game.size;
- game_state_struct.current_color = Player.flip_color (game.current_color);
+ size = game.size;
+ current_color = Player.flip_color (game.current_color);
neighbor_tiles = game.neighbor_tiles;
empty_neighbors = game.empty_neighbors;
tiles = game.tiles;
- game_state_struct.n_light_tiles = game.n_light_tiles;
- game_state_struct.n_dark_tiles = game.n_dark_tiles;
+ n_light_tiles = game.n_light_tiles;
+ n_dark_tiles = game.n_dark_tiles;
- game_state_struct.current_player_can_move = true;
- game_state_struct.is_complete = false;
+ current_player_can_move = true;
+ is_complete = false;
+ x_saved = 0;
+ y_saved = 0;
}
- internal GameState.copy_and_move (GameState game, PossibleMove move)
+ internal GameStateStruct.copy_and_move (GameStateStruct game, PossibleMove move)
{
Player move_color = game.current_color;
- game_state_struct.size = game.size;
- game_state_struct.current_color = Player.flip_color (move_color);
+ size = game.size;
+ current_color = Player.flip_color (move_color);
neighbor_tiles = game.neighbor_tiles;
empty_neighbors = game.empty_neighbors;
tiles = game.tiles;
- game_state_struct.n_light_tiles = game.game_state_struct.n_light_tiles;
- game_state_struct.n_dark_tiles = game.game_state_struct.n_dark_tiles;
+ n_light_tiles = game.n_light_tiles;
+ n_dark_tiles = game.n_dark_tiles;
flip_tiles (ref tiles, move.x, move.y, move_color, 0, -1, move.n_tiles_n );
flip_tiles (ref tiles, move.x, move.y, move_color, 1, -1, move.n_tiles_ne);
@@ -112,10 +101,10 @@ private class GameState : Object
}
}
- internal GameState.from_grid (uint8 _size, Player [,] _tiles, Player color, uint8 [,] _neighbor_tiles)
+ internal GameStateStruct.from_grid (uint8 _size, Player [,] _tiles, Player color, uint8 [,]
_neighbor_tiles)
{
- game_state_struct.size = _size;
- game_state_struct.current_color = color;
+ size = _size;
+ current_color = color;
neighbor_tiles = _neighbor_tiles;
tiles = _tiles;
@@ -132,35 +121,31 @@ private class GameState : Object
\*/
[CCode (notify = false)] internal uint8 n_tiles
- { internal get { return game_state_struct.n_dark_tiles +
game_state_struct.n_light_tiles; }}
- [CCode (notify = false)] internal uint8 n_light_tiles
- { internal get { return game_state_struct.n_light_tiles; }}
- [CCode (notify = false)] internal uint8 n_dark_tiles
- { internal get { return game_state_struct.n_dark_tiles; }}
+ { internal get { return n_dark_tiles + n_light_tiles; }}
[CCode (notify = false)] internal uint8 n_current_tiles
- { internal get { return current_color == Player.LIGHT ?
game_state_struct.n_light_tiles : game_state_struct.n_dark_tiles; }}
+ { internal get { return current_color == Player.LIGHT ?
n_light_tiles : n_dark_tiles; }}
[CCode (notify = false)] internal uint8 n_opponent_tiles
- { internal get { return current_color == Player.DARK ?
game_state_struct.n_light_tiles : game_state_struct.n_dark_tiles; }}
+ { internal get { return current_color == Player.DARK ?
n_light_tiles : n_dark_tiles; }}
private void add_tile_of_color (Player color)
{
if (color == Player.DARK)
- game_state_struct.n_dark_tiles++;
+ n_dark_tiles++;
else if (color == Player.LIGHT)
- game_state_struct.n_light_tiles++;
+ n_light_tiles++;
}
private void flip_n_tiles_to_color (uint8 count, Player color)
{
if (color == Player.LIGHT)
{
- game_state_struct.n_dark_tiles -= count;
- game_state_struct.n_light_tiles += count;
+ n_dark_tiles -= count;
+ n_light_tiles += count;
}
else // if (color == Player.DARK)
{
- game_state_struct.n_light_tiles -= count;
- game_state_struct.n_dark_tiles += count;
+ n_light_tiles -= count;
+ n_dark_tiles += count;
}
// else assert_not_reached ();
}
@@ -169,18 +154,6 @@ private class GameState : Object
* * public information
\*/
- internal Player get_owner (uint8 x, uint8 y)
- // requires (is_valid_location_unsigned (x, y))
- {
- return tiles [x, y];
- }
- // internal new uint8 get (uint8 x, uint8 y) // allows calling game [x, y]
- // requires (x < size)
- // requires (y < size)
- // {
- // return tiles [x, y];
- // }
-
internal bool is_current_color (uint8 x, uint8 y)
// requires (is_valid_location_unsigned (x, y))
{
@@ -202,15 +175,14 @@ private class GameState : Object
* * get possible moves
\*/
- [CCode (notify = false)] internal bool current_player_can_move { internal get { return
game_state_struct.current_player_can_move; }}
- [CCode (notify = true)] internal bool is_complete { internal get { return
game_state_struct.is_complete; }}
-
- private uint8 x_saved = 0;
- private uint8 y_saved = 0;
+ private uint8 x_saved;
+ private uint8 y_saved;
private void update_who_can_move ()
{
Player enemy = Player.flip_color (current_color);
+ x_saved = 0;
+ y_saved = 0;
bool opponent_can_move = false;
for (; x_saved < size; x_saved++)
{
@@ -218,8 +190,8 @@ private class GameState : Object
{
if (can_place (x_saved, y_saved, current_color))
{
- game_state_struct.current_player_can_move = true;
- game_state_struct.is_complete = false;
+ current_player_can_move = true;
+ is_complete = false;
return;
}
if (opponent_can_move)
@@ -227,14 +199,14 @@ private class GameState : Object
if (can_place (x_saved, y_saved, enemy))
{
opponent_can_move = true;
- game_state_struct.is_complete = false;
+ is_complete = false;
}
}
y_saved = 0;
}
- game_state_struct.current_player_can_move = false;
+ current_player_can_move = false;
if (!opponent_can_move)
- game_state_struct.is_complete = true;
+ is_complete = true;
}
internal void get_possible_moves (out SList<PossibleMove?> moves)
@@ -440,9 +412,83 @@ private class GameState : Object
}
}
+private class GameStateObject : Object
+{
+ private GameStateStruct _game_state_struct;
+ [CCode (notify = false)] internal GameStateStruct game_state_struct { internal get { return
_game_state_struct; }}
+
+ [CCode (notify = false)] internal Player current_color { internal get { return
game_state_struct.current_color; }}
+ [CCode (notify = false)] internal uint8 size { internal get { return
game_state_struct.size; }}
+
+ [CCode (notify = false)] internal uint8 n_tiles { internal get { return
game_state_struct.n_tiles; }}
+ [CCode (notify = false)] internal uint8 n_light_tiles { internal get { return
game_state_struct.n_light_tiles; }}
+ [CCode (notify = false)] internal uint8 n_dark_tiles { internal get { return
game_state_struct.n_dark_tiles; }}
+ [CCode (notify = false)] internal uint8 n_current_tiles { internal get { return
game_state_struct.n_current_tiles; }}
+ [CCode (notify = false)] internal uint8 n_opponent_tiles { internal get { return
game_state_struct.n_opponent_tiles; }}
+
+ [CCode (notify = false)] internal bool current_player_can_move { internal get { return
game_state_struct.current_player_can_move; }}
+ [CCode (notify = true)] internal bool is_complete { internal get { return
game_state_struct.is_complete; }}
+
+ internal string to_string ()
+ {
+ return game_state_struct.to_string ();
+ }
+
+ /*\
+ * * board
+ \*/
+
+ internal GameStateObject.copy_and_pass (GameStateObject game)
+ // requires (!game.current_player_can_move)
+ // requires (!game.is_complete)
+ {
+ _game_state_struct = GameStateStruct.copy_and_pass (game.game_state_struct);
+ }
+
+ internal GameStateObject.copy_and_move (GameStateObject game, PossibleMove move)
+ {
+ _game_state_struct = GameStateStruct.copy_and_move (game.game_state_struct, move);
+ }
+
+ internal GameStateObject.from_grid (uint8 size, Player [,] tiles, Player color, uint8 [,] neighbor_tiles)
+ {
+ _game_state_struct = GameStateStruct.from_grid (size, tiles, color, neighbor_tiles);
+ }
+
+ /*\
+ * * public information
+ \*/
+
+ internal Player get_owner (uint8 x, uint8 y)
+ // requires (is_valid_location_unsigned (x, y))
+ {
+ return game_state_struct.tiles [x, y];
+ }
+
+ internal inline bool is_valid_location_signed (int8 x, int8 y)
+ {
+ return x >= 0 && x < size
+ && y >= 0 && y < size;
+ }
+
+ /*\
+ * * proxy calls
+ \*/
+
+ internal void get_possible_moves (out SList<PossibleMove?> moves)
+ {
+ game_state_struct.get_possible_moves (out moves);
+ }
+
+ internal bool test_placing_tile (uint8 x, uint8 y, out PossibleMove move)
+ {
+ return game_state_struct.test_placing_tile (x, y, out move);
+ }
+}
+
private class Game : Object
{
- private GLib.ListStore undo_stack = new GLib.ListStore (typeof (GameState));
+ private GLib.ListStore undo_stack = new GLib.ListStore (typeof (GameStateObject));
[CCode (notify = false)] internal uint8 number_of_moves
{
internal get
@@ -461,10 +507,10 @@ private class Game : Object
* * creation
\*/
- [CCode (notify = false)] public uint8 size { internal get; protected construct;
}
- [CCode (notify = false)] public GameState current_state { internal get; protected construct
set; }
- [CCode (notify = false)] public bool alternative_start { internal get; protected construct;
}
- [CCode (notify = false)] public uint8 initial_number_of_tiles { internal get; protected construct;
}
+ [CCode (notify = false)] public uint8 size { internal get; protected
construct; }
+ [CCode (notify = false)] public GameStateObject current_state { internal get; protected
construct set; }
+ [CCode (notify = false)] public bool alternative_start { internal get; protected
construct; }
+ [CCode (notify = false)] public uint8 initial_number_of_tiles { internal get; protected
construct; }
construct
{
@@ -511,7 +557,7 @@ private class Game : Object
uint8 [,] _neighbor_tiles;
init_neighbor_tiles (_size, out _neighbor_tiles);
- GameState _current_state = new GameState.from_grid (_size, tiles, /* Dark always starts */
Player.DARK, _neighbor_tiles);
+ GameStateObject _current_state = new GameStateObject.from_grid (_size, tiles, /* Dark always starts
*/ Player.DARK, _neighbor_tiles);
Object (size : _size,
current_state : _current_state,
@@ -538,7 +584,7 @@ private class Game : Object
uint8 [,] _neighbor_tiles;
init_neighbor_tiles (_size, out _neighbor_tiles);
- GameState _current_state = new GameState.from_grid (_size, tiles, to_move, _neighbor_tiles);
+ GameStateObject _current_state = new GameStateObject.from_grid (_size, tiles, to_move,
_neighbor_tiles);
Object (size : _size,
current_state : _current_state,
@@ -581,7 +627,7 @@ private class Game : Object
if (!current_state.test_placing_tile (x, y, out move))
return false;
- current_state = new GameState.copy_and_move (current_state, move);
+ current_state = new GameStateObject.copy_and_move (current_state, move);
undo_stack.append (current_state);
end_of_turn (/* undoing */ false, /* no_draw */ false);
return true;
@@ -592,7 +638,7 @@ private class Game : Object
if (current_player_can_move)
return false;
- current_state = new GameState.copy_and_pass (current_state);
+ current_state = new GameStateObject.copy_and_pass (current_state);
undo_stack.append (current_state);
end_of_turn (/* undoing */ false, /* no_draw */ true);
return true;
@@ -615,9 +661,9 @@ private class Game : Object
{
uint undo_stack_n_items = undo_stack.get_n_items ();
Object? tmp_current_state = undo_stack.get_object (undo_stack_n_items - 2);
- if (tmp_current_state == null || !((!) tmp_current_state is GameState))
+ if (tmp_current_state == null || !((!) tmp_current_state is GameStateObject))
assert_not_reached ();
- current_state = (GameState) (!) tmp_current_state;
+ current_state = (GameStateObject) (!) tmp_current_state;
/* for now, we forget about this undone move in the undo stack
TODO keep an index of current state instead, and allow redo */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]