Flags don't work as intended

Dear all,
I am growing desperate over basic principles again. I want an icicle to melt after one turn when the room it or the player is in is warm. So i tried this:

When play begins:
        (...)
	A thing can be flagged or unflagged. A thing is usually unflagged.
	A room can be warm or cold. A room is usually cold.

(In the icicle code:)
Every turn:
	let umgebung be the location of the icicle;
	if the player is holding the icicle, now umgebung is the location of the player;
	if umgebung is warm:
		if the icicle is unflagged:
			now the icicle is flagged;
			say "The icicle starts to melt in your hands!";
			stop the action;
		if the icicle is flagged:
			now the icicle is in Dummyroom;
			say "The icicle melts in your hands!";
			stop the action;
	now the icicle is unflagged.

And although the icicle is “unflagged” before and after I walk into a warm room, it immediately melts in my hands. What’s the problem behind this?

Thanks and kind regards,
G.

I’m not in front of my computer so can’t immediately check this, but I’m pretty sure that what’s going on is that you’re trying to use “stop the action” to terminate an every turn rule. But by definition, by the time an every turn rule is running, the player’s action has finished. So that’s not doing anything, and as a result an unflagged icicle will trigger the first if statement, which flags it and therefore means it immediately trigger the second if statement.

If that’s the issue, turning the second if statement to an “otherwise if” should sort things out by making the two statements mutually exclusive.

You also need to clean up that last now the icicle is unflagged” statement since as written it’ll apply after the previous logic fires, meaning a flagged icicle will immediately get unflagged again. Hope this is helpful!

Edit: also, it looks like the icicle can melt even if the player isn’t holding it - like, if they drop it after it starts to melt - so you might want to tweak how melting is described.

Hrmpf. I’m still doing something wrong. :frowning:

Every turn:
	let umgebung be the location of the icicle;
	if the player is holding the icicle, now umgebung is the location of the player;
	if umgebung is warm:
		if the icicle is flagged:
			now the icicle is in Dummyroom;
			say "The icicle melts in your hands!";
		otherwise if the icicle is unflagged:
			now the icicle is flagged;
			say "The icicle starts to melt in your hands!".

Event 1 (“The icicle melts in your hands!”) is always triggered, although the icicle is definately unflagged. :frowning:

This seems to be working as intended:

"Melting"

A thing can be flagged or unflagged. A thing is usually unflagged.
A room can be warm or cold. A room is usually cold.

Every turn:
	let umgebung be the location of the icicle;
	if the player is holding the icicle, now umgebung is the location of the player;
	if umgebung is warm:
		if the icicle is flagged:
			now the icicle is in Dummyroom;
			say "The icicle melts in your hands!";
		otherwise if the icicle is unflagged:
			now the icicle is flagged;
			say "The icicle starts to melt in your hands!".

The outdoors are a cold room.
The indoors are north from the outdoors. The indoors are warm.

The player is carrying an icicle.

Dummyroom is a room.

outdoors

>n

indoors
The icicle starts to melt in your hands!

>z
Time passes.

The icicle melts in your hands!

>i
You are carrying nothing.

Are you sure you aren’t accidentally setting the icicle to be “flagged” somewhere else in your code? (You could try putting showme the icicle; at the beginning of the rule.)

2 Likes

I found the mistake… And it was simply a glitch I managed to include elsewhere in the code. Thanks for your time!!!

It’s actually the opposite of that. In an every turn rule, “stop the action” terminates the rule and the entire every-turn phase. This is usually a terrible idea because every-turn rules are supposed to be independent. You will be very sad later on when trying to figure out why half of them aren’t running any more.

(The every-turn phase isn’t an action, but the underlying I6 implementation is similar.)

There isn’t a built-in phrase for this case. You can define one though:

To stop the rule: (- rfalse; -) - in to only.

(There are several built-in phrases that do the same thing under the hood: “continue the action”, “continue the activity”, “make no decision”, “decide no”. But they’re all quite unintuitive in the context of an every-turn rule.)

2 Likes

Oh geez. Well I was totally wrong on what goes on underneath the hood but at least my incorrect understanding was similarly keeping me from doing this!

Random question: is there a reason to use a dummy room rather than nowhere?

Unsolicited suggestion: every boolean property is a flag, so the term “flagged” doesn’t convey any useful meaning. Something specific to the use case, like “melting/frozen”, would be clearer when reading the code.

When compiling for the Z-Machine, it can make sense to conserve on properties/attributes (leading to constructs like the general attribute in I6, whose explicit purpose is to be repurposed like that). When compiling for Glulx, I agree that readability should be preferred.

Interesting… Is compiling for the Z-machine to expand the audience or is it more of a demo scene kind of thing?

That said, it’s still an approach I’d recommend putting off until you actually start seeing memory issues. It’s much easier to change a bunch of things to “flagged/unflagged” than the other way around.

I have taken some habits with me from I6 to I7, is all. Using generic, multiply used flags to save on memory among them. I have two I6 games almost ready where I constantly need to watch memory capacities (especially regarding variables, forcing me to occasionally recode a few things on the fly) so I have sort of a trauma there.

1 Like

This just makes me more eager for the open source release of Inform. This is low hanging frurt for compiler optimizations. it should be able to figure out which flags are never used together on the same objects so they can share storage.

Well, from the perspective of a user (author/coder), the least thing I want is an atomization of versions. The scene is small, everyone (except for Zarf) needs support at least every now and then, and that’s already hard when there’s I6, I7, TADS, Adventuron, AGT, PunyInform, ZIL, Adrift and whatnot out there, plus some silverbacks from the late 18th century who still feel an itch to write a homebrew parser from scratch. A new fork of something doh help no-one. Better try and make the very best out of what’s there.

Youse talkin’ to me? Nuttin’ wrong wif scratchn itches. Yea? Best way t’learn, what sum profs sed.

1 Like

I’m not talking about forking, I mean being able to make improvements to the official compiler. Optimizations would be transparent to users except that more things might be able to run on older platforms without modification.