package model.comPlayer.generator; import java.util.Arrays; import java.util.List; import model.Board; import model.BoardScorer; import model.Move; import model.SearchResult; import org.apache.log4j.Logger; public class AlphaBetaMoveGenerator implements MoveGenerator { private static final Logger LOGGER = Logger .getLogger(AlphaBetaMoveGenerator.class.getName()); private static final int DEFAULT_RECURSIVE_PLAYS = 2; private final BoardScorer scorer = new BoardScorer(); private final ValidMoveGenerator validMoveGenerator = new ValidMoveGenerator(); @Override public Move genMove(Board board, boolean asHuman) { if (!asHuman) { return getMaxValue(board, asHuman, DEFAULT_RECURSIVE_PLAYS * 2, Integer.MIN_VALUE, Integer.MAX_VALUE).move; } else { return getMinValue(board, asHuman, DEFAULT_RECURSIVE_PLAYS * 2, Integer.MIN_VALUE, Integer.MAX_VALUE).move; } } private SearchResult getMax(SearchResult sr1, SearchResult sr2) { if (sr1.score >= sr2.score) { return sr1; } else { return sr2; } } private SearchResult getMin(SearchResult sr1, SearchResult sr2) { if (sr1.score <= sr2.score) { return sr1; } else { return sr2; } } private SearchResult getMaxValue(Board board, boolean asHuman, int recursionLevel, int alpha, int beta) { if (recursionLevel < 1) { return new SearchResult(Move.NONE,scorer.getScore(board)); } List validMoves = validMoveGenerator.genMoves(board, asHuman, MoveGenerator.ALL_MOVES); SearchResult bestResult = new SearchResult(Move.NONE,Integer.MIN_VALUE); if (validMoves.size() == 0) { return bestResult; } for (Move nextMove : validMoves) { Board nextBoard = new Board(board); if (!nextBoard.playTile(nextMove.getCell(), nextMove.getColor())) { throw new RuntimeException( "Illegal move attempted during search!"); } SearchResult searchResult = new SearchResult(nextMove,getMinValue(nextBoard, !asHuman, recursionLevel - 1, alpha, beta).score); bestResult = getMax(bestResult,searchResult); if (bestResult.score >= beta) { return bestResult; } alpha = Math.max(alpha, bestResult.score); } return bestResult; } private SearchResult getMinValue(Board board, boolean asHuman, int recursionLevel, int alpha, int beta) { if (recursionLevel < 1) { return new SearchResult(Move.NONE,scorer.getScore(board)); } List validMoves = validMoveGenerator.genMoves(board, asHuman, MoveGenerator.ALL_MOVES); SearchResult bestResult = new SearchResult(Move.NONE,Integer.MAX_VALUE); if (validMoves.size() == 0) { return bestResult; } for (Move nextMove : validMoves) { Board nextBoard = new Board(board); if (!nextBoard.playTile(nextMove.getCell(), nextMove.getColor())) { throw new RuntimeException( "Illegal move attempted during search!"); } SearchResult searchResult = new SearchResult(nextMove,getMaxValue(nextBoard, !asHuman, recursionLevel - 1, alpha, beta).score); bestResult = getMin(bestResult,searchResult); if (bestResult.score <= alpha) { return bestResult; } beta = Math.min(beta, bestResult.score); } return bestResult; } /** * AlphaBetaMoveGenerator2 does not support this method. */ @Override public List genMoves(Board board, boolean asHuman, int nMoves) { Move[] doNothing = new Move[] { Move.NONE }; LOGGER.info("Minimax genMoves() stub returning []"); return Arrays.asList(doNothing); } }