private CommandLineParserResult HandleExcept(CommandLineParserResult result, TokenizedInput tokens, string currentToken)
        {
            var index = tokens.IndexOf(currentToken) + 1;

            if (index >= tokens.Count)
            {
                return(null);
            }

            var except = new List <Object>();

            // process rest of the tokens as objects
            for (int i = index; i < tokens.Count; i++)
            {
                // TODO: handle multiple objects with same name
                var next = tokens[i];

                if (next.IsPreposition() && result.Preposition == null)
                {
                    result.Preposition = Prepositions.Get(next);
                    continue;
                }

                var obj = GetObject(result, next);

                if (obj == null)
                {
                    result.Error = Messages.CantSeeObject;
                    return(result);
                }
                else if (obj is MultipleObjectsFound)
                {
                    var input = GetInput(result.Verb);

                    if (input.Error.HasValue())
                    {
                        return(input);
                    }

                    if (input.Objects.Count > 0)
                    {
                        except.AddRange(input.Objects);
                    }
                }
                else
                {
                    except.Add(obj);
                }
            }

            result.Objects = result.Objects.Where(x => !except.Contains(x)).ToList();

            return(null);
        }
示例#2
0
        public Grammar(string format)
        {
            Format = format;

            foreach (var token in Tokens)
            {
                if (Prepositions.Contains(token))
                {
                    Preposition = token;
                    break;
                }
            }
        }
        private CommandLineParserResult Parse(Verb verb, TokenizedInput tokens)
        {
            var result = new CommandLineParserResult
            {
                Verb = verb
            };

            var lastToken = "";

            foreach (string token in tokens)
            {
                var obj = GetObject(result, token);

                if (obj is Skip)
                {
                    continue;
                }

                if (result.Objects.Contains(obj))
                {
                    // will happen for something like "take the brass lamp"
                    continue;
                }

                if (obj != null)
                {
                    if (obj.InScope)
                    {
                        if (result.Preposition == null || !result.Objects.Any())
                        {
                            // handles commands like "put on coat", "put down book", etc.
                            result.Ordered.Add(obj);
                            result.Objects.Add(obj);
                        }
                        else
                        {
                            result.Ordered.Add(obj);
                            result.IndirectObject = obj;
                        }
                    }
                    else if (obj is MultipleObjectsFound)
                    {
                        return(ResolveMultipleObjects(verb, (MultipleObjectsFound)obj));
                    }
                    else
                    {
                        result.Error = Messages.CantSeeObject;
                        return(result);
                    }
                }

                // distinguish between prepositions and movement - "go south", "put bottle down", "close up grate"
                else if ((result.Verb is IDirectionProxy) && token.IsDirection() && !result.Objects.Any())
                {
                    var v = token.ToVerb();
                    result.Ordered.Add(v);
                    result.Verb = v;
                }

                else if (token.IsPreposition())
                {
                    var p = Prepositions.Get(token);
                    result.Ordered.Add(p);
                    result.Preposition = p;
                }

                else if (token == "all" && !result.Objects.Any())
                {
                    result.IsAll = true;

                    if (!verb.Multi && !verb.MultiHeld)
                    {
                        result.Error = Messages.MultiNotAllowed;
                        break;
                    }

                    var multi = new List <Object>();

                    if (verb.Multi)
                    {
                        var objectsInRoom =
                            from o in CurrentRoom.ObjectsInRoom()
                            where !o.Animate
                            select o;

                        multi.AddRange(objectsInRoom);
                    }

                    if (verb.MultiHeld)
                    {
                        multi.AddRange(Inventory.Items);
                    }

                    // if object count is only 1, we don't add it so it can be handled in the verb using implict
                    // messages e.g. (the small bottle)
                    if (multi.Count > 1)
                    {
                        result.Objects.AddRange(multi);
                    }
                }

                else if (token == "except" && (verb.Multi || verb.MultiHeld) && lastToken == "all")
                {
                    var except = HandleExcept(result, tokens, token);

                    if (except != null)
                    {
                        return(except);
                    }

                    break;
                }

                else
                {
                    obj = result.Objects.FirstOrDefault();

                    if (obj != null && !result.IsAll)
                    {
                        result.Error = Messages.PartialUnderstanding(verb, obj);
                    }
                    else
                    {
                        result.Error = Messages.CantSeeObject;
                    }

                    return(result);
                }

                lastToken = token;
            }

            return(result);
        }
