Beispiel #1
0
        public MatchedCommand ParseCommand(PendingCommand Command)
        {
            var tokens = new LinkedList<String>(Command.RawCommand.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries));

            var rootMatch = new PossibleMatch(tokens.First);
            rootMatch.Upsert("ACTOR", Command.Actor);
            rootMatch.Upsert("LOCATION", Command.Actor == null ? null : Command.Actor.Location);

            // A pending command can have some properties set when it is queued. For example, the 'go' action
            // generates a 'look' command after processing. It will give the 'look' command a property named
            // 'auto' to indicate that the look command was generated. Rules can then use this property to
            // implement behavior. From the same example, 'look' may emit a brief description if it is generated
            // by the 'go' action, but emit a more detailed description if the player enters the command 'look'.
            //      See StandardActions.Go
            if (Command.PreSettings != null)
                foreach (var setting in Command.PreSettings)
                    rootMatch.Upsert(setting.Key.ToUpper(), setting.Value);

            var matchContext = new MatchContext { ExecutingActor = Command.Actor };

            // Try every single command defined, until one matches.
            foreach (var command in Commands)
            {
                IEnumerable<PossibleMatch> matches;

                try
                {
                    matches = command.Matcher.Match(rootMatch, matchContext);
                }
                catch (MatchAborted ma)
                {
                    // The match didn't fail; it generated an error. These means the match progressed to a point
                    // where the author of the command felt that the input could not logically match any other
                    // command, however, the input was still malformed in some way. Abort matching, and dummy up
                    // a command entry to display the error message to the player.
                    return new MatchedCommand(
                        new CommandEntry().ProceduralRule((match, actor) =>
                        {
                            MudObject.SendMessage(actor, ma.Message);
                            return PerformResult.Continue;
                        }),
                        // We need a fake match just so it can be passed to the procedural rule.
                        new PossibleMatch[] { new PossibleMatch(null) });
                }

                // Only accept matches that consumed all of the input.
                matches = matches.Where(m => m.Next == null);

                // If we did consume all of the input, we will assume this match is successful. Note it is
                // possible for a command to generate multiple matches, but not possible to match multiple commands.
                if (matches.Count() > 0)
                    return new MatchedCommand(command, matches);
            }
            return null;
        }
Beispiel #2
0
        /// <summary>
        /// Clone this match, but advance the clone to the end of input and give it an additional property.
        /// </summary>
        /// <param name="ArgumentName"></param>
        /// <param name="Value"></param>
        /// <returns></returns>
        public PossibleMatch EndWith(String ArgumentName, Object Value)
        {
            var r = new PossibleMatch(this, null, ParseDepth + 1);

            r.Upsert(ArgumentName, Value);
            return(r);
        }
Beispiel #3
0
        /// <summary>
        /// Clone this match, but advance the clone to the next token and give it an additional property.
        /// </summary>
        /// <param name="ArgumentName"></param>
        /// <param name="Value"></param>
        /// <returns></returns>
        public PossibleMatch AdvanceWith(String ArgumentName, Object Value)
        {
            var r = new PossibleMatch(this, Next.Next, ParseDepth + 1);

            r.Upsert(ArgumentName, Value);
            return(r);
        }
Beispiel #4
0
        /// <summary>
        /// Clone this match, but give the clone an additional argument.
        /// </summary>
        /// <param name="ArgumentName"></param>
        /// <param name="Value"></param>
        /// <returns></returns>
        public PossibleMatch With(String ArgumentName, Object Value)
        {
            var r = new PossibleMatch(this, Next);

            r.Upsert(ArgumentName, Value);
            return(r);
        }
Beispiel #5
0
        /// <summary>
        /// Actually carryout the command, following all of it's rules, including the before and after command rules.
        /// </summary>
        /// <param name="Command"></param>
        /// <param name="Match"></param>
        /// <param name="Actor"></param>
        /// <returns>The result of the command's procedural rules.</returns>
        private static PerformResult ExecuteCommand(CommandEntry Command, PossibleMatch Match, MudObject Actor)
        {
            var result = PerformResult.Stop;

            Match.Upsert("COMMAND", Command);
            if (GlobalRules.ConsiderMatchBasedPerformRule("before command", Match, Actor) == PerformResult.Continue)
            {
                result = Command.ProceduralRules.Consider(Match, Actor);
                GlobalRules.ConsiderMatchBasedPerformRule("after command", Match, Actor);
            }
            GlobalRules.ConsiderPerformRule("after every command", Actor);
            return(result);
        }
