Having a weird problem with multiple characters following the player

Hey guys, I’m having an issue with multiple NPCs following the player character.

In this game the player character has a “gang” (think Scooby-Doo, not Latin Kings) who follow her around, and individual members can drop in and out of it due to various circumstances. To implement this I created a “Togetherness” relation.

Togetherness relates various people to one person. The verb to be alongside means the togetherness relation.

Members of the gang follow the PC wherever she goes until they drop out of the gang. To code this as a generalized rule, I came up with:

Every turn:
	if a person (called A) is not in the location of the player:
		if A is alongside the player:
			let the way be the best route from the location of A to the location of the player;
			silently try A going the way.

And I have two NPCs:

Ricky is a man in SandBlue. Gnash is a woman in SandBlue.

When play begins:
	now Ricky is alongside the player;
	now Gnash is alongside the player.

The problem seems to be I have an odd, staggered delay in the reporting of the NPCs presence.

Sandbox, Blue Corner
This is the blue corner of the Sandbox.

You can see Ricky and Gnash here.

>e

Sandbox, Red Corner
This is the red corner of the Sandbox.

>l
Sandbox, Red Corner
This is the red corner of the Sandbox.

You can see Ricky here.

>l
Sandbox, Red Corner
This is the red corner of the Sandbox.

You can see Gnash and Ricky here.

>s

Sandbox, Green Corner
This is the green corner of the Sandbox.

>l
Sandbox, Green Corner
This is the green corner of the Sandbox.

You can see Ricky here.

>l
Sandbox, Green Corner
This is the green corner of the Sandbox.

You can see Gnash and Ricky here.

This is driving me a little nuts; I’m not sure why Inform is processing the following rule one character at a time when it’s meant to be instantaneous.

Any thoughts?

I think what’s happening is that the movement code is only firing once per turn, so it’s only applying to one character at a time. Like, in the first round after you’ve moved to a new location, the every turn rule checks whether a person isn’t in the player’s location – and OK, it starts checking with Ricky (probably since he’s declared first) and it turns out he isn’t, so let’s move him, and now that If statement has concluded. Then it’ll fire again for Gnash on the following turn.

This should be pretty easy to fix, though – try this:

Every turn:
	Repeat with A running through people alongside the player:
		If A is not in the location:
			let the way be the best route from the location of A to the location;
			silently try A going the way.

NB you don’t need “the location of the player” – Inform understands “the location” by itself as the location of the player. But easy enough to leave that in if it makes your code more readable to you.

Hope this is helpful!

Edited to add: here’s the relevant section of the documentation, if that’s of use.

2 Likes

Wow, thank you for the quick response! This indeeds solves my problem. “repeat running through” is one of those Inform concepts I’m still getting my head around.

I have only one slight issue now. Adding the code you suggested gives me:

Sandbox, Blue Corner
This is the blue corner of the Sandbox.

You can see Ricky and Gnash here.

>e

Sandbox, Red Corner
This is the red corner of the Sandbox.

>l
Sandbox, Red Corner
This is the red corner of the Sandbox.

You can see Gnash and Ricky here.

>

In that second turn there seems to be a delay before Inform puts their names in the room description. Ricky and Gnash are still there, but I’d like to make it so the player always sees some indicator that they’re in the room.

Removing “silently” gives me:

Sandbox, Blue Corner
This is the blue corner of the Sandbox.

You can see Ricky and Gnash here.

>e

Sandbox, Red Corner
This is the red corner of the Sandbox.

Ricky arrives from the west.

Gnash arrives from the west.

Which serves that purpose, but I’d like to modify those default movement responses, and ideally consolidate them into one line. I can’t find anything in the handbook that covers consolidating multiple default responses into one, though.

Oh, I think this one’s a little trickier – I remember an exchange with someone else trying to do a similar thing a couple months back, let me see if I can dig up the thread…

Yeah, here we go. There’s an example in the Recipe Book that does this, but it also does like 73 other things, so stripping it down to just the movement-consolidation bit is some work (if you want to take that on, it looks like the relevant bits start in Section 6).

If you just want to modify the default movement responses, that’s much easier – that one’s the describe room gone into rule response (L), which this bit of WWI tells you how to mess around with.

Edited to add: it just occurred to me that an easier way to do this might be to keep the “silently” in there, and then just use your existing Every Turn rule to spit out a Say command at the end. Like, you could test whether A is now in the location at the end of its movement (i.e. if it has reached the player), and if so add it to a list L, and then at the end of the repeat running through, use a say command to output L. I won’t have time to try messing around with that tonight, but if it’s useful I might see if I can hack something together tomorrow.

1 Like

Yeah, I was never able to strip all that extraneous code out to just the part about consolidating movement announcements to one line/paragraph. (The cookbook is really frustrating about that kind of stuff.) Decided to punt it down the road and/or not care about it.

But, if you solve it, I’m all ears :slight_smile:

1 Like

OK, this version of the problem is actually pretty easy! I’m sure there are cleverer ways to do this since I haven’t done much with lists, but see if this gets you somewhere:

Every turn:
	Let L be a list of people;
	Repeat with A running through people alongside the player:
		If A is not in the location:
			let the way be the best route from the location of A to the location;
			silently try A going the way;
			If the location of A is the location, add A to L;
	if the number of entries in L is 1, say "[L] walks in alongside you.";
	if the number of entries in L  is greater than 1, say "[L] walk in alongside you."

Obviously you can elaborate this out to include directions, etc., varying text depending on who’s the one doing the walking, etc.

1 Like

You might want to create a kind-of-person for the gang, and repeat through that. (Or have a followable attribute, or keep an explicit list. There are several ways to do it.)

Right now this checks every person in the game, including the player. The player will never get moved (since the player is always in the location!) but it’s a bit of unnecessary work. Plus, you might add a new non-gang person or animal to the game someday, and then you’d see some surprising following behavior.

2 Likes

thank you for these solutions guys! Gonna explore these more as I get ready for introcomp, but I think I have what I need.

2 Likes