int EvaluateHeuristic(GameBoardState boardState, PlayerTurn maxTurn) { if (boardState.Winner != null) { return(boardState.Winner == maxTurn ? int.MaxValue : int.MinValue); } int score = 0; foreach (Point[] winningComb in WinningCombinations) { foreach (Point position in winningComb) { PlayerTurn?piece = boardState.Board[position.Y, position.X]; if (piece == maxTurn) { score++; } else if (piece == GameLogicUtils.Next(maxTurn)) { score--; } } } return(score); }
public GameState AddPlayer([DisallowNull] GameState gameState, [DisallowNull] Player newPlayer) { // TODO: Write assertion helpers if (gameState.Stage != GameStage.WAITING_FOR_OPPONENT) { throw new ArgumentException($"Invalid state: {gameState.Stage}.Game must be waiting for opponent to add another player"); } if (gameState.Player1 == null) { throw new ArgumentException("Game must have a first player"); } if (gameState.Player2 != null) { throw new ArgumentException("Second player must be null"); } return(new GameState { Id = gameState.Id, Type = gameState.Type, StartTimeUtc = gameState.StartTimeUtc, Player1 = gameState.Player1, Player2 = newPlayer, Stage = GameStage.PLAYING, BoardState = GameLogicUtils.InitializeGameBoard(PlayerTurn.TWO) }); }
// We assume Winner field is updated and correct => No need to recalculate winner int Evaluate(GameBoardState boardState, PlayerTurn maxTurn, int currentDepth, int maxDepth) { bool maximizing = boardState.CurrentTurn == maxTurn; if (currentDepth == maxDepth || boardState.Winner != null) { return(EvaluateHeuristic(boardState, maxTurn)); } List <GameAction> possibleActions = GameLogicUtils.GetAllAvailableActions(boardState); int evaluation; if (maximizing) { int maxEvaluation = int.MinValue; foreach (GameAction action in possibleActions) { GameBoardState afterMove = gameLogic.ApplyAction(boardState, action); int afterMoveEvaluation = Evaluate(afterMove, maxTurn, currentDepth + 1, maxDepth); if (afterMoveEvaluation > maxEvaluation) { maxEvaluation = afterMoveEvaluation; } } evaluation = maxEvaluation; } else { int minEvaluation = int.MaxValue; foreach (GameAction action in possibleActions) { GameBoardState afterMove = gameLogic.ApplyAction(boardState, action); int afterMoveEvaluation = Evaluate(afterMove, maxTurn, currentDepth + 1, maxDepth); if (afterMoveEvaluation < minEvaluation) { minEvaluation = afterMoveEvaluation; } } evaluation = minEvaluation; } return(evaluation); }
public GameAction CalculateComputerMove(GameBoardState gameState, GameDifficulty difficulty) { int maxDepth = ToRecursiveDepth(difficulty); PlayerTurn maxTurn = gameState.CurrentTurn; List <GameAction> possibleActions = GameLogicUtils.GetAllAvailableActions(gameState); int maxEvaluation = int.MinValue; GameAction bestMove = null; foreach (GameAction action in possibleActions) { GameBoardState afterMove = gameLogic.ApplyAction(gameState, action); int afterMoveEvaluation = Evaluate(afterMove, maxTurn, 0, maxDepth); if (afterMoveEvaluation > maxEvaluation || (afterMoveEvaluation >= maxEvaluation && bestMove == null)) { maxEvaluation = afterMoveEvaluation; bestMove = action; } } return(bestMove); }
public GameBoardState ApplyAction(GameBoardState boardState, GameAction action) { PlayerTurn currentTurn = boardState.CurrentTurn; int currentTurnNumber = boardState.TurnNumber; PlayerTurn?[,] currentBoard = boardState.Board; PlayerTurn?[,] newBoard = new PlayerTurn?[currentBoard.GetLength(0), currentBoard.GetLength(1)]; Array.Copy(currentBoard, newBoard, currentBoard.Length); if (action is PutPieceAction putPieceAction) { newBoard[putPieceAction.Position.Y, putPieceAction.Position.X] = currentTurn; } else if (action is MovePieceAction movePieceAction) { newBoard[movePieceAction.To.Y, movePieceAction.To.X] = currentTurn; newBoard[movePieceAction.From.Y, movePieceAction.From.X] = null; } PlayerTurn?winner = null; // No need to check if other player is winner if (GameLogicUtils.IsWinner(newBoard, currentTurn)) { winner = currentTurn; } return(new GameBoardState { TurnNumber = currentTurnNumber + 1, Board = newBoard, CurrentTurn = GameLogicUtils.Next(currentTurn), GameMode = currentTurnNumber < 6 ? GameMode.PUT : GameMode.MOVE, Winner = winner }); }
public GameAction CalculateComputerMove(GameBoardState gameState, GameDifficulty difficulty) { List <GameAction> actions = GameLogicUtils.GetAllAvailableActions(gameState); return(actions[rand.Next(0, actions.Count)]); }