Outputting varied text based on an accumulating score?

Hi there,

Working in Inform 7 and a bit stumped on how to do something. I’ve got a score that accumulates in points as the player does various actions, and I’d like events to take place in the narrative as that score reaches particular milestones.

ie; one point - say “hello”, four points - say “You are accumulating points”

I’m reading through the “Day One” example which seems to accomplish what I need - an advancing series of events - but I’m stumped on bending this example to instead trigger events on an increasing counter.

I have a table with the “trigger” amount and the text; any advice for going the rest of the way?

Maybe something like this?

Table of Score Messages
Designated Score (a number)	Message (a text)
1	"Hello!"
4	"You are accumulating points!"
10	"Now you have ten points!"


Every turn:
	Repeat through the Table of Score Messages:
		if the Designated Score entry is the score:
			say the Message entry;
			blank out the whole row;
			rule succeeds.

(It seems like there is a standard “[Your score has just gone up by one point.]” message when the score increases–this doesn’t affect that message.)

1 Like

This can be done a few ways depending on what you are trying to accomplish. Here is an example of how this can be achieved through an every turn rule:

Use scoring.

Every turn:
	if the score is 1:
		say "You have 1 point";
	otherwise if the score is 2:
		say "You have 2 points";

If you are trying to change how things appear or what people say depending on the score, then you will want to use this conditional (if the score is x) within the description of those items or in the dialog of those characters. As well you can use the score to start scenes, here’s an example.

Use scoring.

Congratulate is a scene. Congratulate begins when the score is 1.

When congratulate begins:
	say "You have 1 point";
1 Like

or…

Lab is a room.
the-score is initially zero.
instead of jumping: increment the-score.

Table of Score Messages
Designated Score (a number)	Message (a text)
1	"Hello!"
4	"You are accumulating points!"
10	"Now you have ten points!"

Every turn:
  if the-score is a designated score listed in the Table of Score Messages, say the message entry.

test me with "jump / jump / jump / jump"

Or… (it’s not shorter, but it reads somewhat nicely)

Lab is a room.
the-score is initially zero.
instead of jumping: increment the-score.
announcing is a number based rulebook.

announcing 1: say "Hello!".
announcing 4: say "You are accumulating points!".
announcing 10: say "Now you have ten points!".

this is the announcing stage rule: follow the announcing rules for the-score.
The announcing stage rule is listed before the every turn stage rule in the turn sequence rules.

test me with "jump / jump / jump / jump"

I used the-score 'cause it seemed marginally easier than doing Use scoring but then deactivating the notify score changes rule.

3 Likes

This illustrates neatly how rulebooks can operate similarly to ‘switch’ statements, where the variable to be switched on is the basis of the rulebook (I have always assumed that this is why Inform 7’s switch syntax:

if <variable of kind K> is:
    -- <constant 1 of kind K>: <phrase>
    -- <constant 2 of kind K>: <phrase>
... -- <constant n of kind K>: <phrase>
   [-- otherwise: <phrase>]

is so limited- you’re supposed to make rulebooks for anything more complex).

But here’s a problem. The rules of a rulebook act on a description of the basis of that rulebook. So for the example given above, a description of numbers. Which is fine for constant values such as 1 or 5 or 10. Or even for adjectives defined by a calculation:

Definition: A number (called the candidate-prime) is prime rather than composite if:
	if the candidate-prime is 2:
		decide yes;
	if the candidate-prime is even or the candidate-prime is at most 1:
		decide no;
	let n be 3;
	while 1 is 1:
		if the candidate-prime is less than n multiplied by n:
			break;
		if the remainder after dividing the candidate-prime by n is 0:
			decide no;
		now n is n plus 2;
	decide yes.
Announcing prime: say "You are truly a prime candidate!".
Announcing a composite number: say "You are truly a divisive candidate!"

note that we can use just the adjective, or specify both the adjective and the base

We can use ‘which’ to extend this, applying either a named adjective, or a condition which is applied to the base value but which is not a named adjective:

Announcing a number which is prime: say "You are truly a prime candidate!".
Announcing a number which is at least 7: say "Now we're really cooking!"

The constraint with using ‘which’ is that it can only be followed by a single simple condition, i.e. we can’t construct complex conditions using ‘and’ or ‘or’

The way round that is to use ‘when’, which can be used with complex conditions:

Announcing a number (called n) when n is at least 7 and n is at most 15: say "Moving up through the gears!".

but even by I7’s standards this is rather longwinded (and not particularly literate) compared to the equivalent line of an I6 switch statement, which would be:*

	7 to 15: print "Moving up through the gears!";

We can start to improve things by using the knowledge that the parameter of a value-based rulebook is always held in the I6 variable parameter_object - this is true even when the rulebook is not based on an object but, for example as here, a number. We can expose this I6 variable to I7 by:

To decide which number is po: (- parameter_object -).

Armed with this, we can dispense with the a number (called n) part of the rule:

Announcing when po is at least 7 and po is at most 15: say "Moving up through the gears!".

It can be seen from this that the effect of a number (called n) was to assign parameter_object to n. We no longer need that, because we have separately told Inform to always read ‘po’ as the number held in the I6 variable parameter_object.

This is definitely an improvement, but we really want to be able to write 7 to 15 rather than that longwinded po is at least 7 and po is at most 15. Unfortunately trying to implement 7 to 15 or 7 - 15 both confuse the I7 compiler because they cause an overlap with existing phrase definitions. But we can do this:

To decide whether (lo - a number) -> (hi - a number): if po is at least lo and po is at most hi, yes.

after which this works:

Announcing when 7 -> 15: say "Now we're really cooking!".

Similarly, we can succinctly implement the ‘list’ version of an I6 switch statement:

	3, 5, 11: print "You're one of the chosen ones!";

in I7:

To decide whether in (L - a list of numbers): if po is listed in L, yes.
Announcing when in {3, 5, 11}: say "You're one of the chosen ones!"

We can also use ‘or’ or ‘and’ to include several conditions in the preamble of one rule:

Announcing when in {1, 3, 6} or 9 -> 12 or in {12, 17, 21}: say "A random number!".

It would be nice to just be able to write

Announcing 7 -> 15: ...

etc. but I can’t see any way of doing that, because only named adjectives can be used in that way, and declarations of named adjectives can’t have parameters other than the value they apply to. So we can write:

Definition: a number (called n) is divisible by 3 if the remainder after dividing n by 3 is 0.

but not

Definition: a number (called n) is divisible by a number (called d) if the remainder after dividing n by d is 0.
  • small print The I6 → Inter compiler used for ‘Include’ statements is more limited in regard to switch statements than the I6 compiler that ultimately produces a story file, in that the former doesn’t recognise conditions in the form ‘x to y’, so that even if writing directly in I6 these can’t be used by switch statements within ‘Include’ segments
2 Likes