Example #1
0
        //Room MainLocation { get; }

        public bool CanRecognize(Item item, StringWords input, int start, int end)
        {
            //TODO eventually: Features like sight flags and ignore color codes and so on. For now...

            if (TextParsing.CheckAutoCompleteText(input, item.Name, start, end) || TextParsing.CheckAutoCompleteText(input, item.Description, start, end))
            {
                return(true);
            }
            return(false);
        }
        public override void Execute(MOB mob, QueuedCommand command)
        {
            StringWords  input    = command.parsedCommand;
            int          distance = -1;
            MovementUnit unit;

            if (input.Segments.Length > 1)
            {
                TextParsing.ParseAsDistance(input, out distance, out unit, 1);
            }
            //TODO: finish this
        }
Example #3
0
        /// <summary>
        /// Attempt to parse input as a distance. Text inputs must be a number, followed by an optional unit, to be parsed as
        /// a distance.
        /// </summary>
        /// <param name="text">Input to parse</param>
        /// <param name="mob"></param>
        /// <param name="distance">Distance to move, in millimeters. If -1, then parsing failed.</param>
        /// <param name="startIndex">Where the distance is expected to be.</param>
        /// <returns>Number of words successfully parsed. 0 if failed, up to 2 if succeeded. </returns>
        public static int ParseAsDistance(StringWords text, out int distance, out MovementUnit unit, int startIndex = 0, int endIndex = 0)
        {
            distance = -1;
            unit     = MovementUnit.NoDistance;
            if (startIndex >= text.Segments.Length)
            {
                return(0);
            }

            string firstWord, secondWord = null;

            firstWord = text.Segments[startIndex];
            if (startIndex < text.Segments.Length - 1)
            {
                secondWord = text.Segments[startIndex + 1];
            }
            int magnitude, distanceType;

            if (!int.TryParse(firstWord, out magnitude))
            {
                if (secondWord == null || !int.TryParse(secondWord, out magnitude))
                {
                    return(0);
                }
                //firstWord MUST be a valid distance enum.
                if (FindAPreposition(text, typeof(Distances), out distanceType, startIndex, startIndex + 1) == -1)
                {
                    return(0);
                }
            }
            else
            {
                if (secondWord == null || FindAPreposition(text, typeof(Distances), out distanceType, startIndex + 1, startIndex + 2) == -1)
                {
                    distanceType = (int)Distances.Default;
                    secondWord   = null;
                }
            }
            if (distanceType >= (int)Distances.Default)
            {
                distance = magnitude;
                unit     = distanceType == (int)Distances.Default ? MovementUnit.Unspecified :
                           distanceType == (int)Distances.Step ? MovementUnit.Step :
                           MovementUnit.NoDistance;
            }
            else
            {
                distance = (int)((magnitude * (long)distanceConversions[distanceType]) / 10);
                unit     = MovementUnit.Absolute;
            }
            return(secondWord == null ? 2 : 1);
        }
Example #4
0
 public static int FindMatchingWord(StringWords text, string[] options)
 {
     foreach (string option in options)
     {
         for (int i = 0; i < text.Segments.Length; i++)
         {
             if (text.Segments[i].Equals(option, StringComparison.CurrentCultureIgnoreCase))
             {
                 return(i);
             }
         }
     }
     return(-1);
 }
Example #5
0
        public static List <Item> FindKnownItems(StringWords input, MOB mob, int start, int end)
        {
            input.ValidateEndIndex(ref end);
            Item[]      items         = GeneralUtilities.VisibleItems(mob, mob.Body);
            List <Item> matchingItems = new List <Item>();

            foreach (Item item in items)
            {
                if (mob.CanRecognize(item, input, start, end))
                {
                    matchingItems.Add(item);
                }
            }
            return(matchingItems);
        }
