Advertisement
Guest User

Untitled

a guest
Dec 22nd, 2016
17
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.94 KB | None | 0 0
  1.  
  2. package nl.tue.s2id90.group05;
  3.  
  4. import java.util.Arrays;
  5. import java.util.Collections;
  6. import java.util.Comparator;
  7. import java.util.HashMap;
  8. import java.util.List;
  9. import java.util.Map;
  10. import java.util.Objects;
  11. import nl.tue.s2id90.draughts.DraughtsState;
  12. import nl.tue.s2id90.draughts.player.DraughtsPlayer;
  13. import org10x10.dam.game.Move;
  14.  
  15. /**
  16.  *
  17.  * @author Frank van Heeswijk
  18.  */
  19. public class AlphaBetaPlayer extends DraughtsPlayer {
  20.     /**
  21.      * Function mapping a (state, depth) pair to a heuristic value.
  22.      *
  23.      * The state corresponds to the current state of the board.
  24.      * The depth corresponds to the current depth in the alpha beta search.
  25.      */
  26.     private final Heuristic heuristic;
  27.    
  28.     private boolean hasToStop = false;
  29.     private Integer bestMoveValue = null;
  30.    
  31.     public AlphaBetaPlayer(final Heuristic heuristic) {
  32.         super();
  33.         this.heuristic = Objects.requireNonNull(heuristic, "heuristic");
  34.     }
  35.  
  36.     @Override
  37.     public Move getMove(final DraughtsState draughtsState) {
  38.         Map<Triple, Integer> transpositionTable = new HashMap<>();
  39.         Map<Triple, Move> bestMoveTable = new HashMap<>();
  40.        
  41.         boolean isWhitePlayer = draughtsState.isWhiteToMove();  //calculate before going into the alphaBeta algorithm
  42.         GameNode<DraughtsState> node = new GameNode<>(draughtsState);
  43.  
  44.         Move bestMove = null;
  45.         for (int depthLimit = 1; ; depthLimit++) {
  46.             try {
  47.                 bestMoveValue = alphaBeta(transpositionTable, bestMoveTable, node, isWhitePlayer, depthLimit, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, true);
  48.                 bestMove = node.getBestMove();
  49.             } catch (AIStoppedException ex) {
  50.                 break;
  51.             }
  52. //            System.out.println("Evaluated AlphaBeta with depth limit " + depthLimit);
  53.         }
  54.        
  55.         return bestMove;
  56.     }
  57.  
  58.     @Override
  59.     public Integer getValue() {
  60.         return bestMoveValue;
  61.     }
  62.    
  63.     private int alphaBeta(final Map<Triple, Integer> transpositionTable, final Map<Triple, Move> bestMoveTable, final GameNode<DraughtsState> node, final boolean isWhitePlayer, final int depthLimit, final int depth, final int alpha, final int beta, final boolean maximizingPlayer)
  64.         throws AIStoppedException {
  65.         if (hasToStop) {
  66.             hasToStop = false;
  67.             throw new AIStoppedException();
  68.         }
  69.        
  70.         DraughtsState state = node.getState();
  71.         List<Move> moves = state.getMoves();
  72.         Collections.shuffle(moves); //ensure random behavior if the value of moves is the same
  73.         moves.sort(Comparator.comparing(Move::getCaptureCount).reversed()); //sort for better pruning performance
  74.        
  75.         //if leaf node
  76.         Triple triple = new Triple(state, isWhitePlayer, depth);
  77.         if (state.isEndState() || depth == depthLimit) {
  78.             if (transpositionTable.containsKey(triple)) {
  79.                 return transpositionTable.get(triple);
  80.             }
  81.             int heuristicValue = heuristic.calculateValue(state, isWhitePlayer, depth);
  82.             transpositionTable.put(triple, heuristicValue);
  83.             return heuristicValue;
  84.         }
  85.        
  86.         if (maximizingPlayer) {
  87.             Move bestMove = moves.get(0);   //make sure bestMove is set
  88.             int newAlpha = alpha;
  89.            
  90.             //analyze previously known best move first
  91.             Move bestMoveFromTable = bestMoveTable.get(triple);
  92.             if (bestMoveFromTable != null) {
  93.                 moves.add(0, bestMoveFromTable);
  94.             }
  95.            
  96.             //create children states
  97.             for (Move move : moves) {
  98.                 state.doMove(move);
  99.                 int alphaBetaValue = alphaBeta(transpositionTable, bestMoveTable, node, isWhitePlayer, depthLimit, depth + 1, newAlpha, beta, false);
  100.                 if (alphaBetaValue > newAlpha) {
  101.                     newAlpha = alphaBetaValue;
  102.                     bestMove = move;
  103.                 }
  104.                 state.undoMove(move);
  105.                 if (beta <= newAlpha) {
  106.                     break;  //stop evaluation
  107.                 }
  108.             }
  109.            
  110.             node.setBestMove(bestMove);
  111.             bestMoveTable.put(triple, bestMove);
  112.             return newAlpha;
  113.         }
  114.         else {
  115.             Move bestMove = moves.get(0);   //make sure bestMove is set
  116.             int newBeta = beta;
  117.            
  118.             //analyze previously known best move first
  119.             Move bestMoveFromTable = bestMoveTable.get(triple);
  120.             if (bestMoveFromTable != null) {
  121.                 moves.add(0, bestMoveFromTable);
  122.             }
  123.            
  124.             //create children states
  125.             for (Move move : moves) {
  126.                 state.doMove(move);
  127.                 int alphaBetaValue = alphaBeta(transpositionTable, bestMoveTable, node, isWhitePlayer, depthLimit, depth + 1, alpha, newBeta, true);
  128.                 if (alphaBetaValue < newBeta) {
  129.                     newBeta = alphaBetaValue;
  130.                     bestMove = move;
  131.                 }
  132.                 state.undoMove(move);
  133.                 if (newBeta <= alpha) {
  134.                     break;  //stop evaluation
  135.                 }
  136.             }
  137.            
  138.             node.setBestMove(bestMove);
  139.             bestMoveTable.put(triple, bestMove);
  140.             return newBeta;
  141.         }
  142.     }
  143.    
  144.     @Override
  145.     public void stop() {
  146.         hasToStop = true;
  147.     }
  148.    
  149.     private static class Triple {
  150.         private final DraughtsState draughtsState;
  151.         private final int[] draughtsStatePieces;
  152.         private final boolean isWhitePlayer;
  153.         private final int depth;
  154.        
  155.         private Triple(final DraughtsState draughtsState, final boolean isWhitePlayer, final int depth) {
  156.             this.draughtsState = draughtsState;
  157.             this.draughtsStatePieces = draughtsState.getPieces();
  158.             this.isWhitePlayer = isWhitePlayer;
  159.             this.depth = depth;
  160.         }
  161.  
  162.         @Override
  163.         public int hashCode() {
  164.             int hash = 5;
  165.             hash = 23 * hash + Arrays.hashCode(this.draughtsStatePieces);
  166.             hash = 23 * hash + (this.isWhitePlayer ? 1 : 0);
  167.             hash = 23 * hash + this.depth;
  168.             return hash;
  169.         }
  170.  
  171.         @Override
  172.         public boolean equals(Object obj) {
  173.             if (obj == null) {
  174.                 return false;
  175.             }
  176.             if (getClass() != obj.getClass()) {
  177.                 return false;
  178.             }
  179.             final Triple other = (Triple) obj;
  180.             if (!Arrays.equals(this.draughtsStatePieces, other.draughtsStatePieces)) {
  181.                 return false;
  182.             }
  183.             if (this.isWhitePlayer != other.isWhitePlayer) {
  184.                 return false;
  185.             }
  186.             if (this.depth != other.depth) {
  187.                 return false;
  188.             }
  189.             return true;
  190.         }
  191.     }
  192. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement