//01 function alphabeta(node, depth, α, β, maximizingPlayer) //02 if depth = 0 or node is a terminal node //03 return the heuristic value of node //04 if maximizingPlayer //05 v := -∞ //06 for each child of node //07 v := max(v, alphabeta(child, depth – 1, α, β, FALSE)) //08 α := max(α, v) //09 if β ≤ α //10 break (* β cut-off *) //11 return v //12 else //13 v := ∞ //14 for each child of node //15 v := min(v, alphabeta(child, depth – 1, α, β, TRUE)) //16 β := min(β, v) //17 if β ≤ α //18 break (* α cut-off *) //19 return v // //Initial - alphabeta(origin, depth, -∞, +∞, TRUE) public GameTree MinimaxAlphaBeta(GameTree node, int depth, double alpha, double beta, bool maximizingPlayer) { bool terminal = node.Children.Count() == 0; if (depth == 0 || terminal) { node.Score = Evaluation.Evaluate(node.State, PlayerNumber, OpponentNumber); return(node); } GameTree gameTreeScore = new GameTree(); if (maximizingPlayer) { gameTreeScore.Score.Score = double.MinValue; foreach (GameTree child in node.Children) { GameTree childScore = MinimaxAlphaBeta(child, depth - 1, alpha, beta, false); if (childScore.Score.Score >= gameTreeScore.Score.Score) { gameTreeScore = childScore; } alpha = Math.Max(alpha, gameTreeScore.Score.Score); if (beta <= alpha) { break; } } return(gameTreeScore); } else { gameTreeScore.Score.Score = double.MaxValue; foreach (GameTree child in node.Children) { GameTree childScore = MinimaxAlphaBeta(child, depth - 1, alpha, beta, true); if (childScore.Score.Score <= gameTreeScore.Score.Score) { gameTreeScore = childScore; } beta = Math.Min(beta, gameTreeScore.Score.Score); if (beta <= alpha) { break; } } return(gameTreeScore); } }
string compute() { // GameState currentState = States[States.Count() - 1]; // int dof = currentState.GetDOF(PlayerNumber); if (dof > 1) { // Timer.Reset(); Timer.Start(); // string opponentDebug = ""; int opponent = currentState.GetOpponent(PlayerNumber, PlayerCount, ref opponentDebug); debug(opponentDebug.Trim()); int depth = 3; //SpanTree(null, current, playerNumber, opponentNumber, 3 (me them me), 0 (current)) GameTree root = GameTree.SpanTree(null, currentState, PlayerNumber, opponent, depth, 0); //alphabeta(origin, depth, -∞, +∞, TRUE) TronMinimax tronMinimax = new TronMinimax(PlayerNumber, opponent); GameTree next = tronMinimax.MinimaxAlphaBeta(root, depth, double.MinValue, double.MaxValue, true); // string vis = currentState.GetVisual(next.Score.TerritoryPlayer, next.Score.TerritoryOpponent); debug("Score - " + next.Score.Score); // Timer.Stop(); long time = Timer.ElapsedMilliseconds; debug("Time elapsed - " + time + "ms"); debug(vis); // return(next.Label.Trim('>').Split('>')[0]); } else { Point target = currentState.GetAnyPoint(PlayerNumber); Direction dir = GameState.GetDirection(currentState.Players[PlayerNumber], target); return(dir.ToString()); } }
//Initial - SpanTree(null, current, playerNumber, opponentNumber, 3 (me them me), 0 (current)) public static GameTree SpanTree(GameTree ancestor, GameState state, int playerNumber, int opponentNumber, int depth, int ply) { GameTree gameTree = new GameTree(); gameTree.Ancestor = ancestor; gameTree.State = state; gameTree.Label = ancestor == null ? "" : (ancestor.Label + ">" + GameState.GetDirection( ancestor.State.Players[(ply % 2 == 1) ? playerNumber : opponentNumber], state.Players[(ply % 2 == 1) ? playerNumber : opponentNumber]).ToString()); gameTree.Ply = ply; if (depth > 0) { int currentPly = ply + 1; int currentPlayer = (currentPly % 2 == 1) ? playerNumber : opponentNumber; List <GameState> childStates = state.GetChildren(currentPlayer); foreach (GameState childState in childStates) { gameTree.Children.Add(SpanTree(gameTree, childState, playerNumber, opponentNumber, depth - 1, currentPly)); } } return(gameTree); }