The Foxaroo tinkering around with Inform7

Just to prove to everyone that I do sometimes solve problems on my own, I completed my rudimentary test of using tables to create a gnome character who moves the treasures outside the building into the building by following instrucitons from a table.

[code]“Treasures”

Building is a room. “You are inside a building, a well house for a large spring…”

End of road is a room. “You are standing at the end of a road before a small brick building.” End of road is west of Building. End of road is outside from Building.

The player is in building. The Gnome is a man in building. The Gnome has a number called G_Seq. The G_Seq of The Gnome is 1.
Persuasion rule for asking someone to try doing something: persuasion succeeds.

A treasure is a kind of thing. A treasure has a number called treasure_points.

Some treasures in the Building are defined by the Table of Treasure Scores. The description of a treasure is “[treasure_description]”.

Table 1.0 - Treasure Scores
Treasure Treasure_start treasure_points treasure_description
Gold nugget End of road 10 “Sparkly”
Diamonds Building 20 “Glittery”
Silver bars End of road 5 “Smooth and silvery”
Jewelry Building 5 “Assorted gems and trinkets”
Rare coins End of road 10 “Varied”
Emerald Building 25 “The size of a plover’s eg”
Platinum Pyramid End of road 30 “30 inches on a side”
Pirate’s Treasure Building 30 “Nondescript”

Check examining a treasure:
instead say “The [The noun], [description of the noun] is worth [treasure_points of noun].”

When play begins:
repeat with item running through treasures:
move item to the Treasure_start of item.

Table 2.0 - The Gnome’s actions
Gnome_moves Gnome_takes Gnome_drops
End of road – --
– Gold Nugget –
Building – --
– -- Gold Nugget
End of road – --
– Silver bars –
Building – --
– -- Silver Bars
End of road – --
– Rare coins –
Building – --
– -- Rare coins
End of road – --
– Platinum Pyramid –
Building – --
– -- Platinum Pyramid

Every turn:
let N be the G_Seq of The Gnome;
if N minus one is less than the number of rows in the Table of The Gnome’s actions:
choose row N in the Table of The Gnome’s actions;
if there is a Gnome_moves in row N of the Table of The Gnome’s actions:
let last space be the location of The Gnome;
if The Gnome can be seen by the player, say “The Gnome heads to [the Gnome_moves entry].”;
move The Gnome to the Gnome_moves entry;
if The Gnome can be seen by the player, say “The Gnome arrives from the [the last space].”;
if there is a Gnome_takes in row N of the Table of The Gnome’s actions:
try The Gnome taking the Gnome_takes entry;
if there is a Gnome_drops in row N of the Table of The Gnome’s actions:
try The Gnome dropping the Gnome_drops entry;
say “The Gnome is at turn sequence [G_Seq of The Gnome]”;
increase the G_Seq of The Gnome by 1.
[/code]

Though what you see is all you get I became interested in what it would be like to have friendly helper characters in Colossal Cave. Has anyone re-created any Inform7 versions of Colossal Cave with the source code provided? Failing that, if I do need to create the whole thing from scratch (time cosuming but not that difficult) does anyone know of any comprehensive maps of the game?

There’s this thread: I7 port of Crowther's Colossal Cave looking for testers

I don’t know what happened to it, though.

Oh, I’m still around, and my latest unreleased version fixes a few bugs people have reported in the meantime. My decision to hold off on a release until after the next version of I7 seemed like a better idea 2 years ago, though…

LOL! :laughing:

Life has it’s twisty little turns, all unalike. Does it not? :wink:

(To all)
Anyway, I decided to make it a project of my own and it’s going well. This one has proved far less challenging than my earlier project and is proving a useful learning exercise. Best of all it doesn’t matter if my health problems take me a way from the project for a few days because it’s so simple that I can resume where I left off without having to remember what I was up to.

I’m up to creating the steel grate, and Inform is behaving oddly.

This is what should happen:

This is what’s happening instead:

(Gah! No kidding Inform?)

Tried this, it didn’t help:

Does the player mean unlocking the keys with the keys: it is very unlikely. Does the player mean unlocking the steel grate with the keys: it is very likely.

I also tried:

Does the player mean unlocking the steel grate: it is very likely.

