0

Im trying to build a game tree to my game in order to find my next move. At first, Im building the tree using a recursive algorithm, and then, to find the best move Im using the alpha - beta pruning algorithm. I want to build the game tree using the alpha - beta pruning in order to minimize the size of the game tree, but Im having problem writing the algorithm. Could you help me add the alpha - beta pruning to the expand algorithm?

Here is the expand algorithm:

public void expand(int depth) 
    {
        expand++;
        if(depth > 0)
        {
            this.children = new ArrayList<GameTreeNode>();
            List<Move> possibleMoves = this.b.possibleMoves(this.b.turn);

            ReversiBoard tmp = null;

            for(Move m : possibleMoves)
            {
                TurnState nextState = (this.state == TurnState.PLUS ? TurnState.MINUS : TurnState.PLUS);
                tmp = new ReversiBoard(this.b);
                tmp.makeMove(m);
                int nextTurn = (turn == PLAYER1 ? PLAYER2 : PLAYER1);
                if(tmp.possibleMoves(nextTurn).isEmpty())
                    nextTurn = turn;
                this.children.add(new GameTreeNode(tmp, nextState, m, nextTurn));

                for(GameTreeNode child : children)
                        child.expand(depth - 1);
            }
        }
    }

Here is the alpha - beta pruning code:

int alphaBetaMax( int alpha, int beta, int depthleft ) {
        alphaBetaNum++;
           if ( depthleft == 0 ) return this.b.evaluate();
           for (GameTreeNode tree : this.children) {
              bestValue = alphaBetaMin( alpha, beta, depthleft - 1 );
              if( bestValue >= beta )
              {
                 bestMove = tree.move;

                 return beta;   // fail hard beta-cutoff
              }
              if( bestValue > alpha )
                 alpha = bestValue; // alpha acts like max in MiniMax
           }
           return alpha;
        }

        int alphaBetaMin( int alpha, int beta, int depthleft ) {
            alphaBetaNum++;
           if ( depthleft == 0 ) return -this.b.evaluate();
           for ( GameTreeNode tree : this.children) {
              bestValue = alphaBetaMax( alpha, beta, depthleft - 1 );
              if( bestValue <= alpha )
              {
                  bestMove = tree.move;
                 return alpha; // fail hard alpha-cutoff
              }
              if( bestValue < beta )
                 beta = bestValue; // beta acts like min in MiniMax
           }
           return beta;
        }

        public void summonAlphaBeta(int depth)
        {
            this.bestValue  = alphaBetaMax(Integer.MIN_VALUE, Integer.MAX_VALUE, depth);
        }

Thank You!

Golan Kiviti
  • 3,895
  • 7
  • 38
  • 63

1 Answers1

0

You have two options.

  1. You could just combine the two algorithms by converting your expand method into expandAndReturnMin and expandAndReturnMax methods which each take the alpha and beta values as arguments. Ideally any shared code would be put into a third method to keep your code clean.

Here is some example code for you to consider. In this example I've assumed a static member is storing the best move.

public int bestValue(Board board, int depth, int alpha, int beta, boolean aiPlayer) {
    if (depth >= MAX_DEPTH || board.possibleMoves(aiPlayer).isEmpty()) {
        return board.getValue();
    } else {
        for (Move move: board.possibleMoves(aiPlayer) {
            int value = bestValue(board.makeMove(move), depth + 1, alpha, beta, !aiPlayer);
            if (aiPlayer && value > alpha) {
                alpha = value;
                bestMove = move;
                if (alpha >= beta)
                    break;
            } else if (!aiPlayer && value < beta) {
                beta = value;
                bestMove = move;
                if (beta >= alpha)
                    break;
            }
        }
        return aiPlayer ? alpha : beta;
    }
}

The best initial move is determined by: board.bestValue(board, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, true); and then using board.getBestMove().

  1. A more elegant solution would be to store the alpha and beta values in the tree itself. That is very simple: after generating each child node you update the values in the current node. Then if they fall outside the allowed range you can stop generating child nodes. This is the more standard approach and is computationally cheap but makes the nodes use more memory.
sprinter
  • 27,148
  • 6
  • 47
  • 78
  • The first Option you mentioned is exactly what i want, but Im having a little trouble writing the code, I dont know how to combine them. Could you give me an example of the code? – Golan Kiviti Dec 29 '14 at 07:46
  • Ok I'll post some sample code in my answer some time today. – sprinter Dec 29 '14 at 21:55