Scoping problem? Why doesn't this counter work all the time?

The fuse count is a number that varies. The fuse count is 0.
To count the fuses:
	let fuse count be 0;
	if the aqua fuse is in socket one, increment the fuse count;
	if the crimson fuse is in socket three, increment the fuse count;
	if the emerald fuse is in socket five, increment the fuse count;
	if the grey fuse is in socket seven, increment the fuse count;
	if the indigo fuse is in socket nine, increment the fuse count;
	if the khaki fuse is in socket eleven, increment the fuse count;
	say "in count the fuses: The fuse count is [fuse count].".
	
instead of examining the control panel:
	count the fuses;
	say "The control panel is [if fuse count is 6]lit up like a Christmas tree[otherwise]dark[end if]. [fuse count]";
	display the figure of ControlPanel.

this code produces the following output:

l at control panel
in count the fuses: The fuse count is 6.
The control panel is dark. 0

This feels like this is some sort of scoping problem. The fuse count is correct inside the “count the fuses” code. Why is the value zero after immediately exiting the code?

Help me Obi wan, You’re my only hope!

d.

I think indeed this might be an ambiguity issue with how you are scoping the words fuse count. You have created a local fuse count inside the routine you’ve created for To count the fuses, but you also have a number that varies called fuse count. You will likely have to disambiguate or connect the two.

By “connect” what I mean is to refer directly to the fuse count within the routine. Here, I am removing let fuse count be 0 because I can just refer to the global number that varies by that name.

Lab is a room.

The control panel is in the Lab.

Socket one, socket three, socket five, socket seven, socket nine, and socket eleven are containers in the Lab.

The aqua fuse is in socket one.
The crimson fuse is in socket three.
The emerald fuse is in socket five.
The grey fuse is in socket seven.
The indigo fuse is in socket nine.
The khaki fuse is in socket eleven.

The fuse count is a number that varies. The fuse count is 0.

To count the fuses:
	if the aqua fuse is in socket one, increment the fuse count;
	if the crimson fuse is in socket three, increment the fuse count;
	if the emerald fuse is in socket five, increment the fuse count;
	if the grey fuse is in socket seven, increment the fuse count;
	if the indigo fuse is in socket nine, increment the fuse count;
	if the khaki fuse is in socket eleven, increment the fuse count;
	say "in count the fuses: The fuse count is [fuse count].".
	
instead of examining the control panel:
	count the fuses;
	say "The control panel is [if fuse count is 6]lit up like a Christmas tree[otherwise]dark[end if]. [fuse count]";

Output:

Lab
You can see a control panel, Socket one (in which is an aqua fuse), socket three (in which is a crimson fuse), socket five (in which is an emerald fuse), socket seven (in which is a grey fuse), socket nine (in which is an indigo fuse) and socket eleven (in which is a khaki fuse) here.

>x control panel
in count the fuses: The fuse count is 6.
The control panel is lit up like a Christmas tree. 6

If you need a local variable inside the routine To count the fuses that is distinct from the global fuse count, then I would just suggest hyphenating the variable and using the hyphenated version of it there however it needs to be handled. Honestly, anything that would differentiate it from the number that varies called fuse count to reduce the likelihood of scoping issues.

4 Likes

thank you. i thought it must be something like that!

d.

Yeah, local variables shadow global variables, because it’s assumed the variable closer to where you’re using it is the one you want.

How about this?

To decide what number is the fuse count:
    let the counter be zero;
    if the aqua fuse is in [...] increment the counter;
    [...]
    decide on the counter.

Now there’s no global to worry about!

5 Likes

I was just typing a “to decide example” too! A benefit of having a general use number is that you can just write an item description rather than use an instead rule.

The description of the control panel is "There are presently [fuse count in words] fuses installed.";
4 Likes

In your original code it looks like you intended let the fuse count be 0 to assign 0 to the current value of the fuse count - but as several others have pointed out, let creates a new local variable instead of modifying anything. I think the line you probably wanted there was now the fuse count is 0.

Just because there’s a certain class of Inform author who loves doing everything in as declarative a style as possible, I should point out that you can also do this:

A fuse is a kind of thing. An aqua fuse, a crimson fuse, an emerald fuse, a grey fuse, an indigo fuse and a khaki fuse are fuses.

A fuse has a thing called the home.

Definition: a fuse is correctly situated if it is in its home.

The home of the aqua fuse is socket one.
The home of the crimson fuse is socket three.
The home of the emerald fuse is socket five.
The home of the grey fuse is socket seven.
The home of the indigo fuse is socket nine.
The home of the khaki fuse is socket eleven.
	
The description of the control panel is "The control panel is [if every fuse is correctly situated]lit up like a Christmas tree[otherwise]dark[end if].";
3 Likes

i had no idea. i’m just learning inform and there are still a few concepts i have to grok

I must point that if one put, say, the aqua fuse in socket one, then remove it and put it back again six times, the puzzle is solved NOT in its intended way. You should have also a rule which decrease the counter when the fuse is removed…

Best regards from Italy,
dott. Piergiorgio.

1 Like

I don’t believe that any of the solutions posted here have this problem. The fuse count is always reset to zero immediately before counting how many fuses are in the right sockets - none of the solutions use ongoing state-tracking.

My example solution actually does have this problem if it is used verbatim.

>x control panel
in count the fuses: The fuse count is 6.
The control panel is lit up like a Christmas tree. 6
>x control panel
in count the fuses: The fuse count is 12.
The control panel is dark. 12

Thus, @Piergiorgio_d_errico is correct. Either the count needs to be decremented, or, alternatively as I said in my reply, you can create a distinct and unambiguous local variable that is initialized to 0, and then at the end of the routine, have that set to the number that varies.

let c be 0;
...
...[increment c]...
...
now fuse count is c;

Or, the usage of To decide phrases as demonstrated elsewhere would also not require the global and would not have this problem. Or, setting/resetting fuse count to 0 when examining the control panel prior to counting the fuses.

Adam,

IIRC, this is a variable setting, not resetting, but

This is what you actually means. So, I suggest to john to put the “let the fuse count be 0” suggested by Daniel at the very beginning of his rule (“To count the fuses”).

Best regards from Italy,
dott. Piergiorgio.

Right, I was misled by suggesting that you could bypass the puzzle by inserting and removing the aqua fuse six times. I don’t believe that that will actually do anything - however, inserting one fuse and then examining the control panel six times would cause it to light up, which is possibly even worse.

Wouldn’t that give you the same code as in the OP? If you’re using the fuse count is a number that varies then you have to say now the fuse count is 0 rather than the subtly different let the fuse count be 0.