Dialog release announcements

This is odd. I tried instantiating the Choice Mode example, and when compiling for z8, I get this:

Warning: A query is made to '(program entry point)', but there is no matching rule definition.
Warning: No release number declared.

In addition, it produces a story file that, when run, gives me a blank screen. The same happens when trying to compile the Cloak of Darkness example. I haven’t tried any others yet.

Sounds odd indeed.

Is there something wrong with your library file? That’s where the default release number is declared, and a rule for (program entry point) is defined.

…oh dear. Yes, that was my bad. I’ve been on hiatus and when I went back to Dialog, I didn’t check the manual for the inclusion of the library, I just looked at the command line instructions (–?), so in my grogginess I entirely overlooked the need for the library file.

Here is Dialog version 0k/03 (library 0.40).

Notable changes

  • When expanding a complex action (e.g. due to “TAKE ALL”), the library now prints the name of each object in turn, instead of spelling out the entire action.

  • “DOWN”, “UP”, and “OUT” (with some variations) are now understood as ambiguously referring to [leave $] and [go $] when the player is on a supporter, in or on a seat, or in a container, respectively. A rationale is in this post. Thanks @Karona!

Bugfixes

  • Debugger: When updating a running program, the debugger needs to match the (select) statements in the old and new versions of the code using a diff-like algorithm, in order to preserve as much of the game state as possible. The code for this has been reimplemented from scratch in a cleaner way. The old version had a bug that would sometimes result in the debugger reporting an “internal inconsistency in select”. Hopefully that bug is no longer present.

  • Debugger: No longer crashes when encountering output boxes while collecting words.

  • Library: Updating the environment around the player (the cache variables) before drawing the status line. Reported by @Karona.

  • Library: Allowing (from $ go $ to room $) to be invoked with just the first parameter bound, to backtrack over all exits.

  • Library: (perform [leave $]) now uses (move player to $ $) instead of setting the location of the player object directly.

  • Library: (them $) can now deal with a list argument.

Also, minor improvements to the optimizer.

8 Likes

Having built up a somewhat complex library (threaded conversation) and most of a full game (Sand-dancer, re-implemented in Dialog) I have to say that the each Dialog upgrade to a new versions has added features, but been virtually painless. Great backwards compatibility - that’s an accomplishment I appreciate.

6 Likes

I’m happy to release Dialog version 0k/04 (library 0.41).

Library

  • Open a closed container before stepping out of it. Thanks @JimB!

  • Don’t describe contents when opening a box from the inside. Thanks @JimB!

  • Fixed a bug where objects immediately inside a closed opaque visibility ceiling weren’t considered visible.

  • Added missing helper predicate: (Its $). Thanks @mount2010!

Compiler

  • Allow (now) together with a double-negated flag, such as in (now) ~($Obj is on) when @($ is on) is an access predicate for ~($ is off). Thanks @mount2010!

  • Warn if the last filename on the commandline does not refer to a library. Thanks @mount2010, @jcompton, @Karona, @Eleas! A file is considered a library if it defines a rule for (library version).

Debugger

  • Improved support for cursor keys in TTY driver.

Manual

  • Removed wrongly formatted CSS comments. Thanks @mount2010!
6 Likes

Dialog version 0k/05 (library 0.42) is out!

Group actions