No good - compilation error.

Suggestions?

I think you need to use a “for supplying a missing noun” rule here. That’s what I did, anyway.

No, that has no effect on the unlocking action. (With the standard grammar.)

See discussion in this thread: Unlocking Issue: Handcuffs?

You should try:

Does the player mean unlocking the steel grate with: it is very likely.

However, my advice in this situation is always to not worry about it. The parser tends to pick objects arbitrarily when there’s a single portable object in scope, but nearly always the player will have more than one object lying around, so you won’t get that response anyhow.

Thanks Zarf, that worked a treat!

I’m going to have to read that thread a few times though to understand it. Inform is a highly capable language… also highly complex for those like myself who get mentally stuck on little details. :blush:

Latest problem:
In the Colossal Cave Adventure there were steps linking the rooms “Top of Small Pit” and “Hall of Mists”, and which were part of a puzzle involving a large gold nugget. The nugget was too heavy to lift up the steps.

You had to carry the nugget to the Y2 room and use the magic word “Plugh” to return to the building. An alternative solution was to wander around until the pirate stole the nugget, then retrieve it from his hiding spot and descend from the maze into the Splendid Chamber.

(In fact if you succeeded and then went back to the Top of Small Pit and then tried going down the steps while carrying it you would suffer a fatal fall.)

The description of the stairs themselves would be removed from the room descriptions whenever the nugget was in the player’s inventory. It took me a bit of fiddling around, but I eventually figured out how to control that (I do sometimes succeed in solving my own problems). The below code works, I’m just looking for opinions as to whether it’s the most straightforward approach?

[code]A room called Top of Small Pit is west of Splendid Chamber. “At your feet is a small pit breathing traces of white mist. An east passage ends here except for a small crack leading on.[spiel for rough stone steps]”.

The rough stone steps is down from Top of Small Pit and up from Hall of Mists. The rough stone steps is an open door. The rough stone steps is not openable. The rough stone steps is scenery.

To say spiel for rough stone steps:
if the player does not carry the large gold nugget:
say "[Line break][Line break]Rough stone steps lead [if the player is in Top of Small Pit]down the pit[otherwise]up the dome[end if]. "; [Note, the space after the full stop is to prevent a superfluous line break]
otherwise:
stop the action.

Hall of Mists is a room. “You are at one end of a vast hall stretching forward out of sight to the west. There are openings to either side. Nearby, a wide stone staircase leads downward. The hall is filled with wisps of white mist swaying to and fro almost as if alive. A cold wind blows up the staircase. There is a passage at the top of a dome behind you.[spiel for rough stone steps]”.[/code]

You can drop the “otherwise: stop the action” lines. They don’t do anything.

“[Paragraph break]” does the same thing as “[Line break][Line break]”. (In this case, anyhow – there may be subtle differences in other cases.)

The code becomes very slightly simpler (albeit weird-looking) if you shift the period around:

A room called Top of Small Pit is west of Splendid Chamber.  "At your feet is a small pit breathing traces of white mist. An east passage ends here except for a small crack leading on[spiel for rough stone steps]."

To say spiel for rough stone steps:
	if the player does not carry the large gold nugget:
		say ".[Paragraph break]Rough stone steps lead [if the player is in Top of Small Pit]down the pit[otherwise]up the dome[end if]"

Hall of Mists is a room. "You are at one end of a vast hall stretching forward out of sight to the west. There are openings to either side. Nearby, a wide stone staircase leads downward. The hall is filled with wisps of white mist swaying to and fro almost as if alive. A cold wind blows up the staircase. There is a passage at the top of a dome behind you[spiel for rough stone steps]."

This way you don’t have to stuff in a spurious space.

[EDIT: Hadn’t seen your post above yet Zarf]

For my colossal cave adventure remake I created an electric light simply named “Lamp” (I was going to change its name later to “brass lamp” and expand the descriptions). Worked fine but I grew tired of typing “Turn lamp on” and put in some code so I could just say “Light lamp.” That’s when I found out that the two states work independently. Initially I used “now the lamp is switched on” / “off” and found that this did not in fact change whether or not the lamp was producing light. So I changed to “now the lamp is lit” / “unlit”. This worked to control the lighting, but alter the lamp’s on/off state. Eg: The lamp could be giving off light but when told “Turn lamp off” the player may be told “The lamp is already off.”

The final code I implemented works OK, but it’s odd that I need to alter both states. Is there a better approach?

[code]Understand the command “light” as something new. Understand “Light [something]” as lighting. Lighting is an action applying to one carried thing.
Does the player mean lighting the lamp: it is very likely.
Instead of lighting the lamp:
now the lamp is lit;
now the lamp is switched on;
say “Your lamp is now on.[Line break]”.

Extinguishing is an action applying to one carried thing.
Understand “extinguish [something]” as Extinguishing.
Does the player mean extinguishing the lamp: it is very likely.
Instead of extinguishing the lamp:
now the lamp is unlit;
now the lamp is switched off;
say “Your lamp is now off.[Line break]”.[/code]

Thanks Zarf!

Didn’t know about [Paragraph break]. I’ll have to commit that one to memory. I’ve re-read chapter 5.8 now and hopefully I’ll be better familiar with those special codes. Trouble with these things is that you have to actually USE them at least once before you mentally acknowledge that they exist.

I moved the full stop to the end of the spiel because it was appearing as a double full stop on the previous line. Other than that it works and is much simpler than mine, thanks.

(I think I had some other approach in mind when I originally wrote the “stop the action” line and I’ve completely forgotten what it was for now.)

I’m still hopeful that someone can let me know if the below code is the most efficient way of turning an electric light kind on & off in Inform (see my earlier post about the difficulties I had with the differences between lit/unlit & on/off)

[code]Understand the command “light” as something new. Understand “Light [something]” as lighting. Lighting is an action applying to one carried thing.
Does the player mean lighting the lamp: it is very likely.
Instead of lighting the lamp:
now the lamp is lit;
now the lamp is switched on;
say “Your lamp is now on.[Line break]”.

Extinguishing is an action applying to one carried thing.
Understand “extinguish [something]” as Extinguishing.
Does the player mean extinguishing the lamp: it is very likely.
Instead of extinguishing the lamp:
now the lamp is unlit;
now the lamp is switched off;
say “Your lamp is now off.[Line break]”.[/code]
Now my latest problem, and I’ve been struggling with this on & off over the course of a couple of months.

The crystaline bridge in Colossal Cave linked the two sides of the fissure to the west of the Hall of Mists (2 adjacent rooms), but only after the player waved the black rod, and the bridge could be made to dissapear again the same way. Therefore I need a manipulable bridge. The bridge is visible in both locations and its very presence permits egress. The obvious conclusion: the bridge is an Inform door.

The crystaline bridge is west of East Bank of Fissure and east of West Side of the Fissure. The bridge is an open door. The bridge is not openable. The description of the crystaline bridge is "A crystalline bridge now spans the fissure." (Code adapted from chapter 3.12 of the manual).

Now I was expecting it to be very easy to manipulate the bridge in and out of gameplay, but all my attempts have failed. (Leaving me with serious doubts as to whether I’m smart enough to be playing with Inform in the first place).

Inform immediately rejected me removing and replacing the bridge from play, saying that this is not allowed on doors.

Re-mapping the bridge’s connections involving two limbo rooms didn’t work either. It had to be worded carefully to prevent the player ending up trapped in one of the limbos, and even when the connections worked I still couldn’t get the bridge into view.

My final idea was to use concealment. I suspect that concealment was probably used on the final puzzle of Zork II; the door that was invisible until the player switched off their lamp and then became permanently visible in light or dark. However I haven’t been able to determine the syntax for concealing objects that are not poessions of a particular actor.

Googling around I found that there’s an extension by Krister Fundin that permits hidden doors. Is this extension necessary, or is there a simpler way?

I hope I’m making sense. I’m on the verge of coming down with another cold, my third in only two months.

Is the bridge a room? You can manipulate exits easily enough, but if the bridge is a door, there’s no simple way to move it around. The hidden items extension is the simplest way. It does all the nasty hackery for you.