示例#4
0
        public InputResult Parse(string input)
        {
            var result = new InputResult();

            var tokenizer = new InputTokenizer();
            var tokens    = tokenizer.Tokenize(input);

            if (tokens.Count == 0)
            {
                result.Action = () =>
                {
                    Context.Parser.Print(L.DoNotUnderstand);
                    return(true);
                };
                return(result);
            }

            // there can be more than one match for verbs like "switch"
            // which has one class that handles "switch on" and another
            // class that handles "switch off"
            var possibleVerbs = VerbList.GetVerbsByName(tokens[0]);

            if (possibleVerbs.Count == 0)
            {
                result.Verb   = new NullVerb();
                result.Action = ErrorAction(L.VerbNotRecognized);
                return(result);
            }

            if (possibleVerbs.Count == 1)
            {
                result.Verb = possibleVerbs.First();
            }

            // remove verb token
            tokens.RemoveAt(0);

            var  grammarTokens  = new List <string>();
            bool hasPreposition = false;

            foreach (string token in tokens)
            {
                // var objects = Objects.WithName(token);
                var objects = (
                    from o in Objects.WithName(token)
                    where L.ObjectsInScope().Contains(o)
                    select o
                    ).ToList();

                bool hasObject = result.Objects.Count > 0;

                if (!hasObject)
                {
                    var rooms = Rooms.WithName(token);
                    foreach (var room in rooms)
                    {
                        objects.Add(room);
                    }
                }

                if (objects.Count == 0)
                {
                    bool isDirection = possibleVerbs.Count == 1 &&
                                       Compass.Directions.Contains(token) &&
                                       result.Objects.Count == 0;
                    bool isPreposition = Prepositions.Contains(token);

                    if (isDirection)
                    {
                        possibleVerbs.Clear();
                        possibleVerbs.Add(VerbList.GetVerbByName(token));
                    }
                    else if (isPreposition)
                    {
                        hasPreposition = true;
                        grammarTokens.Add(token);
                        result.Preposition = token;
                    }
                    else if (token == K.ALL)
                    {
                        grammarTokens.Add(token);
                        result.IsAll = true;
                    }
                    else if (token == K.EXCEPT)
                    {
                        if (!result.IsAll && !result.Objects.Any())
                        {
                            result.Action = ErrorAction(L.CantSeeObject);
                            return(result);
                        }
                        result.IsExcept = true;
                    }
                    else
                    {
                        result.Action = ErrorAction(L.CantSeeObject);
                        return(result);
                    }
                }
                else
                {
                    // need to implement "Which do you mean, the red cape or the black cape?" type behavior here
                    Object obj;
                    var    ofInterest = objects.Where(x => x.InScope).ToList();

                    if (ofInterest.Count > 1)
                    {
                        obj = ofInterest.FirstOrDefault(x => x.InInventory);
                    }
                    else
                    {
                        obj = ofInterest.FirstOrDefault();
                    }

                    //-------------------------------------------------------------------------------------

                    bool isIndirectObject = hasPreposition && hasObject;

                    if (obj == null)
                    {
                        result.Action = ErrorAction(L.CantSeeObject);
                        return(result);
                    }

                    if (isIndirectObject)
                    {
                        grammarTokens.Add(K.INDIRECT_OBJECT_TOKEN);
                        result.IndirectObject = obj;
                    }
                    else if (result.IsExcept)
                    {
                        result.Exceptions.Add(obj);
                    }
                    else
                    {
                        if (!grammarTokens.Contains(K.OBJECT_TOKEN))
                        {
                            grammarTokens.Add(K.OBJECT_TOKEN);
                        }
                        if (!result.Objects.Contains(obj))
                        {
                            result.Objects.Add(obj);
                        }
                    }
                }
            }

            result.Pregrammar = string.Join(" ", grammarTokens.ToArray());

            var grammarBuilder = new GrammarBuilder(grammarTokens);
            var grammars       = grammarBuilder.Build();

            FindVerb(result, possibleVerbs, grammars);

            if ((result.IsAll || result.Objects.Count > 1) && !result.Verb.AllowsMulti)
            {
                return(DoesNotAllowMulti());
            }

            if (result.Grammar == null)
            {
                var incomplete = new IncompleteInput();
                incomplete.Handle(result);
            }

            if (result.IsAll)
            {
                if (result.ObjectsMustBeHeld)
                {
                    result.Objects = Inventory.Items.Reverse().ToList();
                }
                else
                {
                    // This is different from Inform 6 which will include scenery and static
                    // objects (resulting in the generation of ridiculous messages like
                    // "well house: that's hardly portable"
                    result.Objects = (
                        from o in L.ObjectsInScope()
                        where o != L.CurrentLocation && !o.IsScenery && !o.IsStatic &&
                        !Inventory.Contains(o)
                        select o
                        ).ToList();
                }
            }

            if (result.IsExcept)
            {
                if (!result.Exceptions.Any())
                {
                    return(WhatDoYouWantToDo(result));
                }

                result.Exceptions.ForEach(x => result.Objects.Remove(x));
            }

            return(result);
        }
