Refused actions and the passage of time

Hi everyone,

I am using the Variable Time Control by Eric Eve extension. One of my beta testers noted that some refused actions (such as trying to go a direction that isn’t available) still forward time by one minute.

But this doesn’t seem to be universal.

The “You can’t see any such thing” response doesn’t forward the clock. Nor does “There are none at all available!” in response to “take all” in an empty room. But trying to take scenery, which prompts the “That’s hardly portable” response, does forward the clock.

First, is there an easy way to see every type of action that will or will not forward the clock? I’d rather not try to type everything that I expect to produce a generic fail response to see if it moves the clock forward.

Secondly, I understand how to apply “[no-time]” to a specific action or even a kind of action, but if there are several different kinds of “fail” responses, Is there an easy way to apply “[no-time]” to all of them at once, or do I need to use a “before” or “instead” construction for every type of action?

Thanks in advance,

Frotzing

1 Like

The summary version is, the things called parser errors don’t take a turn, so they won’t make time progress with that extension. This includes ‘You can’t see any such thing’, which is a parser error response, not the output of one particular action.

Actions defined as being out of world never take a turn, so anything printed by them won’t make time progress, either.

Things not in either of the above not-large categories will always take a turn by default. e.g. Trying to take scenery. The taking action processes what the player did, decides they tried to take something not portable, then says ‘That’s hardly portable.’ This is the output of the taking action, not a fundamental parser error message, so it takes a turn. Unless you go poke a [no-time] into the response message ‘That’s hardly portable.’

If you look at 18:35 in the Inform Docs, you’ll see a list of the parser error messages.

Apart from poking [no-time]'s into particular rules or responses from actions, you can group actions. e.g.

jumping is acting fast. tasting is acting fast.

Then if you tweak the variable advance time rule in the extension, it also won’t take time when the player does an action that’s been defined as ‘acting fast’. This tweak also doesn’t fire twice if the action is both ‘acting fast’ and happens to have a no-time in it.

This is the variable advance time rule:
	if time-reset is true or acting fast:[This is the only line I changed]
		now time-reset is false;
		stop;
	if seconds_used is false, 
		now seconds is previous_seconds + seconds_per_turn;
	let mins be seconds / 60;
	now seconds is remainder after dividing seconds by 60;
	now the time of day is mins minutes after the time of day;
	increase turn count by 1;
	now seconds_used is false;
	now previous_seconds is seconds;

-Wade

3 Likes

The idea being, “you can’t see any such thing” doesn’t represent the player character doing anything. The parser couldn’t even generate an action, because it couldn’t understand the command you typed. Same for > DKSJFH and so on.

But “that’s hardly portable” represents the player character trying to do something, and failing. Even if it didn’t work, the attempt took some time. The parser generated an action, passed that action to the world model, and the world model said no.

2 Likes

The list of parser errors (which never take a turn) are in manual chapter 18.35.

It’s not always obvious. The parser doesn’t distinguish between the player trying an action and failing (“You try to lift the rock, but it’s too heavy”) from the player refusing to try an action (“That rock looks too heavy to lift.”) From the parser’s point of view, they’re both failed actions that take a turn.

But a couple of the parser errors sound a lot like refusing to try an action. The “can’t talk to inanimate things” error, in particular. (You get this if you try KISS SWORD.) In a more sensible world, this would probably be changed to a world model refusal, but oh well – Inform has some quirks.

2 Likes

Thank you! I appreciate your detailed response. It helps me to understand what is going on better.

You mentioned poking [no-time] into the response message for various actions. I want to explain what I would do and then see if that’s the best or most efficient way.

For example, I think most of the time, it’s a minor judgement call on whether or not time should advance on these non-parser error actions. But trying to go an exit that doesn’t exist probably shouldn’t take any time in most instances.

So, if I were to address this, I would try something like the below:

Before going a direction (called the way1):
	let further place be the room the way1 from the location;
	if further place is not a room:
		say "[no-time]You can't go that way.";
		stop the action;	

Is that the best way to handle issues like this, or is there a more efficient way that I’m not considering?

Thank you! That helps. That’s exactly what I was having a hard time seeing: the difference between parser errors, failing an action and refusing an action.

And to be fair to Inform, even though my game makes use of a clock, most of the time it isn’t going to matter if the clock advances for failures and refusals but not errors. And most players won’t even notice. But I did want to address my tester’s concern if there was an easy way to do it.

