Using tracked variables to customize the ending of a game.
last time, on let’s make IF…
You might be thinking: “Another episode already? Slow down!” I have another project to get to after this one, so I’m feeling some time pressures. You can read at your own pace, of course. These posts will be here when you’re ready.
In the last post, I talked about a number of player conveniences related to command abbreviations before moving on to a very basic means for ending the game with two empty text substitutions. It’s time to revisit the subject of endings, adding complexity and yet another table that authors can fill in with text to make the experience their own. You can catch up here:
the clicker.
If we look back at our action rules for card-picking, we can see that we added a mechanism for tracking which cards are picked:
a tarot has a number called clicker.
a clicker is usually zero.
carry out card-picking (this is the basic card-picking rule):
say "[a default fortune]";
increment the clicker of the noun;
increment the magic number;
now cnoun is the noun.
Every time the player chooses a card, its clicker will go up by one. We can use this value to decide outcomes in the game. Perhaps drawing a yellowc (“yellow card”) three times will have a specific effect. Perhaps specific mixtures of cards will lead to unique outcomes. It isn’t yet time to decide that, but, as the title suggests, the clickers do give us a way to decide on ways to end games. Before doing that, though, let’s add some tweaks to let player’s see how many cards have been drawn. First, let’s revisit the way the cards are printed as part of the room description.
A small metal table stands under the light. It is covered in gray, chipped paint. The following items rest atop it:
a red card
a blue card
a yellow card
an orange card
The cards are printed, as they would in any default project, in a list according to their printed names (‘the printed name of redc is “red card”). I think it would be best to display the clicker of each card here as part of the table description. We could change the printed name of the card to do this easily, since printed names are normal texts that we can vary and substitute as we wish. This is fine, for instance:
the printed name of redc is "red card [if the clicker of redc is not zero](times drawn: [clicker of redc])".
Whenever the name of rec prints, it will provide count information if it has been chosen before.
A challenge here is that printed names can appear unexpectedly in error messages or default responses, and seeing the count information might be jarring for players. Here’s an silly and unlikely possibility:
>red, hello
You can't talk to the red card (times drawn: 1).
There is another option: we could change the way the description of the table (and its contents) prints as part of the room description. We can start by making a very simple list using Inform 7’s built-in listmaking feature. Some day, when we’re all feeling brave, maybe I’ll write about customizing the way player inventories print! But we have a much simpler task before us, so I’ll try to keep things brief. Inform 7 will print the contents of the table automatically, but how can we manipulate that process?
Fortunately, “listing contents” is what Inform 7 calls an “activity,” and we have ways to determine when activities are and aren’t happening. We start by making a new rule.
rule for printing the name of a tarot (called the current card) while listing contents:
We need a clear way to reference the card in question while the activity is occurring. I chose “current card” because it makes sense to me. You can call it anything you like. By using the “while listing contents” designation, we’re telling Inform that this rule only applies while printing lists (like the contents of our table). We can now add the detail we need.
rule for printing the name of a tarot (called the current card) while listing contents:
say "[printed name of the current card][if the clicker of the current card is not zero] (times drawn: [clicker of the current card])".
This is very powerful! Using the [current card] designation, we can refer to any property or value associated with it. In this case, we use the clicker and printed name. This single rule will apply to every card, though we have to make sure we have printed names defined.
Note that Inform 7’s default behavior will print the [printed name] alone in all other cases, so there is no need to define a second case. However, if we did, the correct way to ask Inform 7 to determine the status of an activity is “going on” and “not going on”:
rule for printing the name of a tarot (called the current card) while listing contents is not going on:
Finally: this isn’t a game where players are scanning room descriptions for things to do, so let’s just reprint the room description after every card draw.
after card-picking when the magic number is not 9:
try looking.
deciding on endings.
I’m not ready to commit to how these endings will play out yet, but let’s frame something in. My idea is that if the player chooses six or more of one card, they will get a specific card-themed ending. Otherwise, they will get a generic “default” ending. We’ll use values for our endings.
an outcome is a kind of value.
In earlier posts, I defined values by listing them “the outcomes are good, bad, [etc]”. Let’s work out of a table instead. Our ending texts will be there, so shouldn’t we put everything in one place? Getting started is as simple as this:
the outcomes are defined by the table of concluding texts.
When we make this kind of declaration, we are committing to making a row for every possible “outcome.” The first entry in each row will be the specific outcome. We can store information related to each outcome in the same row. What should be there? Thinking of our last post, we will need an epitaph and a final blurb. That’s two columns. If a specific card is related to an ending, I want to store that as well. Here’s an idea:
table of concluding texts
outcome tarot tombstone epitaph
default -- "Default Blurb" "A default ending."
redE redc "Red Blurb" "A red ending."
blueE bluec "Blue Blurb" "A blue ending."
yellowE yellowc "Yellow Blurb" "A Yellow ending."
orangeE orangec "Orange Blurb" "An orange ending."
How can we pick an ending? I’ve already said that I want to choose endings based on the number of cards picked. Let’s try something simple, using a “to decide” definition.
to decide which outcome is the ending:
Note that I haven’t declared what an “ending” is elsewhere in the code. This definition is that declaration.
This should never come up unless we are messy and refer to endings mid-game, but let’s get something out of the way:
unless the magic number is nine:
decide on default;
As a reminder: the magic number increments when the player draws a card, and the game ends when the magic number is nine. There is no real need to set an “incomplete” ending value, as [if magic number is less than nine] already accounts for that. I’m only setting this because nature abhors a vacuum. If strange cases arise, we may have to be more diligent or set up some error-catching values.
In the meantime, we should ask Inform to check the clicker of every card. If one of them is above, let’s say… six, we’ll assign an ending based on that card. The magic phrase here is “repeat with x running through y“. In this construction, x is any nickname we choose to represent a single instance in the group or kind y. If we wanted to run through every thing in the game, we could say “repeat with item running through things”. “Item” is a term I picked. It has no built-in significance to Inform. “Things,” on the other hand, is meaningful. We use this phrase to evaluate all members of a group, one at a time.
Note that some things don’t work, like numbers. We can’t “running through numbers.” Many finite groupings will do: things, scenes, kinds thereof, and so forth (11.11 “Repeat Running Through”). In our case, we have previously made “tarot,” a kind of thing, that will serve our purposes. I’ll set a temporary placeholder value, [EC], where we can store our results.
let EC be nothing;
repeat with card running through tarots:
For each card, we simply need to check its clicker and, if it is greater than six, make a decision.
if the clicker of card is greater than six:
let EC be card;
choose row with a tarot of card from the table of concluding texts;
decide on outcome entry;
Here, one we find a number over six, we update the value of EC, then find our card in the table of concluding texts. The “outcome” we’ve defined there will be the ending. What if no match is found? We’ll include a fallback.
if EC is nothing:
decide on default;
Important: “to decide” phrases end immediately once a “decide on” phrase is reached. If it were possible to have multiple clickers over six, Inform would stop deciding after finding the first match. Be sure that your conditions are exclusive!
With that, we’ve decided on an ending. Let’s revisit our code from last time, incorporating our new table and logic.
after card-picking when the magic number is 9:
end the story finally saying "[the final blurb]".
to say the final blurb:
choose row with an outcome of the ending in the table of concluding texts;
say the tombstone entry.
when play ends:
choose row with an outcome of the ending in the table of concluding texts;
say the epitaph entry.
bonus!
I’ve been working on a template for customizing every built-in response within Inform 7’s standard rules. If you want to write your own, this is a good place to start! Other examples exist (Nathanael Nerode’s Neutral Standard Reponses is quite good), but this one explains how and why parser errors print, which can be very confusing for new authors (and experienced one’s, too!). I’ve made a new itch.io page for it. Have a look and let me know what you think! It’s a draft, so feedback is welcome.
https://kamin3ko.itch.io/default-reponses-template
next
As promised some posts ago, we are making our way to a design for a highly variable text. We currently have a basic framework for an eight-turn “game” involving four unique printable texts per turn as well as five unique endings. What else is there? Quite a bit, believe it or not. Next time, let’s take things in a surprising (I hope) direction.
One response to “let’s write IF #10: support for multiple endings”
-

[…] let’s write IF #10: support for multiple endings […]
LikeLike

Leave a comment