示例#5
0
        public bool Parse(string input)
        {
            InputTokenizer tokenizer = new InputTokenizer();

            var tokens = tokenizer.Tokenize(input);

            if (tokens.Count == 0)
            {
                Error = L.DoNotUnderstand;
                return(false);
            }

            IList <Verb> possibleVerbs = VerbList.GetVerbsByName(tokens[0]);

            if (possibleVerbs.Count == 0)
            {
                Error = L.VerbNotRecognized;
                return(false);
            }

            // remove verb token
            tokens.RemoveAt(0);

            var  grammarTokens  = new List <string>();
            bool hasPreposition = false;
            bool isException    = false;

            foreach (string token in tokens)
            {
                var obj = Adventure.Net.Objects.GetByName(token);

                if (obj == null)
                {
                    if (Prepositions.Contains(token))
                    {
                        hasPreposition = true;
                        grammarTokens.Add(token);
                    }
                    else if (token == "all")
                    {
                        grammarTokens.Add(token);
                    }
                    else if (token == "except")
                    {
                        isException = true;
                    }
                    else
                    {
                        Error = L.DoNotUnderstand;
                        return(false);
                    }
                }
                else
                {
                    if (hasPreposition && Objects.Count > 0)
                    {
                        grammarTokens.Add("y");
                        IndirectObject = obj;
                    }
                    else if (isException)
                    {
                        Exceptions.Add(obj);
                    }
                    else
                    {
                        if (!grammarTokens.Contains("x"))
                        {
                            grammarTokens.Add("x");
                        }
                        Objects.Add(obj);
                    }
                }
            }

            Pregrammar = string.Join(" ", grammarTokens.ToArray());

            var grammarBuilder = new GrammarBuilder(grammarTokens);
            var grammars       = grammarBuilder.Build();

            return(true);
        }
