Chased by Monsters. Mystery error?

I’ve created some code to create monsters that follow the player according to various rules. The code works, however on only some of the player’s turns while being chased by the monsters, I keep getting this mystery ouput saying “You’ll have to say which compass direction to go in” and “I didn’t understand that instruction.” I have no idea what is causing it in my code, nor do I know how to suppress or fix it. Any thoughts?

Apologies in advance. This code block is long. Don’t worry though, it repeats. You wont need to read it all to get the gist.

A monster is a kind of person.
A monster can be dumb, smart, or genius. A monster is usually dumb.
A monster can be slow, average, or fast. A monster is usually slow.

Every turn:
	Let S be the list of monsters that are slow;
	Let A be the list of monsters that are average;
	Let F be the list of monsters that are fast;
	repeat with slowster running through S:
		if the location of the slowster is not the location of the player:
			let RAND be a random number between 0 and 3;
			if RAND is 0:
				if slowster is dumb:
					move slowster to a random room adjacent to slowster;
				otherwise if slowster is smart:
					let the path be the best route from the location of slowster to the location of the player;
					try slowster going the path;
				otherwise if slowster is genius:
					let the better_path be the best route from the location of slowster to the location of the player, using doors;
					try slowster going the better_path;
	repeat with averagester running through A:
		if the location of the averagester is not the location of the player:	
			let RAND be a random number between 0 and 1;
			if RAND is 0:
				if averagester is dumb:
					move averagester to a random room adjacent to averagester;
				otherwise if averagester is smart:
					let the path be the best route from the location of averagester to the location of the player;
					try averagester going the path;
				otherwise if averagester is genius:
					let the better_path be the best route from the location of averagester to the location of the player, using doors;
					try averagester going the better_path;
	repeat with fastster running through F:
		if the location of the fastster is not the location of the player:
			if fastster is dumb:
				move fastster to a random room adjacent to fastster;
			otherwise if fastster is smart:
				let the path be the best route from the location of fastster to the location of the player;
				try fastster going the path;
			otherwise if fastster is genius:
				let the better_path be the best route from the location of fastster to the location of the player, using doors;
				try fastster going the better_path;

Without more of your source code, it’s hard to tell, but I think part of it is that the best route from... phrase can return nothing if no route is found (e.g. if there are doors in the way and you’re not allowing doors in the route). I think that, in turn, can trigger the “You'll have to say what compass direction...” error, because your try slowster going... statement causes the slowster to try going with the noun set to nothing.

An aside: You might be interested in WWI 8.18 Randomness, which has a handy phrase if a random chance of... that looks like it could be useful. I’d also recommend WWI 11.3 Pattern matching, to set up a phrase (like a function in other languages) to handle the repetitive block of deciding what kind of routefinding to do and pick a direction, e.g.

To have (M - monster) chase the player:
    if the location of M is not the location of the player:...

Then you can just say:

repeat with slowster running through slow monsters:
    have slowster chase the player;

If none of that helps, then please update your post with more details; it will help with the attempts to debug.

1 Like

=>

if the path is not nothing, try slowster going the path;

Although this can still run into trouble if you have other complications along some routes – but by default things like instead of going north rules don’t apply to NPCs, which is probably what you want in this case. If you do have rules that can apply to NPCs as well then you need to write them carefully such that they won’t print things if the NPC is out of view of the player.

It might be useful to have a read through the examples under Travelling Characters.

1 Like

That worked- sweet! I’ll probably take @otisdog’s advice as well to make my code a little cleaner. Thanks guys!

Something like this should work:

To have (M - monster) chase the player with delay (N - number):
	if M is not in the location:
		if a random chance of 1 in N succeeds:
			if M is dumb:
				move M to a random room adjacent to M;
			otherwise if M is smart:
				let the path be the best route from the location of M to the location;
				if the path is not nothing, try M going the path;
			otherwise:
				let the path be the best route from the location of M to the location, using doors;
				if the path is not nothing, try M going the path;

(So the slower monsters have a higher delay number – the fastest have a delay of 1.)

It’s also possible to rewrite that with some early returns to reduce the indentation a bit, if you prefer. And you could even parameterise the player as well if you wanted monsters able to chase NPCs too…

1 Like

Actually, thinking about it some more, the following is probably slightly more efficient (note this is just air code, it may contain some minor syntax errors):

[In some other rule]
	repeat with M running through all monsters:
		have M chase the player;
[Or possibly qualify that a little, such as "all alive monsters" or
 "all active monsters", if there can be some in states where they
 shouldn't chase the player.]

To have (M - monster) chase the player:
	if M is not in the location and M randomly decides to move:
		if M is dumb:
			move M to a random room adjacent to M;
		otherwise if M is smart:
			let the path be the best route from the location of M to the location;
			if the path is not nothing, try M going the path;
		otherwise:
			let the path be the best route from the location of M to the location, using doors;
			if the path is not nothing, try M going the path;

To decide if (M - monster) randomly decides to move:
	if M is fast, yes;
	if M is average, decide on whether or not a random chance of 1 in 2 succeeds;
	decide on whether or not a random chance of 1 in 4 succeeds.

(Essentially, it’s better to have one loop with conditions in the body than to have three loops with slightly different conditions on what you’re looping for, unless the order is super important.)

Or rather than the fixed fast/average/slow speeds you could give each monster a speed numeric property and decide based on that – e.g:

To decide if (M - monster) randomly decides to move:
	let S be the speed of M;
	decide on whether or not a random chance of S in 10 succeeds.

Now a monster with speed 10 is the fastest and speed 1 is the slowest.

Oh hey, I like this. This lets me keep my original schema where I can simply label characters as fast, slow, smart, or dumb without having to keep making decisions about every character’s stats. This format also makes it clearer to me how I could make a turn-based system of actions in general using Inform.