Limiting/requiring vehicle use

Ok, there’s an awful lot going on here, but I think its all related.

I’ve got three locations the player is allowed to drive to/from: Street1, Street2, and the Park. I set them up as roads and made the other locations in the game “offroad” as in Example 104, “No Relation.” I put an enterable vehicle (the Car) in Street 1.

So far, so good. The player can only drive between those three locations and can’t take the car anywhere else.

Here is where my trouble begins. I have two characters the player plays as over the course of the game. One character is described as loving the car - I don’t want him to walk around Street1, Street2 and the Park. He should only drive from place to place and refuse to walk.

The second character doesn’t know how to drive. He should be able to enter the car to find objects inside, but he should refuse to drive and insist on walking when the player tries to take him around Street1, Street2 and the Park.

(Honestly, it winds up sounding like that “One guard only tells the truth, one guard only tells lies” riddle, doesn’t it?)

Since the number of streets is limited, I can do

Instead of going from Street1 to the Park when the player is not in the car:	
	if the player is John:
		say "Why walk when you can drive?";
	if the player is Steve:
		now the player is in the Park.

or similar a bunch of times, but I know there must be a more elegant, DRY solution. I tried

Instead of going from one road (called the start) to a second road (called the destination) when the player is not in the car:
     if the player is John:
		say "Why walk when you can drive?";
	 if the player is Steve:
		now the player is in destination.

but the parser doesn’t like that. I know I’ve seen similar constructions for this kind of problem…I’m just having trouble constructing it myself.

Additionally, (and I swear this relates to stuff in the first question) the player eventually will acquire a raft they need to float from the Park to an island in an adjacent lake. I installed Rideable Vehicles, of course, but I’m running into two puzzlers:

  1. The raft should only float between the park and the island, but the road/offroad setup from “No Relation” would allow the raft to go among all the road-designated rooms. And if I make the Island a road in the first place, it would also allow the car to drive from the park to the island. Not what I’m looking for.

  2. Rideable Vehicles seems to remove the behavior where, if the player is on a supporter, they can move in a direction without using a turn on “Get off bed” or whatever. I’m looking to keep the behavior where the player goes south and the parser says “(first getting off the bed)”. I had the behavior I wanted before I included the extension, and it came back when I commented it out.

That was a lot, but it’s all sort of tangled up together in one big vehicle- and vehicle-extension knot in my head. I’m trying to learn on my own through the docs and examples (honest!) but sometimes instruction does the trick. Any help is much appreciated.

So this:

Instead of going from one road (called the start) to a second road (called the destination) when the player is not in the car:
     if the player is John:
		say "Why walk when you can drive?";
	 if the player is Steve:
		now the player is in destination.

looks like it’s almost ready to compile–the issue is that instead of saying “from one road… to another road…” you just need to say “from a road” and “to a road.” This is one of those “Inform isn’t really English” moments–when you’re writing a rule header to check whether you’re dealing with something of a particular kinds, you just write “a this-or-that” even if some other words like “another” would be more natural in English.

There are some other things you can do to make this neater, as well:

Instead of “Instead” use a “check” rule. This will let you stop the action in the case where you want to stop it, and let it proceed through the standard action machinery in the case where you want it to continue.

As well as “from” and “to” there is an action variable for going called the “vehicle gone by” which you can invoke with “by,” which lets you tighten up your rules a bit.

So:

Check going from a road to a road when the player is not in the car and the player is John:
     say "Why walk when you can drive?" instead.

(The “instead” in the rule stops the action, so you don’t proceed to going.)

Check going by the car when the player is Steve:
     say "You can't drive." instead.

(Another point is that in both these cases we could actually stick to “Instead” rules, since if the player is Steve the first rule won’t even run, so the regular going rules will still run. But, it’s a good habit to handle these by “check” rules.)

Also, I haven’t tried to run this code myself, so you should check and see if it works! It could be wrong.

Sounds like maybe you need to make a separate roadlike kind, like in addition to “road” you could make a “waterway” kind, a “landlocked” adjective for something that’s not a waterway and have a similar rule for “instead of going by the raft to somewhere landlocked.”–In fact, now that I think of it, you might want to change the code so that instead of being kinds of rooms, “road” and “waterway” were adjectives applied to the rooms, so you can make the Park both a road and a waterway.

This is because “Rideable Vehicles” includes the line The stand up before going rule is not listed in any rulebook. This takes away the rule that provided the (first getting off the bed) behavior.

We don’t want to completely restore the rule, because it would make the player exit a rideable vehicle before going anywhere, which would spoil the point of the rideable vehicle. But we can copy the rule from the Standard Rules and add a clause that makes sure it doesn’t apply when the player is on a rideable vehicle:

Include Rideable Vehicles by Graham Nelson.

Park is a room. Drive is north of Park. 

The hoverboard is a rideable vehicle in Park. The bench is an enterable supporter in Park.

Check an actor going when the actor is on a supporter (called the chaise)
	(this is the new stand up before going rule):
	unless the chaise is a rideable vehicle:
		if the actor is the player:
			say "(first getting off [the chaise])[command clarification break]" (A);
		silently try the actor exiting.

(I did check this one, but I didn’t check what happens if the player is somehow in an enterable supporter that’s inside a rideable vehicle. If that is something that is possible for you, you might want some more complicated behavior.)

3 Likes

Wow, that’s really helpful! I can’t wait until work is over and I can try some of this out. Thanks!

1 Like

Matt’s got you covered, but I’ll also plug Recipe Book §8.1. Bicycles, Cars and Boats http://inform7.com/book/RB_8_1.html

Example 27 Peugeot demonstrates how to limit travel by vehicle, and this can be further delineated by character with rules.

Example 104 No Relation shows how to make a “road” kind of room that requires a vehicle.

Another way to handle that would be to restore the rule but give it an extra condition. This is usually my preferred method of overriding the standard rules for specific situations (other than using an Instead rule), and arguably what Rideable Vehicles should have done instead (but I assume it didn’t because this syntax isn’t something you could do in older versions of I7):

The stand up before going rule is listed in the check going rulebook.
The stand up before going rule does nothing if the actor is enclosed by a rideable vehicle.
The stand up before going rule does nothing if the actor is enclosed by a rideable animal.

The first line simply restores the default behaviour (as if Rideable Vehicles never removed it). The next two disable the rule for the required cases.

3 Likes

Ooh, I didn’t know you could do “is listed in”! Yes, I think it would have been more modern for the Rideable Vehicles extension to use the “does nothing” to conditionally disable the rule, instead of delisting it completely.

This seems very much like what i’m trying to do. I’m trying to find a way to make a condition that you have visited certain passages in order to open up a new passage. This would work for a car too, the story would just follow a certain passage once you have selected enter car.

(Another point is that in both these cases we could actually stick to “Instead” rules, since if the player is Steve the first rule won’t even run, so the regular going rules will still run. But, it’s a good habit to handle these by “check” rules.)

Looking at my code, I’ve been using Instead in a lot of places, but it seems like I should be using Check. I think I understand Instead better than Check because Instead does what it says on the tin, you know? Is there a reason Check is preferred to Instead? Is there an example of when Instead is better than Check? I’m just trying to wrap my head around the best way to use my tools.

(I can take this to a new thread if you think it’s more appropriate and might be useful for others down the line.)

There’s a whole page in the manual but it mostly amounts to “it depends”.

It’s a bit situational, but the rule of thumb that I usually use is that where there’s a specific action for a specific item that I want to completely override all the usual rules, I’ll use Instead. Where there’s only a tiny change I want to the standard behaviour, I’ll usually use Check/After.

When I’m defining an entirely new action I’ll usually write Check/Carry Out/Report for the “usual cases” (usually for groups or classes of items, and not anything specific) and then sometimes also an Instead for a special case specific to a particular item in the story.