I think I’m going to address some of the more noticeable ones in my game (like going a direction that doesn’t exist) and let the more minor ones slide by. Whether or not taking scenery should take time is a bit of a judgement call. In a perfect world, trying to take the sky or a river probably shouldn’t take time as one glance would show that is impossible, but trying to take a large statue probably should take time because a character could reasonably spend time making the attempt.

But I’m not sure trying to weed out the differences there is really worth the effort when the impact on the final product is pretty minimal.

Thank you! I appreciate you taking the time to respond. You all have helped me to understand this a lot better.

Overall, this is good. I do like to put the [no-time] right next to the blocking message, too, as it makes the code easy to read and understand later.

However you don’t really need to make this a Before rule. It matches the typical case for a Check rule (check if the proposed action should be allowed to take place – block it if it shouldn’t). Which would be like:

Check going a direction (called the way1):

then the same code as you have.

Inform’s ideal concept of when to use a before rule is when you need to have something happen before the action is even attempted. So before rules aren’t predicated on the action succeeding or being blocked; they don’t even know what the outcome will be. If the player tries to go through a door, a before rule may try to open the door, which is a prerequisite for attempting to go through it.

In practice you don’t have to obey Inform’s rule ideas to the letter, but it’s a good idea to understand where they’re coming from before going against them, as they do have functional consequences. (As everyone seems to find out when they try to write a whole game with just Instead rules :))

-Wade

I have a few questions.

First, if I use “Check…” instead of “Before…” do I still need to stop the action at the end? My understanding is that I wouldn’t need it, but as you’re about to see, I have difficulty with this concept.

Secondly, I have read the differences between “Check” and “Before/Instead” multiple times and it still doesn’t click for me. I understand that I might want to use “Before” if I want something to happen before the action runs (whether or not it succeeds). But it feels like there is no difference between these three things:

  1. A “Before” rule that prevents the action from succeeding because it ends with “stop the action.”
  2. An “Instead” rule.
  3. A “Check” rule.

My understanding is that there is very little (if any) difference between 1 and 2. But I feel like there is a difference between those first two and number 3, but that I don’t understand what that difference is.

Finally, and this is my ignorance, not your ability to explain, but I’m not sure what you mean by putting [no-time] right next to the blocking message.

Thanks again for helping me through this! I have said before that this site is one of the best places on the internet. I’ve never seen a place so dedicated to people just helping each other because they enjoy being helpful. It’s awesome.

1 Like

Ah, I just mean like in the line:
say “[no-time]You can’t go that way.”;

The message ‘You can’t go that way’ is immediately adjacent to the [no-time] token. It makes it obvious - if the player reads that message, it’s going to take no time. It’s about as impossible to miss the connection as can be, reading it later at speed or searching for it.

It can be hard to grok the value of the differences when starting out. But as you get into more complicated circumstances, it starts to come clearer. Anyway, I’ll try and give some more perspective.

Three of the rulebooks are considered Default: Check, Carry Out and Report. So they’re the ones that the core system of actions is built of. Check if something is possible, Carry Out code if it is, and Report (print an outcome) if it does succeed.

The Before and Instead (and After) rulebooks are considered Exception rulebooks. They can break or alter the flow of the defaults. So usually, you’ll want to turn to them less often.

Note that if a before rule fires, the flow of the action continues, unless the same rule manually stops it. The same goes for Check rules.

Instead rules are atypical in that they have a default outcome of failure (for the continued flow of the action). If an Instead rule checks some conditions and does something, that something happens instead of a continuation of the action. Four rulebooks are skipped in this case (Check, Carry Out, Report, After). So Instead is best for doing something Completely Different. If you want an action to go ahead in the case that it doesn’t meet any of the blocking conditions (e.g. ten check rules you’ve prepared), it’s best and easiest to use Checks, so that the action eventually flows to the Carry Out stage and happens as normal.

Why not just Instead a bunch of stuff in general? One reason is because actions can invoke each other, and insteads can break the chain. Doors are again a good example. If the player goes west towards a door, you might wanna have the program check if the door’s open, try opening it if it’s not, maybe even try unlocking it if its locked… Having unlocked it, try opening it again. Then try going through it. This all comes from the player just typing W.

Now if we got to the ‘try unlocking bit’ and coded it like ‘if door is locked: instead try unlocking (the door)’ we stop the whole queue of actions up to that point and replace it with one new action – unlocking the door. This could cause the player to unlock the door, then the turn’s over and they just stand there, when they expected to go through as well. Removing the ‘instead’ fixes this and lets it continue.

