Reporting Actions Not In the Location

I’ve defined some of my own rules that have actions taking place in other rooms, like npcs roaming about doing things of their own. The actions are printing the “say” results of these actions I’ve defined, even when the player isn’t in the same location. I could go through to each and every place where I am “reporting” something and add a condition that checks if the actor is in the location, but this could be very tedious and messy…

Is there a way to write something like this (that actually works, obviously this does not):

Instead of saying something while the person asked is not in the location:
          do nothing;

“Saying something” is not valid, but is there a way to do this as a general rule?

I don’t really see the problem…the report rules by default don’t run unless the player can see the actor.

And doing something to the “say” command like that, even if it were possible, wouldn’t be a good idea–if the NPC is doing an action on their own they won’t necessarily be “the person asked”, and not all printing happens as the result of an action.

I’m not using the standard reporting rules, as I’ve wired in a lot of other things to these actions, there are other say phrases besides a final report for an action. Actions might be interrupted, but if not, they continue and say more… it is all wired in throughout my framework, so it would be impossible to paste it here, but in any case, I don’t have a single report phrase after the action is done, but different phrases embedded throughout the code block for the “action”.

The example I gave there was just an example. If it were possible to catch “saying” with a condition, I’d have different conditions than just “the person asked in the location.”

So, on topic though, there isn’t a way to refer to “saying” as something that can have a rule applied to it? Regardless of what the perceived need I may have for this is based on what I described above, is there not a way to target saying with a general rule with a condition?

No. “say” is a phrase, which is the lowest level of execution. Phrases aren’t executed through the rule mechanism.

You could define a new phrase “display [text] in [room]”, and have that check the argument.

Ohh, you mean like this?

To here-say (x - a text):
	if the person asked is in the location:
		say "[x]";

... some other rule:
         here-say "the reported action text";

Again, this is only one example condition, there may be others… but in general, this seems to be working so far. Are there any sticky issues the above is likely to run into in general?

Only one that I can think of. You can’t pass a let-variable to a function like that. For example, if I “let N be 5”, then I can’t “here-say “[N]”.”

I believe using indexed text instead of normal text fixes this problem, but I am not sure.

I think

say x

should work and might avoid some problems that could arise with using a variable in a bracketed text substitution.

Also, you might want to give here-say an extra parameter; making it always depend on the person asked seems potentially fragile. And you might want to say “if the player can see the person asked [or whatever]” in case the room is dark, or the player is in a closed container, or the person asked is in scope from where the player is.

Are you trying to create line of sight / hearing rules? You can use “if the x is adjacent to the location of the player”, or “if x is y moves away from the player”.

Or, something like this:

Every turn while … :
repeat with n running through npcs:
if the location of the n <= x number of moves from the location of the n to the location of the player,
say “You hear / see the [n] moving around.”.

You’ll also need to indent each line of the loop.

Yep, this was true, and thank you for pointing out to use indexed text instead, that solved that.

I also took the advice here about just using the variable, not the quoted text, to reference the indexed text. Thank you.

I also changed it from “in the location” to “player can see”… but I’m not sure what the [whatever] might be. If something is happening without a person doing it, that would be an entirely “custom function” which would need it’s own reporting rules separate from actions right? Do you have an example of what you mean by the [whatever] besides the person asked?

Thanks for this as well. I didn’t know about “number of moves” before this, as I have trouble retaining anything from the documentation without trying it first. This is very useful.

I wouldn’t recommend Craftian’s approach as it is now, simply because the route-finding will take a very long time when it’s run repeatedly for every action (it’s run once for every NPC every turn).

Route-finding is actually pretty efficient. It runs many times each turn in Kerkerkruip.

Does it? I’m surprised–I know Kerkerkruip has dynamic room placement, which means no compile-time route finding.

In that case ignore my previous comment.

I’m not exactly sure how often route finding happens, but there are several not uncommon adjectives that use it. (I.e., the adjectives that determine whether two persons are in the same world – necessary for deciding whether stuff like soul absorption, demon-of-rage-growing and so on do or do not take place.)

I recall that Graham implemented more efficient route-finding a couple of Inform7’s ago.

Well, the “[whatever]” was a parameter that you might pass to this phrase. You may be right that “the person asked” will always work. I can think of some special scenarios where you want something different – if it’s possible to remote-enchant something, you might want to be able to report that when the player can see the enchanted thing even if the player can’t see the enchanter – but that’s pretty esoteric.

Oh, you’re right… OK, yes, a thing might be acted upon remotely, or otherwise something is affected by an actor that can’t be seen. I guess remote enchanting, or someone shooting from a distance, or someone hidden doing something so you can see the effects but not necessarily the actor.

I wonder if instead of having to do parameters though, there might need to be alternate phrases cued by alternate conditions for if the player can see the noun but not the person asked. So, if a mortar explodes nearby, you can certainly see the noun, no question, but not the person that fired it.

Something like (and again, this is rudimentary, I plan to expand on it):

To aware-actor-noun-say (x - an indexed text):
	if the player can see the person asked and the player can see the noun:
		say x;

To aware-noun-say (x - an indexed text):
	if the player cannot see the person asked and the player can see the noun:
		say x;

To aware-actor-say (x - an indexed text):
	if the player can see the person asked and the player cannot see the noun:
		say x;

Each “x” would be in front of a different phrase in the other code block for the given action reporting rules, of course. So, if someone is “remote enchanting” something, you might need something like this:

...enchanting code...
aware-actor-noun-say "[the person asked] [enchantment effect] [the noun].";
aware-actor-say "[The person asked] seems to be doing something suspiciously magical, but you can't tell what.";
aware-noun-say "[The noun] suddenly [enchantment effect]!";

Or something like that… this is definitely a lot of work though, not just coding the original setup, but using this and keeping track of it throughout a game. Hm.

Thanks for that – good to see I’m on the right track. I have dozens of loops interlocking to create A.I. for enemies, that have grown in complexity since I started. Most of them use route finding, and I’ve never experienced the game slowing down, even with 30 creatures and 5 NPCs duking it out at once. I’m going to be pushing those numbers to the hundreds (thousands?) before I’m done, just to see where I7 breaks.

(edit)

This is not dissimilar to how fast databases are crawled for information. You can have thousands of database rows, and dozens of columns being searched for a string or number match, and all of this happening behind the scenes in the blink of an eye with for, while, and array-based loops when you go on a dynamic website. It all depends on the efficiency of the program, and from what I’ve seen, I7 is amazingly efficient at this.

(Late edit)

Okay, Draconis was right on this one. Route finding, when the route gets pretty big (I have 10x10 grid) and number of moves, does slow things down. Didn’t see this until I expanded things to this scope. I’m creating a workaround for this. Good call, Draconis.