Concealment (the I7 “undescribed” property") is a valid way of handling this. An undescribed door is not passable, exactly for cases like this. The extensions probably make use of this.

Another approach is to not make the bridge a door. Instead, make a normal map connection, and two “bridge” objects. Move the bridge objects into the two rooms at the appropriate time. Then:

Check entering the west-side bridge:
	instead try going east.
Check going east from the West Side when the west-side bridge is not in West Side:
	instead say "The chasm is impassable."

Inform’s parser and world model are not derived from Infocom’s. Infocom doors wouldn’t have had the same restrictions (or abilities!) that Inform doors have.

Inform7 indeed tracks the “lit” and “switched on” states separately, and AFAIK there’s no way to automatically synchronize those states with something like “the lamp is lit if it is switched on.” However, what you can do is make the “switching on” and “switching off” actions also update the “lit” state, and then handle commands like “light lamp” with “Instead of lighting the lamp, try switching on the lamp.” like this:

The Maze of Twisty Little Passages is a dark room. "You are in a maze of twisty little passages, all alike."

The lamp is a device. It is switched on. It is lit. The player carries the lamp.

Carry out switching on the lamp: now the lamp is lit.
Carry out switching off the lamp: now the lamp is unlit.

Lighting is an action applying to one thing.
Understand "light [something preferably held]" as lighting.
Check lighting: instead say "You're not sure how to light [the noun]."

Extinguishing is an action applying to one thing.
Understand "extinguish [something preferably held]" as extinguishing.
Check extinguishing: instead say "You're not sure how to extinguish [the noun]."

Instead of lighting the lamp, try switching on the lamp.
Instead of extinguishing the lamp, try switching off the lamp.

Note that, since the updating of the “lit” state is handled using “carry out” rules, the normal action processing rules for switching the lamp on and off (which just update the “switched on” state and report it) still run. For our new verbs, however, the “instead” rules cause the normal processing (defined by the “check” rules above) to be skipped for the lamp.

In fact, in this specific case, it would’ve been even easier to just tell Inform to understand “light” and “extinguish” as synonyms for switching on and switching off respectively. In a more complex story, however, this might produce unexpected responses: on one hand, we might want to include light sources that are not devices; on the other hand, a command like “light blender” should probably not succeed.

Also note that there might be situations where it might be meaningful for the “lit” state not to always track the “switched on” state: for example, if the lamp was out of batteries, switching it on should not make it light up. The Inform model is flexible enough to allow this, but tracking the state transitions (and supplying appropriate messages to the player in each case) becomes somewhat more complicated. (Of course, an alternative approach would be to just make the lamp turn off when the batteries run out, and disallow turning it back on until they’ve been replaced.)

Thanks Vyznev, that covers it nicely and I can shorten a lot of code now.

Thanks for directing attention to that. I’d forgotten to add code to produce an error message when the player attempts to light something other than the lamp. Done!

Creating “light” and “extinguish” as synonyms for switching on and switching off sounds even more convenient. I haven’t created synonyms for verbs yet (just nouns). I tried a few times, but couldn’t get it right. What’s the correct syntax?

Also, if I want to include the command “Blow lamp out” (even though the lamp is electric) how would I implement this? Inform hasn’t been too happy about me using the word “Out” due to its reservation as a direction.

Yes the extension worked superbly. I didn’t even have to write in any tricky code; it worked exactly as it appeared in the instructions. Kudos to Krister Fundin; I think this is a feature that should be standard.

To answer the question; no the bridge itself doesn’t serve as a room. However your idea would have been my 2nd choice if the hidden doors extension hadn’t worked. A similar approach was used in my (on hiatus) Dr Who I7 project where I needed to re-direct the TARDIS’ exit to variable locations, and that worked especially well.

Wouldn’t ZIL have had it’s own version of concealment though? Or did they simply move objects in and out of play? I’d need to jog my memory a bit, but I can recall there was a button hidden in the library in the murder mystery “Deadline” which only appeared to the player if they watched the murder victim’s son opening the secret passage. Same for the holes that gardner McNabb finds in his garden; they don’t appear until he shows them to you.

You could just tell Inform to understand those commands as denoting the switching on/off actions, like this:

Understand the command "light" as something new. [Remove old synonym "light" -> "burn".]
Understand "light [something]" as switching on.
Understand "extinguish [something]" as switching off.

(By the way, I realized that I forgot to include the “Understand the command “light” as something new.” line in my earlier example, which meant that Inform was still treating “light” and “burn” as synonyms. The reason it still worked is that I’d specified “light [something preferably held]” as the command for lighting, and the “[something preferably held]”, being more specific, took precedence over the “burn [something]” command for the built-in “burning” action. However, as a side effect, “burn lamp” would also be understood as lighting the lamp. If you use my example code from above, you’ll probably want to add that line before the definition of the lighting action.)

I’m not sure why you’re having problems with it. The following works just fine for me.

Blowing out is an action applying to one thing.
Understand "blow [something] out" and "blow out [something]" as blowing out.
Check blowing out: instead say "You huff and puff as hard as you can at [the noun], but nothing happens."

[Blowing out the lamp is something the player might actually try. Let's provide a better message for that.]
Instead of blowing out the lit lamp: say "You huff and puff as hard as you can at the electric lamp, but nothing happens. Maybe you should just try switching it off?"

Alternatively, instead of creating an actual “blowing out” action, you could just designate those commands as mistakes:

Understand "blow [something] out" and "blow out [something]" as a mistake ("You huff and puff as hard as you can at [the noun], but nothing happens.")

Understand "blow [lamp] out" and "blow out [lamp]" as a mistake ("You huff and puff as hard as you can at the electric lamp, but nothing happens. Maybe you should just try switching it off?").

A subtle difference between these two solutions is that mistakes don’t take a turn, whereas actions do. If your game isn’t particularly time-sensitive, it probably doesn’t matter, but it’s worth keeping in mind. For instance, “every turn” rules don’t fire after mistakes, so if you have, say, other characters moving around every turn, then the difference might matter. In this case, since the message I chose to give for trying to blow something out involves the player actually doing something, it probably should consume a turn, and so a real action might be the better choice. But with a different message, a mistake might be preferable.

Also, mistakes always take precedence over actual actions, so defining “blow [something] out” as a mistake would prevent you from using it as a valid action if you did want to let the player blow something out. However, you could work around that by defining the mistake as, say, “blow [something nonblowable] out”, and then adding, say, “Definition: a thing is nonblowable if it is not a candle.” to your code. That said, just using a real action is IMO better here anyway.

I can’t really recommend making “light” and “extinguish” global synonyms to switching on/off unless you can come up with a default response that reasonably covers both verbs ( >LIGHT PANTS – “That’s not something you can switch”). It also assumes that the lamp is the only item in the game that can be switched on or lighted (or that the same coupling applies to every such item).

I think simply doing this works to create a special case for the lamp (can’t test it right now):

Understand "light [lamp]" as switching on. Understand "extinguish [lamp]" as switching off.

One or the other. I’d have to look at the decompiled source code to tell, and that’s a lot of work.

(Did Allen wind up making a decompile-metadata file for Zork 2? I don’t remember.)

My point is, I7’s data structures are not compatible with moving doors into and out of play. But this was possible with I6, and I have no reason to think that it was a problem in ZIL.

Back to the lamp: Since “light” and “burn” are normally the burning action, I’d go with that:

Check burning the lamp: now the lamp is lit.
Check switching on the lamp: instead try burning the lamp.

This covers the turning-on half without any grammar changes, and it’s no big deal that “burn lamp” is also accepted.

Juhana suggests “Understand “light [lamp]” as switching on” but I avoid these special-noun-cased grammar lines unless they’re absolutely necessary. They muck up disambiguation, because Inform can only consider a single grammar line when generating disambiguation prompts.

I agree, which is why I didn’t do it that way in my original example. In fact, my personal rule of thumb is that, in most cases, every valid verb really should have its own action, even if the actual effects of those actions are just delegated to a single “master” action via “instead” rules.

Of course, it’s OK to map multiple verbs to a single actions they really are synonymous in all contexts, but if you start merging a lot of almost synonymous verbs that way, it makes writing meaningful default responses for them a lot harder. The Inform standard library does do that a lot, and it often gets away with it by making the output really generic, but it also often produces silly results. The default synonymization of “light” and “burn” is a case in point: there are plenty of things, like electric lights, which can be meaningfully lit but not burned.