When the player types something like “EAT OYSTER, HAM AND CHEESE”, the usual outcome is that three separate actions are tried in sequence, i.e. [eat #oyster], [eat #ham], and [eat #cheese].

This new feature lets you specify certain combinations of actions and objects that your code can deal with in a single go, e.g. as [eat [#oyster #ham #cheese]]. Read all about it in the new manual section on group actions.

Library improvements

  • The parser now deals properly with “and” and “,” inside object names, so that e.g. “TAKE BLACK AND WHITE PHOTOGRAPH” does not result in two separate attempts to take the same object.

  • (The $) and friends now list fungible objects with a definite article, i.e. “the N items” instead of “N items”.

  • Improved memory performance when working with fungible objects.

Compiler and debugger

  • An informative message is printed when attempting to display memory statistics from within the debugger. Thanks @Karona!

  • Fixed a bug in the Z-machine backend where (no space) would be ignored immediately after a unicode character. Thanks @jcompton!

  • Miscellaneous bugfixes.

7 Likes

At last.

The epic tale of Zork V: The Great Underground Sandwich Franchise can be told!

3 Likes

Here is Dialog version 0k/06 (library 0.43).

Default response

There is now a default perform-rule saying “You can’t” followed by the action description. So now, if you define some new grammar:

(grammar [transmogrify [object]] for [transmogrify $])

then you get this by default:

> transmogrify me
You can't transmogrify yourself.

This response is as bland as they get, so you’d normally want to override it. But this eliminates the dreaded blank response if you forget to create a fallback rule for a new action.

Opaque

The dynamic flag ($ is opaque) has been renamed to (opaque $), and the negated alias ($ is transparent) has been removed.

Opaqueness is nearly always a static property, and the new name reflects that. If some particular object can change from opaque to transparent, it is better to model this with a global flag:

#crystalball
(opaque *)      (crystal ball is opaque)

or perhaps compute it in some other way:

#crystalball
(switchable *)
(opaque *)      (* is on)

This change breaks compatibility with existing code. For most projects, it should be easy to search for “opaque” and “transparent” and manually change them to the new syntax. But it’s also possible to get the old behaviour back by adding the following definitions to the story code:

(opaque $Obj)           ($Obj is opaque)
@($Obj is transparent)  ~($Obj is opaque)

Other library changes

  • Changed the output of “exits” to make compass directions clickable if library links are enabled, and to use “the” instead of “a” for doors.

  • When default actions are enabled, the library no longer adds “open” as a dict-word for any open object. This prevents “open door” from being ambiguously understood as [open #door] and [examine #door] when the door is open.

  • “Hug” is now a separate action from “kiss”. Hug redirects to kiss by default, for backwards compatibility.

  • The default rules for NPC actions, (let $NPC ...), now invoke (notice $NPC) to set the pronouns.

  • When describing each step of a complex action, the object names are now clickable (if library links are enabled).

  • When printing a group of fungible objects with (the $), the plural name is no longer clickable. This is consistent with (the $) for ordinary objects.

  • The default rules now prevent cycles in the object tree when the player attempts to pick up an object that is their ancestor, such as a seat. Thanks @ifste!

  • The default rules for climb and enter now use (move player to $ $).

  • Miscellaneous bugfixes and optimizations.

Debugger

The debugger now imposes a limit of 50 undo steps, to conserve memory.

Undo states in the debugger are much larger than undo states in a normal interpreter. They contain information necessary for tracing, as well as references to old versions of predicates (to support modifications to the source code while the program is running). For large games with large transcripts, limiting the size of the undo history can save gigabytes of RAM and speed up testing substantially.

Manual

  • Added a section about creating custom grammar tokens.

  • Fixed an outdated example in the Items chapter.

4 Likes

Numbers in the range 90-99 are reserved for story authors … is there some reason why numbers greater than 99 are a problem? I just jumped up to 1000 or so for some grammar tokens inside the threaded conversation library; is that a problem?

My reading of that passage is that the standard library will always avoid using that range (and extension libraries probably too), so that the author of an individual story can always count on it to be free for their own use.

For example, if I wrote Scroll Thief in Dialog, I could use 90 for [spell], 91 for [zifmia-target], and so on—and I wouldn’t have to worry that a new standard library release, or a new version of Threaded Conversation, or a new extension that I install, would suddenly break that in inscrutable ways.

That’s one take; I don’t know the internals of the two machines, and was wondering if there’s an optimization based on size of that number (though I’d expect that to hit at either 127 or 255, for example).

Ahh, I see.

To my understanding, Dialog on the surface treats all numbers from 0 to 16383 in the same way.

On the Z-machine (don’t know about the Å-machine), there’s a certain low-level optimization for constant operands smaller than 256. But it only saves one byte per value, and only works with constants. So I wouldn’t worry about that.

(It’s a worthwhile optimization in general, of course, since there are a lot of small constants in a Z-machine program, and those single bytes add up. But the vast majority of those are e.g. branch offsets, loop counter increments, array indices, etc. Choosing a “small” vs “large” value for a magic number shouldn’t make any meaningful difference in the final code.)

Right, there is no particular reason to stay below 100 other than forward compatibility. Maybe larger numbers will represent something entirely different in the future, or maybe not.

There is no particular optimization of small numeric constants in this case.

“640k is enough”… the major pitfall in futureproofing design :smiley:

My suggestion is reserving from 8192 above, this should allow for eventually inplementing high-bit sign, and on top of it, allow also an egalitarian partition of the numbers between users and librarians :wink:

Best regards from Italy,
dott. Piergiorgio.

Get Dialog version 0m/01 (library 0.44)! Also make sure to get the companion release, Å-machine tools 0.5.1.

(There is no language version “0l”, for reasons of typography.)

New language features

  • Added (clear old) to clear, from the main area, any text that the player has already had a chance to read.

  • Added (clear div) to clear, hide, or fold away the current div.

  • Added (inline status bar $) ... for a status area that appears as an ordinary div inside the main area. The inline status bar is removed from display when a new one appears.

The above three features are optional, and can be ignored by interpreters. They are supported by the Å-machine web interpreter (0.5.1).

  • Added (interpreter supports status bar) and (interpreter supports inline status bar) to check for these features at runtime.

Library improvements

A number of minor tweaks and bugfixes, most notably:

  • The default behaviour is now to close doors before locking them. Thanks @ifste!

  • It is now deemed unlikely to put something where it already is.

  • Certain actions (commands and [inventory] by default) now preserve the current implicit action as set up by (asking for object in $) or (asking for direction in $).

  • Changed (narrate undoing) to (narrate undoing $), where the parameter is the player input being undone, as a list of words. The default rule prints this.

Compiler improvements

  • Frontend: At most ten interface violation warnings are reported.

  • Frontend: Increased maximum size of word-to-object maps.

  • All backends: (split word $ into $) and (get key $) now return digits as numbers. Thanks @Draconis!

  • Z-backend: If the interpreter doesn’t support the unicode bullet (U+2022), an * is printed instead.

  • Å-backend: Improved performance thanks to new Å-machine 0.5 features.

7 Likes

Get up to date with Dialog version 0m/02 (library 0.45)!

Library

  • SWITCH now only redirects to SWITCH ON if the object is switchable (and off). Thanks @Mikawa!

  • EXITS now properly prints the name of an inherently dark room that is lit up by an object. Thanks @ifste!

  • The output of (list objects $ $) no longer includes the current player.

  • Cleaned up the grammar rules to avoid ambiguous parsing of e.g. GET OUT as both [leave] and [leave $]. Thanks @hlship!

  • Added PROFFER as a synonym for GIVE.

  • Added HEY as a synonym for GREET.

  • Asterisk-prefixed input is now consistently ignored, also when typed in response to disambiguation questions and at the game-over prompt.

Debugger

  • Improved the algorithm for matching select statements when updating a running program.

  • Fixed an inconsistency in the interaction between (uppercase) and hyperlinks.

Manual

  • Added clarifications on how to use (plural name $) and (plural dict $) and fixed the corresponding example in the section on identical objects.

  • Miscellaneous improvements to Part I.

10 Likes

Dialog version 0m/03 (library 0.46) introduces some compatibility-breaking changes, so please keep on reading!

Darkness

The first important change is that when the lights go out, reachable objects remain in scope. Since time immemorial, darkness in text adventures has been incapacitating. Inform 6 established (or perpetuated?) the practice of moving the player object to a separate room (called “thedark”), so they could still interact with their possessions but not with the objects around them.

The Dialog standard library (until now) accomplished the same thing by modifying the scope, i.e. the set of objects that the player is allowed to refer to. A lack of light wouldn’t actually move the player into a separate room, but objects in the current room would be considered out of scope (except when held or worn by the player). This was, in hindsight, equally surprising and problematic.

The design choice may have been sensible three or four decades ago, but times have changed: There is now a general consensus that, unless there’s a compelling reason to do otherwise, games ought to be merciful—impossible to put in an unwinnable state. But this is incompatible with a world model where things go out of scope in darkness, because e.g. putting a flashlight on a table and turning it off would make it impossible for the player to get it back. In practice, authors would have to remember to call things back into scope in darkness, in order to keep their games merciful.

So to remedy this, I’m now changing the default scope. The new rule is essentially: “Everything that the player can see or reach is in scope.”

To summarize:

  1. The new rule is more realistic and less surprising.
  2. The new rule can be implemented with cleaner code.
  3. The new rule is merciful by default.

But beware: If you have a puzzle that relies on things being unreachable in the dark, you will have to add some code to prevent sequence-breaking. You’ll need things like:

(prevent [open/search #secretcompartment])
        ~(player can see)
        You can't see well enough to do that in the dark.

The words “dark” and “darkness” are no longer automatically added as synonyms for the current room when it is dark. However, a new library-provided object called #darkness (responding to those words) is added to the scope instead. It is intangible, so the player can’t do much with it by default, but examining it invokes (narrate darkness) which usually prints “You are surrounded by darkness”.

The manual contains the complete set of rules for light and darkness and for reachability, visibility and scope.

Layered clothing

The other big new thing in this version is support for layered clothing. I want to acknowledge the work of @MultidimensionalStep; this thread has been a source of inspiration.

My approach starts with the novel idea that clothes can be worn #under other clothes. To implement this, I had to make two compatibility-breaking changes to the rules for visibility and reachability:

  • Light can no longer reach #under an opaque object.

  • Objects #under other objects are reachable except when they have an ancestor that is #wornby a non-player character.

Games that do not use the #under relation should be unaffected by these changes.

Get the full story in the new section on Clothing in the manual.

Other improvements (Library)

  • (look $) now falls back on (descr $) by default.

  • Searching animate objects is now prevented by default.

Other improvements (Compiler)

  • Improved typo detection for predicate names (e.g. warn if they only appear once in the source code).

  • Don’t include the standard library in the total linecount when deciding whether the story is big enough to need metadata.

  • Print a better error message when the output isn’t a regular file.

11 Likes

More and more, Dialog looks like the choice for those who want to embrace both the past we look back on nostalgically and the present with all its wonderful offerings. Thank you for the update!

4 Likes

I just wanted to add my 2c to welcome the new approach to darkness. The issue of being merciful hadn’t occurred to me, but I’ve long felt that the old Inform/Infocom notion of darkness was too much “everything or nothing.” Either the light level is normal and everything is possible, or the player is “in darkness” and (almost) nothing is possible.

All dark rooms were reduced to a single problem: how to obtain light, and this made darkness much less useful for storytelling. If the author wanted to model some more subtle effect (like some rooms being dimly lit, and offering different opportunities like stealth actions) then the standard library hindered this process, and it was necessary to hack it at a really deep level, re-implementing all of the light handling from the ground up. This was certainly beyond my coding skills.

Very interesting!

6 Likes