Example #6
0
        /// <summary>
        /// Find the first word in an input that matches a preposition from a list of prepositions
        /// </summary>
        /// <param name="text">Input to search</param>
        /// <param name="typeOfPreposition">Type/List of prepositions</param>
        /// <param name="prepositionValue">Which preposition was found (can be cast to that preposition). -1 if no preposition found.</param>
        /// <param name="startIndex">Which word in input to start searching on (inclusive). Defaults to 0 (start of input)</param>
        /// <param name="endIndex">Which word in input to stop searching on (exclusive). Defaults to -1 (end of input)</param>
        /// <returns>Index of the first word of the preposition</returns>
        public static int FindAPreposition(StringWords text, Type typeOfPreposition, out int prepositionValue, int startIndex = 0, int endIndex = -1) //TODO: Replace typeOfPreposition for an easier-to-use type of variable. An enum of enums?
        {
            text.ValidateEndIndex(ref endIndex);

            //Array values = Enum.GetValues(typeOfPreposition);
            string[][] options = OptionsForPreposition(typeOfPreposition);
            for (int i = startIndex; i < endIndex; i++)
            {
                int j = i;
                prepositionValue = MatchString(options, text.Segments, ref j); //NOTE: This assumes enums always have default-assigned values (0, 1, 2, etc.)
                if (prepositionValue != -1)
                {
                    return(i);
                }
            }
            prepositionValue = -1;
            return(-1);
        }
Example #7
0
        /// <summary>
        /// Find an item that the specified mob can sense and identify from the given text input.
        /// </summary>
        /// <param name="input"></param>
        /// <param name="mob"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="onPrompt"></param>
        /// <param name="addToPrompt"></param>
        /// <returns></returns>
        public static Item FindKnownItem(StringWords input, MOB mob, int start, int end, SelectAction onPrompt = null, StandardHeldPrompt addToPrompt = null) //, out RoomLink viaExit
        {
            //viaExit = null; //TODO later: When finding items in other rooms, report what direction the item is in.
            List <Item> options = FindKnownItems(input, mob, start, end);

            if (options.Count == 1)
            {
                return(options[0]);
            }

            Client client = mob.Client;

            if (client == null)
            {
                //TODO: Have an NPC say they don't know what item they were told to find?
                return(null);
            }

            if (options.Count == 0)
            {
                client.sendMessage("You don't notice a '" + input.StringRange(start, end) + "'");
                return(null);
            }

            if (onPrompt == null)
            {
                client.sendMessage("There are too many things that fit that description.");
                return(null);
            }
            //TODO: Consider an alternative function to move prompt stuff to and add an out bool for prompting instead, not
            //sure if there's a need for that bool right now though; leave this one without prompt stuff

            //TODO: Some way to check if the prompt is still valid would be nice too, but not sure how to do that well without
            // just requiring another function passed into here. Might do that anyways.
            SelectFromList <Item> itemSelectPrompt = new SelectFromList <Item>(onPrompt.Invoke);

            if (addToPrompt == null || !addToPrompt.TransitionTo(itemSelectPrompt, true))
            {
                client.Prompt(itemSelectPrompt);
            }
            return(null);
        }
Example #8
0
        /// <summary>
        /// Check if 'input' (or a specific part of it) can be found inside of 'text'.
        /// </summary>
        /// <param name="input">Text to search for</param>
        /// <param name="text">Text to look inside for matches</param>
        /// <param name="startIndex">First word of 'input' to start searching for</param>
        /// <param name="endIndex">After last word of 'input' to search for (exclusive end)</param>
        /// <returns>True if text contains input in the same order.</returns>
        public static bool CheckAutoCompleteText(StringWords input, string text, int startIndex = 0, int endIndex = -1)
        {
            input.ValidateEndIndex(ref endIndex);
            if (startIndex >= endIndex)
            {
                throw new ArgumentException("startIndex must be before endIndex");
            }

            int textIndex = 0;

            for (int inputIndex = 0; textIndex < text.Length; textIndex++)
            {
                string wordToFind = input.Segments[inputIndex];

                textIndex = text.IndexOf(wordToFind, textIndex);
                if (textIndex == -1)
                {
                    return(false);                 //Input word was not found.
                }
                if (textIndex != 0)
                { //Check to make sure this could reasonably be the start of a word. If not, continue at the next character.
                    char prevChar = text[textIndex - 1];
                    //TODO: Finetune below checks.
                    //if (!Char.IsWhiteSpace(prevChar)) continue;
                    if (Char.IsLetterOrDigit(prevChar))
                    {
                        continue;
                    }
                }

                //Found a match. Continue with the next word.
                inputIndex++;
                if (inputIndex == endIndex)
                {
                    return(true);               //No next word, found all the words.
                }
                textIndex += wordToFind.Length; //Skip the matched text (plus 1 character from loop counter)
            }
            //Ran out of letters before matching all the words.
            return(false);
        }
