Better scoring code

In the game i’m writing the explorer has to collect various items and put them into the toy chest. I was trying to find something that would trigger on “when the chest contents change, run through the scoring routine…”. Instead, I landed on an “every turn” loop to update the scoring, which just feels crazy inefficient.

Every turn:
	now the score is 0;
	repeat with toy running through things enclosed by The Toy Chest:
		if toy is not inside a closed container:
			let toy_name be the printed name of toy;
			if toy_name is a Treasure listed in the Table of Point Values:
				increase the score by the Points corresponding to a Treasure of toy_name in the Table of Point Values;
	if the score is 100:
		say "Congratulations. You have recovered all of the family treaures!";
		end the story.

Check out the documentation regarding scoring:
Manual: 9.2. Awarding points
Recipe book: 11.4. Scoring

You shouldn’t need to reset and recalculate the score manually as this is built into Inform 7.


Use scoring.

A prize is a kind of thing. A prize has a number called worth.

Laboratory is a room. 

A stuffed bear is a prize in laboratory. The worth is 10.
A bouncy ball is a prize in laboratory. The worth is 5.
A squirt gun is a prize in laboratory. The worth is 5.
Some scissors are in laboratory. The indefinite article is "a pair of".
Some styrofoam is in laboratory.

A toy chest is a container in Laboratory.

After inserting a prize into the toy chest:
	increase the score by the worth of the noun;
	say "Whoohoo!";
	if the score is 20:
		end the story saying "You've cleaned up all the toys!";

First carry out taking a prize:
	if the noun is in toy chest:
		decrease the score by the worth of the noun;
		say "Awww, that's not what you're supposed to do."

Check inserting scissors into the toy chest:
	say "Scissors are not toys." instead.
1 Like

As @HanonO said, Inform does check for this behind the scenes.

In the (slightly old) version of Standard Rules, I see the lines

The notify score changes rule is listed last in the turn sequence rulebook. [Last.]

This is the notify score changes rule:
	if the score is not the last notified score:
		issue score notification message;
		now the last notified score is the score;

What this means is, Inform may process it more than once, but it’s not a big deal in terms of processing time, since it’s just one if-then statement, and it isn’t doing anything complex like seeing if you can see an item.

So it should be there, but if not, there’s a workaround, and I was surprised how simple it was! This may be a tangent, but hopefully it helps you feel agency being able to adjust score-checking as needed.

I had a case in one game where a player got a point if they performed an action, but it didn’t cause a turn to go forward, according to Inform, because I caught it in the parser error rules.

The big example is probably if you have a code word and want to check if it is in the player’s command. You can also check in the “After reading a command” rules.

after reading a command:
	if the player's command includes "booyah":
		say "Cooler than the other side of the pillow, you drop an incontrovertibly authoritative and decisive booyah.";
		increment the score;
		reject the player's command;

This doesn’t display a score change without follow/consider/process the notify score changes rule; (Also, it gives points repeatedly. Blocking this is an exercise for the reader.)

Another example would be an (admittedly odd) tutorial where you got a point for requesting the score for the first time or using “mistake” syntax, e.g.


understand "xyzzy" as a mistake ("OK, have a point.[point-up]")

to say point-up:
    increment the score;
    follow the notify score changes rule; [this creates extra line break problems, but you get the idea]

This is great, but i’m hitting a roadblock. The snippet works perfectly in a new project, but when i weave it into my project, the decrease part never gets called. Is there a specific place in the code this needs to be? My project has been growing in size, so i’ve been organizing it, but the order that things need to be in hasn’t sunk in, yet.

In this case, the order of the source code shouldn’t matter unless you have added another “first taking” rule. (In that case, the last one declared as first will become the first rule checked and the previous “first rule” will be bumped to second.) It’s more likely that you’ve added something in a before stage or used instead somewhere to preempt this rule.

The easiest way to troubleshoot these kinds of things is to use rules tracing: run the game and type “rules” at the command prompt. You will then see which rules are firing when your actions are executed. You can also try “rules all” which additionally shows rules that don’t apply and were therefore skipped.

Edited to add: this is really only helpful for named rules, which is just another reason why we should name them. (I always do this when coding for myself, but usually don’t bother when giving a quick example here.)


Thanks! I was able to track it down with this. Everything is working as expected.

1 Like