top expert

a biting cat website

more goal-tracking: improvements and additions

In a complex game–perhaps even in a simple one–it is kind to help the player keep track of their current objectives. Sometimes figuring out what to do next is part of a game’s design–part of the fun–but when that isn’t the case, it might be best to just come out and say what it is.

As a reminder: this blog documents my experiences with Inform 7 as a beginning author. If you are new to Inform 7, we can hopefully all make progress together. Inform is for everyone!

If I find problems in testing, I’ll report them in the next post.

having thought about it….

Since I’ve had some time to think about my code from last time, I have some thoughts:

  • should this be rolled into an already existing “after” rule for updating the player’s score?
  • should there be error messages for weird conditions (multiple table matches, perhaps)
  • do I really want to have multiple definitions invoked by made up actions without grammar?

My answers, after kicking it around, are yes, no, and no. I want to use one rule that can keep things in sequence while remaining highly readable. I think error messages are overkill for this situation, but I’ll share a method in case anyone is interested. The big design change from last time is getting way from manually updating goals, instead automating checks and updates after every action.

In today’s post, I’ll use definitions to both update the score and evaluate goals. This will leave us with a clean-looking “after” rule. We can use those same definitions to “control-f” if we need a closer look at something. Under this model, I’ll first make a definition for updating the score (this is mostly identical to code I wrote last time).

To assess the score:
	let CA be the current action;
	repeat through Table of Demerits: [this code is almost directly copied from the "Bosch" example]
		if CA is the action performed entry and turn stamp entry is less than 0:
			now the turn stamp entry is the turn count;
			decrease the score by the point value entry;
			now score change is true.

The only new thing here is the “now score change is true.” I’m adding a truth state that I can use to check at the end of the turn (an “every turn rule,” since those fall at the end of action processing). Once everything else is done, I’ll work on that.

Next, I’ll move my goal-setting code into a new definition:

to assess the current goal:
	let CA be the current action;
	if there is an inciting act of the CA in the table of high-level goals:
		choose row with an inciting act of the CA in the table of high-level goals;
		if completed entry is less than zero:
			let the old goal be the big picture objective of the player;
			choose row with a big picture objective of the old goal from the table of high-level goals;
			now the completed entry is the turn count;
			choose row with an inciting act of CA from the table of high-level goals;
			now the initiated entry is the turn count;
			now the big picture objective of the player is the big picture objective entry;
			now goal change is true.

This has been tweaked a bit, now that it is running after every action. Last time, I was manually invoking this update after specific actions, but the basic principle is the same: check the current action against a table and update values as needed. Here’s how things have turned out:

After doing something (this is the character sheet rule):
	assess the score;
	assess the current goal;
	assess the task list; [see below for details]
	continue the action.

What is the benefit of this approach, rather than keeping all the code in a single chunk? I think having separate definitions makes for easier reading. It’s also easier to add and manage debug phrases if needed. Having one rule guarantees that my checks will run in a specific order, which may become important. On the other hand, if I want to break this code apart, the work is already done.

I did say I’d look into a check for redundant entries in my goal-setting table. It wouldn’t be too hard to set up a counter that increments every time a match is found. I think it’s overkill, adding unwanted complexity.

	let unique entries be 0;
	if there is an inciting act of the CA in the table of high-level goals:
		repeat through the table of high-level goals:
			if inciting act entry is CA:
				increment unique entries;
		if unique entries is greater than 1:
			say "Oh, my, the author has left duplicate entries in the table of high-level goals! How embarrassing. Please be so kind as to let him know.";

Here, we’re just running through the table, incrementing a value for every hit we find against the current action. If that value is greater than one at the end of that process, the code will print an error message. Again, I’m not doing this, as it feels needlessly complicated for a modest table like this one. Still, for reference, it’s a fairly easy way to check for redundant values, even adding printed text or error reporting if needed.

what about smaller tasks.

Things are moving along! We have a big rule that checks the current action against two tables to update score and broad player objectives. But what about individual tasks needed to complete an objective?

