Interpretation Setup Consultation (C#)
Hello. This is my first question ever. Party right here. Now, onto the question!
I am creating a framework for a game. It is a M(ulti) U(ser) D(ungeon) or a text based imagination driven interactive book or at least that's how I see it. I'm taking an approach to it that is hopefully rather fresh. I have not really looked into all the different ones already in existence because I do not want the vision I have to be tainted (you will not change my mind on this). Enough about that though. Right now I am working on the command text interpretation system.
I view all input from the user to fall into the following 6 categories:
Actions - grab/touch/look/feel
Action Arguments - the action "stand" takes an argument "up" (things that indicate how-to do an action)
Quantity Indicators - some/three/dozen/all
Identity References - my/he/it/Bob/them
Identity Descriptors - dark/blue/tall/ignorant
Order of Execution - before/after/next/previous/then/and
The idea is that Actions know what they need to look for. The action "grab" knows how to check for a who or a what and possibly a quantity in the command text. If multiple actions are present they execute in the order they are found unless Order of Execution modifies are present. Now this is all swell and dandy but what exactly is my question?
I am all about coding simplicity. Easy to understand readable flexible code design as I am sure most of the people on this site are. I picture there being three steps to interpenetration:
All of this is design work. A string of text comes in and I am deciding how I want to handle it from there. Please feel free to suggest anything as I have nothing more than "string comes in now what?".
Thanks in advance! I do appreciate the time it takes to wrap you're head around what I've said and also the time it takes to devise and respond to my question.
Karl Wessels, Jul 25, 2011
Let me start off by thanking you. I was quite suprised to see your reply but even more so when I noticed that you (maybe) created your account to just reply to my question! Sweet ^_^
I'll address what you have me in much the same manner it was given.
1. I wouldn't use a third party. I'll take concepts from other things but as for simply using them is not something I plan to do. It creates a dependency in most cases. I want full liberities with the design and implementation of my model/system.
2. You did lose me a little bit in your bird example but let me try to give me thoughts on it.
"Put bird in cage" is definitly viable. Now, I add an aviary to my game where there are hundreds of birds. I'm not sure what you mean by the implied "the" but here is how I see things going down. "Put" should be intelligent enough to go:
put> what?> looks at the identity reference "bird" > can we find a sole instance of bird? > no > is a quanity given > no > put fails.
what if it was "put five bird in cage" though incorrect grammatically someone could try it:
put> what?> looks at the identity reference "bird" > can we find a sole instance of bird? > no > is a quanity given > yes > are there identity descriptors given? > no > take first 5 or less identities (entities/objects) that match "bird" and put them into cage (assuming it allows that) up to however many will fit.
I foresee the actions being rather intellegent about what they do; developing with the needs of my game/framework. I plan to let the objects, cage in this case, handle the addition of birds.
I really do not forsee "the" really being used. It simply states "an identity reference is coming up" or more often it connects words for the tongue. I've tried to think of cases where it matters but so far I haven't. I will be consulting a few "english major" friends of mine as I progress.
3. It seems like the purpose of my reordering step is a bit foggy. First, let me say that my game is not going to be like any prior. I am always asking "What we would be the best version of this idea/feature be?" then proceeding to *try* and create it. Let's just say I have a big dream for this game. Anyhoo!
Take the sentence, "grab the hat after standing up", which to me is a worthy command in game. Without reordering it I would "grab the hat" then "stand up" while the command clearly was intended to be the other way around. I want this type of syntax to be do-able because it allows more natural combo commands. In addition to that eventually the command input will be wired to a voice-to-text system (I think it will be easy to do).
4. I believe the parts of speech are irrelevant. The reason being I look at them in more simpler terms being the six I mentioned above almost programmatic if you will.
"My" says "The one who gave the command" so then "My knife" says "The giver of the command's knife."
The reason for breaking things down differently is to avoid the pitfall of an expected format. Using the examples you gave as reference it seems far more complex than letting the actions define what they do. Take "statistics" for example. If that was the entire command it would come back with "of what?" because is that not what you thought when you read it? Now, "statistics for Bob" it would come back with "Bob is age 24 currently eating an ice cream cone in his villa in Arizona." for example. The word knows what it expects to operate on and how to find it. You could leave out "for" and that would be shorthand because it is merely a connector in this case.
I can see why you might think this "would be fiendish to hand code" but it really only becomes that when you try to add a lot to a simple thing. As we (the developers of the framework) have a need for new action or an existing one to do more it can be incorperated then directly into the action.
5. I love your examples. WE GET CHICKEN! (that might be an easter egg :P)
You bring up some good points to consider. When throwing a bird does the bird have a state and how does that affect the action.
All I can tell you now is that as I am thinking about the command system I am also modeling out my Obj (objects since C# has it as a keyword) and Entity models. I forsee my model developing as my actions are. In order to "unlock and open the door" I first must have a door and the commands unlock and open.
6. This really made me smile/laugh because of your examples.
"throw axe" would expect a direction or a target.
"take axe at dwarf" might operate like this: take> what?> found axe> at dwarf are not actions therefore there is nothing to do.
however given "take axe from dwarf": take> what? found axe> is there a what or who?> found from> from what/who?> found dwarf> take the axe from the dwarf (which I am guessing would trigger off an event on the dwarf).
"take dwarf": take> what?> dwarf found> is dwarf take-able> no> do nothing.
"take knife": take> what?> knife word found> can we resolve a knife reference> no> do nothing.
7. This is where my mind is grid locked at the moment. The reason I brought up the command pattern is that it *could* be called via "Action.Execute(commandText)" in which the Action knows how to execute it. The next part I question is from there how do we execute the next command if it exists which is why I brought up the chain of responsibility pattern at least for the idea of "passing it off to the next".
This is the part I am trying to map out. I'd like to keep it to the "three steps to interpertation" I mentioned about. How it actually comes together is really up to the imagination. Maybe the "thought process" I use in response 6 will give you more of an idea of what I got/am thinking.
I'll keep reviewing what you answered above and see if it sparks any ideas. You have given me a lot of good things to think about as well as a good laugh or two :) I'd love to keep discuss things with you or even work with you. If you're interested in either then perhaps we could get some email correspondence going. I won't be offended at all if you are not.
Thank you! Catch you later.
Karl Wessels, Jul 28, 2011
Here are a bunch of thoughts generated by your question. Some may be way off the mark - in which case please forgive me. Hopefully, however, some will be helpful and will give you new directions of inquiry as you design your system.
1. You can rule out third party parsers
2. Planning for complexity
Consider a room with a bird in it; the adventurer has a cage.
"Put bird in cage" is a viable command.
Now, consider that you'd like to add an aviary to your game - where there are several (maybe hundreds) of birds in the room. An implied "the" may not be sufficient - maybe you'll want the user to be able to say "put five birds in cage" or "fill cage with birds" (requires bird size and cage volume, or cage bird count capacity, constraints, etc.).
The above scenario is intended to illustrate that you need to strongly consider whether ignoring words like "the" will always work, or will only be acceptable depending on context. This greatly affects your parser.
Perhaps you plan to implement some temporal constraint on commands - so that commands issued on the same command line have a different relationship with each other than commands issued on distinct command lines do.
Either way, I'd make my engine start by splitting the input on the sequencing keywords; it can then sort the now distinct commands, and submit them one at a time to the true command interpreter - just as if they had been typed one per input line. And, if you have a 'commands on the same line are related' you can pass to the command interpreter a token of some kind (a line number, perhaps) that indicates their relationship.
The bottom line is that I see the reordering action as a step prior to true command interpretation, making the latter simpler.
4. Command interpretation
6. Incomplete and meaningless commands
I keep trying to find a way to use the Command Pattern, but it just doesn't seem to fit: each type of object (and place) likely has different actions that it can, or cannot, perform. If there are hundreds of objects in your world, and some can be thrown while some can't, how do you express the throwability of an object, using the Command Pattern? The point of the command pattern is that each command implements a stragety (Strategy Pattern) that depends on all commandable objects having a common set of properties, - but each command is completely agnostic about the specific type of object being commanded (and objects are command-agnostic, too, so an IsThrowable property is out of the question).
Chris Trelawny-Ross, Jul 26, 2011