Thursday, November 25, 2010

Let's Make Us A Game! -- Fixing The Bugs

It's Thanksgiving Day!  And time to wrap our adventure game development series up with some finishing touches.  Our simple Riley's Adventure game is functionally complete -- it has a map, some objects, an independent character (Mom), a couple of puzzles, and a victory condition.  Riley can enter the house, get onto the dinner table when Mom isn't looking, steal a leg of turkey, and escape to enjoy his ill-gotten snack.

Our game also has a number of bugs and gameplay issues that we ought to fix before calling this project done.  As simple as this brief bit of interactive fiction is, it still has plenty of room for errors, inconsistencies and misleading player feedback.  So to finish this project off, I'm going to list the issues I have discovered (note that this is almost certainly not a comprehensive list!), and document the code additions and modifications required to address each of these problems.

* LEAVE PUDDLE and EXIT PUDDLE do not work, only GET OUT and EXIT.

This requires a little dictionary modification to recognize these verbs as applied to the puddle, because normally EXIT does not require or accept an object.  But the player might try to phrase it this way, so we'll adjust the parsing as follows:

Understand the commands "leave" and "exit" as something new.  Egressing is an action applying to one visible thing.   Understand "leave [container]" and "exit [container]" as egressing.  Instead of egressing something, try exiting.

* The player is told there's a tree in the backyard, but LOOK TREE produces "You can't see any such thing."

Inform handily understands the concept of scenery, for objects that can be referenced but not otherwise manipulated.  We'll add some description, and also foil any unnecessary attempts to climb the tree:

The tree is scenery in the Back Yard.  "A tall tree looms over the yard.  It's probably full of intriguing creatures you would enjoy barking at, if you could see them."

Instead of climbing the tree, say "Even the lowest branch is too high for you to reach with a jump.  And the bark is too vertical to climb."



* When we enter the puddle, we aren't immediately given a description to indicate the presence of the collar, which is the only reason the player needs to go into the puddle in the first place.

So we'll modify the puddle entry to mention it, if it's there: 

After entering the Mud Puddle:
    say "SPLASH!  Mud, glorious mud!  It squishes delightfully between your claws.";
    now the player is muddied;
    if your collar is in the mud puddle:
        say "Your collar is here, lying in the mud.  Now how did that happen?"

* Also, Riley can't see the collar until he's actually in the mud puddle.

So we'll expand the exterior perspective to hint that the player should investigate further:

Instead of examining the Mud Puddle:
    if the player is not inside the Mud Puddle:
        if your collar is in the mud puddle:
            say "Something is lying in the mud.  It seems familiar.";
        otherwise:
            say "It's full of mud."


* The Kitchen text mentions that the floor is always worth checking for treasure, but CHECK FLOOR produces "You can't see any such thing."

This is a quick fix:

The floor is scenery in the Kitchen. Instead of examining the floor, say "You sniff hopefully around the linoleum, but find nothing tasty at the moment."



* Navigation is unclear -- directions are not mentioned in room descriptions.

I meant to do this early on but never got back to it -- I drew the map myself, so of course I knew where everything was!  I expanded the room descriptions and modified the puppy door details to make it easier for the player to get his or her bearings.  See the complete source code below for these changes.

* Mom isn't seen to be doing anything in the Dining Room unless she's delivering the turkey.  If Riley is there to observe her, we should see her actively setting the table.

To handle this, we add a general case for when the turkey is NOT being delivered:

        otherwise:
            if the player is in the Dining Room, say "Mom puts something on the dinner table, but it doesn't smell interesting.";


* The player doesn't see Mom take the turkey from the Kitchen, or notice that she has it in the Hallway.


This requires some additional checking of the turkey countdown counter, to describe Mom's actions appropriately at this moment, based on the player's perspective.  See the complete source code for details, below.


* Mom's debugging output is still exposed.

While this was handy for testing during development, we don't want players to see Mom talking about her various timers and countdowns.  But just in case we need to explore this again, I'll comment out the old material and add something more appropriate:

Instead of talking Mom, say "Mom replies with your name, followed by some gibberish, followed by your name."





* Score is reported as "x of a possible 0" at the end of the game.

To fix this, we just need to define the maximum score, by adding:

The maximum score is 2.

* Riley can repeatedly GET TURKEY on the dinner table, earning a point each time for retrieving the same old turkey leg.

To fix this scoring bug, we can use Inform's concept of whether an object has been handled:

        otherwise:
            if the turkey leg has not been handled:
                say "You pull, and pull, and pull some more... and are rewarded with a turkey... leg!";
                move the the turkey leg to the player;
                award 1 point;
            otherwise:
                say "You already pulled off a turkey leg.  What did you do with it?"