Example #9
0
        public override void Execute(MOB mob, QueuedCommand command)
        {
            /*
             * Form is always (optional direction/distance) (optional preposition) (optional target)
             *  direction/distance can work alone (implies 'from here')
             *  if direction/distance is missing, if preposition is not specific, 'in reach' is implied
             *  preposition requires a target
             *  target can work alone (depends on target. If target defaults to enterable, implies 'in'. Else 'near')
             * Search for prepositions, get a list of them.
             *  Validate prepositions. Need to have nothing or a valid direction/distance before preposition.
             *  How many can actually be possible? I think only zero or one preposition is really possible?
             *  TODO: Special user input to specify a preposition instead of parser guessing. Mostly goes in StringWords but
             *  matching prepositions/item names needs to respect that too (might work automatically).
             *      Some system similar to quotes probably. Quotes may be useful though, like book titles or something.
             * If no prepositions, attempt to parse full string as direction/distance. If successful, do that
             * //Search whole string for item/target matches and associated strings.
             *  In general, 'visible to MOB' items.
             *  Must match to end of string?
             *  Nevermind, this string will be identified but targets will not be searched for until a TryGoEvent is run.
             * //Find associated strings that line up with a preposition
             * Instead of above two major points:
             *  Identify all valid strings (start after preposition, go to end of string)
             *      TODO: Special user input to specify a string instead of parser guessing?
             *          This is basically implied by a preposition. However it maybe makes more sense to specify the target instead of the preposition.
             *  //Search all 'visible to MOB' items that exactly match any of the valid strings.
             * How to pick best match?
             *  Maybe just not go if more than one match found, request more info. prompt?
             */
            StringWords goToInput = command.parsedCommand;

            //See if there's a preposition
            int start = 1; //Skip command ("go")
            int prepValue;
            MovementPreposition prepEnum;
            MovementDirection   direction = null;
            TryGoEvent          moveEvent = new TryGoEvent();
            int index = TextParsing.FindAPreposition(goToInput, typeof(MovementPreposition), out prepValue, start);

            if (index != -1)
            {
                //Is this a valid preposition? Check if it starts correctly.
                prepEnum = (MovementPreposition)prepValue;
                if (!prepEnum.AllowDirection() && !prepEnum.AllowDistance())
                {
                    if (index != start + 1)
                    {
                        //Invalid preposition for this location, needs to be at start of command.
                        goto noPrepositionFound;
                    }
                }
                else if ((prepEnum.RequireDirection() || prepEnum.RequireDistance()) && index == start + 1)
                {
                    //Invalid preposition for this location, needs to come after a direction/distance.
                    goto noPrepositionFound;
                }
                else
                {
                    direction = TextParsing.ParseAsDirection(goToInput, start, ref index, prepEnum.RequireDirection(), prepEnum.RequireDistance(), prepEnum.AllowDirection(), prepEnum.AllowDistance());
                    if (direction == null) //Not a valid preposition. Ignore it.
                    {
                        goto noPrepositionFound;
                    }
                    else //Maybe valid preposition.
                    {
                        //Check if preposition matches direction more closely? I think the previous checks have finished that successfully at this point.

                        //Valid preposition. Parse the REST of the sentence as an object.
                        start = index;
                        goto startEvent;
                    }
                }
            }
            else
            {
                //Is the whole thing a direction?
                direction = TextParsing.ParseAsDirection(goToInput, start, ref index);
                if (direction != null)
                {
                    if (direction.direction != Directions.NoDirection && index == goToInput.Segments.Length)
                    {
                        //Mark it as ONLY a direction, no destination (goToInput has been completely parsed/consumed)
                        goToInput = null;
                        //goto startEvent;
                    }
                    else
                    {
                        //Can't go only a distance with NoDirection. Cancel this parsing.
                        direction = null;
                    }
                }
                //Else try to parse the whole thing as an object to go to
            }
            //Text parsing has decided what words go to what (i.e. direction vs. target).
            //Text parsing has NOT identified objects yet.
noPrepositionFound:
            moveEvent.targetDescription = goToInput;
            start    = 1;
            prepEnum = MovementPreposition.To; // null; ?

startEvent:                                    //foundPreposition
            moveEvent.targetDescriptionStart = start;
            moveEvent.direction = direction;
            moveEvent.relation  = prepEnum;
            moveEvent.SetMoveSource(mob, null);

            //Raw command parsing done, target parsing has not been done.
            //Run the event to try to find a path to the target.
            moveEvent.FullRunEvent();
        }
