A person has script called...

Hi guys, I’ve come across something undocumented I really want to use in my combat system. Here’s what I have so far that compiles:

Every person has a script called Victory Text.

The idea is that I can set up a custom script to play when the player wins or when they are defeated, or whatever. Snag is I can’t work out how to set up the script itself, or if I have even done what I think I have.

[code]To Goblin Greg Victory:
Say “You win!”;
[other stuff]

The Victory Text of Goblin Greg is Goblin Victory.[/code]

Any ideas on how to set this up?

To adapt the method you’re using:

A person has a rule called the victory script. The victory script of a person is usually the little-used do nothing rule.

This is Greg's victory rule:
    say "You win! Greg is sad."

The victory script of Greg is Greg's victory rule.

I’d do it differently, though. This approach gives you a bit more flexibility.

Victory is an object based rulebook. Victory has default outcome success.

First victory for a person:
    increase the score by 5;
    make no decision.

Victory for a goblin:
    say "You defeated a goblin! Well done!"

Victory for a person (called the subject):
    say "You defeated [a subject]!"

This lets you have all sorts of different rules. To invoke the rulebook, say “follow the victory rules for” whatever the player just defeated. Then Inform will start with any “First” rules, then run the others in order from most to least specific. Unless you specify “make no decision”, it will continue until it finds a rule that applies, then stop. So you won’t get two messages when you defeat a goblin in this example.

Oh cool, I love it, thanks! It works very well!

By the way, you know any way to trigger them attacking the player if the player is at the same location? Something like:

When the location of the player is the location of the goblin:
Every turn when a hostile person is in the location of the player...

(I’m guessing you have some sort of adjective set up for if a character wants to attack the player; substitute that for ‘hostile’.)

Thanks a lot, that works very well!

By the way, if you know there are a number of objects in one place, is there a way to move them all at once instead of singularly? Could I, say, “move 6 things” or better yet “move X things”?

Or a way to repeat a script moving one object? I haven’t found a way to do that yet.

A coin is a kind of thing. 
The treasury is a room. 10 coins are in the treasury.

When play begins:
	repeat with lucre running through coins in the treasury:
		now the lucre is in Home.

Home is a room. The player is in home.

Thanks a lot!

By the way, does anyone know what this means:

I got it in the middle of combat in an extension I’m writing using Attack as a basis. All the game was doing at that exact point was rolling a D20, but it was deep into round thirty or so of combat. The game said that I was trying to run more than 25 things at once, but I wasn’t. Is there a way to raise this cap, or am I stuck with it?

That usually means that you have an infinite loop somewhere. For example, if you have “Instead of taking something: try taking the coin” will get stuck doing the same thing over and over again (when you try to take something it tries to take the coin, and when it tries to do that the rule fires again and it tries to take the coin again and so on.) Raising the recursion limit wouldn’t help.

It can be difficult to find out where the problem is but you can try commanding >RULES before it happens and seeing which is the last rule that runs before getting that message.

Huh, the only thing I can think of is that combat itself is looped. But it should never trigger an infinite loop because it needs to get the player’s input twice to fully reset it. Could a warning about a loop happen if the whole combat took place in the space of one in-game turn? It did take thirty combat rounds to happen, but the actual event took place in one turn so I’m wondering if the warning was triggered accidentally simply because hundreds of calculations happened in one in-game turn? If so, incrementing the turn with every reset might stop this problem.

Did you loop it with recursion? (Having a phrase or action call itself.) That will cause this problem. The call stack can only get so deep before it overflows. (Nothing to do with the turn counter.)

Instead, loop using the “while …” construct. In your case it would be “while combat is not finished…” or however you’re testing that.

I haven’t actually used any loop or repeats in the whole thing, I created a main chat node and had the others dump you back to it, it was pretty much the only way I could think to do it. Most of the times you select an option it starts a new conversation. I don’t know if this is enough to reset the action counter or not.

That sounds like it’s likely the problem. Maybe each action is starting a new one back at the main node, but none of them are ever finishing, so once you go through too many the call stack overflows.

If so, that could be hard to get round, unless there some way to refresh the turn count? Or increment it? The only other options I can see is to keep kicking the player in and out of combat, somehow. Or somehow getting them to press enter at a blank command prompt so the attack system restarts.

As Zarf said, the turn counter is not relevant to the problem. It definitely sounds like the logic could be easily rewritten to avoid filling up the call stack, but it’s hard to give specific advice without seeing the code.

It’s actually really simple, all it is is the “Activity Based Simple Chat” extension on a loop:

Attack-Main is a chat node with quip "Back to Main Attack Menu". Rule for giving text about Attack-Main: [Script here] Rule for finding responses to Attack-Main: start a conversation with Attack Options;

Once you pick an option, it then jumps back to a node like that, runs through it, and goes back to the menu. It works very well, until inform hits that memory limit. Unfortunately, no matter how hard I look, this seems to be literally the only proper working menu-based system I can find, so it really seems unlikely that there is another option.

Well a common way to handle this is to repeat the conversation inside a loop instead of having a previous conversation node restart the whole thing. Something like this:

Combat finished is a truth state that varies.

Instead of attacking the troll:
	now combat finished is false;
	while combat finished is false:
		start a conversation with Attack Options.

…and when the combat is ready to end change the flag to true and the loop stops. Now the previous activity ends before the next one starts and the stack doesn’t increase regardless of how long the combat takes.

I think I’m already doing that, the whole thing lasts until either side drops bellow 1hp, and then it quits. I think the problem is that Inform is trying to remember every calculation that happens during the chat, even though it involves triggering half a dozen different scripts running at different times.

What worries me is that I have a hunch that it isn’t my script that’s overloading, but the chat extension itself hitting its absolute limit and crashing. This seems to be the most likely thing since it’s what’s governing the entire exchange.

If you have, as you said before,

Rule for finding responses to Attack-Main: start a conversation with Attack Options;
Then you’re not doing what I suggested because this means a new conversation is started while the previous one is still happening. The previous conversation then has to wait for the next one to finish before it can itself finish. That was the point of taking the “start a conversation…” out of there and putting it inside an external loop so that the previous conversation can finish cleanly before the next iteration begins.

Ah, I see, I didn’t realise. I guess I could solve this by just using the chat system’s inbuilt links, but I really don’t want to do that as it encourages the player to press 1 repeatedly until they win or loose and not consider the options.