Beispiel #6
0
        override protected List <PossibleMatch> ImplementMatch(PossibleMatch State, MatchContext Context)
        {
            var useObjectScoring = ScoreResults != null;

            var R = new List <PossibleMatch>();

            if (State.Next == null)
            {
                return(R);
            }

            if ((Settings & ObjectMatcherSettings.UnderstandMe) == ObjectMatcherSettings.UnderstandMe)
            {
                if (State.Next.Value.ToUpper() == "ME")
                {
                    var possibleMatch = State.Advance();
                    possibleMatch.Upsert(CaptureName, Context.ExecutingActor);
                    possibleMatch.Upsert(CaptureName + "-SOURCE", "ME");
                    R.Add(possibleMatch);
                }
            }

            foreach (var matchableMudObject in ObjectSource.GetObjects(State, Context))
            {
                PossibleMatch possibleMatch = State;
                bool          matched       = false;
                while (possibleMatch.Next != null && matchableMudObject.GetProperty <NounList>("nouns").Match(possibleMatch.Next.Value.ToUpper(), Context.ExecutingActor))
                {
                    if (matched == false)
                    {
                        possibleMatch = State.Clone();
                    }
                    matched            = true;
                    possibleMatch.Next = possibleMatch.Next.Next;
                }

                if (matched)
                {
                    possibleMatch.Upsert(CaptureName, matchableMudObject);

                    if (useObjectScoring)
                    {
                        var score = ScoreResults(Context.ExecutingActor, matchableMudObject);
                        possibleMatch.Upsert(CaptureName + "-SCORE", score);

                        var insertIndex = 0;
                        for (insertIndex = 0; insertIndex < R.Count; ++insertIndex)
                        {
                            if (score > (R[insertIndex][CaptureName + "-SCORE"] as MatchPreference?).Value)
                            {
                                break;
                            }
                        }

                        R.Insert(insertIndex, possibleMatch);
                    }
                    else
                    {
                        R.Add(possibleMatch);
                    }
                }
            }
            return(R);
        }
Beispiel #7
0
 /// <summary>
 /// Actually carryout the command, following all of it's rules, including the before and after command rules.
 /// </summary>
 /// <param name="Command"></param>
 /// <param name="Match"></param>
 /// <param name="Actor"></param>
 /// <returns>The result of the command's procedural rules.</returns>
 private static PerformResult ExecuteCommand(CommandEntry Command, PossibleMatch Match, Actor Actor)
 {
     var result = PerformResult.Stop;
     Match.Upsert("COMMAND", Command);
     if (GlobalRules.ConsiderMatchBasedPerformRule("before command", Match, Actor) == PerformResult.Continue)
     {
         result = Command.ProceduralRules.Consider(Match, Actor);
         GlobalRules.ConsiderMatchBasedPerformRule("after command", Match, Actor);
     }
     GlobalRules.ConsiderPerformRule("after every command", Actor);
     return result;
 }
