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; }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
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); }
/// <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; }
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) } )); }
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); }