private static int NegamaxAlphaBeta(Board board, int alpha, int beta, int depth, int colour) { GameState gameState = BoardScorer.GetGameState(board); if (depth == 0 || gameState != GameState.NOONE) { return(colour * BoardScorer.GetScore(gameState)); } List <Move> validMoves = board.GenerateValidMoves(); // NOTE: Possible to add move ordering here int score = int.MinValue; foreach (Move move in validMoves) { board.MakeMove(move); score = Math.Max(score, -NegamaxAlphaBeta(board, -beta, -alpha, depth - 1, -colour)); board.UndoMove(move); alpha = Math.Max(alpha, score); if (alpha >= beta) { break; } } return(score); }
private async void PlayGame() { Board board = new Board(); Stopwatch stopwatch = new Stopwatch(); PlayerType currentPlayer = PlayerType.ORDER; GameState gameState = GameState.NOONE; while (gameState == GameState.NOONE) { stopwatch.Start(); Move move = await Task.Run(() => Bot.GetBestMove(board, searchDepth, currentPlayer)); stopwatch.Stop(); long elapsedTime = stopwatch.ElapsedMilliseconds; stopwatch.Reset(); board.MakeMove(move); PrintOutput($"{currentPlayer}: {elapsedTime} ms", true); PrintOutput(board.GenerateBoardVisualization() + Environment.NewLine, false); gameState = BoardScorer.GetGameState(board); switch (currentPlayer) { case PlayerType.CHAOS: currentPlayer = PlayerType.ORDER; break; case PlayerType.ORDER: currentPlayer = PlayerType.CHAOS; break; default: throw new InvalidOperationException($"Unexpected player type encountered: {currentPlayer}"); } } PrintOutput($"{gameState} won!", true); }