public override int chooseMove(Board b) { myWatch.Restart(); moveResult myMove = miniMax(b, 5); // 5 beats bonzo by the most. can be put up to like 100 as long as the timer is set to a few seconds return(myMove.move); }
public override int chooseMove(Board b) { int tL = 4; Timer timer = new Timer(tL); timeOut = false; timer.Elapsed += timeOutTrigger; timer.Enabled = true; timer.AutoReset = false; timer.Start(); List <int> choices = new List <int>(); int choice = 0; int startDepth = 11; //Pass in timer to minimax? //If the elapsed time matches or exceeds the time limit, break the loop while (true) { if (timeOut || b.gameOver()) { break; } Console.WriteLine("Depth: " + startDepth); if (startDepth > 20) { Console.WriteLine("We might have a problem"); } //If the value of choice is not 0, add it to the list of choices. moveResult choiceResult = new moveResult(0, 0); if (!timeOut) { choiceResult = miniMax(b, startDepth, tL, 1, timer); } if (choiceResult.getScore() != 0 && b.legalMove(choiceResult.getMove())) { //TODO: Adding stuff to a list seems to not work choices.Add(choiceResult.getMove()); } //choice = miniMax(b, startDepth, tL).getScore(); //TODO: Modify timer and Stop, store and print time elapsed //update depth. startDepth += 1; if (timeOut == true) { timer.Stop(); } } //Close the timer and return the move from the last item in the list of choices timer.Close(); return(choices.Last()); }
/// <summary> /// MiniMax algorithm for mankalah. Uses the moveResult class, probably doesn't need to and /// could use it much more efficiently, but for times sake... /// This method finds returns the best move based on its rating. /// </summary> /// <param name="b"></param> which mankalah board /// <param name="d"></param> depth of which algotithm will recurse /// <returns></returns> private moveResult miniMax(Board b, int d) { moveResult moveVal = new moveResult(0, 0); //uses result class at bottom moveResult bestMoveVal = new moveResult(0, 0); // ^^ if (b.gameOver() || d == 0) { return(new moveResult(0, evaluate(b))); //evaluate function is simple. Bad thing? } if (b.whoseMove() == Position.Bottom) { bestMoveVal.val = 999; for (int move = 0; move <= 5; move++) //for all possible moves, { if (b.legalMove(move) && myWatch.ElapsedMilliseconds < timePerMove) /*and time not expired*/ { Board b1 = new Board(b); //dup board b b1.makeMove(move, false); //make move moveVal = miniMax(b1, d - 1); //recurse and return value if (moveVal.val < bestMoveVal.val) { bestMoveVal = moveVal; bestMoveVal.move = move; } //overwrite if better move } } return(bestMoveVal); //return best move found. } else //similar comments as above... { bestMoveVal.val = -999; for (int move = 7; move <= 12; move++) { if (b.legalMove(move) && myWatch.ElapsedMilliseconds < timePerMove) /*and time not expired*/ { Board b1 = new Board(b); //dup board b b1.makeMove(move, false); moveVal = miniMax(b1, d - 1); if (moveVal.val > bestMoveVal.val) { bestMoveVal = moveVal; bestMoveVal.move = move; } } } return(bestMoveVal); } }
//int d is depth of miniMax search. int max should be 1 for getting the max result, -1 for min. Should return moveResult object public moveResult miniMax(Board b, int d, double timeLimit, int max, Timer timer) { //Set up variables int bestVal = int.MinValue; int bestMove = 0; moveResult bestMR = new moveResult(bestMove, bestVal); //Base case: depth is 0, time is up or game is over. Returns a moveResult with the best score value and 0 move value if (d == 0 || timeOut || b.gameOver()) { bestVal = evaluate(b); //Console.WriteLine("Best score found to be " + bestVal); moveResult bestMoveResult = new moveResult(bestMove, bestVal); return(bestMoveResult); } if (b.whoseMove() == Position.Top) { for (int move = 7; move <= 12; move++) { //Console.WriteLine(""); //Recurse if the move is legal, time hasn't expired and game isn't over int val = 0; if (b.legalMove(move) && !timeOut && !b.gameOver()) { Board b1 = new Board(b); b1.makeMove(move, true); int newDepth = d - 1; //Switch the value of max to be the opposite for the recursion int mnOrMx = max * -1; //Console.WriteLine("Recursing from " + d + " to " + newDepth + "..."); val = miniMax(b1, newDepth, timeLimit, mnOrMx, timer).getScore(); //If at "max" level, prioritize and return maximum value if (max == 1) { //If there's a new max, update bestValue and bestMove if (val > bestVal) { bestVal = val; bestMove = move; } } //If at "min" level, prioritize and return minimum value if (max == -1) { //If there's a new min, update bestValue and bestMove if (val < bestVal || val != int.MinValue) { bestVal = val; bestMove = move; } } } } bestMR = new moveResult(bestMove, bestVal); return(bestMR); } else { for (int move = 0; move <= 5; move++) { //Console.WriteLine(""); //Recurse if the move is legal, time hasn't expired and game isn't over if (b.legalMove(move) && !timeOut && !b.gameOver()) { Board b1 = new Board(b); b1.makeMove(move, true); int newDepth = d - 1; //Switch the value of max to be the opposite for the recursion int mnOrMx = max * -1; // Console.WriteLine("Recursing from " + d + " to " + newDepth + "..."); int val = miniMax(b1, newDepth, timeLimit, mnOrMx, timer).getScore(); // Console.WriteLine("New Value: " + val); //If at "max" level, prioritize and return maximum value if (max == 1) { //If there's a new max, update bestValue and bestMove if (val > bestVal) { bestVal = val; bestMove = move; } } //If at "min" level, prioritize and return minimum value if (max == -1) { //If there's a new min, update bestValue and bestMove if (val < bestVal || val != int.MinValue) { bestVal = val; bestMove = move; } } } } bestMR = new moveResult(bestMove, bestVal); return(bestMR); } //Console.WriteLine("Best move: " + bestMove + " Best score: " + bestVal); bestMR = new moveResult(bestMove, bestVal); return(bestMR); }