/// <summary> /// MaxN Algorithm /// </summary> /// <param name="position">Root position</param> /// <param name="player">Player to evaluate</param> /// <param name="currentPlyDepth">Depth to evaluate at</param> private Vector4 MaxNAlgorithm(PlySearch s) { if (ShouldStop()) { return(Vector4.Zero); } List <PositionNode> children = board.GetNodes(s.Value, s.CurrentPlayer); if (children.Count == 0 || s.CurrentPlyDepth == 0) { Vector4 baseEval = eval.Evaluate(s.Value, s.RolledDoubles ? s.CurrentPlayer : Board.NO_PLAYER); return(Vector4.Multiply(baseEval, s.EvalWeight)); } Nodes += children.Count; Vector4 best = MaxNAlgorithm(s.Next(children[0])); for (int i = 1; i < children.Count; i++) { Vector4 curr = MaxNAlgorithm(s.Next(children[i])); if (curr.GetMagnitude(s.RootPlayer) > best.GetMagnitude(s.RootPlayer)) { Best = children[i]; this.currentEvaluation = curr; best = curr; } } return(best); }
/// <summary> /// Gets the next target search /// </summary> /// <param name="current">Next Node</param> public PlySearch Next(PositionNode current) { sbyte nextPlayer = board.NextPlayer(CurrentPlayer); PlySearch next = new PlySearch(board, current, RootPlayer, nextPlayer, CurrentPlyDepth - 1); next.NextDepth = next.CurrentPlyDepth - 1; if (current.RolledDoubles) { next.NextPlayer = next.CurrentPlayer; next.NextDepth = next.CurrentPlyDepth; next.DoublesCount = DoublesCount + 1; if (next.DoublesCount >= 3) { current.Value.RemoveFrontMarble(next.CurrentPlayer); next.DoublesCount = 0; next.NextPlayer = board.NextPlayer(next.CurrentPlayer); next.NextDepth = next.CurrentPlyDepth - 1; } } else { next.DoublesCount = 0; } return(next); }
/// <summary> /// Gets the next target search for a minimax algorithm /// </summary> /// <param name="current">Next node</param> public PlySearch NextMiniMax(PositionNode current) { //Flipped maximizing because this is normally after we invert the bool sbyte nextPlayer = (!Maximizing) ? board.NextPlayer(CurrentPlayer) : CurrentPlayer; PlySearch next = new PlySearch(board, current, RootPlayer, nextPlayer, CurrentPlyDepth - 1); next.Maximizing = !Maximizing; next.NextDepth = next.CurrentPlyDepth - 1; if (current.RolledDoubles) { next.NextPlayer = next.CurrentPlayer; next.NextDepth = next.CurrentPlyDepth; next.DoublesCount = DoublesCount + 1; if (next.DoublesCount >= 3) { current.Value.RemoveFrontMarble(next.CurrentPlayer); next.DoublesCount = 0; next.NextPlayer = board.NextPlayer(next.CurrentPlayer); next.NextDepth = next.CurrentPlyDepth - 1; } } else { next.DoublesCount = 0; } return(next); }
/// <summary> /// Paranoid Algorithm /// </summary> /// <param name="position">Root position</param> /// <param name="player">Player to evaluate</param> /// <param name="currentPlyDepth">Depth to evaluate at</param> public Vector4 ParanoidAlgorithm(PlySearch s, double alpha, double beta) { if (ShouldStop()) { return(Vector4.Zero); } List <PositionNode> children = board.GetNodes(s.Value, s.CurrentPlayer); if (children.Count == 0 || s.CurrentPlyDepth == 0) { Vector4 baseEval = eval.Evaluate(s.Value, s.RolledDoubles ? s.CurrentPlayer : Board.NO_PLAYER); return(Vector4.Multiply(baseEval, s.EvalWeight)); } Nodes += children.Count; if (s.Maximizing) { Vector4 bestValue = ParanoidAlgorithm(s.NextMiniMax(children[0]), alpha, beta); for (int i = 1; i < children.Count; i++) { Vector4 curr = ParanoidAlgorithm(s.NextMiniMax(children[i]), alpha, beta); alpha = Math.Max(alpha, curr.GetMagnitude(s.RootPlayer)); if (curr.GetMagnitude(s.RootPlayer) > bestValue.GetMagnitude(s.RootPlayer)) { bestValue = curr; } if (beta < alpha) { break; } } return(bestValue); } else { Vector4 bestValue = ParanoidAlgorithm(s.NextMiniMax(children[0]), alpha, beta); for (int i = 1; i < children.Count; i++) { Vector4 curr = ParanoidAlgorithm(s.NextMiniMax(children[i]), alpha, beta); double min = curr.GetLength(s.RootPlayer); double max = curr.GetMagnitude(s.RootPlayer); double dif = max - min; beta = Math.Min(beta, dif); if (dif < bestValue.GetMagnitude(s.RootPlayer)) { bestValue = curr; } if (beta < alpha) { break; } } return(bestValue); } }
/// <summary> /// Starts the initial call of the Paranoid algorithm /// </summary> private void Run() { PlySearch start = new PlySearch(board, Root, Player, board.NextPlayer(Player), Board.TEAM_COUNT * 2); ParanoidAlgorithm(start, double.MinValue, double.MaxValue); }
/// <summary> /// Starts the initial call of the MaxN algorithm /// </summary> private void Run() { PlySearch search = new PlySearch(board, Root, Player, board.NextPlayer(Player), Board.TEAM_COUNT * 2); //8 Ply ahead MaxNAlgorithm(search); }
/// <summary> /// Starts the initial call of the MaxN algorithm /// </summary> private void Run() { PlySearch search = new PlySearch(board, Root, Player, board.NextPlayer(Player), Board.TEAM_COUNT); OffensiveAlgorithm(search); }