private int MiniMaxAlgo(Node root, ITeamIdentifier player, ITeamIdentifier opponentPlayer, bool isAdversaryTurn, int depth) { ITeamIdentifier playingPlayer = isAdversaryTurn ? opponentPlayer : player; ITeamIdentifier otherPlayer = !isAdversaryTurn ? opponentPlayer : player; Helper.PopulateTree(root, playingPlayer, otherPlayer, 1); if (root.Combinaison.NextResolvableState.IsGameOver() || !root.ChildrenNodes.Any() || depth == 0) { return root.Combinaison.NextResolvableState.GetValueFor(player); } --depth; int bestCurrentValueForCurrentPlayerTurn = isAdversaryTurn ? int.MaxValue : int.MinValue; foreach (var node in root.ChildrenNodes) { int nodeValue = MiniMaxAlgo(node, player, opponentPlayer, !isAdversaryTurn, depth); // Find min if (isAdversaryTurn) { bestCurrentValueForCurrentPlayerTurn = Math.Min(nodeValue, bestCurrentValueForCurrentPlayerTurn); } // Find max else { bestCurrentValueForCurrentPlayerTurn = Math.Max(nodeValue, bestCurrentValueForCurrentPlayerTurn); } } return bestCurrentValueForCurrentPlayerTurn; }
/// <summary> /// /// </summary> /// <param name="root"></param> /// <param name="player"></param> /// <param name="opponentPlayer"></param> /// <param name="alpha">Best already explored option along path to the root for the maximizer</param> /// <param name="beta">Best already explored option along path to the root for the minimizer</param> /// <param name="isAdversaryTurn"></param> /// <returns></returns> private int AlphaBetaAlgo(Node root, ITeamIdentifier player, ITeamIdentifier opponentPlayer, int alpha, int beta, bool isAdversaryTurn, int depth) { ITeamIdentifier playingPlayer = isAdversaryTurn ? opponentPlayer : player; ITeamIdentifier otherPlayer = !isAdversaryTurn ? opponentPlayer : player; Helper.PopulateTree(root, playingPlayer, otherPlayer, 1); if (root.Combinaison.NextResolvableState.IsGameOver() || !root.ChildrenNodes.Any() || depth == 0) { return root.Combinaison.NextResolvableState.GetValueFor(player); } --depth; int bestCurrentValueForCurrentPlayerTurn = isAdversaryTurn ? int.MaxValue : int.MinValue; foreach (var node in root.ChildrenNodes) { int nodeValue = AlphaBetaAlgo(node, player, opponentPlayer, alpha, beta, !isAdversaryTurn, depth); // Minimizer if (isAdversaryTurn) { bestCurrentValueForCurrentPlayerTurn = Math.Min(nodeValue, bestCurrentValueForCurrentPlayerTurn); beta = Math.Min(bestCurrentValueForCurrentPlayerTurn, beta); if (beta < alpha) { return beta; } } // Maximizer else { bestCurrentValueForCurrentPlayerTurn = Math.Max(nodeValue, bestCurrentValueForCurrentPlayerTurn); alpha = Math.Max(bestCurrentValueForCurrentPlayerTurn, alpha); if (alpha > beta) { return alpha; } } } return bestCurrentValueForCurrentPlayerTurn; }
public static void PopulateTree(Node root, ITeamIdentifier playerTurn, ITeamIdentifier opponentPlayer, int depthAvailable) { if (depthAvailable == 0) { root.ChildrenNodes = new List<Node>(); return; } List<MoveStateCombinaison> childrens = root.Combinaison.NextResolvableState.GetPossibleStates(playerTurn).ToList(); root.ChildrenNodes = childrens.Select(children => new Node() { Combinaison = children }).ToList(); foreach (Node children in root.ChildrenNodes.Where(pair => !pair.Combinaison.NextResolvableState.IsGameOver())) { PopulateTree(children, opponentPlayer, playerTurn, depthAvailable - 1); } }
public IMove FindBestMove(IResolvableState resolvableState, ITeamIdentifier player, ITeamIdentifier opponentPlayer) { Node root = new Node() { Combinaison = new MoveStateCombinaison() { NextResolvableState = resolvableState, Move = null } }; Helper.PopulateTree(root, player, opponentPlayer, 1); int currentBestValue = Int32.MinValue; IMove currentBestMove = null; Stopwatch watch = new Stopwatch(); watch.Start(); foreach (var node in root.ChildrenNodes) { // The next turn is the adversary turn int nodeValue = NodeSolver.CalculateNodeValue(node, player, opponentPlayer, true, Depth); Console.WriteLine("{0} --> {1}", node.Combinaison.Move.GetDescription(), nodeValue); if (nodeValue > currentBestValue) { currentBestValue = nodeValue; currentBestMove = node.Combinaison.Move; } } watch.Stop(); Console.WriteLine("Elapse time: {0}", watch.ElapsedMilliseconds); return currentBestMove; }
public int CalculateNodeValue(Node root, ITeamIdentifier player, ITeamIdentifier opponentPlayer, bool isAdversaryTurn, int depth) { return AlphaBetaAlgo(root, player, opponentPlayer, Int32.MinValue, Int32.MaxValue, true, depth); }
public int CalculateNodeValue(Node root, ITeamIdentifier player, ITeamIdentifier opponentPlayer, bool isAdversaryTurn, int depth) { return MiniMaxAlgo(root, player,opponentPlayer, true, depth); }