Mostly it just affects the order in which the rules are run, and thus which particular error is printed when something breaks a rule. A good way to visualise this is to look in Index → Actions and click on the magnifying class next to the appropriate action (sometimes it’s easier to find it in Commands first, sometimes not). That will show you all the related rules and which order they run in.

1 Like

The main difference between “Instead” and “Check” rules is that an “Instead” rule will by default stop the action from running completely, unless you tell it to keep running with “continue the action,” and a “Check” rule will by default let the action keep going, unless you tell it to stop the action with “stop the action” or “instead.”

The main reason I liked using “Check” here is that it avoids this trap:

Instead of going from a road to a road by the car:
    if the player is Steve:
        say "You can't drive."

This would run even when the player isn’t Steve, which would mean that if the player was John going from a road to a road by a car would fail silently! You didn’t have this, of course… but I do tend to prefer using check for “make the action fail in these circumstances, otherwise let the usual action proceed” kind of cases. As Gavin says, it depends though.

One thing where Instead is useful is if you want to replace the whole action mechanism–you want to do specific stuff in one case that goes outside the action mechanism. Like this:

Instead of going by the car when the player is Steve:
    say "You attempt to start the car, but you somehow fall out the door and empty your pockets instead.";
    now the player is in the location;
    now everything carried by the player is in the location.

This was a little like what you were doing by having the Instead rule move the player in the “good” case, but that was a case where you might well want to use the standard action mechanisms, which was one reason I thought it could be a Check–though as you mention it doesn’t really make a difference once we make the rule more specific to the “bad” case.

Agree with the above but want to add one more difference: you can use instead rules with multiple actions, such as:

Instead of dropping or inserting the ball into:
	say "You need to keep that for now."

You can’t use a single check rule for that. (Although you could just write two separate ones.) Why? Because each action as its own set of Check, Carry out, and Report rules. On the other hand, there is only one Instead rulebook which runs in the appropriate spot for all actions. This is also true for the Before and After rulebooks.

1 Like

And on the flipside, this also means that a game with a ton of Check rules will run faster than a game with a ton of Instead rules. You have to have a truly enormous game for this to matter much, though.

1 Like

So I’ve got this situation where there’s a floppy disk attached to a filing cabinet with a magnet. (Yes, I know.) If I want to simplify the process of getting the disk and the magnet, these two Instead rules are probably ok, since I’m changing the whole action:

Instead of taking bootdisk:
	if the player is John:
		if John has the bootdisk:
			say "You've got that already.";
		if bootdisk is in diskdrive:
			say "You remove the boot disk.";
			now John has bootdisk;
		otherwise:
			say "You prise the magnet off the side of the filing cabinet and catch the boot disk midair as it falls.";
			now the player has the magnet;
			now the player has the bootdisk;
	if the player is Steve:
		say "You don't need the disk - it's probably melted in the smoking ruin of the computer anyway."
	
Instead of taking magnet:
	if the player is John:
		if John has the magnet:
			say "You've got that already.";
		otherwise:
			say "You prise the magnet off the side of the filing cabinet and catch the boot disk midair as it falls.";
			now the player has the magnet;
			now the player has the bootdisk;
	if the player is Steve:
		say "You don't need to stick anything to anything metal, so you leave the magnet where it is."

But this other Instead I’ve written elsewhere

Instead of closing drawer:
	if the player is John:
		say "You don't go around tidying up after yourself.";
	if the player is Steve:
		now the drawer is closed.

is a better candidate for Check because I only want to change the behavior for one of the characters, and it saves me having to write the condition for Steve. Is that right?

All of those are vulnerable to suddenly blocking all the named actions if the player happens to be neither John or Steve. With Instead rules in particular it’s a good habit to get into never using if within the body of the rule (or at least never using it without a directly paired otherwise).

So you could write separate rules for each unique case:

Instead of taking magnet when the player is John and the magnet is carried:
    say "You already have that."
