Programming error -- but only on the first turn

I’m pecking away at a game idea I’ve had for a while that involves a crowd of NPCs. I’m aware it’s well above my pay grade and I’ll undoubtably be back, but what’s stumping me at the moment is the mechanic by which NPCs who are bored of a conversation’s direction will drift off.

The code I have at the moment is compiling, and it’s even sort of working (ignoring the glitch where it’s displaying a pronoun where I want a name, but I’m sure I can hammer my way through finding the right variable eventually.) But the game output looks like this:

**By the Veranda**
A glittering ballroom, gaudily ornamented and brilliantly lit.

You can see Juliet, Iago and Othello here.

> **z**
Time passes.

[** Programming error: tried to find the "." of (something) **]
[** Programming error: tried to find the "." of (something) **]
[** Programming error: tried to find the "." of (something) **]
[** Programming error: tried to find the "." of (something) **]
[** Programming error: tried to find the "." of (something) **]
[** Programming error: tried to find the "." of (something) **]
[** Programming error: tried to find the "." of (something) **]
[** Programming error: tried to find the "." of (something) **]
[** Programming error: tried to find the "." of (something) **]
[** Programming error: tried to find the "." of (something) **]

> **z**
Time passes.

her wanders in.
him wanders in.

> **z**
Time passes.

Bored, her wanders off.
Bored, him wanders off.

It seems to be only that very first iteration of the code that throws the ugly block of errors, so… if anyone could point me to my blindingly obvious mistake, I’d be much obliged.

The code:

A theme is a kind of thing. The current theme is a thing that varies. 

Boredom relates various themes to various people. The verb to bore means the boredom relation.

Gossip is a theme.

The current theme is gossip.
	

Every turn:
	Follow the character action rules.

A person can be active or passive. The player is passive.	

The last person named is a person that varies. Before printing the name of a person (called target): now the last person named is the target. 

Definition: a person is bored if it is not the player and the current theme bores it.

The character action rules are a rulebook.

The first character action rule:
	now the last person named is the player;
	now every person is active.
			
A character action rule:
	repeat with mover running through bored people:
		now the mover is active;
		now the last person named is the mover;
		let current space be the location of the mover;
		let next space be a random room which is adjacent to the current space;
		if the mover is visible, say "Bored, [mover] wanders off." ;
		move the mover to next space;
		if the mover is visible, say "[the last person named] wanders in.";
		now the mover is passive;
			
To decide whether movement has not yet occurred: 
    if the player is passive, no; 
    yes.

The Ballroom is a region. 

A ballroom section is a kind of room. They have the description "A glittering ballroom, gaudily ornamented and brilliantly lit."


By the Veranda is a ballroom section in the Ballroom. 
At the Entrance is a ballroom section in the Ballroom. It is south of By the Veranda.
At the Bottom of the Stairs is a ballroom section in the Ballroom. It is north of By the Veranda.

Juliet is a woman in By the Veranda. Gossip bores her.
Iago is a man in By the Veranda. 
Othello is a man in By the Veranda. Gossip bores him.
1 Like

I don’t know what the deep root of the error is, but part of it is that Inform 7’s compiler doesn’t recognize ‘her’ as Juliet or ‘him’ as Othello. Instead, it is creating characters named ‘her’ and ‘him’.

If you replace that part of the code with:

Juliet is a woman in By the Veranda. Gossip bores Juliet.
Iago is a man in By the Veranda. 
Othello is a man in By the Veranda. Gossip bores Othello.

it works.

I found this problem by adding debug code saying ‘say mover’ in the middle of the ‘repeat through’ block of code.

I’m sure that the error stems from cases where next space is set to nothing. Probably because the “him” and “her” characters are off-stage.

2 Likes

It’s usually a good habit to get into to check the Index → World tab to see if there are any objects created that you’re not expecting, to help catch these sorts of issues. Especially off-stage ones, but you can also accidentally create objects in other locations.

1 Like

facepalm That was indeed a blindingly obvious error. I’d been clunking through the new business of getting my head around relationships and their verbs for so many compiler runs, I forgot that other blind spot of mine, the bit where Inform almost – but not quite – understands natural language as well as I expect it to.

Thanks for the hint about checking the Index; I still haven’t gotten the hang of remembering to use all the tools at my disposal, or knowing when to look when I do.

I appreciate all the help, guys! Onwards to tie myself into new knots with the actual conversation mechanics!

1 Like

In general, whenever you do pathfinding or “a random adjacent room”, you should check whether the result is nothing. At least you can print a more informative error message.

Ah, okay; I suppose I’d assumed that since “next space” was defined to be a random room, rather than a random direction, it wouldn’t return a null response – unless I somehow got someone into a room with no exits, which does, to be fair, sound like the kind of dumb thing I would do.

Is this workable?

repeat with mover running through bored people:
		now the mover is active;
		now the last person named is the mover;
		let current space be the location of the mover;
		let next space be a random room which is adjacent to the current space;
        if next space is nothing, stop;
		if the mover is visible, say "Bored, [mover] wanders off." ;
		move the mover to next space;
		if the mover is visible, say "[the last person named] wanders in.";
		now the mover is passive;

It’s compiling and playing fine, but I’m a little nervous because I don’t entirely understand the structure of these repeat loops yet. Hopefully “stop” simply stops the loop for that particular NPC and moves the next one in line through the repeat, rather than ending the loop entirely, but I’m having trouble finding documentation for that.

1 Like

stop is documented in Writing with Inform 11.13. The definition isn’t quite enough for me to be confident in answering your question, though: All it really says is “This phrase causes the current rule to end immediately.”

I take it (and I hope someone will correct me if I’m wrong) that “rule” is here taken to mean a single iteration through the block under the repeat phrase, but the definition of a repeat phrase in Writing with Inform 21.4 isn’t quite clear enough for me, either: “This phrase [repeat] causes the block of phrases following it to be repeated once for each item in the given list.” This is not quite the same thing as calling the block of phrases a “rule,” though it’s pretty close.

But I think you’re right, here.

WI 11.12 gives the phrases to use to control repetition within a repeat loop.

‘next’ interrupts the current iteration and moves on immediately to the next iteration. I think this is what you are looking for.

‘break’ halts the sequence of repeats completely and moves on immediately to the next phrase after the repeat loop (if there is one)

‘stop’ is a nuclear option- it immediately stops and exits from the entire rule that is running at the moment, and is applicable both inside and outside repeat loops. A rule is rather more than a repeat loop- it’s a sequence of one or more phrases actually defined as a rule, although the variation allowed to introduce a rule definition means that it’s not always obvious a rule is being declared- e.g. ‘Before jumping:’ is shorthand for ‘A Before rule when jumping:’ and it is automatically listed n the ‘Before rulebook’

2 Likes

Ah! Okay, so what I want is actually:

if next space is nothing, next;

Thank you! Off to read the phrases section and lecture myself on looking under every header next time I get confused. :slight_smile:

In traditional programming terms, “stop” returns from the function. (A rule is a function.) “break” breaks out of the current loop; “next” does a continue to the next loop iteration.

So “next” is what you want here, yes. If you think that next space should never be nothing, it’s worth printing an obvious message:

if next space is nothing:
    say "(BUG) [mover] found no adjacent rooms!";
    next;

If you see that message, you’ll know what happened. If a player sees that message, they’ll report it and you’ll know what happened. :)

1 Like

Ah yes, the excellent habit of error reporting which I have… never actually developed. :roll_eyes: I’ll make this the first step in reforming my bad programmer ways, thank you.