示例#1
0
        /// <summary>
        /// Given a state and a maximum search depth, this performs a recursive search using the alpha-beta algorithm to find the optimal action to take.
        /// </summary>
        /// <param name="state">The current state.</param>
        /// <param name="max_depth">The maximum number of sequential actions that may be taken.</param>
        /// <param name="state_hueristic">The means of determining how good a state is.</param>
        /// <param name="action_enumerator">The means of proceeding to a new state.</param>
        /// <param name="updater">The means by which a state is updated with new actions.</param>
        /// <param name="maximising">True if the algorithm should maximise at this step and false if it should minimise.</param>
        /// <param name="alpha">The best maximisation value so far.</param>
        /// <param name="beta">The best minimisation value so far.</param>
        /// <returns>Returns the value of the optimal action to take in the given state.</returns>
        private static int RSearch(S state, int depth, StateEvaluator <S> state_hueristic, ActionEnumerator <A, S> action_enumerator, ActionApplier <A, S> updater, Maximising <S> maximising, int alpha, int beta)
        {
            // If we've reached our terminal depth, evaluate and return
            if (depth == 0)
            {
                return(state_hueristic(state));
            }

            // Enumerate the available moves in the given state
            IEnumerator <A> actions = action_enumerator(state);

            // If there are no moves, we've reached a terminal state and need to evaluate it and return
            if (!actions.MoveNext())
            {
                return(state_hueristic(state));
            }

            if (maximising(state))
            {
                int max = int.MinValue;

                do
                {
                    max   = Math.Max(max, RSearch(updater(state, actions.Current), depth - 1, state_hueristic, action_enumerator, updater, maximising, alpha, beta));
                    alpha = alpha > max ? alpha : max;

                    if (alpha >= beta)
                    {
                        break;
                    }
                }while(actions.MoveNext());

                return(max);
            }

            int min = int.MaxValue;

            do
            {
                min  = Math.Min(min, RSearch(updater(state, actions.Current), depth - 1, state_hueristic, action_enumerator, updater, maximising, alpha, beta));
                beta = beta < min ? beta : min;

                if (alpha >= beta)
                {
                    break;
                }
            }while(actions.MoveNext());

            return(min);
        }
示例#2
0
        /// <summary>
        /// Given a state and a maximum search depth, this performs a search using the alpha-beta algorithm to find the optimal action to take.
        /// </summary>
        /// <param name="state">The current state.</param>
        /// <param name="max_depth">The maximum number of sequential actions that may be taken.</param>
        /// <param name="state_hueristic">The means of determining how good a state is.</param>
        /// <param name="action_enumerator">The means of proceeding to a new state.</param>
        /// <param name="updater">The means by which a state is updated with new actions.</param>
        /// <param name="maximizing">Determines if we are in a maximizing or minimizing state.</param>
        /// <returns>Returns the optimal action to take in the given state or default(A) if something went wrong.</returns>
        public static A Search(S state, int max_depth, StateEvaluator <S> state_hueristic, ActionEnumerator <A, S> action_enumerator, ActionApplier <A, S> updater, Maximising <S> maximising)
        {
            // Sanity check
            if (max_depth < 1 || state == null || state_hueristic == null || action_enumerator == null || maximising == null)
            {
                return(default(A));
            }

            // Bookkeeping
            List <A> best_actions = new List <A>();
            int      best_val     = int.MinValue;

            // Enumerate the available moves in the given state
            IEnumerator <A> actions = action_enumerator(state);

            // If there are no moves, we've reached a terminal state and can't do anything
            if (!actions.MoveNext())
            {
                return(default(A));
            }

            // If there's only one move (a forced move) then just take it
            // Note that this is only a useful case in the inital call as later one we're trying to compute the values of each move we could take
            if (!actions.MoveNext())
            {
                actions.Reset();
                actions.MoveNext();

                return(actions.Current);
            }

            // There's more than one move, so check them all out
            actions.Reset();
            actions.MoveNext();

            // We assume we start with the maximising player
            do
            {
                // Check out how good the current action is
                int val = RSearch(updater(state, actions.Current), max_depth - 1, state_hueristic, action_enumerator, updater, maximising, best_val, int.MaxValue);

                // If the current action is trash, ignore it
                if (val < best_val)
                {
                    continue;
                }

                // If the current action is okay, add it to the list
                if (val == best_val)
                {
                    best_actions.Add(actions.Current);
                    continue;
                }

                // The current action is crazy, so rock on
                best_actions.Clear();
                best_actions.Add(actions.Current);

                best_val = val;
            }while(actions.MoveNext());

            // We're garunteed to have at least one action to take, so this list will never be empty
            return(best_actions[rand.Next() % best_actions.Count]);
        }