* If Mom catches Riley on the dining room table, while he still has the turkey leg in his unconcealed possession, she throws him outside but doesn't take the turkey leg away from him.

To fix this, we'll send Riley outside but leave the turkey leg on the dinner table; apparently Mom is none too fastidious about these things, and it allows the player a retry.  We have to be careful with the phrasing, though, as the sequence of events actually moves the player visibly to the Back Yard before moving the turkey leg back to the dinner table.  So I'll write this so the player notices that the leg is gone after Riley is already back outside:

            if the player has the turkey leg and the turkey leg is not inside your collar:
                say "Gasp!  Your hard-won turkey leg is gone!";                move turkey leg to the dinner table;


* If Riley pulls on the turkey, "Nothing obvious happens."  It should act like getting the turkey, based on the result.

 Instead of pulling the turkey, try taking the turkey.




And with all this patching of known bugs in place, our work here is done.  The complete, final source code is below the fold.

RILEY'S ADVENTURE SOURCE CODE - INFORM 7


"Riley's Adventure" by GamingAfter40

The maximum score is 2.

Mom's Kitchen is a room. "This is where the magic happens. Strange and mysterious scents fill the air, and the floor is always worth checking for treasure.  A doorway to the north leads into the hallway."

The floor is scenery in the Kitchen.  Instead of examining the floor, say "You sniff hopefully around the linoleum, but find nothing tasty at the moment."

Mom is a female person. Mom is in the Kitchen. "[if Mom is in the kitchen]Mom is busy preparing dinner.[otherwise if Mom is in the Hallway]Mom is passing through the hallway.[otherwise if Mom is in the Dining Room][Mom action details]"

To say Mom action details:
    if the turkeycountdown of Mom is 0:
        say "Mom is putting... the... TURKEY!!!... on the table! ";
    otherwise:
        say "Mom is setting the table for dinner. "

Mom has a number called agenda. The agenda of Mom is 0.

Mom has a number called turkeycountdown.  The turkeycountdown of Mom is 1.

Every turn:
    change the agenda of Mom to the agenda of Mom plus 1;
    if the agenda of Mom is 2:
        if the player is in the Kitchen, say "Mom gives you a warning glance, and bustles out of the room.[if the turkeycountdown of Mom is 0]Hey -- she took the turkey with her!";
        if the player is in the Hallway, say "Mom steps deftly over you as she enters the hallway.[if the turkeycountdown of Mom is 0]She has the TURKEY!!!";
        move Mom to the Hallway;
    if the agenda of Mom is 4:
        if the player is in the Dining Room:
            if the player is not on the Dinner Table, say "Mom enters the room and gives you a suspicious glance, as if to ask what you are up to and answer at the same time.[if the turkeycountdown of Mom is 0]The lovely odor of turkey surrounds her.";
        if the player is on the Dinner Table:
            say "CAUGHT!  Mom enters the room and...";
            move player to the Back Yard;

            if the player has the turkey leg and the turkey leg is not inside your collar:
                say "Gasp!  Your hard-won turkey leg is gone!";
                move turkey leg to the dinner table;
        if the player is in the Hallway, say "Mom steps around you and enters the dining room.[if the turkeycountdown of Mom is 0]The delicious scent of turkey trails behind her.";
        move Mom to the Dining Room;
    if the agenda of Mom is 5:
        if the turkeycountdown of Mom is 0:
            move the turkey to the Dinner Table;
            change the turkeycountdown of Mom to -1;
            if the player is in the Dining Room, say "Mom just... she just put it on the dinner table!  Turkey is here!";
        otherwise:
            if the player is in the Dining Room, say "Mom puts something on the dinner table, but it doesn't smell interesting.";
    if the agenda of Mom is 6:
        if the player is in the Dining Room, say "Mom leaves the dining room.";
        if the player is in the Hallway, say "Mom enters the hallway.";
        move Mom to the Hallway;
    if the agenda of Mom is 8:
        if the player is in the Kitchen, say "Mom enters and quickly surveys the room to make sure you haven't gotten into any mischief.";
        if the player is in the Hallway, say "Mom goes into the kitchen.";
        move Mom to the Kitchen;
        change the agenda of Mom to 0;
        change the turkeycountdown of Mom to the turkeycountdown of Mom minus 1.


Barking is an action applying to nothing. Understand "bark" as barking.

Growling is an action applying to one thing.  Understand "growl [person]" and "growl [something]" and "growl at [person]" and "growl at [something]" as growling.

Instead of barking in the presence of Mom, say "Mom says, 'Shhhhh, Riley!'".

Instead of growling Mom: say "Mom says, 'RILEY! Outside!'  It's much like a magic word, isn't it?"; move player to the Back Yard.

Carry out barking:
    say "You bark merrily.".

