//Does a game tree search 1 layer deep. public string GetEasyMove(string playerMove) { float weight1; if (MoveNum < 4) { weight1 = 0; } else if (MoveNum > 3 && MoveNum < 8) { weight1 = 2; } else { weight1 = new System.Random().Next(0, 1); } TreeNode.weights = new List <float> { weight1, 1f }; TreeNode.wallValues = new List <float> { 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f }; HandlePlayerMove(playerMove); TreeNode rootNode = new TreeNode(CurrentBoard); Dictionary <string, float> depthOneValues = IterateStart(rootNode, 1); Dictionary <string, float> depthTwoValues = IterateStart(rootNode, 2); string moveSelected = "error"; float max = float.NegativeInfinity; foreach (KeyValuePair <string, float> move in depthOneValues) { float moveValue; if (depthTwoValues[move.Key] > 1000 || depthTwoValues[move.Key] < -1000) { moveValue = depthTwoValues[move.Key]; } else { moveValue = move.Value; } if (max < moveValue) { max = moveValue; moveSelected = move.Key; } } CurrentBoard.MakeMove(moveSelected); MoveNum++; return(moveSelected); }
public void MakeMove(ChessMove move) { PreviousMove = move; PreviousBoard = CurrentBoard.Clone(); CurrentBoard.MakeMove(move); if (CurrentPlayerColor == ChessColor.White) { CurrentPlayerColor = ChessColor.Black; } else { CurrentPlayerColor = ChessColor.White; } }
//This handles game start logic and updating the board during the game. private void HandlePlayerMove(string playerMove) { //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); } }
//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); }
//Initiates a minimax search 2 layers deep. public string GetHardMove(string playerMove) { TreeNode.weights = new List <float> { 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(); Dictionary <string, MoveInfo> moveValues = new Dictionary <string, MoveInfo>(); foreach (TreeNode moveNode in possibleMoves) { MoveInfo thisMovesInfo = new MoveInfo(); foreach (TreeNode childNode in moveNode.GetChildren()) { thisMovesInfo.UpdateValues(childNode.CalcValue(), moveNode.CalcValue()); } moveValues.Add(moveNode.GetMoveMade(), thisMovesInfo); } //Analyzing the results of tree evaluation starts here. bool moveFound = false; string moveSelected = "none"; float moveSelectedValue = float.NegativeInfinity; //Check for level 2 single wall placement. float requiredChangedInEval = 5; foreach (KeyValuePair <string, MoveInfo> move in moveValues) { if (move.Value.min > requiredChangedInEval) { moveFound = true; if (moveSelectedValue < move.Value.min) { moveSelected = move.Key; } } } //Check for level 2 double wall placement. if (!moveFound) { } //Check for pawn moves. if (!moveFound) { List <string> possiblePawnMoves = CurrentBoard.GetPawnMoves(); float currentMax = float.NegativeInfinity; foreach (string move in possiblePawnMoves) { TreeNode n = new TreeNode(CurrentBoard, move); MoveInfo mi = moveValues[move]; if (!(mi.singleLevelValue - mi.min == 2)) { if (mi.min > currentMax) { currentMax = mi.min; moveSelected = move; moveFound = true; } } } } if (!moveFound) { float max = float.NegativeInfinity; List <string> maxMoves = new List <string>(); foreach (KeyValuePair <string, MoveInfo> move in moveValues) { if (move.Value.min > max) { max = move.Value.min; maxMoves.Clear(); maxMoves.Add(move.Key); } else if (move.Value.min == max) { maxMoves.Add(move.Key); } } moveSelected = maxMoves[new Random().Next(0, maxMoves.Count)]; } CurrentBoard.MakeMove(moveSelected); return(moveSelected); }