[iagno] Introduce empty_neighbors.
- From: Arnaud B. <arnaudb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [iagno] Introduce empty_neighbors.
- Date: Wed, 22 May 2019 13:00:12 +0000 (UTC)
commit 94cc1d94d9d280cfdb058b3d43557dcc700d3d55
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date: Sat Apr 27 10:03:32 2019 +0200
Introduce empty_neighbors.
Yay performances.
src/computer-reversi.vala | 55 +++-----------------
src/game.vala | 129 +++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 135 insertions(+), 49 deletions(-)
---
diff --git a/src/computer-reversi.vala b/src/computer-reversi.vala
index c823016..8a0667c 100644
--- a/src/computer-reversi.vala
+++ b/src/computer-reversi.vala
@@ -217,7 +217,7 @@ private class ComputerReversi : ComputerPlayer
return tile_difference;
/* Normal strategy: try to evaluate the position */
- return tile_difference + eval_heuristic (g, ref heuristic) + around (g) ;
+ return tile_difference + eval_heuristic (g, ref heuristic);
}
private static int16 eval_heuristic (GameState g, ref int16 [,] heuristic)
@@ -228,63 +228,22 @@ private class ComputerReversi : ComputerPlayer
{
for (uint8 y = 0; y < size; y++)
{
+ // heuristic
int16 h = heuristic [x, y];
if (g.get_owner (x, y) != g.current_color)
h = -h;
count += h;
- }
- }
- return count;
- }
-
- private static int16 around (GameState g)
- {
- int16 count = 0;
- int8 size = (int8) g.size;
- int8 xpp;
- int8 xmm;
- int8 ypp;
- int8 ymm;
- for (int8 x = 0; x < size; x++)
- {
- xpp = x + 1;
- xmm = x - 1;
- for (int8 y = 0; y < size; y++)
- {
- ypp = y + 1;
- ymm = y - 1;
-
- int16 a = 0;
- a -= is_empty (g, xpp, y );
- a -= is_empty (g, xpp, ypp);
- a -= is_empty (g, x, ypp);
- a -= is_empty (g, xmm, ypp);
- a -= is_empty (g, xmm, y );
- a -= is_empty (g, xmm, ymm);
- a -= is_empty (g, x, ymm);
- a -= is_empty (g, xpp, ymm);
-
- /* Two points for completely surrounded tiles */
- if (a == 0)
- a = 2;
-
- count += (g.get_owner ((uint8) x, (uint8) y) == g.current_color) ? a : -a;
+ // around
+ int16 a = (int16) g.get_empty_neighbors (x, y);
+ if (a == 0) // completely surrounded
+ a = -2;
+ count += (g.get_owner ((uint8) x, (uint8) y) == g.current_color) ? -a : a;
}
}
return count;
}
- private static int16 is_empty (GameState g, int8 x, int8 y)
- {
- if (!g.is_valid_location_signed (x, y))
- return 0;
- if (g.get_owner ((uint8) x, (uint8) y) != Player.NONE)
- return 0;
-
- return 1;
- }
-
/*\
* * First random moves
\*/
diff --git a/src/game.vala b/src/game.vala
index 5174dfa..a5837bb 100644
--- a/src/game.vala
+++ b/src/game.vala
@@ -48,7 +48,9 @@ private class GameState : Object
construct
{
- tiles = new Player [size, size];
+ tiles = new Player [size, size];
+ empty_neighbors = new uint8 [size, size];
+ neighbor_tiles = new uint8 [size, size];
}
internal GameState.copy (GameState game)
@@ -57,7 +59,11 @@ private class GameState : Object
for (uint8 x = 0; x < size; x++)
for (uint8 y = 0; y < size; y++)
+ {
set_tile (x, y, game.tiles [x, y]);
+ empty_neighbors [x, y] = game.empty_neighbors [x, y];
+ neighbor_tiles [x, y] = game.neighbor_tiles [x, y];
+ }
update_who_can_move ();
if (current_player_can_move != game.current_player_can_move
@@ -71,7 +77,11 @@ private class GameState : Object
for (uint8 x = 0; x < size; x++)
for (uint8 y = 0; y < size; y++)
+ {
set_tile (x, y, game.tiles [x, y]);
+ empty_neighbors [x, y] = game.empty_neighbors [x, y];
+ neighbor_tiles [x, y] = game.neighbor_tiles [x, y];
+ }
// we already know all that, it is just for checking
update_who_can_move ();
@@ -86,7 +96,11 @@ private class GameState : Object
for (uint8 x = 0; x < size; x++)
for (uint8 y = 0; y < size; y++)
+ {
set_tile (x, y, game.tiles [x, y]);
+ empty_neighbors [x, y] = game.empty_neighbors [x, y];
+ neighbor_tiles [x, y] = game.neighbor_tiles [x, y];
+ }
if (place_tile (move_x, move_y, move_color, /* apply move */ true) == 0)
{
@@ -105,6 +119,7 @@ private class GameState : Object
for (uint8 y = 0; y < _size; y++)
set_tile (x, y, _tiles [x, y]);
+ calculate_neighbors ();
update_who_can_move ();
}
@@ -183,6 +198,8 @@ private class GameState : Object
{
if (tiles [x, y] != Player.NONE)
return 0;
+ if (empty_neighbors [x, y] == neighbor_tiles [x, y])
+ return 0;
uint8 tiles_turned = 0;
tiles_turned += flip_tiles (x, y, color, 1, 0, apply);
@@ -198,7 +215,10 @@ private class GameState : Object
return 0;
if (apply)
+ {
set_tile (x, y, color);
+ update_empty_neighbors (x, y);
+ }
return tiles_turned;
}
@@ -238,6 +258,8 @@ private class GameState : Object
{
if (tiles [x, y] != Player.NONE)
return false;
+ if (empty_neighbors [x, y] == neighbor_tiles [x, y])
+ return false;
if (can_flip_tiles (x, y, color, 1, 0) > 0) return true;
if (can_flip_tiles (x, y, color, 1, 1) > 0) return true;
@@ -250,6 +272,111 @@ private class GameState : Object
return false;
}
+ /*\
+ * * surrounding tiles
+ \*/
+
+ private uint8 [,] empty_neighbors;
+ private uint8 [,] neighbor_tiles;
+
+ internal uint8 get_empty_neighbors (uint8 x, uint8 y)
+ {
+ return empty_neighbors [x, y];
+ }
+
+ private inline void calculate_neighbors ()
+ {
+ calculate_neighbor_tiles (size - 1, ref neighbor_tiles);
+ calculate_empty_neighbors ();
+ }
+
+ private static void calculate_neighbor_tiles (uint8 /* size less one */ max,
+ ref uint8 [,] neighbor_tiles)
+ {
+ for (uint8 i = 1; i < max; i++)
+ {
+ // edges
+ neighbor_tiles [i , 0 ] = 5;
+ neighbor_tiles [i , max] = 5;
+ neighbor_tiles [0 , i ] = 5;
+ neighbor_tiles [max, i ] = 5;
+
+ // center
+ for (uint8 j = 1; j < max; j++)
+ neighbor_tiles [i, j] = 8;
+ }
+
+ // corners
+ neighbor_tiles [0 , 0 ] = 3;
+ neighbor_tiles [0 , max] = 3;
+ neighbor_tiles [max, max] = 3;
+ neighbor_tiles [max, 0 ] = 3;
+ }
+
+ private void calculate_empty_neighbors ()
+ {
+ int8 _size = (int8) size;
+
+ int8 xmm; int8 ymm;
+ int8 xpp; int8 ypp;
+ for (int8 x = 0; x < _size; x++)
+ {
+ xmm = x - 1;
+ xpp = x + 1;
+
+ for (int8 y = 0; y < _size; y++)
+ {
+ ymm = y - 1;
+ ypp = y + 1;
+
+ empty_neighbors [x, y] = is_empty (xpp, y )
+ + is_empty (xpp, ypp)
+ + is_empty (x, ypp)
+ + is_empty (xmm, ypp)
+ + is_empty (xmm, y )
+ + is_empty (xmm, ymm)
+ + is_empty (x, ymm)
+ + is_empty (xpp, ymm);
+ }
+ }
+ }
+
+ private uint8 is_empty (int8 x, int8 y)
+ {
+ if (!is_valid_location_signed (x, y))
+ return 0;
+ if (get_owner ((uint8) x, (uint8) y) != Player.NONE)
+ return 0;
+
+ return 1;
+ }
+
+ private void update_empty_neighbors (uint8 x, uint8 y)
+ {
+ int8 xmm = ((int8) x) - 1;
+ int8 ymm = ((int8) y) - 1;
+ int8 xpp = ((int8) x) + 1;
+ int8 ypp = ((int8) y) + 1;
+
+ bool ymm_is_valid = ymm >= 0;
+ bool ypp_is_valid = ypp < size;
+
+ if (xmm >= 0)
+ {
+ empty_neighbors [xmm, y ] -= 1;
+ if (ymm_is_valid) empty_neighbors [xmm, ymm] -= 1;
+ if (ypp_is_valid) empty_neighbors [xmm, ypp] -= 1;
+ }
+ if (ymm_is_valid) empty_neighbors [x , ymm] -= 1;
+ if (ypp_is_valid) empty_neighbors [x , ypp] -= 1;
+ if (xpp < size)
+ {
+ empty_neighbors [xpp, y ] -= 1;
+ if (ymm_is_valid) empty_neighbors [xpp, ymm] -= 1;
+ if (ypp_is_valid) empty_neighbors [xpp, ypp] -= 1;
+ }
+ }
+
/*\
* * flipping tiles
\*/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]