Having trouble with list equality

So I have the following little puzzle:

Zeldaesque Puzzle Room is a room. "You're almost at the triforce!"

A puzzle lock is a fixed in place container in the Zeldaesque Puzzle Room. 
"In the wall is a series of three sockets.[if anything is in the puzzle lock] In them, from left, are [gem order with indefinite articles].[end if]". 
Understand "socket/sockets" as the puzzle lock.

A gem is a kind of thing. A blue gem, a red gem, and a yellow gem are gems in the Zeldaesque Puzzle Room.

The gem order is a list of gems that varies. The gem order is initially {}.

After inserting a gem into the puzzle lock:
	say "You slide [the noun] into the leftmost open socket in the wall.";
	add the noun to the gem order;
	if the gem order is {the red gem, the yellow gem, the blue gem}:
		end the story saying "The wall slides open! Victory over Ganon is at hand!";
	otherwise if the number of entries in the gem order is three:
		say "DEBUG: the gem order is [the gem order in brace notation]";
		end the story saying "Nothing happens. Uh oh..."

Unfortunately, this doesn’t work:

Zeldaesque Puzzle Room
You’re almost at the triforce!
In the wall is a series of three sockets.
You can also see a blue gem, a red gem and a yellow gem here.

> put red in socket
(first taking the red gem)
You slide the red gem into the leftmost open socket in the wall.

> put yellow in socket
(first taking the yellow gem)
You slide the yellow gem into the leftmost open socket in the wall.

> l
Zeldaesque Puzzle Room
You’re almost at the triforce!
In the wall is a series of three sockets. In them, from left, are a red gem and a yellow gem.
You can also see a blue gem here.

> put blue in socket
(first taking the blue gem)
You slide the blue gem into the leftmost open socket in the wall.
DEBUG: the gem order is {582015, 582047, 581983}
****** Nothing happens. Uh oh… ******

As you can see from the debug line, the list doesn’t seem to contain the actual items? (Are these, eg, uninterpreted raw pointers or something?) But when I look on the previous turn, “gem order with indefinite articles” works fine.

I can solve this with if the number of entries in the gem order is three and entry 1 of gem order is the red gem and entry 2 of gem order is the yellow gem and entry 3 of gem order is the blue gem, but that’s much clunkier and verbose (my actual puzzle has more than three things), and also I just want to figure out what’s going wrong here.

Try dropping the part:

The gem order is initially {}.

I think this part is confusing the compiler about the kind of the list for gem order. Since you’re providing no members, it will automatically start out as an empty list of gems.

2 Likes

Well, it makes the part of my brain that likes ensuring everything is nice and explicitly initialized itch, but yup, that solved it. Thanks!

Could someone explain why that causes this behavior? I’ve never encountered this until today, but I’m able to reproduce it with a variable list of anything. The solution is sound, I’m just curious :slight_smile:

You’re welcome.

Given that the type of the list is explicitly declared to be a list of gems, the original code seems like it should work fine. Perhaps you can just comment that declaration out so that the list starting out empty is still obvious when reading the source.

This looks like a possible compiler bug. The official bug tracker is no longer in service for reasons unknown. An unofficial bug tracker to centralize reports from the forum can be found at Issues · i7/inform7-bugs · GitHub if you would like to report it.

@rainmaze, the underlying reason is that a data structure that holds a list includes a kind identifier. The declaration of a list being the empty list seems to (incorrectly) have priority over any other declaration to the compiler, and, since the empty list has no elements to let it identify the kind of the list’s elements, it seems to decide to create a list of an unexpected kind. (I’m not sure what kind, but it’s not a list of numbers.)

The list equality test invokes a specialized I6 routine for comparing lists, and that routine includes some preliminary checks to disqualify the impossible matches as cheaply as it can. One of these checks is whether the kinds of the two lists being compared are identical. So a list assigned the weird kind value can never be the same as another list (unless it, too, has the weird kind).

2 Likes

Thank you for that.