GitLab repository storage has been migrated to hashed layout. Please contact Infrastructure team if you notice any issues with repositories or hooks.

Commit a818be7d authored by Arnaud B.'s avatar Arnaud B.

Use uint8 more.

parent 6bd79f30
......@@ -20,7 +20,7 @@
private enum Difficulty { EASY, MEDIUM, HARD; }
private int playgame(string moves_until_now)
private uint8 playgame(string moves_until_now)
{
DecisionTree t = new DecisionTree();
return t.playgame(moves_until_now);
......@@ -34,34 +34,32 @@ private class DecisionTree
MAX_HEURIST_VALUE < NEG_INF/plies */
private const int NEG_INF = -100000;
private const int MAX_HEURIST_VALUE = 10000;
private const int BOARD_ROWS = 6;
private const int BOARD_COLUMNS = 7;
/* to mantain the status of the board, to be used by the heuristic function, the top left cell is [0, 0] */
private Player[,] board = new Player [BOARD_ROWS, BOARD_COLUMNS];
/* plies - depth of the DecisionTree */
private int plies = 8;
private uint8 plies = 8;
/* last_moving_player - The player who made the last move, set to Player.NOBODY if no one has made a move yet */
private Player last_moving_player = Player.NOBODY;
/* next_move_in_column - stores the column number in which next move is to be made */
private int next_move_in_column = -1;
private uint8 next_move_in_column = uint8.MAX;
/* stores the difficulty level of the game */
private Difficulty level;
/* Initializes an empty board */
internal DecisionTree()
{
for (int i = 0; i < BOARD_ROWS; i++)
for (int j = 0; j < BOARD_COLUMNS; j++)
for (uint8 i = 0; i < BOARD_ROWS; i++)
for (uint8 j = 0; j < BOARD_COLUMNS; j++)
board [i, j] = Player.NOBODY;
}
/* utility function for debugging purposes, prints a snapshot of current status of the board */
internal void print_board()
{
for (int i = 0; i< BOARD_ROWS; i++)
for (uint8 i = 0; i < BOARD_ROWS; i++)
{
for (int j = 0; j < BOARD_COLUMNS; j++)
for (uint8 j = 0; j < BOARD_COLUMNS; j++)
stdout.printf("%d\t", board [i, j]);
stdout.printf("\n");
}
......@@ -70,7 +68,7 @@ private class DecisionTree
/* Recursively implements a negamax tree in memory with alpha-beta pruning. The function is first called for the root node.
It returns the value of the current node. For nodes at height == 0, the value is determined by a heuristic function. */
private int negamax(int height, int alpha, int beta)
private int negamax(uint8 height, int alpha, int beta)
{
/* base case of recursive function, returns if we have reached the lowest depth of DecisionTree or the board if full */
if (height == 0 || board_full())
......@@ -89,9 +87,9 @@ private class DecisionTree
/* Local variable that stores the column number in which next move is to be made.
Initialized with -1 because we do not know the column number yet. */
int next = -1;
uint8 next = uint8.MAX;
for (int column = 0; column < BOARD_COLUMNS; column++)
for (uint8 column = 0; column < BOARD_COLUMNS; column++)
{
/* make a move into the i'th column */
if (!move(column))
......@@ -125,10 +123,10 @@ private class DecisionTree
}
/* all these functions return true if last_moving_player wins, or false */
private bool victory(int column)
private bool victory(uint8 column)
{
/* find the cell on which the last move was made */
int row;
uint8 row;
for (row = 0; row < BOARD_ROWS && board [row, column] == Player.NOBODY; row++);
return vertical_win(row, column) ||
......@@ -137,41 +135,50 @@ private class DecisionTree
backward_diagonal_win(row, column);
}
private inline bool forward_diagonal_win(int i, int j)
private inline bool forward_diagonal_win(uint8 _i, uint8 _j)
{
int count = 0;
int8 i = (int8) _i;
int8 j = (int8) _j;
uint8 count = 0;
for (int k = i, l = j; k >= 0 && l < BOARD_COLUMNS && board [k, l] == last_moving_player; k--, l++, count++);
for (int k = i + 1, l = j - 1; k < BOARD_ROWS && l >= 0 && board [k, l] == last_moving_player; k++, l--, count++);
for (int8 k = i, l = j; k >= 0 && l < BOARD_COLUMNS && board [k, l] == last_moving_player; k--, l++, count++);
for (int8 k = i + 1, l = j - 1; k < BOARD_ROWS && l >= 0 && board [k, l] == last_moving_player; k++, l--, count++);
return count >= 4;
}
private inline bool backward_diagonal_win(int i, int j)
private inline bool backward_diagonal_win(uint8 _i, uint8 _j)
{
int count = 0;
int8 i = (int8) _i;
int8 j = (int8) _j;
for (int k = i, l = j; k >= 0 && l >= 0 && board [k, l] == last_moving_player; k--, l--, count++);
for (int k = i + 1, l = j + 1; k < BOARD_ROWS && l < BOARD_COLUMNS && board [k, l] == last_moving_player; k++, l++, count++);
uint8 count = 0;
for (int8 k = i, l = j; k >= 0 && l >= 0 && board [k, l] == last_moving_player; k--, l--, count++);
for (int8 k = i + 1, l = j + 1; k < BOARD_ROWS && l < BOARD_COLUMNS && board [k, l] == last_moving_player; k++, l++, count++);
return count >= 4;
}
private inline bool horizontal_win(int i, int j)
private inline bool horizontal_win(uint8 _i, uint8 _j)
{
int count = 0;
int8 i = (int8) _i;
int8 j = (int8) _j;
for (int k = j; k >= 0 && board [i, k] == last_moving_player; k--, count++);
for (int k = j + 1; k < BOARD_COLUMNS && board [i, k] == last_moving_player; k++, count++);
uint8 count = 0;
for (int8 k = j; k >= 0 && board [i, k] == last_moving_player; k--, count++);
for (int8 k = j + 1; k < BOARD_COLUMNS && board [i, k] == last_moving_player; k++, count++);
return count >= 4;
}
private inline bool vertical_win(int i, int j)
private inline bool vertical_win(uint8 i, uint8 j)
{
int count = 0;
uint8 count = 0;
for (int k = i; k < BOARD_ROWS && board [k, j] == last_moving_player; k++, count++);
for (uint8 k = i; k < BOARD_ROWS && board [k, j] == last_moving_player; k++, count++);
return count >= 4;
}
......@@ -179,17 +186,17 @@ private class DecisionTree
/* returns true if the board is full, false if not */
private bool board_full()
{
for (int i = 0 ; i < BOARD_COLUMNS ; i++)
for (uint8 i = 0 ; i < BOARD_COLUMNS ; i++)
if (board [0, i] == Player.NOBODY)
return false;
return true;
}
/* makes a move into the column'th column. Returns true if the move was succesful, false if it wasn't */
private bool move(int column)
private bool move(uint8 column)
{
/* find the cell on which to move */
int row;
int8 row;
for (row = BOARD_ROWS - 1; row >= 0 && board [row, column] != Player.NOBODY; row--);
if (row < 0)
......@@ -204,11 +211,11 @@ private class DecisionTree
}
/* unmove the last move made in the column'th column */
private void unmove(int column)
private void unmove(uint8 column)
requires(last_moving_player != Player.NOBODY)
{
/* find the cell on which the last move was made */
int row;
uint8 row;
for (row = 0; row < BOARD_ROWS && board [row, column] == Player.NOBODY; row++);
board [row, column] = Player.NOBODY;
......@@ -219,19 +226,19 @@ private class DecisionTree
/* vstr is the sequence of moves made until now. We update DecisionTree::board to reflect these sequence of moves. */
private void update_board(string vstr)
{
next_move_in_column = -1;
next_move_in_column = uint8.MAX;
/* AI will make the first move, nothing to add to the board */
if (vstr.length == 2) return;
Player move = vstr.length % 2 == 0 ? Player.OPPONENT : Player.HUMAN;
for (int i = 1; i < vstr.length - 1; i++)
for (uint8 i = 1; i < vstr.length - 1; i++)
{
int column = int.parse(vstr [i].to_string()) - 1;
uint8 column = (uint8) int.parse(vstr [i].to_string()) - 1;
/* find the cell on which the move is made */
int row;
int8 row;
for (row = BOARD_ROWS - 1; row >= 0 && board [row, column] != Player.NOBODY; row--);
board [row, column] = move;
......@@ -242,16 +249,16 @@ private class DecisionTree
last_moving_player = Player.HUMAN;
}
/* Check for immediate win of HUMAN or OPPONENT. It checks the current state of the board. Returns -1 if no immediate win for Player P.
/* Check for immediate win of HUMAN or OPPONENT. It checks the current state of the board. Returns uint8.MAX if no immediate win for Player P.
Otherwise returns the column number in which Player P should move to win. */
private int immediate_win(Player p)
private uint8 immediate_win(Player p)
{
Player old_last_moving_player = last_moving_player;
last_moving_player = p == Player.OPPONENT ? Player.HUMAN : Player.OPPONENT;
bool player_wins = false;
int i;
uint8 i;
for (i = 0; i < BOARD_COLUMNS; i++)
{
if (!move(i))
......@@ -266,12 +273,12 @@ private class DecisionTree
last_moving_player = old_last_moving_player;
/* returns -1 if no immediate win for Player p */
return player_wins ? i : -1;
/* returns uint8.MAX if no immediate win for Player p */
return player_wins ? i : uint8.MAX;
}
/* returns the column number in which the next move has to be made. Returns -1 if the board is full. */
internal int playgame(string vstr)
/* returns the column number in which the next move has to be made. Returns uint8.MAX if the board is full. */
internal uint8 playgame(string vstr)
{
/* set the Difficulty level */
set_level(vstr);
......@@ -279,23 +286,22 @@ private class DecisionTree
/* update DecisionTree::board to reflect the moves made until now */
update_board(vstr);
/* if AI can win by making a move immediately, make that move;
main.c has indexing beginning from 1 instead of 0, hence, we add 1 */
int temp = immediate_win(Player.OPPONENT);
if (temp != -1)
return temp + 1;
/* if AI can win by making a move immediately, make that move */
uint8 temp = immediate_win(Player.OPPONENT);
if (temp < BOARD_COLUMNS)
return temp;
/* if HUMAN can win by making a move immediately,
we make AI move in that column so as avoid loss */
temp = immediate_win(Player.HUMAN);
if (temp != -1)
return temp + 1;
if (temp < BOARD_COLUMNS)
return temp;
/* call negamax tree on the current state of the board */
negamax(plies, NEG_INF, -1 * NEG_INF);
/* return the column number in which next move should be made */
return next_move_in_column + 1;
return next_move_in_column;
}
/* The evaluation function to be called when we have reached the maximum depth in the DecisionTree */
......@@ -335,9 +341,9 @@ private class DecisionTree
last_moving_player = p;
for (int j = 0; j < BOARD_COLUMNS; j++)
for (uint8 j = 0; j < BOARD_COLUMNS; j++)
{
for (int i = 0; i < BOARD_ROWS; i++)
for (uint8 i = 0; i < BOARD_ROWS; i++)
{
if (board [i, j] != Player.NOBODY)
break;
......@@ -358,11 +364,14 @@ private class DecisionTree
}
/* checks if all adjacent cells to board [i, j] are empty */
private inline bool all_adjacent_empty(int i, int j)
private inline bool all_adjacent_empty(uint8 _i, uint8 _j)
{
for (int k = -1 ; k <= 1; k++)
int8 i = (int8) _i;
int8 j = (int8) _j;
for (int8 k = -1 ; k <= 1; k++)
{
for (int l = -1; l <= 1; l++)
for (int8 l = -1; l <= 1; l++)
{
if (k == 0 && l == 0)
continue;
......@@ -387,7 +396,7 @@ private class DecisionTree
level = Difficulty.MEDIUM;
plies = 7;
}
else
else // TODO if (vstr [0] == 'c') / else assert_not_reached ();
{
level = Difficulty.HARD;
plies = 7;
......@@ -395,21 +404,21 @@ private class DecisionTree
}
/* utility function for testing purposes */
internal int playandcheck(string vstr)
internal uint8 playandcheck(string vstr)
{
set_level(vstr);
update_board(vstr);
int temp = immediate_win(Player.OPPONENT);
if (temp != -1)
return 1000;
uint8 temp = immediate_win(Player.OPPONENT);
if (temp < BOARD_COLUMNS)
return 100;
temp = immediate_win(Player.HUMAN);
if (temp != -1)
return temp + 1;
if (temp < BOARD_COLUMNS)
return temp;
negamax(plies, NEG_INF, -1 * NEG_INF);
return next_move_in_column + 1;
return next_move_in_column;
}
}
......@@ -21,13 +21,6 @@
using Gtk;
// if you want to play, update also the two const in ai.vala
private const uint8 BOARD_COLUMNS = 7;
private const uint8 BOARD_COLUMNS_MINUS_ONE = 6;
private const uint8 BOARD_ROWS = 6;
private const uint8 BOARD_ROWS_PLUS_ONE = 7;
private const uint8 BOARD_SIZE = 7; // as long as that is needed, impossible to have n_rows != n_cols - 1
private class FourInARow : Gtk.Application
{
private GLib.Settings settings = new GLib.Settings ("org.gnome.Four-in-a-row");
......@@ -362,10 +355,8 @@ private class FourInARow : Gtk.Application
{
vstr [0] = vlevel [ai_level];
playgame_timeout = Timeout.add (COMPUTER_INITIAL_DELAY, () => {
int c = playgame ((string) vstr) - 1;
if (c > BOARD_COLUMNS_MINUS_ONE)
assert_not_reached ();
if (c < 0)
uint8 c = playgame ((string) vstr);
if (c >= BOARD_COLUMNS) // c could be uint8.MAX if board is full
return Source.REMOVE;
process_move ((uint8) c);
playgame_timeout = 0;
......@@ -527,11 +518,9 @@ private class FourInARow : Gtk.Application
{
playgame_timeout = Timeout.add (COMPUTER_MOVE_DELAY, () => {
vstr [0] = vlevel [ai_level];
int col = playgame ((string) vstr) - 1;
if (col < 0)
uint8 col = playgame ((string) vstr);
if (col >= BOARD_COLUMNS) // c could be uint8.MAX if the board is full
set_gameover (true);
else if (col > BOARD_COLUMNS_MINUS_ONE)
assert_not_reached ();
var nm = new NextMove ((uint8) col, this);
Timeout.add (SPEED_DROP, nm.exec);
playgame_timeout = 0;
......@@ -779,9 +768,6 @@ private class FourInARow : Gtk.Application
private inline void on_game_hint ()
{
string s;
uint8 c;
if (timeout != 0)
return;
if (gameover)
......@@ -794,10 +780,9 @@ private class FourInARow : Gtk.Application
set_status_message (_("I’m Thinking…"));
vstr [0] = vlevel [/* strong */ 3];
int _c = playgame ((string) vstr) - 1;
if (_c < 0 || _c > BOARD_COLUMNS_MINUS_ONE)
assert_not_reached ();
c = (uint8) _c;
uint8 c = playgame ((string) vstr);
if (c >= BOARD_COLUMNS)
assert_not_reached (); // c could be uint8.MAX if the board if full
column_moveto = c;
while (timeout != 0)
......@@ -809,8 +794,7 @@ private class FourInARow : Gtk.Application
blink_tile (0, c, game_board [0, c], /* blink n times */ 3);
/* Translators: text displayed in the headerbar/actionbar, when a hint is requested; the %d is replaced by the number of the suggested column */
s = _("Hint: Column %d").printf (c + 1);
set_status_message (s);
set_status_message (_("Hint: Column %d").printf (c + 1));
if (moves <= 0 || (moves == 1 && is_player_human ()))
window.allow_undo (false);
......
......@@ -18,6 +18,12 @@
with GNOME Four-in-a-row. If not, see <https://www.gnu.org/licenses/>.
*/
private const uint8 BOARD_COLUMNS = 7;
private const uint8 BOARD_COLUMNS_MINUS_ONE = 6;
private const uint8 BOARD_ROWS = 6;
private const uint8 BOARD_ROWS_PLUS_ONE = 7;
private const uint8 BOARD_SIZE = 7; // as long as that is needed, impossible to have n_rows != n_cols - 1
private enum Player
{
NOBODY,
......
......@@ -19,9 +19,9 @@
with GNOME Four-in-a-row. If not, see <https://www.gnu.org/licenses/>.
*/
private const int NUMBER_GAMES = 5;
private const int MAXIMUM_GAMES = 100;
private const int THRESHOLD_DENOMINATOR = 4;
private const uint8 NUMBER_GAMES = 5;
private const uint8 MAXIMUM_GAMES = 100;
private const uint8 THRESHOLD_DENOMINATOR = 4;
private int main (string[] args)
{
......@@ -47,110 +47,110 @@ private int main (string[] args)
private static inline void test_horizontal_win ()
{
/*In the first statement below, the AI has made moves into the 1st, 2nd and 3rd columns. To win, AI must move in the 4th column.*/
assert (playgame ("a1727370") == 4);
assert (playgame ("a7315651311324420") == 6);
assert (playgame ("a232225657223561611133440") == 4);
assert (playgame ("a242215322574255543341746677453337710") == 1);
assert_true (playgame ("a1727370") == 3);
assert_true (playgame ("a7315651311324420") == 5);
assert_true (playgame ("a232225657223561611133440") == 3);
assert_true (playgame ("a242215322574255543341746677453337710") == 0);
}
/* Tests if the AI makes moves so as to take up immediate vertical wins.*/
private static inline void test_vertical_win ()
{
assert (playgame ("a1213140") == 1);
assert (playgame ("a14456535526613130") == 1);
assert (playgame ("a432334277752576710") == 7);
assert (playgame ("a547477454544323321712116260") == 2);
assert_true (playgame ("a1213140") == 0);
assert_true (playgame ("a14456535526613130") == 0);
assert_true (playgame ("a432334277752576710") == 6);
assert_true (playgame ("a547477454544323321712116260") == 1);
}
/* Tests if the AI makes moves so as to take up immediate forward diagonal wins.*/
private static inline void test_forward_diagonal_win ()
{
assert (playgame ("a54221164712446211622157570") == 7);
assert (playgame ("a4256424426621271412117175776343330") == 3);
assert (playgame ("a132565522322662666775443351131113540") == 4);
assert (playgame ("a4571311334541225544112245262577767733360") == 6);
assert_true (playgame ("a54221164712446211622157570") == 6);
assert_true (playgame ("a4256424426621271412117175776343330") == 2);
assert_true (playgame ("a132565522322662666775443351131113540") == 3);
assert_true (playgame ("a4571311334541225544112245262577767733360") == 5);
}
/* Tests if the AI makes moves so as to take up immediate backward diagonal wins.*/
private static inline void test_backward_diagonal_win ()
{
assert (playgame ("5422327343142110") == 1); // TODO no "a"?
assert (playgame ("a1415113315143220") == 2);
assert (playgame ("a547323452213345110") == 1);
assert (playgame ("a4256424426621271412117175776343330") == 3);
assert_true (playgame ("5422327343142110") == 0); // TODO no "a"?
assert_true (playgame ("a1415113315143220") == 1);
assert_true (playgame ("a547323452213345110") == 0);
assert_true (playgame ("a4256424426621271412117175776343330") == 2);
}
/* Tests if the AI makes moves which prevents HUMAN from taking immediate vertical victories. Consider that a HUMAN has 3 balls in the
first column. The AI's next move should be in the 1st column or else, HUMAN will claim victory on his next turn.*/
private static inline void test_avoid_vertical_loss ()
{
assert (playgame ("a42563117273430") == 3);
assert (playgame ("a3642571541322340") == 4);
assert (playgame ("a144566264475171137750") == 5);
assert (playgame ("a54747745454432332171210") == 1);
assert_true (playgame ("a42563117273430") == 2);
assert_true (playgame ("a3642571541322340") == 3);
assert_true (playgame ("a144566264475171137750") == 4);
assert_true (playgame ("a54747745454432332171210") == 0);
}
/* Tests if the AI makes moves which prevents HUMAN from taking immediate forward diagonal victories*/
private static inline void test_avoid_forward_diagonal_loss ()
{
assert (playgame ("a34256477331566570") == 7);
assert (playgame ("a1445662644751711370") == 7);
assert (playgame ("a43442235372115113340") == 4);
assert (playgame ("a4143525567766443543125411170") == 7);
assert_true (playgame ("a34256477331566570") == 6);
assert_true (playgame ("a1445662644751711370") == 6);
assert_true (playgame ("a43442235372115113340") == 3);
assert_true (playgame ("a4143525567766443543125411170") == 6);
}
/* Tests if the AI makes moves which prevents HUMAN from taking immediate backward diagonal victories*/
private static inline void test_avoid_backward_diagonal_loss ()
{
assert (playgame ("a47465234222530") == 3);
assert (playgame ("a4344223537211510") == 1);
assert (playgame ("a4141311525513520") == 2);
assert (playgame ("a1445662644751711377553330") == 3);
assert_true (playgame ("a47465234222530") == 2);
assert_true (playgame ("a4344223537211510") == 0);
assert_true (playgame ("a4141311525513520") == 1);
assert_true (playgame ("a1445662644751711377553330") == 2);
}
/* Tests if the AI makes moves which prevents HUMAN from taking immediate horizontal victories*/
private static inline void test_avoid_horizontal_loss ()
{
assert (playgame ("a445360") == 7);
assert (playgame ("a745534131117114777720") == 2);
assert (playgame ("a243466431217112323350") == 5);
assert (playgame ("a24147356465355111336631615240") == 4);
assert_true (playgame ("a445360") == 6);
assert_true (playgame ("a745534131117114777720") == 1);
assert_true (playgame ("a243466431217112323350") == 4);
assert_true (playgame ("a24147356465355111336631615240") == 3);
}
/* Tests if AI can detect full boards, and thus draw games.*/
private static inline void test_draw ()
{
assert (playgame ("a1311313113652226667224247766737374455445550") == 0);
assert (playgame ("a6121151135432322433425566474425617635677770") == 0);
assert (playgame ("a4226111412113275256335534443264375577676670") == 0);
assert (playgame ("a4212116575717754775221133434432366655342660") == 0);
assert_true (playgame ("a1311313113652226667224247766737374455445550") == uint8.MAX);
assert_true (playgame ("a6121151135432322433425566474425617635677770") == uint8.MAX);
assert_true (playgame ("a4226111412113275256335534443264375577676670") == uint8.MAX);
assert_true (playgame ("a4212116575717754775221133434432366655342660") == uint8.MAX);
}
/* Tests if AI makes valid moves, i.e., between column 1 and column 7*/
private static inline void test_random ()
{
int x = playgame ("a443256214350");
assert (x >= 1 && x <= 7);
uint8 x = playgame ("a443256214350");
assert_true (x <= 6);
x = playgame ("a241473564653551113366316150");
assert (x >= 1 && x <= 7);
assert_true (x <= 6);
x = playgame ("a24357315461711177416622623350");
assert (x >= 1 && x <= 7);
assert_true (x <= 6);
x = playgame ("a1445662644751711377553333665775446110");
assert (x >= 1 && x <= 7);
assert_true (x <= 6);
}
/* Pits two AI's of varying difficulty levels against each other and returns the number of games won by easier AI.*/
private static inline int test_ai_vs_ai (string easier, string harder)
private static inline uint8 test_ai_vs_ai (string easier, string harder)
{
int easier_wins = 0;
int draw = 0;
int harder_wins = 0;
uint8 easier_wins = 0;
uint8 draw = 0;
uint8 harder_wins = 0;
for (int i = 0; i < NUMBER_GAMES; i++)
for (uint8 i = 0; i < NUMBER_GAMES; i++)
{
StringBuilder e = new StringBuilder ();
e.append (easier);
......@@ -160,40 +160,39 @@ private static inline int test_ai_vs_ai (string easier, string harder)
while (true)
{
int move;
DecisionTree t = new DecisionTree ();
move = t.playandcheck (e.str);
if (move == 0)
uint8 move = t.playandcheck (e.str);
if (move == uint8.MAX)
{
draw++;
break;
}
if (move == 1000)
if (move == 100)
{
easier_wins++;
break;
}
e.insert (e.str.length - 1, move.to_string ());
m.insert (m.str.length - 1, move.to_string ());
e.insert (e.str.length - 1, (move + 1).to_string ());
m.insert (m.str.length - 1, (move + 1).to_string ());
DecisionTree d = new DecisionTree ();
move = d.playandcheck (m.str);
if (move == 0)
if (move == uint8.MAX)
{
draw++;
break;
}
if (move == 1000)
if (move == 100)
{
harder_wins++;
break;
}
e.insert (e.str.length - 1, move.to_string ());
m.insert (m.str.length - 1, move.to_string ());
e.insert (e.str.length - 1, (move + 1).to_string ());
m.insert (m.str.length - 1, (move + 1).to_string ());
}
}
return easier_wins;
......@@ -201,7 +200,7 @@ private static inline int test_ai_vs_ai (string easier, string harder)
/* Repeatedly contest between the two AI until either easier win ratio is less than a threshold
or maximum numbers of contests have been played.*/
private static inline void repeat_contests (string easier, string harder, out int games_contested, out int easy_wins)
private static inline void repeat_contests (string easier, string harder, out uint8 games_contested, out uint8 easy_wins)
{
easy_wins = test_ai_vs_ai (easier, harder);
games_contested = NUMBER_GAMES;
......@@ -215,27 +214,27 @@ private static inline void repeat_contests (string easier, string harder, out in
private static inline void test_easy_vs_medium ()
{
int easy_wins;
int games_contested;
uint8 easy_wins;
uint8 games_contested;
repeat_contests ("a0", "b0", out games_contested, out easy_wins);