Talking is an action applying to one thing. Understand "talk to [person]" and "talk to [something]" as talking. Understand "bark at [person]" and "bark at [something]" as talking.

Instead of talking something, say "It does not reply."

Instead of growling something, say "The [noun] ignores your direst threats."

[Instead of talking Mom, say "Mom says, 'I'm feeling rather [agenda of Mom]-ish.'  She looks like the turkeycountdown is [turkeycountdown of Mom]."]

Instead of talking Mom, say "Mom replies with your name, followed by some gibberish, followed by your name."

Understand "scent" as the turkey.

The scent is here. "One scent in particular stands out -- rich and juicy and tasty."

Instead of smelling the scent: Remove scent from play; award 1 point; move the turkey to the Kitchen; say "It's TURKEY!"

Your collar is a wearable container.  Your collar is in the mud puddle.  "Lying forlornly in the mud is your collar, lost during a particularly vigorous round of tail-chasing."  Understand "collar" as your collar.

Instead of examining your collar, say "Your collar was given to you a very long time ago.  It has a jingly thing on it.   When you have it on, you always get stuff caught in it. [if the turkey leg is contained in your collar]  Right now you have a turkey leg tucked into it, held safely beneath your chin."

Understand "tuck [something] in/into/under [something]" and "slip [something] in/into/under [something]" as inserting it into.

Before inserting the turkey leg into the collar, say "The tantalizing odor right under your chin makes the whole world seem bright and turkeyful.  You just... manage to... there!"

The turkey is a thing. "Tuuuurkey..."

The turkey leg is a thing.  "It's a fat, juicy thigh of turkey.  Not quite as good as a whole turkey, but a lot more portable."

Instead of smelling the turkey, say "It smells as delicious as anything you can imagine. Visions of giblets dance in your head."


Instead of pulling the turkey, try taking the turkey.
The scent is fixed in place.  Instead of taking the scent, say "You bite the air with gusto, but as tangible as this delicious odor seems, you can't actually take it."

Instead of taking the turkey:
    if the turkey is in the Kitchen, say "Mom has ensured that the turkey is safely out of your reach.";
    if the turkey is on the Dinner Table:
        say "You look around to make sure nobody's coming.";
        if Mom is in the Dining Room:
            say "Whoops!  Hi, Mom!";
        otherwise:
            if the turkey leg has not been handled:
                say "You pull, and pull, and pull some more... and are rewarded with a turkey... leg!";
                move the the turkey leg to the player;
                award 1 point;
            otherwise:
                say "You already pulled off a turkey leg.  What did you do with it?"

Instead of eating the turkey leg:
    if the player is in the Back Yard:
        say "You settle into the cool grass, place the turkey leg firmly between your paws, and bite.";
        say "[line break]";
        say "Who says it's a dog's life?";
        say "[line break]";
        say "CONGRATULATIONS!  You have finished Riley's Adventure!";
        award 1 point;
        end the story;
    otherwise:
        say "This is not a good place to dine... Mom could show up at any moment!".

The Hallway is north of the kitchen. "The hallway is often populated by feet and shoes coming and going, but it's quiet at the moment.  To the east is the room where the people gather at feeding time.  From the south comes a faint odor of something delicious.  To the north is a huge door, leading to the back yard."

The puppy door is a door.  The puppy door is south of the Back Yard and north of the Hallway.  "A smaller puppy door is built into the huge door."

Instead of opening the puppy door, say "You nudge the door gently, but it seems too heavy to move."

Instead of pushing the puppy door, try opening the puppy door.

Forcing is an action applying to one visible thing.  Understand "push [something] hard" as forcing.  Understand "push hard on/at [something]" as forcing.  Understand "force [something]" as forcing.  Understand "run at/through [something]" as forcing.

Instead of forcing the puppy door:
say "You hit the puppy door with all your might, and suddenly find yourself tumbling through to the other side!";
move player to the other side of the puppy door.

Instead of forcing something, try entering noun.  Instead of forcing direction, try ramming noun.

Ramming is an action applying to one visible thing.  Understand "ram [direction]" as ramming.  Understand "ram [something]" as entering.  Understand "run [direction] fast" and "run to [direction] fast" and "run fast [direction]" and "run fast to [direction]" and "run to [direction] fast" as ramming.

Carry out ramming:
    let the target item be the door noun from the location;
    let the target room be the room noun from the location;
    if the target room is a room and the target item is not a door:
        say "You travel [noun] with full puppy energy!";
        try going noun;
    if the target item is not a door and the target room is not a room:
        say "Your enthusiasm for beating your head against things is impressive, but unproductive.";
    if the target item is a door:
        try forcing the target item.

