[iagno] Allow humans opening for non-standard boards.
- From: Arnaud B. <arnaudb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [iagno] Allow humans opening for non-standard boards.
- Date: Wed, 4 Dec 2019 07:52:06 +0000 (UTC)
commit 77fdaaa49ed486662d1a4005dbf1f01298a7c8f0
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date: Fri Nov 29 01:11:46 2019 +0100
Allow humans opening for non-standard boards.
src/game.vala | 379 ++++++++++++++++++++++++++++++++++++++------------
src/iagno.vala | 2 +-
src/reversi-view.vala | 174 +++++++++++++++++------
3 files changed, 424 insertions(+), 131 deletions(-)
---
diff --git a/src/game.vala b/src/game.vala
index c189585..298a347 100644
--- a/src/game.vala
+++ b/src/game.vala
@@ -133,7 +133,7 @@ private struct GameStateStruct
}
}
- internal GameStateStruct.from_grid (uint8 _size, Player [,] _tiles, Player color, uint8 [,]
_neighbor_tiles)
+ internal GameStateStruct.from_grid (uint8 _size, Player [,] _tiles, Player color, uint8 [,]
_neighbor_tiles, bool humans_opening)
{
// move color
current_color = color;
@@ -158,7 +158,13 @@ private struct GameStateStruct
init_empty_neighbors ();
// who can move
- update_who_can_move ();
+ if (humans_opening)
+ {
+ current_player_can_move = true;
+ is_complete = false;
+ }
+ else
+ update_who_can_move ();
}
private inline void add_tile_of_color (Player color)
{
@@ -230,6 +236,39 @@ private struct GameStateStruct
y_saved = size / 2 - 2;
}
+ internal GameStateStruct.copy_and_add_two (GameStateStruct game, uint8 x1, uint8 y1, uint8 x2, uint8 y2)
+ {
+ // move color
+ opponent_color = game.current_color;
+ current_color = Player.flip_color (opponent_color);
+
+ // always given
+ size = game.size;
+ neighbor_tiles = game.neighbor_tiles;
+
+ // tiles grid
+ tiles = game.tiles;
+ if (tiles [x1, y1] != Player.NONE
+ || tiles [x2, y2] != Player.NONE)
+ assert_not_reached ();
+ tiles [x1, y1] = opponent_color;
+ tiles [x2, y2] = opponent_color;
+
+ // tiles counters
+ n_current_tiles = game.n_opponent_tiles;
+ n_opponent_tiles = game.n_current_tiles + 2;
+ n_tiles = n_current_tiles + n_opponent_tiles;
+
+ // empty neighbors
+ init_empty_neighbors (); // lazyness
+
+ // who can move
+ current_player_can_move = true;
+ is_complete = false;
+ x_saved = size / 2 - 2;
+ y_saved = size / 2 - 2;
+ }
+
/*\
* * public information
\*/
@@ -565,9 +604,9 @@ private class GameStateObject : Object
_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)
+ internal GameStateObject.from_grid (uint8 size, Player [,] tiles, Player color, uint8 [,]
neighbor_tiles, bool humans_opening = false)
{
- _game_state_struct = GameStateStruct.from_grid (size, tiles, color, neighbor_tiles);
+ _game_state_struct = GameStateStruct.from_grid (size, tiles, color, neighbor_tiles, humans_opening);
}
internal GameStateObject.empty (uint8 size, uint8 [,] neighbor_tiles)
@@ -580,6 +619,11 @@ private class GameStateObject : Object
_game_state_struct = GameStateStruct.copy_and_add (game.game_state_struct, x, y);
}
+ internal GameStateObject.copy_and_add_two (GameStateObject game, uint8 x, uint8 y, uint8 x2, uint8 y2)
+ {
+ _game_state_struct = GameStateStruct.copy_and_add_two (game.game_state_struct, x, y, x2, y2);
+ }
+
/*\
* * public information
\*/
@@ -641,7 +685,7 @@ private class Game : Object
if (print_logs)
{
string e_or_i = reverse ? "e" : "i";
- if (initial_number_of_tiles == 0)
+ if (initial_number_of_tiles <= 1)
print (@"\nnew two-player revers$e_or_i game\n");
else
print (@"\nnew one-player revers$e_or_i game ($opening opening)\n"); // TODO is human
Dark or Light?
@@ -657,7 +701,9 @@ private class Game : Object
GameStateObject _current_state;
uint8 _initial_number_of_tiles;
- if (_opening == Opening.HUMANS)
+ bool even_board = _size % 2 == 0;
+ bool humans_opening = _opening == Opening.HUMANS;
+ if (even_board && humans_opening)
{
_initial_number_of_tiles = 0;
@@ -671,12 +717,13 @@ private class Game : Object
for (uint8 y = 0; y < _size; y++)
tiles [x, y] = Player.NONE;
- if (_size % 2 == 0)
+ if (even_board)
setup_even_board (_size, _opening, ref tiles, out _initial_number_of_tiles);
else
setup_odd_board (_size, _opening, ref tiles, out _initial_number_of_tiles);
- _current_state = new GameStateObject.from_grid (_size, tiles, /* Dark always starts */
Player.DARK, _neighbor_tiles);
+ Player first_player = humans_opening ? Player.LIGHT : /* Dark "always" starts */ Player.DARK;
+ _current_state = new GameStateObject.from_grid (_size, tiles, first_player, _neighbor_tiles,
humans_opening);
}
Object (size : _size,
@@ -712,10 +759,13 @@ private class Game : Object
{
/* logical starting position for odd board */
uint8 mid_board = (size - 1) / 2;
- initial_number_of_tiles = 7;
+ initial_number_of_tiles = opening == Opening.HUMANS ? 1 : 7;
Player [,] start_position;
switch (opening)
{
+ case Opening.HUMANS: start_position = {{ Player.NONE , Player.NONE , Player.NONE },
+ { Player.NONE , Player.DARK , Player.NONE },
+ { Player.NONE , Player.NONE , Player.NONE }};
break;
case Opening.REVERSI: start_position = {{ Player.NONE , Player.LIGHT, Player.DARK },
{ Player.LIGHT, Player.DARK , Player.LIGHT },
{ Player.DARK , Player.LIGHT, Player.NONE }};
break;
@@ -808,51 +858,7 @@ private class Game : Object
internal /* success */ bool place_tile (uint8 x, uint8 y)
{
if (opening == Opening.HUMANS)
- {
- uint8 half_game_size = size / 2;
- if (x < half_game_size - 1 || x > half_game_size
- || y < half_game_size - 1 || y > half_game_size)
- return false;
-
- if (current_color == Player.LIGHT && n_light_tiles == 0)
- {
- uint8 opposite_x = x == half_game_size ? half_game_size - 1 : half_game_size;
- uint8 opposite_y = y == half_game_size ? half_game_size - 1 : half_game_size;
- if (get_owner (opposite_x, opposite_y) == Player.DARK)
- return false;
- }
-
- if (current_state.n_dark_tiles == 2)
- {
- if (get_owner (half_game_size - 1, half_game_size - 1) == Player.DARK)
- {
- if (get_owner (half_game_size, half_game_size - 1) == Player.DARK) opening =
Opening.ALTER_TOP;
- else if (get_owner (half_game_size, half_game_size) == Player.DARK) opening =
Opening.REVERSI;
- else opening =
Opening.ALTER_LEFT;
- }
- else
- {
- if (get_owner (half_game_size, half_game_size - 1) == Player.LIGHT) opening =
Opening.ALTER_BOTTOM;
- else if (get_owner (half_game_size, half_game_size) == Player.DARK) opening =
Opening.ALTER_RIGHT;
- else opening =
Opening.INVERTED;
- }
- }
- if (print_logs)
- {
- string current_color_string = current_color == Player.DARK ? "dark :" : "light:";
- print (@"$current_color_string ($x, $y)\n");
- }
- current_state = new GameStateObject.copy_and_add (current_state, x, y);
-
- if (n_light_tiles == 2)
- {
- undo_stack.remove (0);
- undo_stack.append (current_state);
- }
-
- end_of_turn (/* undoing */ false, /* no_draw */ false);
- return true;
- }
+ return humans_opening_place_tile (x, y);
PossibleMove move;
if (!current_state.test_placing_tile (x, y, out move))
@@ -971,22 +977,7 @@ private class Game : Object
{
move = PossibleMove (x, y); // good enough
- uint8 half_game_size = size / 2;
- if (x < half_game_size - 1 || x > half_game_size
- || y < half_game_size - 1 || y > half_game_size)
- return false;
-
- if (get_owner (x, y) != Player.NONE)
- return false;
-
- if (current_color == Player.LIGHT && n_light_tiles == 0)
- {
- uint8 opposite_x = x == half_game_size ? half_game_size - 1 : half_game_size;
- uint8 opposite_y = y == half_game_size ? half_game_size - 1 : half_game_size;
- if (get_owner (opposite_x, opposite_y) == Player.DARK)
- return false;
- }
- return true;
+ return humans_opening_test_placing_tile (x, y);
}
unowned SList<PossibleMove?>? test_move = possible_moves.nth (0);
@@ -1012,39 +1003,245 @@ private class Game : Object
private inline void update_possible_moves ()
{
if (opening == Opening.HUMANS)
+ humans_opening_update_possible_moves ();
+ else
+ current_state.get_possible_moves (out possible_moves);
+ }
+
+ /*\
+ * * humans opening
+ \*/
+
+ private inline bool humans_opening_place_tile (uint8 x, uint8 y)
+ {
+ uint8 half_game_size = size / 2;
+ bool even_board = size % 2 == 0;
+
+ if (!humans_opening_test_placing_tile (x, y))
+ return false;
+
+ if (even_board)
+ {
+ if (current_state.n_dark_tiles == 2)
+ humans_opening_update_opening_even ();
+
+ if (print_logs)
+ {
+ string current_color_string = current_color == Player.DARK ? "dark :" : "light:";
+ print (@"$current_color_string ($x, $y)\n");
+ }
+ current_state = new GameStateObject.copy_and_add (current_state, x, y);
+ }
+ else
+ {
+ if (current_color == Player.LIGHT && n_light_tiles != 0)
+ humans_opening_update_opening_odd (x, y);
+
+ uint8 x2;
+ uint8 y2;
+ if (x == half_game_size) x2 = half_game_size;
+ else if (x == half_game_size - 1) x2 = half_game_size + 1;
+ else /* x == half_game_size + 1 */ x2 = half_game_size - 1;
+ if (y == half_game_size) y2 = half_game_size;
+ else if (y == half_game_size - 1) y2 = half_game_size + 1;
+ else /* y == half_game_size + 1 */ y2 = half_game_size - 1;
+ if (print_logs)
+ {
+ string current_color_string = current_color == Player.DARK ? "dark :" : "light:";
+ print (@"$current_color_string ($x, $y) and ($x2, $y2)\n");
+ }
+ current_state = new GameStateObject.copy_and_add_two (current_state, x, y, x2, y2);
+ }
+
+ if (n_light_tiles == (even_board ? 2 : 4))
{
- possible_moves = new SList<PossibleMove?> ();
+ undo_stack.remove (0);
+ undo_stack.append (current_state);
+ }
+
+ end_of_turn (/* undoing */ false, /* no_draw */ false);
+ return true;
+ }
+ private inline void humans_opening_update_opening_even ()
+ {
+ uint8 half_game_size = size / 2;
+ if (get_owner (half_game_size - 1, half_game_size - 1) == Player.DARK)
+ {
+ if (get_owner (half_game_size, half_game_size - 1) == Player.DARK) opening = Opening.ALTER_TOP;
+ else if (get_owner (half_game_size, half_game_size) == Player.DARK) opening = Opening.REVERSI;
+ else opening = Opening.ALTER_LEFT;
+ }
+ else
+ {
+ if (get_owner (half_game_size, half_game_size - 1) == Player.LIGHT) opening =
Opening.ALTER_BOTTOM;
+ else if (get_owner (half_game_size, half_game_size) == Player.DARK) opening =
Opening.ALTER_RIGHT;
+ else opening = Opening.INVERTED;
+ }
+ }
+ private inline void humans_opening_update_opening_odd (uint8 x, uint8 y)
+ {
+ uint8 half_game_size = size / 2;
+ if (x == half_game_size || y == half_game_size)
+ {
+ if (get_owner (half_game_size - 1, half_game_size - 1) == Player.NONE)
+ opening = Opening.REVERSI;
+ else
+ opening = Opening.INVERTED;
+ }
+ else
+ {
+ if (x == y)
+ {
+ if (get_owner (half_game_size, half_game_size - 1) == Player.LIGHT)
+ opening = Opening.ALTER_LEFT;
+ else opening = Opening.ALTER_BOTTOM;
+ }
+ else
+ {
+ if (get_owner (half_game_size, half_game_size - 1) == Player.LIGHT)
+ opening = Opening.ALTER_RIGHT;
+ else opening = Opening.ALTER_TOP;
+ }
+ }
+ }
+
+ private bool humans_opening_test_placing_tile (uint8 x, uint8 y)
+ {
+ if (get_owner (x, y) != Player.NONE)
+ return false;
+
+ if (size % 2 == 0)
+ return humans_opening_test_placing_tile_even (x, y);
+ else
+ return humans_opening_test_placing_tile_odd (x, y);
+ }
+ private inline bool humans_opening_test_placing_tile_even (uint8 x, uint8 y)
+ {
+ uint8 half_game_size = size / 2;
- uint8 half_game_size = size / 2;
+ if (x < half_game_size - 1 || x > half_game_size
+ || y < half_game_size - 1 || y > half_game_size)
+ return false;
- bool top_left;
- bool top_right;
- bool bottom_left;
- bool bottom_right;
+ if (current_color == Player.LIGHT && n_light_tiles == 0)
+ {
+ uint8 opposite_x = x == half_game_size ? half_game_size - 1 : half_game_size;
+ uint8 opposite_y = y == half_game_size ? half_game_size - 1 : half_game_size;
+ if (get_owner (opposite_x, opposite_y) == Player.DARK)
+ return false;
+ }
+ return true;
+ }
+ private inline bool humans_opening_test_placing_tile_odd (uint8 x, uint8 y)
+ {
+ uint8 half_game_size = size / 2;
+
+ if (x < half_game_size - 1 || x > half_game_size + 1
+ || y < half_game_size - 1 || y > half_game_size + 1)
+ return false;
- if (current_color == Player.LIGHT && n_light_tiles == 0)
+ if (current_color == Player.LIGHT)
+ {
+ if (n_light_tiles == 0)
{
- top_left = get_owner (half_game_size - 1, half_game_size - 1) == Player.NONE
- && get_owner (half_game_size , half_game_size ) == Player.NONE;
- top_right = !top_left;
- bottom_left = !top_left;
- bottom_right = top_left;
+ if (x != half_game_size && y != half_game_size)
+ return false;
}
else
{
- top_left = get_owner (half_game_size - 1, half_game_size - 1) == Player.NONE;
- top_right = get_owner (half_game_size , half_game_size - 1) == Player.NONE;
- bottom_left = get_owner (half_game_size - 1, half_game_size ) == Player.NONE;
- bottom_right = get_owner (half_game_size , half_game_size ) == Player.NONE;
+ if (get_owner (half_game_size - 1, half_game_size - 1) != Player.NONE
+ || get_owner (half_game_size + 1, half_game_size - 1) != Player.NONE)
+ {
+ if (x != half_game_size && y != half_game_size)
+ return false;
+ }
}
+ }
+ return true;
+ }
+
+ private inline void humans_opening_update_possible_moves ()
+ {
+ if (size % 2 == 0)
+ humans_opening_update_possible_moves_even ();
+ else
+ humans_opening_update_possible_moves_odd ();
+ }
+ private inline void humans_opening_update_possible_moves_even ()
+ {
+ possible_moves = new SList<PossibleMove?> ();
+
+ uint8 half_game_size = size / 2;
- if (top_left) possible_moves.prepend (PossibleMove (half_game_size - 1, half_game_size - 1));
- if (top_right) possible_moves.prepend (PossibleMove (half_game_size , half_game_size - 1));
- if (bottom_left) possible_moves.prepend (PossibleMove (half_game_size - 1, half_game_size ));
- if (bottom_right) possible_moves.prepend (PossibleMove (half_game_size , half_game_size ));
+ bool top_left;
+ bool top_right;
+ bool bottom_left;
+ bool bottom_right;
+
+ if (current_color == Player.LIGHT && n_light_tiles == 0)
+ {
+ top_left = get_owner (half_game_size - 1, half_game_size - 1) == Player.NONE
+ && get_owner (half_game_size , half_game_size ) == Player.NONE;
+ top_right = !top_left;
+ bottom_left = !top_left;
+ bottom_right = top_left;
}
else
- current_state.get_possible_moves (out possible_moves);
+ {
+ top_left = get_owner (half_game_size - 1, half_game_size - 1) == Player.NONE;
+ top_right = get_owner (half_game_size , half_game_size - 1) == Player.NONE;
+ bottom_left = get_owner (half_game_size - 1, half_game_size ) == Player.NONE;
+ bottom_right = get_owner (half_game_size , half_game_size ) == Player.NONE;
+ }
+
+ if (top_left) possible_moves.prepend (PossibleMove (half_game_size - 1, half_game_size - 1));
+ if (top_right) possible_moves.prepend (PossibleMove (half_game_size , half_game_size - 1));
+ if (bottom_left) possible_moves.prepend (PossibleMove (half_game_size - 1, half_game_size ));
+ if (bottom_right) possible_moves.prepend (PossibleMove (half_game_size , half_game_size ));
+ }
+ private inline void humans_opening_update_possible_moves_odd ()
+ {
+ possible_moves = new SList<PossibleMove?> ();
+
+ uint8 half_game_size = size / 2;
+
+ // light starts, first ply
+ if (n_light_tiles == 0)
+ {
+ possible_moves.prepend (PossibleMove (half_game_size - 1, half_game_size ));
+ possible_moves.prepend (PossibleMove (half_game_size , half_game_size - 1));
+ possible_moves.prepend (PossibleMove (half_game_size , half_game_size + 1));
+ possible_moves.prepend (PossibleMove (half_game_size + 1, half_game_size ));
+ }
+ // first dark ply
+ else if (current_color == Player.DARK)
+ {
+ for (uint8 x = half_game_size - 1; x <= half_game_size + 1; x++)
+ for (uint8 y = half_game_size - 1; y <= half_game_size + 1; y++)
+ if (get_owner (x, y) == Player.NONE)
+ possible_moves.prepend (PossibleMove (x, y));
+ }
+ // dark played vertically or horizontally the center of the opening zone
+ else if (get_owner (half_game_size - 1, half_game_size - 1) == Player.NONE
+ && get_owner (half_game_size - 1, half_game_size + 1) == Player.NONE)
+ {
+ possible_moves.prepend (PossibleMove (half_game_size - 1, half_game_size - 1));
+ possible_moves.prepend (PossibleMove (half_game_size - 1, half_game_size + 1));
+ possible_moves.prepend (PossibleMove (half_game_size + 1, half_game_size - 1));
+ possible_moves.prepend (PossibleMove (half_game_size + 1, half_game_size + 1));
+ }
+ // light started horizontally, dark played in a corner of the opening zone
+ else if (get_owner (half_game_size, half_game_size - 1) == Player.NONE)
+ {
+ possible_moves.prepend (PossibleMove (half_game_size , half_game_size - 1));
+ possible_moves.prepend (PossibleMove (half_game_size , half_game_size + 1));
+ }
+ // light started vertically, dark played in a corner of the opening zone
+ else
+ {
+ possible_moves.prepend (PossibleMove (half_game_size - 1, half_game_size ));
+ possible_moves.prepend (PossibleMove (half_game_size + 1, half_game_size ));
+ }
}
}
diff --git a/src/iagno.vala b/src/iagno.vala
index 3056fa5..fddb07d 100644
--- a/src/iagno.vala
+++ b/src/iagno.vala
@@ -644,7 +644,7 @@ private class Iagno : Gtk.Application, BaseApplication
}
else if (usual_start)
opening = Opening.REVERSI;
- else if (two_players && even_board && !random_start) // TODO make work on odd board
+ else if (two_players && !random_start)
opening = Opening.HUMANS;
else if (random_start
|| settings.get_boolean ("random-start-position")
diff --git a/src/reversi-view.vala b/src/reversi-view.vala
index 3889508..7cb5937 100644
--- a/src/reversi-view.vala
+++ b/src/reversi-view.vala
@@ -173,10 +173,16 @@ private class ReversiView : Gtk.DrawingArea
last_state_set = false;
if (_game.opening == Opening.HUMANS)
{
- if (!even_board)
- assert_not_reached ();
- overture_steps = { 0, 0, 0, 0 };
- overture_target = { 0, 0, 0, 0 };
+ if (even_board)
+ {
+ overture_steps = { 0, 0, 0, 0 };
+ overture_target = { 0, 0, 0, 0 };
+ }
+ else
+ {
+ overture_steps = { 0, 0, 0, 0, 0, 0 };
+ overture_target = { 0, 0, 0, 0, 0, 0 };
+ }
current_overture_playable = 0;
if (configuration_done)
configure_overture_origin ();
@@ -369,11 +375,36 @@ private class ReversiView : Gtk.DrawingArea
}
private inline void configure_overture_origin ()
{
- overture_origin_xs [0] = 5 * board_size / 16 - border_width - tile_size / 2;
- overture_origin_xs [1] = 7 * board_size / 16 - border_width - tile_size / 2;
- overture_origin_xs [2] = 9 * board_size / 16 - border_width - tile_size / 2;
- overture_origin_xs [3] = 11 * board_size / 16 - border_width - tile_size / 2;
- overture_origin_y = 3 * board_size / 4 - border_width - tile_size / 2;
+ if (game_size % 2 == 0)
+ {
+ overture_origin_xs [0] = (game_size - 3) * board_size / (2 * game_size) - border_width -
tile_size / 2;
+ overture_origin_xs [1] = (game_size - 1) * board_size / (2 * game_size) - border_width -
tile_size / 2;
+ overture_origin_xs [2] = (game_size + 1) * board_size / (2 * game_size) - border_width -
tile_size / 2;
+ overture_origin_xs [3] = (game_size + 3) * board_size / (2 * game_size) - border_width -
tile_size / 2;
+
+ if (game_size == 4)
+ // where we can
+ overture_origin_y = (int) ((game_size + 2.6) * board_size / (2 * game_size) - border_width
- tile_size / 2);
+ else
+ // on the line under the center zone
+ overture_origin_y = (game_size + 4) * board_size / (2 * game_size) - border_width -
tile_size / 2;
+ }
+ else
+ {
+ overture_origin_xs [0] = (game_size - 2) * board_size / (2 * game_size) - border_width -
tile_size / 2;
+ overture_origin_xs [2] = game_size * board_size / (2 * game_size) - border_width -
tile_size / 2;
+ overture_origin_xs [4] = (game_size + 2) * board_size / (2 * game_size) - border_width -
tile_size / 2;
+ overture_origin_xs [1] = overture_origin_xs [0];
+ overture_origin_xs [3] = overture_origin_xs [2];
+ overture_origin_xs [5] = overture_origin_xs [4];
+
+ if (game_size == 5)
+ // where we can
+ overture_origin_y = (int) ((game_size + 3.6) * board_size / (2 * game_size) - border_width
- tile_size / 2);
+ else
+ // on the line under the center zone
+ overture_origin_y = (game_size + 5) * board_size / (2 * game_size) - border_width -
tile_size / 2;
+ }
}
protected override bool draw (Cairo.Context cr)
@@ -502,10 +533,17 @@ private class ReversiView : Gtk.DrawingArea
for (uint8 x = 0; x < game_size; x++)
for (uint8 y = 0; y < game_size; y++)
{
+ // even and odd boards
if ((x == half_game_size || x == half_game_size - 1)
&& (y == half_game_size || y == half_game_size - 1))
continue;
+ // odd boards only
+ if (game_size % 2 != 0
+ && (((y == half_game_size + 1) && (x == half_game_size - 1 || x == half_game_size || x ==
half_game_size + 1))
+ || ((x == half_game_size + 1) && (y == half_game_size - 1 || y == half_game_size))))
+ continue;
+
darken_tile (cr, x, y);
}
@@ -649,24 +687,35 @@ private class ReversiView : Gtk.DrawingArea
}
private const uint8 OVERTURE_STEPS_MAX = 10;
- private int [] overture_origin_xs = new int [4];
+ private int [] overture_origin_xs = new int [6]; // 4 for even boards, 6 for odd ones
private int overture_origin_y = 0;
- private uint8 [] overture_steps = { 0, 0, 0, 0 };
- private uint8 [] overture_target = { 0, 0, 0, 0 };
+ private uint8 [] overture_steps = { 0, 0, 0, 0, 0, 0 }; // { 0, 0, 0, 0 } for even boards
+ private uint8 [] overture_target = { 0, 0, 0, 0, 0, 0 }; // { 0, 0, 0, 0 } for even boards
private uint8 current_overture_playable = 0;
private inline void draw_overture_playables (Cairo.Context cr)
{
- if (current_overture_playable < 4)
+ bool even_board = game_size % 2 == 0;
+ if (current_overture_playable < (even_board ? 4 : 6))
draw_overture_indicator (cr);
- for (uint8 i = 0; i < 4; i++)
+
+ for (uint8 i = 0; i < (even_board ? 4 : 6); i++)
draw_overture_playable (cr, i);
+
+ if (!even_board)
+ {
+ uint8 half_game_size = game_size / 2;
+ draw_playable (cr, pixmaps [half_game_size, half_game_size],
+ tile_xs [half_game_size, half_game_size],
+ tile_ys [half_game_size, half_game_size]);
+ }
}
private inline void draw_overture_indicator (Cairo.Context cr)
{
+ double diameter_factor = game_size == 4 ? 1.95 : 1.8;
cr.set_source_rgba (background_red, background_green, background_blue, 1.0);
cr.arc ((double) overture_origin_xs [current_overture_playable] + (double) tile_size / 2.0,
(double) overture_origin_y + (double) tile_size / 2.0,
- (double) tile_size / 1.8,
+ (double) tile_size / diameter_factor,
0.0,
Math.PI * 2.0);
cr.fill ();
@@ -675,7 +724,7 @@ private class ReversiView : Gtk.DrawingArea
{
if (overture_steps [playable_id] == OVERTURE_STEPS_MAX)
{
- int x, y;
+ uint8 x, y;
get_x_and_y (playable_id, out x, out y);
draw_playable (cr, pixmaps [x, y], tile_xs [x, y], tile_ys [x, y]);
return;
@@ -686,7 +735,7 @@ private class ReversiView : Gtk.DrawingArea
if (overture_target [playable_id] != 0)
{
- int x, y;
+ uint8 x, y;
get_x_and_y (playable_id, out x, out y);
tile_x += (tile_xs [x, y] - tile_x) * overture_steps [playable_id] / OVERTURE_STEPS_MAX;
tile_y += (tile_ys [x, y] - tile_y) * overture_steps [playable_id] / OVERTURE_STEPS_MAX;
@@ -694,7 +743,10 @@ private class ReversiView : Gtk.DrawingArea
overture_steps [playable_id]++;
queue_draw ();
}
- _draw_overture_playable (cr, tile_x, tile_y, /* pixmap */ (playable_id % 2) * 30 + 1);
+ if (game_size % 2 == 0)
+ _draw_overture_playable (cr, tile_x, tile_y, /* pixmap */ (playable_id % 2) * 30 + 1);
+ else
+ _draw_overture_playable (cr, tile_x, tile_y, /* pixmap */ ((playable_id / 2 + 1) % 2) * 30 + 1);
}
private void _draw_overture_playable (Cairo.Context cr, int tile_x, int tile_y, int pixmap)
{
@@ -706,17 +758,31 @@ private class ReversiView : Gtk.DrawingArea
cr.rectangle (tile_x, tile_y, /* width and height */ tile_size, tile_size);
cr.fill ();
}
- private void get_x_and_y (uint8 playable_id, out int x, out int y)
+ private void get_x_and_y (uint8 playable_id, out uint8 x, out uint8 y)
{
- int half_game_size = game_size / 2;
- switch (overture_target [playable_id])
- {
- case 1: x = half_game_size - 1; y = half_game_size - 1; break;
- case 2: x = half_game_size ; y = half_game_size - 1; break;
- case 3: x = half_game_size - 1; y = half_game_size ; break;
- case 4: x = half_game_size ; y = half_game_size ; break;
- default: assert_not_reached ();
- }
+ uint8 half_game_size = game_size / 2;
+ if (game_size % 2 == 0)
+ switch (overture_target [playable_id])
+ {
+ case 1: x = half_game_size - 1; y = half_game_size - 1; break;
+ case 2: x = half_game_size ; y = half_game_size - 1; break;
+ case 3: x = half_game_size - 1; y = half_game_size ; break;
+ case 4: x = half_game_size ; y = half_game_size ; break;
+ default: assert_not_reached ();
+ }
+ else
+ switch (overture_target [playable_id])
+ {
+ case 1: x = half_game_size - 1; y = half_game_size - 1; break;
+ case 2: x = half_game_size ; y = half_game_size - 1; break;
+ case 3: x = half_game_size + 1; y = half_game_size - 1; break;
+ case 4: x = half_game_size - 1; y = half_game_size ; break;
+ case 6: x = half_game_size + 1; y = half_game_size ; break;
+ case 7: x = half_game_size - 1; y = half_game_size + 1; break;
+ case 8: x = half_game_size ; y = half_game_size + 1; break;
+ case 9: x = half_game_size + 1; y = half_game_size + 1; break;
+ default: assert_not_reached ();
+ }
}
/*\
@@ -897,19 +963,49 @@ private class ReversiView : Gtk.DrawingArea
{
if (humans_opening_intensity != 0)
{
+ bool even_board = game_size % 2 == 0;
uint8 half_game_size = game_size / 2;
uint8 target;
- if ( (!last_state_set || last_state.get_owner (half_game_size - 1, half_game_size - 1) ==
Player.NONE)
- && game.current_state.get_owner (half_game_size - 1, half_game_size - 1) !=
Player.NONE) target = 1;
- else if ((!last_state_set || last_state.get_owner (half_game_size , half_game_size - 1) ==
Player.NONE)
- && game.current_state.get_owner (half_game_size , half_game_size - 1) !=
Player.NONE) target = 2;
- else if ((!last_state_set || last_state.get_owner (half_game_size - 1, half_game_size ) ==
Player.NONE)
- && game.current_state.get_owner (half_game_size - 1, half_game_size ) !=
Player.NONE) target = 3;
- else if ((!last_state_set || last_state.get_owner (half_game_size , half_game_size ) ==
Player.NONE)
- && game.current_state.get_owner (half_game_size , half_game_size ) !=
Player.NONE) target = 4;
- else assert_not_reached ();
- overture_target [current_overture_playable] = target;
- current_overture_playable++;
+ if (even_board)
+ {
+ if ( (!last_state_set || last_state.get_owner (half_game_size - 1, half_game_size - 1)
== Player.NONE)
+ && game.current_state.get_owner (half_game_size - 1, half_game_size - 1)
!= Player.NONE) target = 1;
+ else if ((!last_state_set || last_state.get_owner (half_game_size , half_game_size - 1)
== Player.NONE)
+ && game.current_state.get_owner (half_game_size , half_game_size - 1)
!= Player.NONE) target = 2;
+ else if ((!last_state_set || last_state.get_owner (half_game_size - 1, half_game_size )
== Player.NONE)
+ && game.current_state.get_owner (half_game_size - 1, half_game_size )
!= Player.NONE) target = 3;
+ else if ((!last_state_set || last_state.get_owner (half_game_size , half_game_size )
== Player.NONE)
+ && game.current_state.get_owner (half_game_size , half_game_size )
!= Player.NONE) target = 4;
+ else assert_not_reached ();
+
+ overture_target [current_overture_playable] = target;
+ current_overture_playable++;
+ }
+ else
+ {
+ if ( (!last_state_set || last_state.get_owner (half_game_size - 1, half_game_size - 1)
== Player.NONE)
+ && game.current_state.get_owner (half_game_size - 1, half_game_size - 1)
!= Player.NONE) target = 1;
+ else if ((!last_state_set || last_state.get_owner (half_game_size , half_game_size - 1)
== Player.NONE)
+ && game.current_state.get_owner (half_game_size , half_game_size - 1)
!= Player.NONE) target = 2;
+ else if ((!last_state_set || last_state.get_owner (half_game_size + 1, half_game_size - 1)
== Player.NONE)
+ && game.current_state.get_owner (half_game_size + 1, half_game_size - 1)
!= Player.NONE) target = 3;
+ else if ((!last_state_set || last_state.get_owner (half_game_size - 1, half_game_size )
== Player.NONE)
+ && game.current_state.get_owner (half_game_size - 1, half_game_size )
!= Player.NONE) target = 4;
+ else if ((!last_state_set || last_state.get_owner (half_game_size + 1, half_game_size )
== Player.NONE)
+ && game.current_state.get_owner (half_game_size + 1, half_game_size )
!= Player.NONE) target = 6;
+ else if ((!last_state_set || last_state.get_owner (half_game_size - 1, half_game_size + 1)
== Player.NONE)
+ && game.current_state.get_owner (half_game_size - 1, half_game_size + 1)
!= Player.NONE) target = 7;
+ else if ((!last_state_set || last_state.get_owner (half_game_size , half_game_size + 1)
== Player.NONE)
+ && game.current_state.get_owner (half_game_size , half_game_size + 1)
!= Player.NONE) target = 8;
+ else if ((!last_state_set || last_state.get_owner (half_game_size + 1, half_game_size + 1)
== Player.NONE)
+ && game.current_state.get_owner (half_game_size + 1, half_game_size + 1)
!= Player.NONE) target = 9;
+ else assert_not_reached ();
+
+ overture_target [current_overture_playable] = target;
+ current_overture_playable++;
+ overture_target [current_overture_playable] = 10 - target;
+ current_overture_playable++;
+ }
}
if (!no_draw)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]