private Player DeterminePlayerColour(MinimaxPlayerType minimaxPlayerType) { if (whoAmI == Player.BLUE) { if (minimaxPlayerType == MinimaxPlayerType.MAX) { return(Player.BLUE); } else { return(Player.RED); } } else { if (minimaxPlayerType == MinimaxPlayerType.MAX) { return(Player.RED); } else { return(Player.BLUE); } } }
private int ConstructTree(MinimaxTreeNode parentNode, int depth, MinimaxPlayerType minimaxPlayer, int alpha, int beta) { // return estimation function if max tree depth reached or game is in finished state if (depth == maxTreeDepth || parentNode.NonExistingLines.Count == 0) { return(EstimationFunction(parentNode)); } if (minimaxPlayer == MinimaxPlayerType.MAX) { int bestValue = int.MinValue; for (int i = 0; i < parentNode.NonExistingLines.Count; i++) { #region New Node Creation MinimaxTreeNode node = new MinimaxTreeNode(); // calculate estimation function only for leaf nodes node.Player = (parentNode.Player == MinimaxPlayerType.MAX ? MinimaxPlayerType.MIN : MinimaxPlayerType.MAX); node.ExistingLines.AddRange(parentNode.ExistingLines); node.ExistingLines.Add(parentNode.NonExistingLines[i]); node.NonExistingLines.AddRange(parentNode.NonExistingLines); node.NonExistingLines.Remove(parentNode.NonExistingLines[i]); node.Boxes.AddRange(parentNode.Boxes); List <Box> newBoxes = AICommon.TryClosingBoxes(parentNode.ExistingLines, DeterminePlayerColour(node.Player), parentNode.NonExistingLines[i], out int[] notUsed); node.Boxes.AddRange(newBoxes); node.DeltaMove = parentNode.NonExistingLines[i]; #endregion /* don't go through this subtree if the delta move is drawing third edge * unless it the only move */ AICommon.TryClosingBoxes(node.ExistingLines, DeterminePlayerColour(node.Player), node.DeltaMove, out int[] surroundingEdges); if ((surroundingEdges[0] == 2 || surroundingEdges[1] == 2)) { if (!(i == parentNode.NonExistingLines.Count - 1 && parentNode.Children.Count == 0)) { Debug.WriteLine(node.DeltaMove.ToString() + " was thrown."); continue; } } node.EstimationScore = ConstructTree(node, depth + 1, MinimaxPlayerType.MIN, alpha, beta); bestValue = (bestValue > node.EstimationScore ? bestValue : node.EstimationScore); alpha = (alpha > bestValue ? alpha : bestValue); parentNode.Children.Add(node); if (beta <= alpha) { break; } } parentNode.EstimationScore = bestValue; return(bestValue); } else { int bestValue = int.MaxValue; for (int i = 0; i < parentNode.NonExistingLines.Count; i++) { #region New Node Creation MinimaxTreeNode node = new MinimaxTreeNode(); // calculate estimation function only for leaf nodes node.Player = (parentNode.Player == MinimaxPlayerType.MAX ? MinimaxPlayerType.MIN : MinimaxPlayerType.MAX); node.ExistingLines.AddRange(parentNode.ExistingLines); node.ExistingLines.Add(parentNode.NonExistingLines[i]); node.NonExistingLines.AddRange(parentNode.NonExistingLines); node.NonExistingLines.Remove(parentNode.NonExistingLines[i]); node.Boxes.AddRange(parentNode.Boxes); List <Box> newBoxes = AICommon.TryClosingBoxes(parentNode.ExistingLines, DeterminePlayerColour(node.Player), parentNode.NonExistingLines[i], out int[] notUsed); node.Boxes.AddRange(newBoxes); node.DeltaMove = parentNode.NonExistingLines[i]; #endregion /* don't go through this subtree if the delta move is drawing third edge * unless it the only move */ AICommon.TryClosingBoxes(node.ExistingLines, DeterminePlayerColour(node.Player), node.DeltaMove, out int[] surroundingEdges); if ((surroundingEdges[0] == 2 || surroundingEdges[1] == 2)) { if (!(i == parentNode.NonExistingLines.Count - 1 && parentNode.Children.Count == 0)) { Debug.WriteLine(node.DeltaMove.ToString() + " was thrown."); continue; } } node.EstimationScore = ConstructTree(node, depth + 1, MinimaxPlayerType.MAX, alpha, beta); bestValue = (bestValue < node.EstimationScore ? bestValue : node.EstimationScore); beta = (beta < bestValue ? beta : bestValue); parentNode.Children.Add(node); if (beta <= alpha) { break; } } parentNode.EstimationScore = bestValue; return(bestValue); } throw new Exception("Something wrong in minimax happened"); }