Exemple #1
0
        /// <summary>
        /// Search the game tree multiple times with increasing depth until the wall clock time limit
        /// specified by the configuration is exhausted. Take best result found at that point and
        /// cancel search.
        /// </summary>
        private static Result BestFixedTime(Configuration c, FastWorld w, int ownIndex)
        {
            Debug.Assert(c.SearchLimit.LimitType == DeepeningSearch.LimitType.Milliseconds);

            // Keep in mind on thread safety:
            // The thread that calls Abort might block if the thread that is being aborted is in a protected
            // region of code, such as a catch block, finally block, or constrained execution region. If the
            // thread that calls Abort holds a lock that the aborted thread requires, a deadlock can occur.
            // https://docs.microsoft.com/en-us/dotnet/api/system.threading.thread.abort?view=netframework-4.7.2

            var    myLock = new object();
            Result best   = null;

            var stop = new DeepeningSearch.Stop();

            Thread t = new Thread(() => {
                try {
                    for (int i = 1; ; ++i)
                    {
                        var result = SearchSelectingStrategy(c, w, ownIndex, i, stop);

                        lock (myLock) {
                            best = result;
                        }
                    }
                }
                catch (DeepeningSearch.StopSearchException) {
                    // Perfectly normal to throw this exception upon stopping deepening
                    return;
                }
            });

            t.Start();

            Thread.Sleep(c.SearchLimit.Limit);

            stop.RequestStop();

            // Should be no more contention since t is aborted and joined
            // But I guess it doesn't hurt
            lock (myLock) {
                return(best);
            }
        }
Exemple #2
0
        private static Result SearchSelectingStrategy(Configuration c, FastWorld w, int ownIndex, int depth, DeepeningSearch.Stop stop)
        {
            var reflexMask     = c.ReflexMask ?? FindMaskForDepth(w, ownIndex, depth);
            var simulatedCount = reflexMask.Count(el => el == false);
            var ordering       = MaxN.CalculateSteppingOrdering(w, ownIndex, reflexMask);

            if (simulatedCount == 2 && c.AlphaBetaFallbackHeuristic != null)
            {
                // If alpha beta fallback heuristic is provided and we have two simulated snakes, use alpha beta search
                var abConf = new DeepeningSearch.Configuration(c.AlphaBetaFallbackHeuristic(ordering[0], ordering[1]), ordering[0], ordering[1]);
                abConf.Stop           = stop;
                var(direction, score) = new AlphaBeta().Search(abConf, w, depth);
                return(new Result(new DeepeningSearch.Result(score, direction, depth)));
            }
            else
            {
                var internalConfiguration = new InternalConfiguration {
                    ReflexMask  = reflexMask,
                    Depth       = depth,
                    OwnIndex    = ownIndex,
                    StopHandler = stop
                };

                var(scoresAbs, scoresRel, directions) = PseudoPlyStep(w, internalConfiguration, c.MaxNHeuristicProducer(ownIndex), 0, 0, ordering, null);

                return(new Result(
                           internalConfiguration.steps,
                           internalConfiguration.ReflexMask.Count(el => el == false),
                           internalConfiguration.Depth,
                           directions[ownIndex],
                           scoresRel[ownIndex],
                           scoresAbs,
                           scoresRel,
                           directions
                           ));
            }
        }