This is the most common way people find using Instead rules or instead clauses trips them up as they proceed. Inform already has lots of actions that will try each other and expect to not be blocked as they do, and throwing in a custom message via ‘Instead’ can stop normal operations if you aren’t careful.

Also, why not stop stuff with Before in general? Well, then it’ll be stopped in isolation of the check rules (which may require you duplicating code. Some actions already have a lot of Check rules in place to make sure they’re feasible. You may end up reproducing the logic of these clauses yourself at the Before stage)… and before lots of other things in the game that you might have carefully placed in the Before phase. If Before is an opportunity to make preparatory stuff happen, you blow that opportunity if too much normal stuff starts to happen there. You can’t easily interfere with an action any earlier than before. That’s maybe the best argument I can think of for using it as intended. It’s as divorced from the default processes as can be.

After is for printing something other than the default Report outcome, and also running additional code for a particular circumstance. That’s why it’s an Exception rulebook.

-Wade

1 Like

Ok, that helps a great deal, actually.

To be honest, I rarely use “Instead.” I don’t particularly like it because “Before” followed by a “stop the action” (if warranted) makes more sense to my brain. In addition, “Before” seems easier to tweak if I messed something up. That’s probably just the way I think. The “Instead” commands in my code tend to be code I’ve copied straight from the Recipe Book. Otherwise, I tend to use “Before…”

And now I see part of my misunderstanding. I had thought that “Check” was an earlier operation (that might not be the right word) than “Before,” but if I understand you correctly, I’ve had it backwards.

So, If I were to create a new action called Gruffling:

Check is used to set up the circumstances that will allow or prevent Gruffling from succeeding most of the time.

Carry Out changes the state of the game (if necessary) when Gruffling succeeds.

Report “says” whatever the parser tells the player when Gruffling succeeds. I’m a little unclear on this one. I have usually added "Say ‘…’ " to my Carry Out statements. Does Report do the same thing? If Gruffling would always and only produce the response “What are you talking about?” in every circumstance, could I skip the Carry Out and go straight to Report?

Before will run commands dealing with exceptions to how Gruffling normally works and it may or may not stop the program from getting to the Check stage.

Instead is a bulldozer that will universally stop the program from ever getting to the Check stage. Gruffling will not succeed.

After will run commands only after Gruffling succeeds and will prevent “Report” from running. Instead will prevent After from running and Before might do so if I “Stop the action.”

Do I have it right?

The progression goes something like:

  • “Reading a command” rules get some text from the player.
  • The parser attempts to turn that into an action. Failure here means it can’t even figure out what action you wanted to attempt, so no time passes.
  • “Before” rules run. These are generally used to redirect one action to another, without doing any processing at all on the original action: “before opening the desk, try opening the desk drawer instead”.
  • Precondition rules run. These ensure that the action is broadly possible. If the action requires something to be touched, the preconditions check that it’s not locked in a case; if it requires light, the preconditions check that you’re not in the dark.
  • “Instead” rules run. These are generally used to override all the usual checks, for special cases in the game. If you want something special to happen when you try to bite a rock, for example, you don’t want the game to object that it’s not edible, so an “instead of eating the rock” rule is perfect.
  • “Check” rules run. These are generally used to see if the normal, default behavior of the action is possible, and if it’s not, explain why. This is where we check if something eaten is edible.
  • “Carry out” rules run. These are generally used to execute that normal, default behavior, once we know it’s possible. For eating, remove the eaten thing from play.
  • “After” rules run. These are used for two different purposes: one, for aftereffects of an action that only run if it happened as expected, and two, to override how an action is described—it’s already been processed, but nothing has been printed yet. This is a very easy source of bugs! So I recommend only using it for the second one.
  • “Report” rules run. These are generally used to describe that normal, default behavior, if not overridden.

Generally, the Check, Carry out, and Report rules are written by the person creating the action (which is the standard library for all the default ones), while the Before, Instead, and After rules are written by the person creating the game (i.e. you).

1 Like

So in other words, the reason to use an “instead” rule instead of a “before” rule is that the preconditions will already have been checked—a “before opening the magic box” rule will run even if you’re locked in a cage and can’t reach it, but an “instead of opening the magic box” rule won’t.

And the reason to use a “check” rule instead of an “instead” rule is that all the instead rules run before any of the check rules run. So if game-specific code goes in “instead” and standard functionality goes in “check”, you can be sure your game-specific code always gets to handle the special cases before the normal processing takes over.

1 Like