private List <float> GetHardWeights(AIBoard board) { float p1spWeight = 1f; float p2spWeight = 1f; //Variables used in weight calculations. int playerOneSP = BoardAnalysis.FindShortestPath(board, true); int playerTwoSP = BoardAnalysis.FindShortestPath(board, true); int playerTwoNumWalls = CurrentBoard.GetPlayerTwoNumWalls(); int distanceBetweenPlayers = BoardAnalysis.FindDistanceBetween(CurrentBoard, CurrentBoard.GetPlayerOnePos(), CurrentBoard.GetPlayerTwoPos()); if (playerOneSP - playerTwoSP > 2) { p1spWeight = 5; } else if (playerOneSP < 5) { p1spWeight = 2; } List <float> w = new List <float> { p1spWeight, p2spWeight }; return(w); }
//Initiates a minimax search 2 layers deep. public string GetHardMove(string playerMove) { timer.Start(); TreeNode.weights = GetHardWeights(CurrentBoard); TreeNode.wallValues = new List <float> { 2f, 2f, 2f, 2f, 1f, 1f, 1f, 1f, 1f, 0f }; //AI starts on e9 and makes the first move of the game. if (playerMove == "gamestart") { CurrentBoard.PlayerTwoGoesFirst(); } //AI starts on e1 and makes the first move of the game. else if (playerMove == "") { } //Updates the board with the player's move. else { CurrentBoard.MakeMove(playerMove); } TreeNode rootNode = new TreeNode(CurrentBoard); float rootNodeValue = rootNode.CalcValue(); List <TreeNode> possibleMoves = rootNode.GetChildren(); //Create dictionary of all useful values of first two levels of analysis. Dictionary <string, MoveInfo> moveValues = new Dictionary <string, MoveInfo>(); foreach (TreeNode moveNode in possibleMoves) { if (timer.ElapsedMilliseconds > 5980) { break; } MoveInfo thisMovesInfo = new MoveInfo(); foreach (TreeNode childNode in moveNode.GetChildren()) { thisMovesInfo.UpdateValues(childNode.CalcValue(), moveNode.CalcValue()); } moveValues.Add(moveNode.GetMoveMade(), thisMovesInfo); } string selectedMove = "none1"; //Minimax of the first two levels. List <string> movesSelected = new List <string>(); float value = float.NegativeInfinity; foreach (KeyValuePair <string, MoveInfo> pair in moveValues) { if (pair.Value.singleLevelValue > 10000) { value = pair.Value.singleLevelValue; movesSelected.Clear(); movesSelected.Add(pair.Key); break; } if (pair.Value.min > value) { value = pair.Value.min; movesSelected.Clear(); movesSelected.Add(pair.Key); } else if (pair.Value.min == value) { movesSelected.Add(pair.Key); } } selectedMove = movesSelected[new System.Random().Next(0, movesSelected.Count)]; //If selected move isn't a wall then use the pawn moves single level evaluation. //And if jump next move isn't a possibility. bool isPawnMove = !(selectedMove.EndsWith("h") || selectedMove.EndsWith("v")); bool jumpPossible = BoardAnalysis.FindDistanceBetween(CurrentBoard, CurrentBoard.GetPlayerOnePos(), CurrentBoard.GetPlayerTwoPos()) == 2; if (isPawnMove && !jumpPossible) { List <string> pawnMoves = CurrentBoard.GetPawnMoves(); value = float.NegativeInfinity; selectedMove = "none2"; foreach (string pm in pawnMoves) { float tempVal = moveValues[pm].singleLevelValue; if (tempVal > value) { selectedMove = pm; value = tempVal; } } } float testVal = value - rootNodeValue; if (value - rootNodeValue < 3) { float currentPotential = float.NegativeInfinity; float currentRisk = float.NegativeInfinity; movesSelected.Clear(); foreach (KeyValuePair <string, MoveInfo> pair in moveValues) { if (pair.Key.EndsWith("h") || pair.Key.EndsWith("v")) { float optimisticPotential = pair.Value.max - rootNodeValue; float pessemisticPotential = pair.Value.min - rootNodeValue; float risk = optimisticPotential - pessemisticPotential; if (optimisticPotential > 2) { if (optimisticPotential > currentPotential) { movesSelected.Clear(); movesSelected.Add(pair.Key); currentPotential = optimisticPotential; currentRisk = risk; } else if (optimisticPotential == currentPotential) { if (risk < currentRisk) { movesSelected.Clear(); movesSelected.Add(pair.Key); currentPotential = optimisticPotential; currentRisk = risk; } else if (risk == currentRisk) { movesSelected.Add(pair.Key); } } } } } if (movesSelected.Count > 0) { selectedMove = movesSelected[new System.Random().Next(0, movesSelected.Count)]; } } timer.Reset(); CurrentBoard.MakeMove(selectedMove); return(selectedMove); }