示例#6
0
        public InputResult Parse(string input)
        {
            var result = new InputResult();

            var tokenizer = new InputTokenizer();
            var tokens    = tokenizer.Tokenize(input);

            Action removeVerbToken = () => tokens.RemoveAt(0);

            if (tokens.Count == 0)
            {
                result.Action = () =>
                {
                    Context.Parser.Print(L.DoNotUnderstand);
                    return(true);
                };
                return(result);
            }

            // there can be more than one match for verbs like "switch"
            // which has one class that handles "switch on" and another
            // class that handles "switch off"
            var possibleVerbs = VerbList.GetVerbsByName(tokens[0]);

            if (possibleVerbs.Count == 0)
            {
                result.Verb   = new NullVerb();
                result.Action = ErrorAction(L.VerbNotRecognized);
                return(result);
            }

            if (possibleVerbs.Count == 1)
            {
                result.Verb = possibleVerbs.First();
            }
            //else { NOT sure what to do about multiple possible verbs here}


            // remove verb token
            removeVerbToken();

            var  grammarTokens  = new List <string>();
            bool hasPreposition = false;

            foreach (string token in tokens)
            {
                bool hasObject = result.Objects.Count > 0;

                var objects = Objects.WithName(token);

                if (!hasObject)
                {
                    var rooms = Rooms.WithName(token);
                    foreach (var room in rooms)
                    {
                        objects.Add(room);
                    }
                }

                if (objects.Count == 0)
                {
                    bool isDirection = possibleVerbs.Count == 1 &&
                                       Compass.Directions.Contains(token) &&
                                       result.Objects.Count == 0;
                    bool isPreposition = Prepositions.Contains(token);

                    if (isDirection)
                    {
                        possibleVerbs.Clear();
                        possibleVerbs.Add(VerbList.GetVerbByName(token));
                    }
                    else if (isPreposition)
                    {
                        hasPreposition = true;
                        grammarTokens.Add(token);
                        result.Preposition = token;
                    }
                    else if (token == K.ALL)
                    {
                        // result.Objects.AddRange(L.ObjectsInScope());
                        grammarTokens.Add(token);
                        result.IsAll = true;
                    }
                    else if (token == K.EXCEPT)
                    {
                        if (!result.IsAll && !result.Objects.Any())
                        {
                            result.Action = ErrorAction(L.CantSeeObject);
                            return(result);
                        }
                        result.IsExcept = true;
                    }
                    else
                    {
                        if (result.IsPartial)
                        {
                            string partial = String.Format("I only understood you as far as wanting to {0} the {1}.", possibleVerbs[0].Name, result.Objects[0].Name);
                            result.Action = ErrorAction(partial);
                            return(result);
                        }

                        result.Action = ErrorAction(L.CantSeeObject);
                        return(result);
                    }
                }
                else
                {
                    // need to implement "Which do you mean, the red cape or the black cape?" type behavior here
                    Object obj;
                    var    ofInterest = objects.Where(x => x.InScope).ToList();
                    if (ofInterest.Count > 1)
                    {
                        obj = ofInterest.FirstOrDefault(x => x.InInventory);
                    }
                    else
                    {
                        obj = ofInterest.FirstOrDefault();
                    }
                    //-------------------------------------------------------------------------------------

                    bool isIndirectObject = hasPreposition && hasObject;

                    if (obj == null)
                    {
                        result.Action = ErrorAction(L.CantSeeObject);
                        return(result);
                    }

                    if (isIndirectObject)
                    {
                        grammarTokens.Add(K.INDIRECT_OBJECT_TOKEN);
                        result.IndirectObject = obj;
                    }
                    else if (result.IsExcept)
                    {
                        //result.Objects.Remove(obj);
                        result.Exceptions.Add(obj);
                    }
                    else
                    {
                        if (!grammarTokens.Contains(K.OBJECT_TOKEN))
                        {
                            grammarTokens.Add(K.OBJECT_TOKEN);
                        }
                        if (!result.Objects.Contains(obj))
                        {
                            result.Objects.Add(obj);
                        }
                        result.IsPartial = true;
                    }
                }
            }

            result.Pregrammar = string.Join(" ", grammarTokens.ToArray());

            var grammarBuilder = new GrammarBuilder(grammarTokens);
            var grammars       = grammarBuilder.Build();

            FindVerb(result, possibleVerbs, grammars);

            if (result.Grammar == null)
            {
                var incomplete = new IncompleteInput();
                incomplete.Handle(result);
            }

            if (result.IsAll)
            {
                if (result.ObjectsMustBeHeld)
                {
                    result.Objects = result.Objects.Where(x => x.InInventory).ToList();
                }
                else
                {
                    result.Objects = L.ObjectsInScope();
                }
            }

            if (result.IsExcept)
            {
                result.Exceptions.ForEach(x => result.Objects.Remove(x));
            }

            return(result);
        }
示例#7
0
 public static bool IsPreposition(this string input)
 {
     return(Prepositions.Contains(input));
 }