Instead of taking magnet when the player is John and the bootdisk is in diskdrive:
    ...

(Though you have to be a little careful with this; separate rules are not necessarily run in the order declared, so things can sometimes surprise you.)

But actually there’s other problems with your original rules above – if John takes the magnet, then drops it, then takes it again, they’ll end up prising the magnet off the cabinet again and acquiring the bootdisk – no matter where it actually has ended up at this point. Similarly if John takes the bootdisk that he already has, he will mysteriously reacquire the magnet no matter where it was.

Given that there are standard rules already for reporting failure to take things you already have, I wouldn’t write most of those rules at all; instead just have something like:

After taking magnet when magnet is not handled and bootdisk is not carried:
    try silently taking bootdisk;
    if bootdisk is carried:
        say "You prise ... " instead;
    continue the action.

Instead of taking bootdisk when the player is Steve: say "Nope, it's melted."

Steve’s Instead rule will block him from taking it – although note that the rule can only possibly trigger if Steve is in a room with the bootdisk, which doesn’t entirely fit with the text you were printing – which means that the After rule cannot possibly be reached by Steve, so you don’t need to check the player again there. Since it’s an After rule, Inform has already verified that the magnet was in the location, not currently held, and successfully taken, so you just need to add the special effect of also taking the bootdisk – and here this is trying it as an internal action so that if it’s taken in a location where the bootdisk isn’t available then it won’t do anything.

The extra check for magnet is not handled prevents an issue where otherwise the player could take the items, drop them both, and then take just the magnet and wind up mysteriously prising the magnet and bootdisk off the cabinet again.

There are other ways to do this, of course – if you want to get fancy you can actually model the “magnet stuck to things” relation and allow the player to use the magnet to stick other things to the cabinet or other objects, and make it so that if they take magnet then the stuck items fall to the floor, but if they take [thing stuck by magnet] then it will carry out implicitly taking for the magnet as well.

It’s 2am for me right now so I’m a bit too asleep to give that a go, but it’s a fun idea.

1 Like

Thanks, Gavin! Looks like I have a lot of thinking to do about how I’ve been doing things.

With special-effect taking rules you should always be careful to either check handled or use for the first time to avoid issues with the player dropping and re-taking an item unexpectedly triggering it, unless it is something you want to happen every time.

Actually on further reflection this probably wouldn’t quite work, since the carry out rule will add handled and the rule will never trigger. It’s probably sufficient to just say this though:

After taking magnet when bootdisk is not handled:

Also, you might want to have a look at the Electricity and Magnetism example. It’s not quite what I was thinking of, but it does demonstrate a way of having things get stuck to a magnet and get automatically picked up with it.

I wanted to pop in and say that redoing one of my puzzles with Check rules instead of my many, many nested Instead rules worked like a charm. Lesson learned!

1 Like

FYI here’s a fairly compact way of handling the boot disk and magnet relationship. It doesn’t do the extra things (like different reactions for different players, or being able to stick the magnet to other things), but perhaps it will give you some ideas.

Small Office is a room.
"An unremarkable office space, except for the complete lack of any doors."

A filing cabinet is in Small Office.  It is fixed in place and a supporter.

A magnet is on the filing cabinet.
"A magnet haphazardly sticks the boot disk to the filing cabinet."

A boot disk is part of the magnet.

Instead of taking disk when disk is part of the magnet, try taking magnet.
After taking magnet for the first time:
	now the player carries the boot disk;
	say "You carefully pry the magnet off the filing cabinet, taking the boot disk as well."

If you want to be able to stick the magnet to other things, the “Brown” example in §3.23. Parts of things shows off a label that can be stuck and removed, which would be similar (except perhaps for limiting it to only ferrous things, which you could define as an additional property and condition), or something a bit grander like the “Rules of Attraction” example that I mentioned previously.

FYI since it seems generally useful (despite being a trivial extension) I’ve packaged up the amendment to Rideable Vehicles as its own extension.

1 Like