public void OrderMoves(List <Move> moves, Gameboard state, Move bestMove = null) { // Assign values to moves, if possible for (int i = 0; i < moves.Count; i++) { moves[i].Value = 0; // Check for best move from last iteration if (moves[i] == bestMove) { // Best move is slightly better rated than other moves moves[i].Value = 1; } Gameboard newState = (Gameboard)state.Clone(); GameLogic newLogic = new GameLogic(newState); newLogic.ApplyMove(moves[i]); Int64 zHash = newState.GetZobristHash(); if (transpositionTable.ContainsKey(zHash)) { Transposition transposition = transpositionTable[zHash]; if (transposition.Lowerbound == transposition.Upperbound) { moves[i].Value += transposition.Lowerbound; } } } moves.Sort(MoveComparison); }
public override Move GetMove(Gameboard gameboard) { GameLogic gameLogic = new GameLogic(gameboard); List <Move> bestMove = new List <Move>(); int bestValue = int.MinValue; var possibleMoves = gameLogic.GetPossibleMoves(); // Don't search if only one move possible if (possibleMoves.Count == 1) { // DEBUG n++; Console.WriteLine("Average Nodes: {0}, n={1}", iterationCounter / n, n); return(possibleMoves[0]); } OrderMoves(possibleMoves, gameboard); int alpha = GameLogic.LOSS_VALUE; int beta = GameLogic.WIN_VALUE; foreach (Move move in possibleMoves) { // DEBUG iterationCounter++; Gameboard newState = (Gameboard)gameboard.Clone(); GameLogic newLogic = new GameLogic(newState); newLogic.ApplyMove(move); int score = -AlphaBeta(newState, depth - 1, -beta, -alpha, false); if (score > alpha) { alpha = score; } if (score > bestValue) { bestMove.Clear(); bestMove.Add(move); bestValue = score; } else if (score == bestValue) { bestMove.Add(move); } } // DEBUG n++; Console.WriteLine("Average Nodes: {0}, n={1}", iterationCounter / n, n); // Return one of the best moves return(bestMove[random.Next(bestMove.Count)]); }
public static HashSet<GamePosition> generateMoves(GameLogic gameLogic, int playerID, GamePosition gamePosition) { HashSet<Node> moves = gameLogic.GetPossibleMoves(playerID, gamePosition); HashSet<GamePosition> possibleMoves = new HashSet<GamePosition>(); foreach(Node move in moves){ possibleMoves.Add(gameLogic.ApplyMove(playerID, move, gamePosition)); } return possibleMoves; }
public static HashSet <GamePosition> generateMoves(GameLogic gameLogic, int playerID, GamePosition gamePosition) { HashSet <Node> moves = gameLogic.GetPossibleMoves(playerID, gamePosition); HashSet <GamePosition> possibleMoves = new HashSet <GamePosition>(); foreach (Node move in moves) { possibleMoves.Add(gameLogic.ApplyMove(playerID, move, gamePosition)); } return(possibleMoves); }
/// <summary> /// Returns a move chosen by the player /// </summary> public override Move GetMove(Gameboard gameboard) { GameLogic gameLogic = new GameLogic(gameboard); List <Move> bestMove = new List <Move>(); int bestValue = int.MinValue; var possibleMoves = gameLogic.GetPossibleMoves(); // Don't search if only one move possible if (possibleMoves.Count == 1) { return(possibleMoves[0]); } OrderMoves(possibleMoves, gameboard); int alpha = GameLogic.LOSS_VALUE; int beta = GameLogic.WIN_VALUE; // The root level is searched in this function, for other levels, the AlphaBeta function is used foreach (Move move in possibleMoves) { // Apply move Gameboard newState = (Gameboard)gameboard.Clone(); GameLogic newLogic = new GameLogic(newState); newLogic.ApplyMove(move); // Search deeper int score = -AlphaBeta(newState, depth - 1, -beta, -alpha, false); // Only alpha value can be adjusted at root level if (score > alpha) { alpha = score; } if (score > bestValue) { // Store new best move bestMove.Clear(); bestMove.Add(move); bestValue = score; } else if (score == bestValue) { // Add move to other currently best moves bestMove.Add(move); } } // Return one of the best moves return(bestMove[random.Next(bestMove.Count)]); }
public int QuiescenceSearch(Gameboard state, int alpha, int beta, bool myMove) { // DEBUG iterationCounter++; int score = int.MinValue; GameLogic gameLogic = new GameLogic(state); var possibleCaptureMoves = gameLogic.GetPossibleCaptureMoves(); // If there are no capture moves possible, use evaluation function and return value if (possibleCaptureMoves.Count == 0) { score = myMove ? evaluation.Evaluate(state) : -evaluation.Evaluate(state); } // If there are capture moves, continue iterating else { foreach (Move move in possibleCaptureMoves) { Gameboard newState = (Gameboard)state.Clone(); GameLogic newLogic = new GameLogic(newState); newLogic.ApplyMove(move); int value = -QuiescenceSearch(newState, -beta, -alpha, !myMove); if (value > score) { score = value; if (score >= beta) { break; } if (score > alpha) { alpha = score; } } } } return(score); }
public int AlphaBeta(Gameboard state, int depth, int alpha, int beta, bool myMove) { // DEBUG iterationCounter++; GameLogic gameLogic = new GameLogic(state); if (depth <= 0 || gameLogic.IsFinished()) { return(-QuiescenceSearch(state, -beta, -alpha, !myMove)); } int score = int.MinValue; var possibleMoves = gameLogic.GetPossibleMoves(); foreach (Move move in possibleMoves) { Gameboard newState = (Gameboard)state.Clone(); GameLogic newLogic = new GameLogic(newState); newLogic.ApplyMove(move); int value = -AlphaBeta(newState, depth - 1, -beta, -alpha, !myMove); if (value > score) { score = value; } if (score > alpha) { alpha = score; } if (score >= beta) { break; } } return(score); }
public override Move GetMove(Gameboard gameboard) { GameLogic gameLogic = new GameLogic(gameboard); List <Move> bestMove = new List <Move>(); int bestValue = int.MinValue; var possibleMoves = gameLogic.GetPossibleMoves(); foreach (Move move in possibleMoves) { // DEBUG iterationCounter++; Gameboard newState = (Gameboard)gameboard.Clone(); GameLogic newLogic = new GameLogic(newState); newLogic.ApplyMove(move); int score = MiniMax(newState, depth - 1, false); if (score > bestValue) { bestMove.Clear(); bestMove.Add(move); bestValue = score; } else if (score == bestValue) { bestMove.Add(move); } } // DEBUG n++; Console.WriteLine("Average Nodes: {0}, n={1}", iterationCounter / n, n); // Return one of the best moves return(bestMove[random.Next(bestMove.Count)]); }
public int MiniMax(Gameboard state, int depth, bool max) { // DEBUG iterationCounter++; GameLogic gameLogic = new GameLogic(state); if (depth <= 0 || gameLogic.IsFinished()) { return(Evaluate(state)); } int score; score = max?int.MinValue:int.MaxValue; var possibleMoves = gameLogic.GetPossibleMoves(); foreach (Move move in possibleMoves) { Gameboard newState = (Gameboard)state.Clone(); GameLogic newLogic = new GameLogic(newState); newLogic.ApplyMove(move); int value = MiniMax(newState, depth - 1, !max); if (max && value > score) { score = value; } else if (!max && value < score) { score = value; } } return(score); }
public int AlphaBeta(Gameboard state, int depth, int alpha, int beta, bool myMove) { Int64 zHash = state.GetZobristHash(); Move bestMove = null; // Check transposition table if (transpositionTable.ContainsKey(zHash)) { Transposition transposition = transpositionTable[zHash]; bestMove = transposition.BestMove; if (transposition.Depth >= depth) { if (transposition.Lowerbound == transposition.Upperbound) { return(transposition.Lowerbound); } if (transposition.Lowerbound >= beta) { return(transposition.Lowerbound); } if (transposition.Upperbound <= alpha) { return(transposition.Upperbound); } alpha = Math.Max(alpha, transposition.Lowerbound); beta = Math.Min(beta, transposition.Upperbound); } } GameLogic gameLogic = new GameLogic(state); int score; // Evaluate if (depth <= 0 || gameLogic.IsFinished()) { score = myMove ? evaluation.Evaluate(state) : -evaluation.Evaluate(state); } // Search deeper else { score = int.MinValue; var possibleMoves = gameLogic.GetPossibleMoves(); OrderMoves(possibleMoves, state, bestMove); // Reset best move bestMove = null; foreach (Move move in possibleMoves) { Gameboard newState = (Gameboard)state.Clone(); GameLogic newLogic = new GameLogic(newState); newLogic.ApplyMove(move); // Continue search int value = -AlphaBeta(newState, depth - 1, -beta, -alpha, !myMove); // Adjust alpha and beta if (value > score) { bestMove = move; score = value; } if (score > alpha) { alpha = score; } if (score >= beta) { break; } } } // Store values in transposition table if (score <= alpha) { if (!transpositionTable.ContainsKey(zHash)) { Transposition transposition = new Transposition(alpha, score, depth, bestMove); transpositionTable.Add(state.GetZobristHash(), transposition); } else { Transposition transposition = transpositionTable[zHash]; transposition.Upperbound = score; transposition.Depth = depth; transposition.BestMove = bestMove; } } else if (score > alpha && score < beta) { if (!transpositionTable.ContainsKey(zHash)) { Transposition transposition = new Transposition(score, score, depth, bestMove); transpositionTable.Add(state.GetZobristHash(), transposition); } else { Transposition transposition = transpositionTable[zHash]; transposition.Lowerbound = score; transposition.Upperbound = score; transposition.Depth = depth; transposition.BestMove = bestMove; } } else if (score >= beta) { if (!transpositionTable.ContainsKey(zHash)) { Transposition transposition = new Transposition(score, beta, depth, bestMove); transpositionTable.Add(state.GetZobristHash(), transposition); } else { Transposition transposition = transpositionTable[zHash]; transposition.Lowerbound = score; transposition.Depth = depth; transposition.BestMove = bestMove; } } return(score); }
public int AlphaBeta(Gameboard state, int depth, int alpha, int beta, bool myMove) { // DEBUG iterationCounter++; Int64 zHash = state.GetZobristHash(); Move bestMove = null; if (transpositionTable.ContainsKey(zHash)) { Transposition transposition = transpositionTable[zHash]; bestMove = transposition.BestMove; if (transposition.Depth >= depth) { if (transposition.Lowerbound == transposition.Upperbound) { return(transposition.Lowerbound); } if (transposition.Lowerbound >= beta) { return(transposition.Lowerbound); } if (transposition.Upperbound <= alpha) { return(transposition.Upperbound); } alpha = Math.Max(alpha, transposition.Lowerbound); beta = Math.Min(beta, transposition.Upperbound); } } GameLogic gameLogic = new GameLogic(state); int score; if (depth <= 0 || gameLogic.IsFinished()) { score = myMove ? evaluation.Evaluate(state) : -evaluation.Evaluate(state); } else { score = int.MinValue; var possibleMoves = gameLogic.GetPossibleMoves(); OrderMoves(possibleMoves, state); // Reset best move bestMove = null; // Calculate score for PVS { Move pvsMove = possibleMoves[0]; Gameboard newState = (Gameboard)state.Clone(); GameLogic newLogic = new GameLogic(newState); newLogic.ApplyMove(pvsMove); score = -AlphaBeta(newState, depth - 1, -beta, -alpha, !myMove); bestMove = pvsMove; } if (score < beta) { for (int i = 1; i < possibleMoves.Count; i++) { Move move = possibleMoves[i]; int lowerbound = Math.Max(alpha, score); int upperbound = lowerbound + 1; Gameboard newState = (Gameboard)state.Clone(); GameLogic newLogic = new GameLogic(newState); newLogic.ApplyMove(move); int value = -AlphaBeta(newState, depth - 1, -upperbound, -lowerbound, !myMove); // Fail high if (value >= upperbound && value < beta) { value = -AlphaBeta(newState, depth - 1, -beta, -value, !myMove); } if (value > score) { bestMove = move; score = value; } if (score >= beta) { break; } } } } if (score <= alpha) { if (!transpositionTable.ContainsKey(zHash)) { Transposition transposition = new Transposition(alpha, score, depth, bestMove); transpositionTable.Add(state.GetZobristHash(), transposition); } else { Transposition transposition = transpositionTable[zHash]; transposition.Upperbound = score; transposition.Depth = depth; transposition.BestMove = bestMove; } } else if (score > alpha && score < beta) { if (!transpositionTable.ContainsKey(zHash)) { Transposition transposition = new Transposition(score, score, depth, bestMove); transpositionTable.Add(state.GetZobristHash(), transposition); } else { Transposition transposition = transpositionTable[zHash]; transposition.Lowerbound = score; transposition.Upperbound = score; transposition.Depth = depth; transposition.BestMove = bestMove; } } else if (score >= beta) { if (!transpositionTable.ContainsKey(zHash)) { Transposition transposition = new Transposition(score, beta, depth, bestMove); transpositionTable.Add(state.GetZobristHash(), transposition); } else { Transposition transposition = transpositionTable[zHash]; transposition.Lowerbound = score; transposition.Depth = depth; transposition.BestMove = bestMove; } } return(score); }
public int AlphaBeta(Gameboard state, int depth, int alpha, int beta, bool myMove) { // DEBUG iterationCounter++; Int64 zHash = state.GetZobristHash(); Move bestMove = null; if (transpositionTable.ContainsKey(zHash)) { Transposition transposition = transpositionTable[zHash]; bestMove = transposition.BestMove; if (transposition.Depth >= depth) { if (transposition.Lowerbound == transposition.Upperbound) { return(transposition.Lowerbound); } if (transposition.Lowerbound >= beta) { return(transposition.Lowerbound); } if (transposition.Upperbound <= alpha) { return(transposition.Upperbound); } alpha = Math.Max(alpha, transposition.Lowerbound); beta = Math.Min(beta, transposition.Upperbound); } } GameLogic gameLogic = new GameLogic(state); int score; if (depth <= 0 || gameLogic.IsFinished()) { score = myMove ? evaluation.Evaluate(state) : -evaluation.Evaluate(state); } else { score = int.MinValue; var possibleMoves = gameLogic.GetPossibleMoves(); OrderMoves(possibleMoves, state); // Reset best move bestMove = null; // Multi-Cut { Move move = possibleMoves[0]; Gameboard newState = (Gameboard)state.Clone(); GameLogic newLogic = new GameLogic(newState); newLogic.ApplyMove(move); int c = 0; int m = 0; while (newState != null && m < 10) { int value = -AlphaBeta(newState, depth - 1 - 2, GameLogic.LOSS_VALUE, GameLogic.WIN_VALUE, false); if (value >= beta) { c++; if (c > 3) { return(beta); } } m++; if (m < possibleMoves.Count) { move = possibleMoves[m]; newState = (Gameboard)state.Clone(); newLogic = new GameLogic(newState); newLogic.ApplyMove(move); } else { newState = null; } } } foreach (Move move in possibleMoves) { Gameboard newState = (Gameboard)state.Clone(); GameLogic newLogic = new GameLogic(newState); newLogic.ApplyMove(move); int value = -AlphaBeta(newState, depth - 1, -beta, -alpha, !myMove); if (value > score) { bestMove = move; score = value; } if (score > alpha) { alpha = score; } if (score >= beta) { break; } } } if (score <= alpha) { if (!transpositionTable.ContainsKey(zHash)) { Transposition transposition = new Transposition(alpha, score, depth, bestMove); transpositionTable.Add(state.GetZobristHash(), transposition); } else { Transposition transposition = transpositionTable[zHash]; transposition.Upperbound = score; transposition.Depth = depth; transposition.BestMove = bestMove; } } else if (score > alpha && score < beta) { if (!transpositionTable.ContainsKey(zHash)) { Transposition transposition = new Transposition(score, score, depth, bestMove); transpositionTable.Add(state.GetZobristHash(), transposition); } else { Transposition transposition = transpositionTable[zHash]; transposition.Lowerbound = score; transposition.Upperbound = score; transposition.Depth = depth; transposition.BestMove = bestMove; } } else if (score >= beta) { if (!transpositionTable.ContainsKey(zHash)) { Transposition transposition = new Transposition(score, beta, depth, bestMove); transpositionTable.Add(state.GetZobristHash(), transposition); } else { Transposition transposition = transpositionTable[zHash]; transposition.Lowerbound = score; transposition.Depth = depth; transposition.BestMove = bestMove; } } return(score); }