The Back Yard is north of the puppy door.  "The back yard is full of grass and bugs and the occasional squirrel. A large tree provides shade on hot summer days.  A huge door leads into the house to the south."

The tree is scenery in the Back Yard.  "A tall tree looms over the yard.  It's probably full of intriguing creatures you would enjoy barking at, if you could see them."

Instead of climbing the tree, say "Even the lowest branch is too high for you to reach with a jump.  And the bark is too vertical to climb."

The Mud Puddle is an enterable container.  The Mud Puddle is in the Back Yard.  "[if the player is not inside the Mud Puddle]A lovely puddle of mud remains from yesterday's rain."

Instead of examining the Mud Puddle:
    if the player is not inside the Mud Puddle:
        if your collar is in the mud puddle:
            say "Something is lying in the mud.  It seems familiar.";
        otherwise:
            say "It's full of mud."

A muddiness is a kind of value.  The muddinesses are clean and muddied.  The player has a muddiness.  The player is clean.

After entering the Mud Puddle:
    say "SPLASH!  Mud, glorious mud!  It squishes delightfully between your claws.";
    now the player is muddied;
    if your collar is in the mud puddle:
        say "Your collar is here, lying in the mud.  Now how did that happen?"

Understand the commands "leave" and "exit" as something new.  Egressing is an action applying to one visible thing.   Understand "leave [container]" and "exit [container]" as egressing.  Instead of egressing something, try exiting.

The paws are a thing.  The paws are part of the player.

Instead of examining the paws, say "Your paws are [if player is clean]sparkling clean.  Well, not sparkling.  But clean. [otherwise]gloriously filthy with mud."

Understand the commands "rub" and "wipe" and "clean" as something new.

Scraping is an action applying to one visible thing.  Understand "rub [something]" and "wipe [something]" and "scrape [something]" as scraping.

Washing is an action applying to one visible thing.  Understand "wash [something]" and "clean [something]" as washing.

Carry out washing: say "You lick at the [noun] ineffectively."

Carry out scraping: say "You can't scrape anything off of that."

Instead of washing the paws:
    say "You lick at your paws.[if player is muddied]But the mud is too thick to clean up this way."

Instead of scraping the paws:
    if the player is in the Back Yard:
        say "You wipe your paws on the grass.[if player is muddied]The mud comes off surprisingly neatly!";
        now the player is clean;
    if the player is inside the Mud Puddle:
        say "You wipe your paws in the mud.  Yep, still muddy!";
    if the player is not in the Back Yard and the player is not inside the Mud Puddle:
        say "You wipe your paws on the floor."

Every turn:
    if the player is in the Hallway:
        if the player is muddied:
            say "Uh-oh!  Mom enters the hallway, sees the mud all over your paws and sends you right back outside again!";
            move player to the Back Yard;
        if the player is clean:
            say "The hallway linoleum feels cool under your clean paws."

Every turn:
    if the player has the turkey leg and Mom can see the player and the turkey leg is not inside your collar:
        say "Mom spots the turkey leg held brazenly between your teeth, and before you can even look guilty you are tossed unceremoniously outside.  You paw at the locked puppy door, never to return, at least while the family dinner is in progress.";
        end the story.
         

After exiting from the Mud Puddle, say "You hop out of the mud puddle, dripping awesomely muddy water."

Instead of taking the Mud Puddle, say "You can probably take some mud with you, but picking the entire puddle up is beyond even your puppy powers."

Instead of examining the Mud Puddle, say "It's rich and thick and pungent, made of dirt and worms and everything else that is wonderful in this world."

The Dining Room is east of the hallway. "This is where the people eat. It is a sumptuous palace of steel and fabric, with chairs [if the player is not on the Dinner Table]rising high into the air.[otherwise]surrounding the table.  From up here you can see the whole dining room.[end if]  The hallway lies to the west."

The Dinner Table is an enterable supporter.  The Dinner Table can be climbed.  The Dinner Table is in the Dining Room. "[if the player is not on the Dinner Table]The dinner table dominates the room, overshadowing everything else with its promise of tasty past and future."

Instead of entering the Dinner Table when the player is not on the Dinner Table, say "Perhaps you could climb up there?"

Instead of climbing or entering the Dinner Table when the player is on the Dinner Table, say "You're already up here."

Instead of climbing the Dinner Table:
    if Mom is not in the Dining Room:
        say "You jump high, higher, and then clamber up onto the dinner table.";
        move player to the Dinner Table;
    if Mom is in the Dining Room:
        say "Mom's look says, 'Don't do it!'"

Instead of going down when the player is on the Dinner Table, try getting off the Dinner Table.

After getting off the dinner table, say "You hop off the dinner table, landing on the floor with a mighty (small) oof."

The player is in The Back Yard.





No comments:

Post a Comment