Beispiel #8
0
        public MatchedCommand ParseCommand(PendingCommand Command)
        {
            var tokens = new LinkedList <String>(Command.RawCommand.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries));

            var rootMatch = new PossibleMatch(tokens.First);

            rootMatch.Upsert("ACTOR", Command.Actor);
            rootMatch.Upsert("LOCATION", Command.Actor == null ? null : Command.Actor.Location);

            // A pending command can have some properties set when it is queued. For example, the 'go' action
            // generates a 'look' command after processing. It will give the 'look' command a property named
            // 'auto' to indicate that the look command was generated. Rules can then use this property to
            // implement behavior. From the same example, 'look' may emit a brief description if it is generated
            // by the 'go' action, but emit a more detailed description if the player enters the command 'look'.
            //      See StandardActions.Go
            if (Command.PreSettings != null)
            {
                foreach (var setting in Command.PreSettings)
                {
                    rootMatch.Upsert(setting.Key.ToUpper(), setting.Value);
                }
            }

            var matchContext = new MatchContext {
                ExecutingActor = Command.Actor
            };

            // Try every single command defined, until one matches.
            foreach (var command in Commands)
            {
                IEnumerable <PossibleMatch> matches;
                matchContext.CurrentParseCommand = command;

                try
                {
                    matches = command.Matcher.Match(rootMatch, matchContext);
                }
                catch (MatchAborted ma)
                {
                    // The match didn't fail; it generated an error. This usually represents an oversite in the command's grammar.
                    // Abort matching, and dummy up a command entry to display the error message to the player.
                    return(new MatchedCommand(
                               new CommandEntry().ProceduralRule((match, actor) =>
                    {
                        Core.SendMessage(actor, ma.Message);
                        return PerformResult.Continue;
                    }),
                               // We need a fake match just so it can be passed to the procedural rule.
                               new PossibleMatch[] { new PossibleMatch(null) }));
                }

                // Only accept matches that consumed all of the input as valid, successful matches.
                matches = matches.Where(m => m.Next == null);

                // If we did consume all of the input, we will assume this match is successful. Note it is
                // possible for a command to generate multiple matches, but not possible to match multiple commands.
                if (matches.Count() > 0)
                {
                    return(new MatchedCommand(command, matches));
                }
            }

            // No command matched; lets return a dummy command that display's the huh? text.
            return(new MatchedCommand(
                       new CommandEntry()
                       .ProceduralRule((match, actor) =>
            {
                // Todo: Expand match arguments into error message.
                if (matchContext.BestFailedCommand != null && matchContext.BestFailedMatch.ParseDepth > 0)
                {
                    Core.SendMessage(actor, "That's the name of a command, but I couldn't figure out what you meant.");
                    Core.SendMessage(actor, "The best failed match was " + matchContext.BestFailedCommand.ManualName + ", which reached a depth of " + matchContext.BestFailedMatch.ParseDepth);
                    if (!String.IsNullOrEmpty(matchContext.BestFailedParseStageDescription))
                    {
                        Core.SendMessage(actor, Core.FormatParserMessage(actor, matchContext.BestFailedParseStageDescription, matchContext.BestFailedMatch));
                    }
                }
                else
                {
                    Core.SendMessage(actor, "I don't think that is a command I know. I could not parse any of it.");
                }

                return PerformResult.Continue;
            }),
                       new PossibleMatch[] { new PossibleMatch(null) }
                       ));
        }
Beispiel #9
0
        public MatchedCommand ParseCommand(PendingCommand Command)
        {
            var tokens = new LinkedList <String>(Command.RawCommand.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries));

            var rootMatch = new PossibleMatch(tokens.First);

            rootMatch.Upsert("ACTOR", Command.Actor);
            rootMatch.Upsert("LOCATION", Command.Actor == null ? null : Command.Actor.Location);

            // A pending command can have some properties set when it is queued. For example, the 'go' action
            // generates a 'look' command after processing. It will give the 'look' command a property named
            // 'auto' to indicate that the look command was generated. Rules can then use this property to
            // implement behavior. From the same example, 'look' may emit a brief description if it is generated
            // by the 'go' action, but emit a more detailed description if the player enters the command 'look'.
            //      See StandardActions.Go
            if (Command.PreSettings != null)
            {
                foreach (var setting in Command.PreSettings)
                {
                    rootMatch.Upsert(setting.Key.ToUpper(), setting.Value);
                }
            }

            var matchContext = new MatchContext {
                ExecutingActor = Command.Actor
            };

            // Try every single command defined, until one matches.
            foreach (var command in Commands)
            {
                IEnumerable <PossibleMatch> matches;

                try
                {
                    matches = command.Matcher.Match(rootMatch, matchContext);
                }
                catch (MatchAborted ma)
                {
                    // The match didn't fail; it generated an error. These means the match progressed to a point
                    // where the author of the command felt that the input could not logically match any other
                    // command, however, the input was still malformed in some way. Abort matching, and dummy up
                    // a command entry to display the error message to the player.
                    return(new MatchedCommand(
                               new CommandEntry().ProceduralRule((match, actor) =>
                    {
                        MudObject.SendMessage(actor, ma.Message);
                        return PerformResult.Continue;
                    }),
                               // We need a fake match just so it can be passed to the procedural rule.
                               new PossibleMatch[] { new PossibleMatch(null) }));
                }

                // Only accept matches that consumed all of the input.
                matches = matches.Where(m => m.Next == null);

                // If we did consume all of the input, we will assume this match is successful. Note it is
                // possible for a command to generate multiple matches, but not possible to match multiple commands.
                if (matches.Count() > 0)
                {
                    return(new MatchedCommand(command, matches));
                }
            }
            return(null);
        }