: Hotspots Admin Pages | Turn-in Site |
Current Links: Cases Final Project Summer 2007
MotherSqueakers Cases Page for P6 & P7
"MotherSqueakers" is made up of:
Emeka Okonkwo gte761m
Nisha Iyer gte982n
Ken Bohannon gte952r
Yinka Alaran gte117p
Here are the requirements for P6:
NOTE - if my explanation of the way our stuff looks like is kind of fuzzy, feel free to scroll all the way down and have a look for yourself at the pictures we uploaded! :)
Going through each requirement stages:
The first thing was interaction with the wonderland. Basically, stuffs like take, drop, put the X on the Y, put the X into the Y etc. Most groups implemented a first person view i.e the player was basically, the camera window and when you took stuffs they just dissappeared and when you dropped them they appeaered...pretty basic and fits the requirements. However, we went a step further...
In our wonderland adventure, we made it in 3rd person perspective. ie you could actually see the player (which was the toysoldier). It was always the back view of the player so when you type look, the whole world rotates and he looks around - imagine fixing a camera at your back and then turning with it 360 degress.
When you type 'take ' he actually MOVES to the object and the object dissapears.
When you say 'drop object', the object drops from his inventory onto the ground next to him.
when you say 'use knife' - the knife moves to the troll and kills the troll (Elvis).
when you say 'use kitten' - the kitten moves to the troll and disappears - case of the missing kitten (guess he got swallowed).
when you put something on another - the object moves together with the toySoldier and when he reaches the table, he puts it on top on the table.
We also implemented music for your listening pleasure and what better music than good ol' bond...James Bond - YEAH BABY YEEAAAHH!!
Each room was distinct - a different scenery for each room. And for the walls, we made it surreal i.e. when you say go west and there is no exit, the toySoldier moves to the west and then turns around.
Going from one room to another makes creates a new wonderland and for each new world he enters (including the starting one) he performs a 360 degree look around to match the feel of 'welcome to the you see ' so as to create the feel of him actually looking around.
Each object and character was a different file thereby allowing you to differentiate them with ease.
We also implemented time - in which upon typing "time" or "what time is it" it displays the current time to the terminal.
Concerning the API, there were some concepts and stuffs which we were kind of happy to do away it. For instance, the syntax for controlling objects and characters were really confusing and required you to keep a record of what function you wanted for certain things eg do I want to use verbMatch: do:, verbHandler?, addRule: do:, indirectVerbMatch: and: do:, stepDo:? AAARRGGGGGHHHH!!!! The nightmare and the pain of it all was overwhelming - (drama added it really wasn't that bad, but it was bad enough).
So what did we do about it? Well, we basically, implemented what was suggested by other groups in the M6 Design. That is we made a behavior class called AGBehavior. And it has a 'rule:' and 'action:'. It totally revolutionalized the way rules were parsed. For example, do you want to redefine the way take works for say kitten? Make a new AGBehavior called take.
Its rule would be 'take &object' and its action would be [:player :me :world | world print: 'HIYA!']. And add it to the kitten AGObject and whala! You have it.
kitten addBehavior:newTake. (or whatever its called)
So now it you say 'take kitten' - the kitten /or should i say world will say HIYA!. Not so sure why you would want that but who cares.
What about a troll attacking you?
easy make an AGBehavior called attack. And its rule would be [:player :me :world | (player container) has: (world character:'troll')] and its action
[:player :me :world | "do whatever here "]. There it is! And just add it to the troll. That's it.
What about world addRule: do: ?
make a worldRulelook AGBehavior, rule:'examine &this' action:[:player :me :world | (me doVerb:'look')].
And add it to all the objects you would like to have this behavior - there.
Ok, what about stepDo for AGDaemon?
bombRule := AGBehavior named:'bombRule'
bomb rule:nil action:[:player :me :world | "what ever you want to do such as ticking and stuff"]
bomb addBehavior: bombRule.
to initialize the bomb, make rule:nil action:["initialize "]
what about speach?
leonspeach := AGBehavior named:'intelligience'
leonspeach rule:'tell me about your mother' action:[:player :me :world | world print:'my mother, let me tell you about my mother']
what about layering/containment?
putIn := AGBehavior named:'putIn'.
puton rule:'put the #object into the $box' action:[:player :me :world :indirect | (indirect name = 'box') ifTrue:[ indirect contain:me].
It really dosen't matter which one you pass in nil either rule or action cause the parser can handle either case.
What about if the behavior was not defined eg you did not define 'take' or 'drop' or 'look' ? No problem, the way we handled this was pretty cool. We created a Verb class where we have all these default behaviors created and each object/character when they get initialized/created also make an instance of the verb class. There is a function called "reinit" which gets called and it is here that these verbs get defined to their default behavior.
What if you redefined take? No problem, for each behavior you create and add to any given object, a search is made to see if the new behavior passed in matches any of those predefined and if so, the new behavior replaces them.
All these have made life easy for our parser. Now we only have to do 2 basic things upon receiving input from user:
1.) Checking if it was a behavior rule
2.) If false, check if it was a predefined verb.
No need for checking if it was an indirectVerbMatch or it was an addRule or a character Add rule or whatever.
The secret is as follows:
When a line is passed in to the parser. The parser goes through each word and for every word checks to see if its either in the players inventory or is in the room. If so, it adds it to an ordered collection.
It then checks the orderedCollection size, if it was 1, it means it was one of the predefined behaviors eg examine $object or something, if it is 2 then it means it was a layering or containment.
It then goes through the sentence passed in and whenever it say the name of any object which corresponded it skips it so for example the sentence:
put the knife into the table
put the into the
Recall that when the rule was created it was constructed as such:
put the #object into the !table
The rule when added to the object (in addBehavior) - checked and removed all words whose first letter was not of type ascii eg # or $ or ! etc.
so the rule added to the objects was
put the into the
Going back to the parser, it then takes the first object out of the
orderd collection and checks if it has the any rule matching the reconstructed string - put the into the.
If it does, it then evaluates it by saying value:player value:[(collection at: 1) - me] value:world value:[(collection at:2) - indirect]
Or it the collection size was one, it evaluates it by saying
value:player value:[(collection at:1) - me] value:world.
Last but not least, we also added, onRoomExits and onRoomEnters this was necessary to show our new feature in P6 which is elvis chasing you from the livingRoom into the next room to continue attacking you, OR Leon, leaving the kitchen and entering another room when you leave the kitchen.
so for example say that of kitchen...
kitchen onRoomExits:[:player :me :world | ((player getOldContainer) has:(world character:'Leon'))ifTrue:[ world print:'hahahah laughs Leon as he chases you into the other room'].
Leon changeContainer:(player container)
So as you can see from the above code, getOldContainer stores the players previous container
Characters can changeContainer so as to enable them to move to another room.
Ok, so we have a nice thing going but it still had some flaws. For example, behaviors have to be defined/created and added to EACH and EVERY object/character that had use of it. Imagine having 10 characters and defining 5 behaviors. Thats fifety times repitition of adding each behavior in the workspace to each character. REALLY REALLY TIRING!!!
I guess there are better ways to right the parser as well eg TGEN but for our purposes, this was not needed.
Other than the above and maybe one or two things i may have overlooked (can't really say that I did) I believe that our design/implementation was pretty impressive :).
NOTE - Here are pictures below:
In die.bmp - You are dead (DUH!!!) so you (toySoldier) lies down horizontally - thats why the stadium is sideways
In elivs.bmp - Elvis the troll is attacking you :)
In Leon.bmp - You are looking at Leon, notice how groucho looks kinda cool
In look.bmp - You are looking at the chair - an AGObject pretty cool eh?
In south.bmp - you just entered into a new room so you are looking around 360 degrees
In look.bmp - You just started the game and the world has rotated 360 degress around you
In table.bmp - You put the box on the table...nice pic :)
Here is our uml diagram...
Here are our documentations of our classes...
Last but not least our CRC cards...
Here are the requirements:
To see the story we came up, with click here:
The Sword of Varrock.doc
To see how we met the requirements, click here:
To see our UML...well, I guess you know where to click :) :
Link to this Page
Cases last edited on 30 July 2011 at 2:33 am by r59h132.res.gatech.edu