Maintaining a task list will be more complicated. While the player can only have one big goal, there can be multiple tasks required for achieving it. I won’t be able to use a value assigned to the player, nor will I be able to readily drop one and add another in-sequence. I’ll start with this:

task status is a kind of value.
the task statuses are undiscovered, actionable, and complete.

I’ll make a table–as similar as possible to my goal-tracking one, but with a few added columns. I could handle my task status value with the initiated and completed values, but I think it will be nice to just use one value and evaluation when it’s enough.

table of to-do items
task	inciting act	concluding act	task status	initiated	completed	original order
"Pass through the plain wooden door"	thief looking	thief reaching the hallway	actionable	1	-1	1

What’s new or different?

  • task: a printed text that will display while the task is active.
  • inciting act: the action that will make a task actionable (I use “thief looking” to avoid having an empty row when play begins).
  • concluding act: the action that will make a task complete.
  • task status: current task status value (as above).
  • initiated: a turn count for when the task is discovered. This is tracked in the table of goals, but here it can do double-duty as a sortable value.
  • completed: a turn count for when the task is completed (also can be used for sorting).
  • original order: This is probably not needed, but since I might be sorting the table, it’s good to have a way back.

The possibility of having multiple tasks coming and going all the time, plus future needs for displaying the information, makes this a more complex endeavor! Since I am already putting definitions into a single “after rule,” I’ll start out with a new definition. Bear with me, I’m working this out as I go.

to assess the task list:
	let CA be the current action;

How to proceed? It’s possible that multiple tasks will spawn from a single action, so the usual “choose row with a inciting act of the current action from the table of to-do items” won’t work. That simply selects the first matching row (running from row 1), then stops the search. We’ll need to check every row, since we may have multiple matches. We’ve run through tables before.

	repeat through the table of to-do items:
		if the inciting act entry is CA:
			if the task status entry is undiscovered:

Note that inciting act (stored action) and task status (value) are not comparable, so I’ve nested one “if” phrase atop another. If both apply, we’ll have a to-do item that is ready to start yet hasn’t started yet. We’ll update some information both inside and outside of the table:

				now the task status entry is actionable;
				now the initiated entry is the turn count;
				now task change is true;

In this way, we can catch all matching entries. Note that there is another truth state update, “task change.” Marking tasks complete is really just more of the same. Here’s the full definition:

to assess the task list:
	let CA be the current action;
	repeat through the table of to-do items:
		if the inciting act entry is CA:
			if the task status entry is undiscovered:
				now the task status entry is actionable;
				now the initiated entry is the turn count;
				now task change is true;
	repeat through the table of to-do items:
		if the concluding act entry is CA:
			if the task status entry is actionable:
				now the task status entry is complete;
				now the completed entry is the turn count;
				now task change is true.

I can put that into my character sheet rule, too. As promised, the need to read every table row, coming and going, makes for the longest and most complex definition of the bunch. But the way here taught us a lot, and we are relaying on familiar techniques.

There are two things left. I think it would be nice to let the player know when a goal or task has updated. I’ll check that in an “every turn” rule, since those fire at the very end of action processing. All of my checks and updates will already be complete. The rule will review these truth states, and give feedback as needed.

last every turn when goal change is true or task change is true (this is the status notification rule):
		say "A task or goal has changed. For more information, review your *STATUS*";
		now score change is false;
		now goal change is false;
		now task change is false.

I have this as “last” at the moment, so that it prints after other “every turn” texts. Adjustments might come later. Since the project currently uses Inform 7’s built-in score notification, I won’t do anything with that specific truth state. For now, anyway. If score notifications and status notifications make for an on-screen jumble, I may want to handle score reports manually. If so, I’ll do that here, in this rule.

But what about this *STATUS* command that I’ve mentioned? Well, it’s no use tracking this stuff if the player can’t check it! I’ll hopefully close the books on goal tracking next time with a new action and some final thoughts and warnings.

Next

A final look at goals and tasks, then a last (for now) look at scenes.

Categories: , , ,

Leave a comment