public async Task <GameNotification> SendGameActionAsync(GameActionRequest actionRequest) { GameState gameState = serverState.GetGameState(actionRequest.GameId); if (!gameLogic.ValidateGameAction(actionRequest, gameState)) { // TODO: make error messages clearer throw new ArgumentException("Invalid move"); } GameState newState = gameLogic.ApplyAction(gameState, actionRequest.Action); Player player = GameLogicUtils.GetCurrentPlayer(newState); if (player.Type == PlayerType.COMPUTER) { if (newState.Stage == GameStage.GAME_OVER) { return(new GameNotification { NewGameState = newState }); } // Get computer's move and return new state to player GameAction computerAction = gameAI.CalculateComputerMove(newState.BoardState, newState.Difficulty); GameState afterComputerMove = gameLogic.ApplyAction(newState, computerAction); serverState.UpdateGameState(afterComputerMove); return(new GameNotification { LastAction = computerAction, NewGameState = afterComputerMove }); } else { serverState.UpdateGameState(newState); // Notify opponent var notification = new GameNotification { NewGameState = newState, LastAction = actionRequest.Action }; await Clients.Client(player.Id).ReceiveGameStateUpdate(notification).ConfigureAwait(false); return(notification); } }
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); }