Commit 75eb88a9 authored by Dave Paul's avatar Dave Paul Committed by Michael Catanzaro
Browse files

Improve computer player behavior

This change actually makes use of the around () and eval_heuristic ()
methods to improve the play of the AI player. At level 1, the behavior
is the same as before.

For testing I ran matches against the old computer player which was
playing LIGHT (both sides were at level 2). I ran a full game for each
of the 244 potentially unique openings of 8 pieces (before 8 pieces are
on the board, the computer just plays randomly).

When dark was played by the old code, its record was 100 - 141 - 3.
When dark was played by the new code, its record was 191 - 47- 6.

This is a significant improvement, and may turn out to be too difficult
of an opponent, especially at level 3. We could try reducing the search
depth to compensate... I'm not sure how to judge absolute difficulty of
the AI.

https://bugzilla.gnome.org/show_bug.cgi?id=708179
parent 67cc266d
......@@ -67,8 +67,10 @@ public class ComputerPlayer
* At the end of the game try and maximise the number of tokens.
* Near the end try and push for a win.
* For the rest of the game try and maximise everything.
* Note, for level 1 we default to the "PERFECT" strategy, which is not as
* good as the "BEST" strategy, so as not to make the AI too difficult.
*/
var strategy = Strategy.BEST;
var strategy = (level == 1) ? Strategy.PERFECT : Strategy.BEST;
if (tiles_remaining <= depth + 10)
strategy = Strategy.PERFECT;
else if (tiles_remaining <= depth + 12)
......@@ -173,6 +175,10 @@ public class ComputerPlayer
return b.n_tiles - a.n_tiles;
}
/* Perhaps surprisingly, the *lower* the return value from this method,
* the "better" the position. So callers want to minimize the result here
* to find the best move.
*/
private int calculate_heuristic (Game g, Strategy strategy)
{
var tile_difference = g.n_dark_tiles - g.n_light_tiles;
......@@ -191,11 +197,11 @@ public class ComputerPlayer
/* Try to maximise a number of values */
default:
return tile_difference + around () + eval_heuristic ();
return tile_difference - around (g) - eval_heuristic (g);
}
}
private int eval_heuristic ()
private static int eval_heuristic (Game g)
{
var count = 0;
for (var x = 0; x < 8; x++)
......@@ -203,7 +209,7 @@ public class ComputerPlayer
for (var y = 0; y < 8; y++)
{
var h = heuristic[y * 8 + x];
if (game.get_owner (x, y) != game.current_color)
if (g.get_owner (x, y) != g.current_color)
h = -h;
count += h;
}
......@@ -212,7 +218,7 @@ public class ComputerPlayer
return count;
}
private int around ()
private static int around (Game g)
{
var count = 0;
for (var x = 0; x < 8; x++)
......@@ -220,20 +226,20 @@ public class ComputerPlayer
for (var y = 0; y < 8; y++)
{
var a = 0;
a += is_empty (x + 1, y);
a += is_empty (x + 1, y + 1);
a += is_empty (x, y + 1);
a += is_empty (x - 1, y + 1);
a += is_empty (x - 1, y);
a += is_empty (x - 1, y - 1);
a += is_empty (x, y - 1);
a += is_empty (x + 1, y - 1);
a += is_empty (g, x + 1, y);
a += is_empty (g, x + 1, y + 1);
a += is_empty (g, x, y + 1);
a += is_empty (g, x - 1, y + 1);
a += is_empty (g, x - 1, y);
a += is_empty (g, x - 1, y - 1);
a += is_empty (g, x, y - 1);
a += is_empty (g, x + 1, y - 1);
/* Two points for completely surrounded tiles */
if (a == 0)
a = 2;
if (game.get_owner (x, y) != game.current_color)
if (g.get_owner (x, y) != g.current_color)
a = -a;
count += a;
}
......@@ -242,9 +248,9 @@ public class ComputerPlayer
return count;
}
private int is_empty (int x, int y)
private static int is_empty (Game g, int x, int y)
{
if (x < 0 || x >= 8 || y < 0 || y >= 8 || game.get_owner (x, y) != Player.NONE)
if (x < 0 || x >= 8 || y < 0 || y >= 8 || g.get_owner (x, y) != Player.NONE)
return 0;
return 1;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment