Compare commits

...

11 Commits

Author SHA1 Message Date
1f7ff56204 Updated build for Java 8. Version 6 is no longer supported as of Java SE JDK 25. 2026-02-10 11:33:51 -05:00
Woody Folsom
b8d9480ae7 Added license and README.txt. 2012-05-02 08:30:14 -04:00
Woody Folsom
3ba0db6ebd All MoveGenerators default to 1 move lookahead.
Made MoveGenerators protected for unit testing.
Added unit test for some analysis of MoveGenerator speeds.
Fixed MDP to consider all states where #turns = maxTurns terminal.
2012-05-01 22:24:02 -04:00
Woody Folsom
924780baaf Substantially improved performance of Board.isLegal().
No longer a static method.
AlphaBeta is now playable with 4-move lookahead (although slow).
2012-05-01 09:38:32 -04:00
Woody Folsom
48915071d4 Now allows a leading - character for command-line arguments. The presence or absence of this character a has not effect. 2012-05-01 09:11:39 -04:00
Woody Folsom
490d3d0bf6 Fixed various errors when target = 0. 2012-04-30 19:53:46 -04:00
Woody Folsom
f4ed883d63 Removed references to log4j. 2012-04-30 19:40:43 -04:00
Marshall
a9fbdfb50e Merge branch 'master' of woodyfolsom.net:/opt/git/cs8803p4 2012-04-30 19:11:48 -04:00
Marshall
f6e4a32b82 - Added rules text. 2012-04-30 19:11:32 -04:00
Woody Folsom
e9ead0edda Merge branch 'master' of woodyfolsom.net:/opt/git/cs8803p4 2012-04-30 18:36:09 -04:00
Marshall
f81db19586 - Test PlayerModel.dat file should not be versioned, I don't think... 2012-04-30 17:59:44 -04:00
24 changed files with 233 additions and 100 deletions

View File

@@ -5,6 +5,5 @@
<classpathentry kind="src" path="test"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/junit-4.10.jar"/>
<classpathentry kind="lib" path="lib/log4j-1.2.16.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

7
LICENSE.txt Normal file
View File

@@ -0,0 +1,7 @@
Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

16
README.TXT Normal file
View File

@@ -0,0 +1,16 @@
MatchAttack! Instructions
---------------------------
Unzip the attached archive 'CS8803_P4.zip' and change to the new directory.
To build MatchAttack!: run 'ant clean' then 'ant' in this directory.
To run MatchAttack!: change to the 'dist' directory, then run java -jar CS8803_P4.jar
For full instructions, see writeup/CS8803_P4.PDF.
For assistance, please contact Woody Folsom <woody.folsom@gatech.edu> or Marshall Gillson <mgillson1@gmail.com>.
NOTICE
------
Unless otherwise attributed, code in the 'aima' package is (c) Ciaran O'Reilly and Ravi Mohan. It is used under the MIT license. See LICENSE.TXT for more information. Note that this is the actual license referenced by the project site, with placeholders for date and author names.

View File

@@ -33,7 +33,7 @@
<target name="compile" depends="copy-resources">
<!-- Compile the java code from ${src} into ${build} -->
<javac srcdir="${src}" destdir="${build}" classpathref="build.classpath" debug="true" source="1.6" target="1.6"/>
<javac srcdir="${src}" destdir="${build}" classpathref="build.classpath" debug="true" source="1.8" target="1.8"/>
</target>
<target name="compile-test" depends="compile">

Binary file not shown.

View File

@@ -33,7 +33,11 @@ public class MDPFactory {
public static ActionsFunction<GridCell<Double>, GridWorldAction> createActionsFunctionForTileGame(
final GridWorld<Double> cw, int maxTiles, int maxScore) {
final Set<GridCell<Double>> terminals = new HashSet<GridCell<Double>>();
terminals.add(cw.getCellAt(maxTiles,maxScore));
for (int score = 1; score <= maxScore; score++) {
terminals.add(cw.getCellAt(maxTiles,score));
}
//terminals.add(cw.getCellAt(maxTiles,maxScore));
ActionsFunction<GridCell<Double>, GridWorldAction> af = new ActionsFunction<GridCell<Double>, GridWorldAction>() {

View File

@@ -12,14 +12,20 @@ public class Board {
public static final int NUM_ROWS = 5;
public static final int ROW_REMOVAL_SIZE = 3;
public static boolean isLegal(Board brd, CellPointer cp) {
private boolean boardEmpty = true;
public boolean isLegal(CellPointer cp) {
//coordinates are out of board bounds
if (cp.r < 0 || cp.r >= Board.NUM_ROWS || cp.c < 0
|| cp.c >= Board.NUM_COLS) {
return false;
}
boolean legal = (brd.getTile(cp.r, cp.c) == TileColor.NONE);
//target coordinate already has a tile
if (board[cp.r][cp.c] != TileColor.NONE) {
return false;
}
boolean rowUp = (cp.r - 1) >= 0;
boolean rowDown = (cp.r + 1) < Board.NUM_ROWS;
boolean colUp = (cp.c - 1) >= 0;
@@ -27,49 +33,49 @@ public class Board {
// r-1 / c-1
if (rowUp && colUp
&& (brd.getTile(cp.r - 1, cp.c - 1) != TileColor.NONE)) {
return legal && true;
&& (board[cp.r - 1][ cp.c - 1] != TileColor.NONE)) {
return true;
}
// r-1 / c
if (rowUp && (brd.getTile(cp.r - 1, cp.c) != TileColor.NONE)) {
return legal && true;
if (rowUp && (board[cp.r - 1][ cp.c] != TileColor.NONE)) {
return true;
}
// r-1 / c+1
if (rowUp && colDown
&& (brd.getTile(cp.r - 1, cp.c + 1) != TileColor.NONE)) {
return legal && true;
&& (board[cp.r - 1][ cp.c + 1] != TileColor.NONE)) {
return true;
}
// r / c-1
if (colUp && (brd.getTile(cp.r, cp.c - 1) != TileColor.NONE)) {
return legal && true;
if (colUp && (board[cp.r][ cp.c - 1] != TileColor.NONE)) {
return true;
}
// r / c+1
if (colDown && (brd.getTile(cp.r, cp.c + 1) != TileColor.NONE)) {
return legal && true;
if (colDown && (board[cp.r][ cp.c + 1] != TileColor.NONE)) {
return true;
}
// r+1 / c-1
if (rowDown && colUp
&& (brd.getTile(cp.r + 1, cp.c - 1) != TileColor.NONE)) {
return legal && true;
&& (board[cp.r + 1][ cp.c - 1] != TileColor.NONE)) {
return true;
}
// r+1 / c
if (rowDown && (brd.getTile(cp.r + 1, cp.c) != TileColor.NONE)) {
return legal && true;
if (rowDown && (board[cp.r + 1][ cp.c] != TileColor.NONE)) {
return true;
}
// r+1 / c+1
if (rowDown && colDown
&& (brd.getTile(cp.r + 1, cp.c + 1) != TileColor.NONE)) {
return legal && true;
&& (board[cp.r + 1][ cp.c + 1] != TileColor.NONE)) {
return true;
}
return brd.isEmpty();
return boardEmpty;
}
private final TileColor[][] board;
@@ -91,6 +97,7 @@ public class Board {
for (int r = 0; r < NUM_ROWS; r++) {
for (int c = 0; c < NUM_COLS; c++) {
this.boardEmpty = that.boardEmpty;
this.board[r][c] = that.board[r][c];
}
}
@@ -163,7 +170,7 @@ public class Board {
}
public boolean playTile(CellPointer cp, TileColor tile) {
if (!isLegal(this, cp)) {
if (!isLegal(cp)) {
return false; // Illegal move.
}
@@ -304,6 +311,8 @@ public class Board {
}
numPlies++;
boardEmpty = false;
return true;
}
@@ -320,16 +329,4 @@ public class Board {
}
return sb1.toString();
}
private boolean isEmpty() {
for (int r = 0; r < Board.NUM_ROWS; r++) {
for (int c = 0; c < Board.NUM_COLS; c++) {
if (getTile(r, c) != TileColor.NONE) {
return false;
}
}
}
return true;
}
}

View File

@@ -6,8 +6,6 @@ import model.comPlayer.Player;
import model.playerModel.GameGoal;
import model.playerModel.PlayerModel;
import org.apache.log4j.Logger;
import view.BoardPanel;
import view.HighScoreDialog;
import view.MainFrame;
@@ -16,8 +14,6 @@ import view.ScorePanel;
public class Referee implements Runnable {
public static final String COM_TURN = "Waiting for the computer's move.";
public static final String GAME_OVER = "Game over!";
public static final Logger LOGGER = Logger.getLogger(Referee.class
.getName());
public static final String PLAYER_TURN = "Waiting for the player's move.";
@@ -153,7 +149,6 @@ public class Referee implements Runnable {
}
private void play() {
int plies = 0;
while (!isOver()) {
if (board.isPlayerTurn()) {
boolean wasInterrupted = false;
@@ -197,7 +192,7 @@ public class Referee implements Runnable {
getScorePanel().updateScore(getPlayerScore());
mf.updateMessage(getMessage());
boardPanel.updateIcons();
LOGGER.info("plies: " + plies++);
try {
Thread.sleep(250L);
} catch (InterruptedException ie) {

View File

@@ -44,7 +44,7 @@ public class AdaptiveComPlayer implements Player {
// take 10 turns to place 6 tiles
double defaultPenalty = -0.25;
int maxScore = target.getTargetScore();
int maxScore = Math.max(1,target.getTargetScore());
int maxTiles = Board.NUM_COLS * Board.NUM_ROWS;
gw = GridWorldFactory.createGridWorldForTileGame(maxTiles,
@@ -79,10 +79,11 @@ public class AdaptiveComPlayer implements Player {
if (action == null || state == null) {
System.out
.println("Board state outside of parameters of MDP. Reverting to failsafe behavior.");
action = GridWorldAction.RandomMove;
}
System.out.println("Performing action " + action + " at state " + state
action = GridWorldAction.AddTile;
} else {
System.out.println("Performing action " + action + " at state " + state
+ " per policy.");
}
switch (action) {
case AddTile:
// System.out.println("Performing action #" +

View File

@@ -8,7 +8,7 @@ import model.playerModel.GameGoal;
import model.playerModel.PlayerModel;
public class AlphaBetaComPlayer implements Player {
private final MoveGenerator moveGenerator = new AlphaBetaMoveGenerator();
final MoveGenerator moveGenerator = new AlphaBetaMoveGenerator();
@Override
public void denyMove() {

View File

@@ -286,7 +286,7 @@ public class CountingPlayer implements Player {
for (int r = 0; r < Board.NUM_ROWS; r++) {
for (int c = 0; c < Board.NUM_COLS; c++) {
if (Board.isLegal(board, new CellPointer(r, c))) {
if (board.isLegal(new CellPointer(r, c))) {
moves.add(new Move(TileColor.BLUE, r, c));
moves.add(new Move(TileColor.GREEN, r, c));
moves.add(new Move(TileColor.RED, r, c));

View File

@@ -8,7 +8,7 @@ import model.playerModel.GameGoal;
import model.playerModel.PlayerModel;
public class MinimaxComPlayer implements Player {
private final MoveGenerator moveGenerator = new MinimaxMoveGenerator();
final MoveGenerator moveGenerator = new MinimaxMoveGenerator();
public MinimaxComPlayer() {
super();

View File

@@ -8,7 +8,7 @@ import model.playerModel.GameGoal;
import model.playerModel.PlayerModel;
public class MonteCarloComPlayer implements Player {
private final MoveGenerator moveGenerator = new MonteCarloMoveGenerator();
final MoveGenerator moveGenerator = new MonteCarloMoveGenerator();
@Override
public void denyMove() {

View File

@@ -29,4 +29,4 @@ public interface Player {
public boolean isReady();
public void setGameGoal(GameGoal target);
}
}

View File

@@ -8,13 +8,9 @@ import model.BoardScorer;
import model.Move;
import model.SearchResult;
import org.apache.log4j.Logger;
public class AlphaBetaMoveGenerator implements MoveGenerator {
private static final int DEFAULT_RECURSIVE_PLAYS = 1;
private static final Logger LOGGER = Logger
.getLogger(AlphaBetaMoveGenerator.class.getName());
private int lookahead = DEFAULT_RECURSIVE_PLAYS;
private final BoardScorer scorer = new BoardScorer();
private final ValidMoveGenerator validMoveGenerator = new ValidMoveGenerator();
@@ -22,10 +18,10 @@ public class AlphaBetaMoveGenerator implements MoveGenerator {
public Move genMove(Board board, boolean asHuman) {
if (!asHuman) {
return getMaxValue(board, asHuman, DEFAULT_RECURSIVE_PLAYS * 2,
return getMaxValue(board, asHuman, lookahead * 2,
Integer.MIN_VALUE, Integer.MAX_VALUE).move;
} else {
return getMinValue(board, asHuman, DEFAULT_RECURSIVE_PLAYS * 2,
return getMinValue(board, asHuman, lookahead * 2,
Integer.MIN_VALUE, Integer.MAX_VALUE).move;
}
}
@@ -36,7 +32,6 @@ public class AlphaBetaMoveGenerator implements MoveGenerator {
@Override
public List<Move> genMoves(Board board, boolean asHuman, int nMoves) {
Move[] doNothing = new Move[] { Move.NONE };
LOGGER.info("Minimax genMoves() stub returning []");
return Arrays.asList(doNothing);
}
@@ -119,4 +114,9 @@ public class AlphaBetaMoveGenerator implements MoveGenerator {
return bestResult;
}
@Override
public boolean setLookahead(int lookahead) {
this.lookahead = lookahead;
return true;
}
}

View File

@@ -8,12 +8,9 @@ import model.BoardScorer;
import model.Move;
import model.SearchResult;
import org.apache.log4j.Logger;
public class MinimaxMoveGenerator implements MoveGenerator {
private static final Logger LOGGER = Logger
.getLogger(MinimaxMoveGenerator.class.getName());
private static final int DEFAULT_RECURSIVE_PLAYS = 2;
private static final int DEFAULT_RECURSIVE_PLAYS = 1;
private int lookahead = DEFAULT_RECURSIVE_PLAYS;
private final BoardScorer scorer = new BoardScorer();
private final ValidMoveGenerator validMoveGenerator = new ValidMoveGenerator();
@@ -24,12 +21,12 @@ public class MinimaxMoveGenerator implements MoveGenerator {
//have different types of moves.
SearchResult searchResult;
if (!asHuman) {
searchResult = getMaxValue(board, Move.NONE, asHuman, DEFAULT_RECURSIVE_PLAYS * 2);
searchResult = getMaxValue(board, Move.NONE, asHuman, lookahead * 2);
} else {
searchResult = getMinValue(board, Move.NONE, asHuman, DEFAULT_RECURSIVE_PLAYS * 2);
searchResult = getMinValue(board, Move.NONE, asHuman, lookahead * 2);
}
System.out.println(searchResult);
//System.out.println(searchResult);
return searchResult.move;
}
@@ -93,13 +90,15 @@ public class MinimaxMoveGenerator implements MoveGenerator {
return recursionLevel < 1;
}
/**
* AlphaBetaMoveGenerator2 does not support this method.
*/
@Override
public List<Move> genMoves(Board board, boolean asHuman, int nMoves) {
Move[] doNothing = new Move[] { Move.NONE };
LOGGER.info("Minimax genMoves() stub returning []");
return Arrays.asList(doNothing);
}
@Override
public boolean setLookahead(int lookahead) {
this.lookahead = lookahead;
return true;
}
}

View File

@@ -8,12 +8,9 @@ import model.BoardScorer;
import model.Move;
import model.SearchResult;
import org.apache.log4j.Logger;
public class MonteCarloMoveGenerator implements MoveGenerator {
private static final Logger LOGGER = Logger
.getLogger(MonteCarloMoveGenerator.class.getName());
private static final int DEFAULT_RECURSIVE_PLAYS = 3;
private static final int DEFAULT_RECURSIVE_PLAYS = 1;
private int lookahead = DEFAULT_RECURSIVE_PLAYS;
private static final int MOVES_PER_LEVEL = 12;
private final BoardScorer scorer = new BoardScorer();
@@ -22,7 +19,7 @@ public class MonteCarloMoveGenerator implements MoveGenerator {
@Override
public Move genMove(Board board, boolean asHuman) {
SearchResult bestResult = genMove(board, asHuman, DEFAULT_RECURSIVE_PLAYS * 2);
SearchResult bestResult = genMove(board, asHuman, lookahead * 2);
return bestResult.move;
}
@@ -73,13 +70,15 @@ public class MonteCarloMoveGenerator implements MoveGenerator {
return new SearchResult(bestResult.move, (int)Math.round((double)totalScore / validMoves.size()));
}
/**
* AlphaBetaMoveGenerator2 does not support this method.
*/
@Override
public List<Move> genMoves(Board board, boolean asHuman, int nMoves) {
Move[] doNothing = new Move[] { Move.NONE };
LOGGER.info("Minimax genMoves() stub returning []");
return Arrays.asList(doNothing);
}
@Override
public boolean setLookahead(int lookahead) {
this.lookahead = lookahead;
return true;
}
}

View File

@@ -10,4 +10,5 @@ public interface MoveGenerator {
public Move genMove(Board board, boolean asHuman);
public List<Move> genMoves(Board board, boolean asHuman, int nMoves);
public boolean setLookahead(int lookahead);
}

View File

@@ -80,7 +80,7 @@ public class NeuralNetworkMoveGenerator implements MoveGenerator {
}
}
while (!Board.isLegal(board, mv.getCell())) {
while (!board.isLegal(mv.getCell())) {
mv = new Move(mv.getColor(), new CellPointer(
PlayerModel.rand.nextInt(Board.NUM_ROWS),
PlayerModel.rand.nextInt(Board.NUM_COLS)));
@@ -94,5 +94,8 @@ public class NeuralNetworkMoveGenerator implements MoveGenerator {
// Do nothing.
return null;
}
@Override
public boolean setLookahead(int lookahead) {
return false;
}
}

View File

@@ -9,15 +9,9 @@ import model.Board.TileColor;
import model.CellPointer;
import model.Move;
import org.apache.log4j.Logger;
public class ValidMoveGenerator implements MoveGenerator {
private static final Logger LOGGER = Logger
.getLogger(ValidMoveGenerator.class.getName());
@Override
public Move genMove(Board board, boolean asHuman) {
LOGGER.info("ValidMoveGenerator genMove() stub returning NONE");
return Move.NONE;
}
@@ -28,13 +22,11 @@ public class ValidMoveGenerator implements MoveGenerator {
for (int r = 0; r < Board.NUM_ROWS; r++) {
for (int c = 0; c < Board.NUM_COLS; c++) {
if (Board.isLegal(board, new CellPointer(r, c))) {
for (TileColor color : TileColor.values()) {
if (color == TileColor.NONE) {
continue;
}
validMoves.add(new Move(color, r, c));
}
if (board.isLegal(new CellPointer(r, c))) {
validMoves.add(new Move(TileColor.BLUE, r, c));
validMoves.add(new Move(TileColor.GREEN, r, c));
validMoves.add(new Move(TileColor.RED, r, c));
validMoves.add(new Move(TileColor.YELLOW, r, c));
}
}
}
@@ -47,4 +39,9 @@ public class ValidMoveGenerator implements MoveGenerator {
return validMoves.subList(0, Math.min(validMoves.size(), nMoves));
}
}
}
@Override
public boolean setLookahead(int lookahead) {
return false;
}
}

View File

@@ -4,12 +4,13 @@ public class ArgParser {
public static ParsedArgs parse(String[] cmdLineArgs) {
ParsedArgs parsedArgs = new ParsedArgs();
for (int i = 0; i < cmdLineArgs.length; i++) {
if (cmdLineArgs[i].toUpperCase().startsWith("COM=")) {
String arg = cmdLineArgs[i].replaceAll("-","");
if (arg.toUpperCase().startsWith("COM=")) {
String comPlayer = cmdLineArgs[i].split("=")[1];
parsedArgs.setComPlayer(comPlayer);
System.out.println("ComPlayer set to: " + comPlayer);
} else {
System.out.println("Ignoring unrecognized argument: " + cmdLineArgs[i]);
System.out.println("Ignoring unrecognized argument: " + arg);
}
}
return parsedArgs;

View File

@@ -25,7 +25,7 @@ public class UserChooserFrame extends JFrame {
public static final String PLAYER_LIST_FILE = "players.dat";
public static final JLabel RULES_TEXT = new JLabel(
"Here should go some rules text. Lorem ipsum dolor sit amet, consectetur adipiscing elit...");
"<html>Welcome to <i>MatchAttack!</i><br><br>The rules of <i>MatchAttack!</i> are very straightforward.<ol><li>The goal of <i>MatchAttack!</i> is to maxmize your score.<br>You earn a point for each tile you place on the board.</li><li>Unless the board is empty, every tile you place must be adjacent to an existing tile.</li><li>If you create a line of three or more tiles of the same color, horizontally or vertically,<br>then every tile in that row will be removed.</li><li>After each tile you place, the computer will place a tile.<br>The computer will attempt to fill the board.</li></ol>Enter your name below to begin!</html>");
private static final long serialVersionUID = 1L;
private final Player comPlayer;

Binary file not shown.

View File

@@ -0,0 +1,114 @@
package model.comPlayer;
import org.junit.Ignore;
import org.junit.Test;
import model.Board;
import model.Board.TileColor;
import model.playerModel.PlayerModel;
import model.CellPointer;
public class SpeedTest {
private static final Board board = new Board();
private static final int nTestRounds = 10;
private static final int lookahead = 3;
static {
board.playTile(new CellPointer(2,2), TileColor.BLUE);
}
@Test
public void testRandom() {
long testTime = 0L;
RandomComPlayer player = new RandomComPlayer();
PlayerModel model = new PlayerModel("test");
for (int testRound = 0; testRound < nTestRounds; testRound++) {
Board newBoard = new Board(board);
long testStart = System.currentTimeMillis();
player.getMove(newBoard, model);
long testEnd = System.currentTimeMillis();
testTime += testEnd - testStart;
}
double avgTime = testTime / (nTestRounds * 1000.0);
System.out.println("Average time for RandomMoveGenerator.genMove() over " + nTestRounds + " tests: " + avgTime);
}
@Test
public void testMonteCarlo() {
long testTime = 0L;
MonteCarloComPlayer player = new MonteCarloComPlayer();
player.moveGenerator.setLookahead(lookahead);
PlayerModel model = new PlayerModel("test");
for (int testRound = 0; testRound < nTestRounds; testRound++) {
Board newBoard = new Board(board);
long testStart = System.currentTimeMillis();
player.getMove(newBoard, model);
long testEnd = System.currentTimeMillis();
testTime += testEnd - testStart;
}
double avgTime = testTime / (nTestRounds * 1000.0);
System.out.println("Average time for MonteCarloGenerator.genMove() over " + nTestRounds + " tests: " + avgTime);
}
@Ignore
public void testMinimax() {
long testTime = 0L;
MinimaxComPlayer player = new MinimaxComPlayer();
player.moveGenerator.setLookahead(lookahead);
PlayerModel model = new PlayerModel("test");
for (int testRound = 0; testRound < nTestRounds; testRound++) {
Board newBoard = new Board(board);
long testStart = System.currentTimeMillis();
player.getMove(newBoard, model);
long testEnd = System.currentTimeMillis();
testTime += testEnd - testStart;
}
double avgTime = testTime / (nTestRounds * 1000.0);
System.out.println("Average time for MinimaxMoveGenerator.genMove() over " + nTestRounds + " tests: " + avgTime);
}
@Test
public void testAlphaBeta() {
long testTime = 0L;
AlphaBetaComPlayer player = new AlphaBetaComPlayer();
player.moveGenerator.setLookahead(lookahead);
PlayerModel model = new PlayerModel("test");
for (int testRound = 0; testRound < nTestRounds; testRound++) {
Board newBoard = new Board(board);
long testStart = System.currentTimeMillis();
player.getMove(newBoard, model);
long testEnd = System.currentTimeMillis();
testTime += testEnd - testStart;
}
double avgTime = testTime / (nTestRounds * 1000.0);
System.out.println("Average time for AlphaBetaMoveGenerator.genMove() over " + nTestRounds + " tests: " + avgTime);
}
}