Example #10
0
        /// <summary>
        /// Attempt to parse user's input text as a direction / distance.
        /// </summary>
        /// <param name="text">Full input to parse</param>
        /// <param name="startIndex">Index of first word to try to parse (inclusive). </param>
        /// <param name="endIndex">Index of last word to try to parse (exclusive). If the text is found, this will be updated
        /// to after the last word found (first index not belonging to the MovementDirection)</param>
        /// <param name="requireDirection">If true, parsing will return failure if no direction component is found.</param>
        /// <param name="requireDistance">If true, parsing will return failure if no distance component is found.</param>
        /// <param name="getDistance">If true, distance may be parsed. This is ignored (assumed true) if requireDistance is true.</param>
        /// <returns>The direction and distance parsed from the input text.</returns>
        public static MovementDirection ParseAsDirection(StringWords text, int startIndex, ref int endIndex, bool requireDirection = false, bool requireDistance = false, bool getDirection = true, bool getDistance = true)
        {
            text.ValidateEndIndex(ref endIndex);

            getDistance |= requireDistance;

            Directions foundDirection = Directions.NoDirection;
            //List<Directions> directions = new List<Directions>();
            KeyValuePair <string[][], Directions[]> directionOptions = DirectionCommand.GetDirectionOptions();

            string[][]   directionStrings = directionOptions.Key;
            Directions[] directionValues  = directionOptions.Value;
            int          foundDistance    = -1;
            MovementUnit foundUnit        = MovementUnit.NoDistance;
            int          i = startIndex;

            for (; i < endIndex; i++)
            {
                string word = text.Segments[i];
                if (foundDirection == Directions.NoDirection)
                {
                    int found = MatchString(directionStrings, text.Segments, ref i);
                    if (found != -1)
                    {
                        foundDirection = directionValues[found];
                        //Loop will increment but i is already the correct value after MatchString,
                        i--; //decrement here to 'skip' the increment.
                        continue;
                    }
                }
                if (getDistance && foundUnit == MovementUnit.NoDistance)
                {
                    int distanceWords = ParseAsDistance(text, out foundDistance, out foundUnit, i, Math.Min(i + 1, endIndex - 1));
                    if (distanceWords != 0)
                    {
                        if (distanceWords == 2)
                        {
                            i++;
                        }
                        continue;
                    }
                }

                break;
            }
            if (foundDirection == Directions.NoDirection && requireDirection)
            {
                return(null);
            }
            if (foundUnit == MovementUnit.NoDistance && requireDistance)
            {
                return(null);
            }
            if (foundDirection == Directions.NoDirection && foundUnit == MovementUnit.NoDistance)
            {
                return(null);
            }

            endIndex = i;
            return(new MovementDirection()
            {
                direction = foundDirection,
                distanceCount = foundDistance,
                distanceUnit = foundUnit
            });
        }