Exemplo n.º 1
0
        /// <summary>
        /// Pick a random item to press.
        /// </summary>
        /// <param name="model">The model to act against.</param>
        /// <param name="random">The source of randomness.</param>
        /// <returns>A valid but random action to take.</returns>
        /// <remarks>Current implementations assumes child suggestions lists are finite.</remarks>
        public static ApplicationRobotAction GetRandom(ApplicationModel model, Random random)
        {
            ApplicationRobotAction action;

            var headCount        = model.HeadItems.Count;
            var tailCount        = model.TailItems.Count;
            var suggestionsCount = 0;

            foreach (var subList in model.SuggestionLists)
            {
                var subListCount = subList.Count();

                // TODO: CommandItem should not be excluded from randomness!
                if (subList.First() is CommandItem)
                {
                    suggestionsCount -= subListCount;
                }
                else
                {
                    suggestionsCount += subListCount;
                }
            }

            var index = random.Next(0, suggestionsCount);

            if (index < headCount)
            {
                action = ApplicationRobotAction.CreateHead(index);
            }
            else if (index < headCount + tailCount)
            {
                action = ApplicationRobotAction.CreateTail(index - headCount);
            }
            else
            {
                var subIndex = index - headCount - tailCount;
                index = 0;
                while (model.SuggestionLists[index].First() is CommandItem)
                {
                    index++;
                }
                while (model.SuggestionLists[index].Count() <= subIndex)
                {
                    subIndex -= model.SuggestionLists[index].Count();
                    index++;
                }

                using (var enumerator = model.SuggestionLists[index].GetEnumerator())
                {
                    for (var position = 0; enumerator.MoveNext() && position < index; position++)
                    {
                    }

                    action = ApplicationRobotAction.CreateSuggestion(index, subIndex);
                    AssertGoodAction(model, action);
                }
            }

            return(action);
        }
Exemplo n.º 2
0
        private static ApplicationRobotAction GetModeEscape(ApplicationModel model)
        {
            Debug.Assert(model.HeadItems[0] is HeadStartItem);

            var escapeLimit = 1;

            while (escapeLimit < model.HeadItems.Count &&
                   model.HeadItems[escapeLimit] is HeadWordItem)
            {
                escapeLimit++;
            }

            var action = ApplicationRobotAction.CreateHead(escapeLimit - 1);

            return(action);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Get the next action to achieve the given goal.
        /// </summary>
        /// <param name="model">The model to act against.</param>
        /// <param name="complete">Finish by presssing a Stop button and returning IsComplete true in the action, otherwise don't press Stop button and return null.</param>
        /// <param name="words">The words to be spoken.</param>
        /// <returns>The next action to take.</returns>
        private static ApplicationRobotAction FindNextAction(ApplicationModel model, bool complete, TileSequence words)
        {
            ApplicationRobotAction action;

            Debug.Assert(model.HeadItems[0] is HeadStartItem);

            var culture = model.HeadItems[0].Culture;

            // Find number of words already correctly entered.
            var wordsMatchLim = 0;

            while (wordsMatchLim < words.Count &&
                   wordsMatchLim + 1 < model.HeadItems.Count &&
                   IsItemMatchExact <HeadWordItem>(model.HeadItems[wordsMatchLim + 1], words[wordsMatchLim], culture))
            {
                wordsMatchLim++;
            }

            if (wordsMatchLim < words.Count &&
                wordsMatchLim + 1 < model.HeadItems.Count &&
                IsItemMatch <HeadWordItem>(model.HeadItems[wordsMatchLim + 1], words[wordsMatchLim], culture))
            {
                if (wordsMatchLim + 2 < model.HeadItems.Count && model.HeadItems[wordsMatchLim + 2] is HeadWordItem)
                {
                    // Make the miscased item the last current item.
                    action = ApplicationRobotAction.CreateHead(wordsMatchLim + 1);
                }
                else
                {
                    var headWordItem = (HeadWordItem)model.HeadItems[wordsMatchLim + 1];
                    action = GetCaseWordAction(model, headWordItem.Tile, words[wordsMatchLim], culture);
                }
            }
            else if (wordsMatchLim + 1 < model.HeadItems.Count &&
                     model.HeadItems[wordsMatchLim + 1] is HeadWordItem)
            {
                // We have a word we don't want, so truncate.
                action = ApplicationRobotAction.CreateHead(wordsMatchLim);
            }
            else if (wordsMatchLim == words.Count)
            {
                // We have all the words in the head we want.
                if (!complete)
                {
                    // We're done.
                    action = null;
                }
                else if (wordsMatchLim + 1 < model.HeadItems.Count &&
                         model.HeadItems[wordsMatchLim + 1] is GhostStopItem)
                {
                    // Click item in head to complete selection.
                    action = ApplicationRobotAction.CreateHeadAndComplete(wordsMatchLim + 1);
                }
                else
                {
                    // Click in tail to complete selection.

                    Debug.Assert(model.HeadItems.Count <= wordsMatchLim + 1 ||
                                 model.HeadItems[wordsMatchLim + 1] is GhostWordItem);
                    Debug.Assert(model.TailItems.Count == 1);
                    Debug.Assert(model.TailItems[0] is TailStopItem);

                    action = ApplicationRobotAction.CreateTailAndComplete(0);
                }
            }
            else
            {
                // See how many ghost items match.
                var ghostMatchLim = wordsMatchLim;
                while (ghostMatchLim < words.Count &&
                       ghostMatchLim + 1 < model.HeadItems.Count &&
                       IsItemMatchExact <GhostWordItem>(model.HeadItems[ghostMatchLim + 1], words[ghostMatchLim], culture))
                {
                    ghostMatchLim++;
                }

                // Have we got enough ghost words to complete?
                if (complete &&
                    ghostMatchLim == words.Count &&
                    ghostMatchLim + 1 < model.HeadItems.Count &&
                    model.HeadItems[ghostMatchLim + 1] is GhostStopItem)
                {
                    // Complete by clicking ghost tail item.
                    action = ApplicationRobotAction.CreateHeadAndComplete(ghostMatchLim + 1);
                }
                else
                {
                    // Click something in the suggestions to advance.
                    action = GetSuggestionsAction(model, complete, words, wordsMatchLim, culture);

                    if (!action.IsComplete && wordsMatchLim < ghostMatchLim)
                    {
                        if (action.Target != ApplicationRobotActionTarget.Suggestion ||
                            action.SubIndex <= ghostMatchLim - wordsMatchLim)
                        {
                            // See if we can snaffle one more ghost.
                            if (ghostMatchLim < words.Count &&
                                ghostMatchLim + 1 < model.HeadItems.Count &&
                                IsItemMatch <GhostWordItem>(model.HeadItems[ghostMatchLim + 1], words[ghostMatchLim], culture))
                            {
                                ghostMatchLim++;
                            }

                            // We would have been no better off than clicking in the ghost words, so do that.
                            action = ApplicationRobotAction.CreateHead(ghostMatchLim);
                        }
                    }
                }
            }

            return(action);
        }