Exceptions to "let X be a random room".

I have an area called “the trap area”. I would like the player to be randomly transported to any room in the trap area except for one room, called “The inner trap”.
Here is what I have tried so far:

	let R be a random room in the trap area that is not the inner trap;
	move the player to R;

If there is any repository for logical syntax, I would be glad to read up on it. I want to be able to communicate complex ideas to the machine.

I think what you need is simply an inner while loop that keeps trying to find a non-inner-trap room. Here’s a dummy game I slapped together that seems to do this (unless I’m screwing up somehow). Note the inner while loop. The banana is what I sometimes use to trigger a test action.

[code]X is a room. B is a room. C is a room. D is a room. E is a room. F is a room. G is a room.

The trap area is a region.

B, C, D, E, F, and G are in the trap area.

The player carries a banana.

Instead of eating the banana:
relocate the player to the trap area.

To relocate the player to the trap area:
let N be a random room in the trap area;
while N is B:
let N be a random room in the trap area;
now the player is in N.[/code]

This should never move the player to B.

You can also define an adjective, which will avoid a loop that in theory could never terminate (well, it’s very unlikely):

[code]X is a room. B is a room. C is a room. D is a room. E is a room. F is a room. G is a room.

The trap area is a region.

B, C, D, and E are in the trap area.

The player carries a banana.

Instead of eating the banana: move the player to a random borderline trap area room.

Definition: a room is borderline trap area if it is in the trap area and it is not B.[/code]

“Borderline trap area” doesn’t have any significance – I just chose it as a string of words that doesn’t look totally weird in the “move the player” phrase.

EDIT: You know what, you don’t even need the damn adjective.

Try this:

Instead of eating the banana: move the player to a random (room in the trap area) that is not B.

You need the parentheses because otherwise Inform will try to attach “that is not B” to “the trap area,” and since B is a room and the trap area is a region, that comparison can’t be made. I think; it’s pretty common that trying to stack modifiers without parentheses leads to one of them attaching wrongly, though I’ve never seen it result in a compiler error before.

Thank you so much for all of the help. I’ve learned a lot about phrasing from this problem.

I used the solution with the parenthesis in the end, though I can see that I would want to use an adjective in a situation any more complex than this.

My question is, why does this work:

a room is borderline trap area if it is in the trap area and it is not B

Why does this not work?:

let R be a room in the trap area and it is not B

The real answer to that question would take you deep into the innards of the compiler. I’m sure someone will be able to provide a technical answer. My non-technical answer is, “Inform code is not actually English. It only looks like English.” In this particular case, a grammarian would respond that “it” has the wrong antecedent. Its antecedent is “area,” when clearly you mean its antecedent to be “room.” So your sentence wouldn’t quite pass muster as English, either. But that’s a grammarian’s answer, not a technical answer about the compiler.

Fair enough. I thought the answer would be something like that.

The project is moving along nicely now, I think it’s going to be a long night for me.

Well, I don’t know the technical innards, but I can give you a few suggestions:

This isn’t even completely grammatical as English. “Let R be a room in the trap area” is an imperative sentence while “It is not B” is a declarative sentence. Sometimes you can conjoin declaratives and imperatives (“Don’t try that again or you’ll be sorry”), but this time it sounds funny.

What that means in a more Informy way is that “it is not B” is a condition, which you can test as part of an “if” statement, but you can’t add conditions to a “let” statement like that. If you want to add stuff to a “let” statement it ought to be a further description of the noun (hence “that is not B,” which is a modifier for “the room,” at least once we put in the parentheses).

Also (and this is really where “Inform isn’t English” comes in) you can only use “it” the way I used it when you’re writing a definition of an adjective. (Or there may be other cases, but most of the time you can’t use “it” this way.) When you’re defining an adjective that starts “Definition: a room is…” then every time you use “it” in the definition, Inform knows “it” means the room you’re looking at. (This is mentioned somewhat offhand in section 11.16 of the documentation.) Most of the rest of the time when you use “it,” Inform won’t know what it’s supposed to refer to. “The room” generally doesn’t work either.

I think you have to write it like this.

let R be a random room in the trap area which is not B;

Hope this helps.

No, that doesn’t work. See matt w’s comment about parentheses, above.

Ah yes, of course! It’s a bit counter-intuitive though!

It’s a lot less likely than that! The probability would be the limit as k tends to infinity of 1/k. The fact that it does terminate is the reason why 1/n + 1/(n^2) + 1/(n^3) + 1/(n^4) + 1/(n^5) + … = 1/(n-1).

One advantage of the “define an adjective” method over the “loop and reject” method, however, is that it fails more cleanly in the case where there are no valid choices, i.e. if the only room in the target region is the excluded one. (The adjective method will, I believe, return “nothing” and then generate a run-time error when trying to move the player into “nothing”; the rejection sampling method will loop forever in that case.)

It’s also faster, which might be a concern if you’re doing it several times in a turn.

Don’t get me wrong here, I also prefer using an adjective as it’s more efficient. It’s just that the loop method has some rather interesting mathematics underneath it.