Thursday, October 21, 2010

Let's Make Us A Game! -- Working the Turkey

We're making a simple adventure game using the Inform 7 development language.  We've established a world, allowed the player to navigate it, and added some perspective and style.  But the game's purported objective is still not reachable -- the story can be explored, but not finished.  Our puppy hero cannot possibly obtain the family's turkey dinner, because it barely exists and never comes within his reach.

Way back at this series' beginning, I pounded out a quick turkey definition out as follows, as part of the Kitchen definition:

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

So let's see where we're at with a little playtesting.  There are bound to be some nasty surprises lurking in the details, even at this very early stage.
 
> smell scent
 
You can't see any such thing.
 
Whoops.  I have defined the turkey as an item, and for doggy-appropriate descriptive purposes I have referred to its scent.  That works fine from my perspective as the designer, but from the player's perspective there is only a scent in the room.  The player can't even refer to it as turkey without guessing, but the parser will only see it as turkey.
 
One way to solve this is to use a synonym, telling the interpreter to treat the word "scent" as if we're referring to the turkey:
 
    Understand "scent" as the turkey.
 
That solves the obvious problem, but now smell scent just returns You smell nothing unexpected, because we haven't defined a smell response for the scent or the turkey.

Game design often requires us to turn a problem into an opportunity -- there's a more natural and interesting way to approach this.  What if the scent leads Riley to discover the presence of the turkey, upon smelling the scent?  And scores a point?  Here's how we do that.  First, we remove the original turkey definition.  Then we add:
 
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!"


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


Of course, this introduces some complications.  If we remove the scent and replace it with the turkey, now we want to be able to smell the turkey. 

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

A little playtesting also reveals that Riley can, at present, carry the scent around before smelling it, in which case dropping it elsewhere results in a credibility-straining You can see a scent statement in its new location (in Inform 7, an item's initial description is always used in its first location, and is simplified after interaction; this generally supports storytelling by not boring the player with the richer description after some initial interaction has occurred.)  Riley can also take the turkey without so much as a by-your-leave, which will make this a very short game.  So we'll fix those things.

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]  Whoops!  Hi, Mom!"
 
We've escaped another potential problem here -- the scent has disappeared from the world after the player discovers its source, which doesn't quite make sense; it ought to stick around for sensory effect, even if its description is no longer appropriate.  But because we have told Inform 7 to understand "scent" as the turkey, and the in-game existence of the two items is mutually exclusive, everything actually works out.  When we smell scent while the scent is in the room, it becomes the turkey; smelling scent after that point actually smells the turkey, which is exactly the right effect.  We also can't smell the turkey before it exists, so the player can't cheat by using a priori knowledge (or miss scoring the associated point.) The only minor hiccup is that now take scent or eat scent will attempt taking the turkey, but Riley knows the scent is coming from the turkey now, so that doesn't seem inappropriately jarring.

That was a little more complicated than I expected.  Details do matter.  (And we have NOT solved another problem in the offing, which is that if Riley does succeed in obtaining the turkey, but drops it in the Kitchen, he will not be allowed to take it again!  We'll just note that for the moment.)


To finish our initial work here, we need to look at the turkey's function in the game.  In order for the player to win:
NEW -- The turkey must move from the Kitchen to the Dinner Table under official escort (i.e., Mom).
ALREADY WORKING -- The player must get onto the Dinner Table.
NEW -- The player must take the Turkey.
NEW -- The player must return to the Back Yard with the Turkey and enjoy it.

To move the turkey to the Dinner Table, we'll piggyback onto Mom's existing agenda, by adding a turkey countdown variable:

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

(within her agenda, when she heads back to the kitchen to start a new cycle)
        change the turkeycountdown of Mom to the turkeycountdown of Mom minus 1.

(and now recognize when the turkeycountdown has reached zero in Mom's moves from the Kitchen to the Dinner Table -- for clarity, we'll use one of Mom's so-far-unused agenda values to handle this, and we already have her programmed to be in the Dining Room when her agenda value is 5:)

    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!";


(for debugging at the moment, we'll modify Mom's conversation too)
Instead of talking Mom, say "Mom says, 'I'm feeling rather [agenda of Mom]-ish.'  She looks like the turkeycountdown is [turkeycountdown of Mom]."

We have ignored some subtleties for now -- the turkey is warping from the Kitchen to the Dining Room, without the player being able to tell that Mom is carrying it in between.  In fact, Mom will visibly leave the turkey in the Kitchen, yet magically put it on the Dinner Table a few turns later.  That simplifies our code, in that the turkey is never actually in the Hallway so we don't have to worry about further complications if Riley attempts to take it there.  But it's a bit of a cheat, and I suspect playtesting will force us to deal with this detail eventually.


Now, Riley is a very small puppy.  So let's surprise the player at the last minute by letting him take only a leg of the turkey.  That should still allow for a satisfying ending, without breaking reality overmuch.  It also makes it possible that Riley can hide the theft from Mom long enough to escape the house; last time, we established that he gets at most 5 turns on the table before Mom spots him and throws him back outside, so this fits comfortably within the limit.  We ultimately need to give him 5 turns' worth of activity to do, for challenge's sake, but let's keep it simple for now.  We'll define the turkey leg and modify the take turkey action as follows:

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."

 ...
     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:
            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;


To wrap up the story, we need to recognize that Riley has made it to the Back Yard with his prize and is chowing down, and award another point as we formally end the game:

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.  Who says it's a dog's life?";
        say "";
        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!".


Now our brief story has a happy ending.  But it's not much of a challenge, and there are several bugs both known and unknown.  For instance, the player can repeatedly take the turkey leg, earning a point for each try.  And if the player hasn't smelled the scent earlier, the turkey is still revealed at this point, AND the scent is still present in the kitchen.  So we should figure out a solution for that problem.  It also seems far too easy for Riley to get out of the house with his contraband turkey leg while Mom is patrolling the hallway on her usual rounds.

In the remainder of this series, following a Halloween break next week, we'll see if we can't add a few more puzzles to the mix, polish up the scoring, and with any luck wrap up the remaining issues in time for Thanksgiving.

The complete current source code is below the fold.





"Riley's Adventure" by GamingAfter40

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."

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 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 player is in the Hallway, say "Mom steps deftly over you as she enters the hallway.";
        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 player is on the Dinner Table:
            say "CAUGHT!  Mom enters the room and...";
            move player to the Back Yard;
        if the player is in the Hallway, say "Mom goes into the dining room.";
        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!";
    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]."

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!"

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."

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:
            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.

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.  Who says it's a dog's life?";
        say "";
        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."

The puppy door is a door.  The puppy door is south of the Back Yard and north of the Hallway.

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."

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."

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.

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."

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 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