示例#1
0
        private void GetBestMoveImpl(Game game, int depth, out Move bestMove, out Estimate bestEstimate)
        {
            Player player          = game.State.NextMovePlayer;
            bool   isMaximizeStage = player == Player.Maximizing;

            Move     curBestMove     = null;
            Estimate curBestEstimate = isMaximizeStage
                ? Estimate.MinInf
                : Estimate.MaxInf;

            foreach (Move move in game.GetAllowedMoves())
            {
                MovesChecked += 1;

                game.DoMove(move);

                Estimate estimate = game.State.StaticEstimate;

                // force AI to win faster
                if (game.State.IsTerminate && estimate != Estimate.Zero)
                {
                    EstimateHelper.AdjustTerminalStateEstimate(depth, ref estimate);
                }

                if (depth < 3)
                {
                    Trace.WriteLine($"{Tab(depth - 1)}Consider {move}");
                }

                if (game.State.IsTerminate || depth == MaxDepth)
                {
                    // no longer go deeper

                    UpdateBestMove(isMaximizeStage, move, estimate, ref curBestMove, ref curBestEstimate);
                }
                else
                {
                    // go deeper
                    Move     bestMoveInternal;
                    Estimate bestEstimateInternal;

                    GetBestMoveImpl(game, depth + 1, out bestMoveInternal, out bestEstimateInternal);

                    UpdateBestMove(isMaximizeStage, move, bestEstimateInternal, ref curBestMove, ref curBestEstimate);
                }

                game.UndoMove(move);
            }

            if (curBestMove == null)
            {
                throw new InvalidOperationException("No moves found");
            }

            bestMove     = curBestMove;
            bestEstimate = curBestEstimate;

#if DEBUG
            if (depth <= 3)
            {
                Trace.WriteLine($"{Tab(depth-1)}RET: {depth}; BM: {bestMove}; E: {bestEstimate} ({(isMaximizeStage ? "max" : "min")})");
            }
#endif
        }
示例#2
0
        private Estimate FindImpl(Game game, Estimate alpha, Estimate beta, int depth, int maxDepth, Metadata meta)
        {
            Player player = game.State.NextMovePlayer;
            bool   isMax  = player == Player.Maximizing;

            if (maxDepth - depth == 0)
            {
                return(game.State.StaticEstimate);
            }

            if (game.State.IsTerminate)
            {
                // make AI pick shortest path to terminate state
                // otherwise there will be funny situation then AI seeing that it won
                // w/o chances for other side will not purse the winning

                Estimate terminateEstimate = game.State.StaticEstimate;

                EstimateHelper.AdjustTerminalStateEstimate(depth, ref terminateEstimate);

                return(terminateEstimate);
            }

            Estimate v = isMax
                ? Estimate.MinInf
                : Estimate.MaxInf;

            List <Move> moves = game.GetAllowedMoves()
                                .OrderByDescending(x => x.Priority)
                                .ToList();

            foreach (Move move in moves)
            {
                meta.MovesChecked += 1;

                using (DisposableMoveHandle.New(game, move))
                {
                    Estimate curEstimate = FindImpl(game, alpha, beta, depth + 1, maxDepth, meta);

                    bool betterMoveFound = isMax
                        ? curEstimate > v
                        : curEstimate < v;

                    if (betterMoveFound)
                    {
                        v = curEstimate;

                        if (depth == 1)
                        {
                            meta.BestMove = move;
                        }
                    }

                    if (isMax)
                    {
                        alpha = Estimate.Max(alpha, v);
                    }
                    else
                    {
                        beta = Estimate.Min(beta, v);
                    }

#if DEBUG
                    if (depth <= 3)
                    {
                        Trace.WriteLine($"{ new string(' ', depth) } - Move {move} for {player} -- {curEstimate} -- Term? {game.State.IsTerminate}");
                    }
#endif

                    if (alpha >= beta)
                    {
                        // alpha/beta cut-off
                        //Trace.WriteLine($"cut-off on depth {depth}");
                        break;
                    }
                }
            }

            return(v);
        }