Every third turn?

I’m writing a short work of interactive fiction, and all is well so far, except that I need the message “Your shoulder hurts.” to come up every three turns. Every turn is easy, but I can’t seem to find a way to get every third turn to work.
Any help would be much appreciated :slight_smile:
p.s. I’m using Inform 7.

Try this:

Every turn when the remainder after dividing the turn count by 3 is 0: say "Your shoulder hurts."

1 Like

Another way:

At the time when shoulder hurts:
	say "Your shoulder hurts.";
	shoulder hurts in two turns from now.

Then repeat the last line within a rule or phrase to get the message to start appearing.

I’ve used this method, but there’s something unsatisfying about it for me. Correct me if I’m wrong, but I don’t think you can add additional conditions to “at the time when…”, so instead of saying:

Every third turn when the shoulder is injured:

You have to say:

At the time when the shoulder hurts: if the shoulder is injured:
…which offends my sensibilities by adding too much nesting. Maybe referring to the turn count would be a way around that, but referring to the turn count also offends my sensibilities by using a global variable, and by being wordy. I’ve often considered using this instead, even though it doesn’t do the same thing:

Every turn when the shoulder is injured and a random chance of 1 in 3 succeeds:

Does that compile? Is it OK to use “random” in a rule condition?

Randomness issues aside, that should work-- although IMHO, trying to avoid using global variables in Inform 7 is like trying to write a novel in English without using the letter “e.” Possible, but masochistic.

I’m not against it all the way. I think global variables are good for representing game state - a little more fine-grained than scenes but a little broader than properties of the PC. I accept things like “the noun” as useful for parsing - after all, pretty much every scope you encounter can need access to the player’s command. I’m a little uncomfortable with a few other globals (like the current row), but I can accept their use.

After getting more comfortable with OO, I don’t really think of any variables as global. Some “global” variables have a scope of the whole story, some have a scope of the current turn, the current rulebook, the player’s command, or the current action. Generally there’s no danger of scope conflicts in those cases.

But the case of the turn count seems unnecessary somehow. Maybe what bugs me is that it has a scope that goes beyond the story - it’s “out of world.” It’s not a story variable, it’s a game variable.

I don’t see the point of avoiding global variables in I7 when nearly everything has global scope. Objects, classes, rules, rulebooks, relations, and so on are all global.

I typically have a “cycler” kind lying around, so that I can say

The arm-hurt-cycler is a cycler. The period is 3.

Every turn when current arm-hurt-cycler is 1:
    ...

You can define the “cycler” kind and the “current (C - cycler)” phrase in a few lines – it’s not even worth posting them. (The phrase just returns 1, 2, 3, 1, 2, 3,… as it’s called. Very simple.)

I’ve just taken a global-variable example and replaced it with a global object (that carries a numeric property). It’s not really any prettier from a code-management standpoint. The sole difference is that it’s easy to read in use, and that’s all I care about.

I would use Juhana’s solution. Every turn when the shoulder is injured and the remainder after dividing the turn count by three is zero, say "Your shoulder hurts."

Yeah, I guess that’s the best, unless you have a particular turn on which you want the messages to start. I might make it briefer by adding this [not tested because my Mac is in the shop]:

To decide whether the turn is a multiple of (N - a number): Decide on whether or not the remainder after dividing the turn count by N is zero

I’m afraid that what is obvious to Zarf is not obvious to everyone. I’m not 100% sure how the cycler kind would work, but it sounds like a useful idea.

It would be nice if there were a “turns since X” phrase, similar to “has been X for N turns”. Or maybe “has been X for a multiple of N turns” instead of “has been X for exactly N turns”. Is there anything like that?

The idea, as I understand it, is that you have an object that has a number associated with it. Every time you look to see what that number is, it automatically increases by one, until it loops back around again. Following zarf’s terminology, here’s one implementation of a cycler object.

[code]A cycler is a kind. A cycler has a number called period. A cycler has a number called current-cycle. The period of a cycler is usually 2. The current-cycle of a cycler is usually 0.

To decide what number is current (C - cycler):
increment the current-cycle of C;
if the current-cycle of C is greater than the period of C, now the current-cycle of C is 1;
decide on the current-cycle of C.[/code]

You can then use zarf’s code to have the message appear every third turn.

Sarge is ahead of me, I see. Yes, that’s what I use, probably word-for-word. Thanks.

Oh, okay. I was expecting some cryptic I6 wizardry or something I guess.

That gives me an idea, though… you could have a table-based cycler, wouldn’t that be fun…

The player has a number called shoulder-pain. The shoulder-pain of the player is 0.

Every turn while the shoulder is injured:
   increase the shoulder-pain of the player by 1;
   if the shoulder-pain of the player is greater than 2:
     say "Your shoulder hurts.";
     now the shoulder-pain of the player is 0.

Or, or, we could use scenes!

[code]A person is either injured or uninjured.

Agony is a recurring scene. Agony begins when the player is injured. Agony ends when the time since Agony began is 3 minutes.

When Agony begins:
say “Your shoulder hurts.”
[/code]

(Okay, I actually use something more like tggdan’s solution.)

That’s definitely my favorite one so far.

Can you use “the time since [a scene] began” anywhere?

I am probably misunderstanding something, because my read on this is that it results in the ‘shoulder hurts’ message only being printed once per injury. How is the loop engaged? What am I missing?

Paul.

It works because the scene’s start-condition, “the player is injured”, remains true.

It took me a while to get my head around it too. A recurring scene will start again immediately after it ends if its start condition is still true.

Yeeeesss, although I haven’t tested recurring scenes much beyond this, so I’m not sure what happens if you’ve got, say, something that fires 20 turns after Agony starts - in this instance, would it fire every three turns starting 20 turns from the injury, or just 20 turns after the end of the latest scene?

Actually, I should go test that.