Dialog

Here is a download link for Dialog 0g/05, library 0.28.

Library feature: Heads of noun phrases

To assist with disambiguation, it is now possible to declare certain words to be potential heads of the noun phrase for a given object. The head of a noun phrase is the main noun, such as “cap” in “the bright red bottle cap of doom”.

Thus, we might define:

#bottle
(name *)        red bottle
(dict *)        crimson decanter
(heads *)       bottle decanter

#cap
(name *)        red bottle cap
(heads *)       cap

Now, if the player types EXAMINE BOTTLE, this is unambiguously interpreted as a request to examine the bottle, not the bottle cap, because one of the heads of #bottle was given. If the player types EXAMINE RED, the game will ask if they wanted to examine the red bottle or the red bottle cap. In response to that, the answer BOTTLE is unambiguously understood as the #bottle.

The list of noun heads is only consulted to resolve ambiguities. If the player attempts to TAKE BOTTLE while holding the bottle but not the cap, for instance, then that is interpreted as a request to take the bottle cap.

Hence, authors may add (heads $) definitions as needed, on a case-by-case basis, when ambiguities turn up during playtesting.

Compiler features

  • Å-machine backend: Now obeys the -s option for stripping away internal object names (hash tags) from the final story file.

  • Compiler: The quadruple-verbose output (-vvvv) now includes a list of all words the story might print. With a bit of scripting, these can be sent to an external spell checker.

  • Debugger: Commandline option -L to disable hyperlinks in the output. This also affects (interpreter supports links).

Bugfixes

  • Compiler: Fixed a bug where (determine object $) didn’t accept integers in the input.

  • Library: If parsing fails when default actions are enabled, don’t assume that a default action was intended. Thus, “enterr car” no longer results in “I only understood you as far as wanting to examine something” (when examine is the default verb).

  • Compiler: Fixed several corner-case bugs discovered through fuzzing.

5 Likes

Dialog 0g/06, library 0.29 contains some small but significant improvements:

  • Library: In the before-rules for eating and drinking, only attempt to pick up the indicated object if it is edible or potable.
  • Library: Treat “X, tell me about Y” as “ask X about Y”.
  • Library: Fixed a bug where (describe topic $) couldn’t deal with ambiguity.
  • Compiler: Fixed a bug related to the optimization of nested disjunctions.

The compiler bug was particularly elusive and would only trigger under very specific conditions. But it could result in code that would crash the game in certain corner cases, so make sure to upgrade.

3 Likes

In case you ever make any progress with your emacs-mode for dialog, let me know. It’s been very helpful so far!

1 Like

Yay! Congrats for the Best Technological Development!

4 Likes

Huge congrats! Incredibly cool.

4 Likes

I have created a mostly-complete conversion of Pick Up the Phone Booth and Die to Dialog.

…enjoy?

Improvements welcome.

3 Likes

Incidentally, is there an official/accepted way to disassemble a Dialog Z-Machine binary? putpbad.z5 seems to break txd’s tiny brain, generating a bunch of errors and >100 MB of output. (OSX build of txd from ztools731)

Txd works, but you have to use -g to stop it from trying to analyze the grammar table. That’s because in Dialog, grammar is just ordinary code.
Dialog Z-code is highly optimized and tricky to follow. Text strings are useful landmarks. Check out zcode.h to learn what the global variables do. You can also run dialogc in quadruple-verbose mode (-vvvv) to see the intermediate code, which is fairly close to the final Z-code, but better annotated. The routines end up in a different order, though.
Happy hacking!

2 Likes

‘but this one has the words “PHONE BOOTH” scratched out and “P#0N3 B00TH” instead.’ …

I didn’t notice until watching my own video playback that Dialog was understandably confused about the # in p#on3.

Escaping it in the (descr) as

P\#0N3

works fine.
But in the dict, it didn’t help:

(dict *)	p\#0n3 b00th

b00th is fine, but I still can’t get the game to treat p#on3 as a valid way to refer to the booth.

Is there a solution, other than “don’t do this”? :slight_smile:

(The video is at https://www.youtube.com/watch?v=ciEBW61IUPo , for the curious.)

Hi!

This sounds like a bug, but I’m not able to reproduce it. Here, “p\#0n3” works correctly on all compiler backends. In your message, you’ve spelt it with a zero in one place, and the letter o in another. Could that be the root cause, or is it just a typo in the message?

I enjoyed watching the video! It allowed me to see the language through a beginner’s eyes, which was cool and also provided useful feedback.

It seems I have to clarify the role of (notice $) in the manual. Notice has nothing to do with the appearance of an object, and defining a rule for (appearance $ $ $) is sufficient to make the object stand out in the room description. Notice binds a pronoun to the object. In this case, because the phone booth is neither (male $), (female $), nor (plural $), the pronoun “it” is bound to it. Hence, the player can type “pick it up” and die.

Instead of the (victory lap $) thing, I would use select/stopping, like this:

(on every tick in #townsquare)
	(booth has been pushed)
	(select)
	(or)
		(par)
		A familiar sound ...
		(game over {You have won})
	(stopping)

On line 207, visible at 14:15, it looks like you have a bug: The condition ($Max) invokes the predicate ($), which is used for hyperlinks. The original code from the library queries (current score $Max), which is something else. You can probably remove this condition altogether, since you already know that a maximum score is defined.

Thanks for taking an interest in Dialog, and for making a nice video!

(I am embarrassed to report that it was in fact me not correctly entering “p#0n3” in-game. Moving right along…)

Thank you for the illustration of how select/or/stopping can be used for this kind of simple counter! Much cleaner.

I’ve cleared out the bad/unnecessary $Max code, and will work on comprehending better what you said about why exactly that condition was not just unnecessary (because, as you say, I as the author know there’s a maximum score) but why I was also using $Max incorrectly.

Thanks for the correction on (notice $), I wish I could explain better why I felt it was necessary.

Speaking of properly defining the #booth:

What would be the Dialog way to replicate this behavior from the Inform original?

[game starts, first move entered is]
>take
(the phone booth)
You grunt with all your might and heave [etc]
    *** You have died ***

My Dialog version produces

> take
(I only understood you as far as wanting to take something.)

Looking at trace info in the debugger produces a lot of things I don’t understand! #booth is mentioned as being in scope and visible but obviously isn’t being chosen.

I don’t know what the Inform code was doing. In ZILF, the TAKEBIT flag is enough to make that maneuver work.

Is it just a design characteristic of the Dialog (and/or the stdlib) that a simple TAKE isn’t expected to work? Or is there a simple way of enabling this behavior that I’ve missed?

1 Like

strange, because of the

(notice #booth)

whose AFAICT should have put the booth in scope and visible to the disambiguation.

Best regards from Italy,
dott. Piergiorgio.

Scope is determined based on where objects are located. The phone booth is in the same room as the player and visible, and therefore in scope. It’s also possible to put extra objects in scope:

(add #foo to scope)
	...typically with some condition here...

The predicate (notice $) is unrelated to scope, and unrelated to appearances. It only binds the pronoun ‘it’ (or ‘him’, ‘her’, or ‘them’ as appropriate) to the object.

However, there’s one more thing to know: The Dialog standard library (unlike Inform) automatically unbinds pronouns when the corresponding objects go out of scope. So if you examine statue, then go north, then try to take it, the game will respond that it only understood you as far as wanting to take something, because ‘it’ is no longer meaningful, since the statue is no longer in scope. (Unless this was a living statue that followed you to the adjacent room. In that case, ‘it’ still refers to it.)

2 Likes

This behaviour is not built-in by default, but you can add a rule for it:

(understand [take] as [take $Obj])
	*($Obj is in scope)
	(item $Obj)
	~($Obj is hidden)

This will backtrack over every object in scope, and then ensure that only items (takable objects) are returned. The last line is only necessary if there are hidden objects in the game at all.

2 Likes

For a joke game reimplementation I’m more inclined to just stick with the library defaults and celebrate differences than to make rule changes, but that’s a helpful example for cases where it might actually be desirable, thank you.

Hello! I just discovered Dialog and I am enamored with its power and readability; thank you so much for all your work on this!

I have a question, and it is kind of an odd one. Is there a way to do Unicode input / output? It seems from Googling that (certain versions of?) the Z-machine standard allow a limited number of Unicode characters from the BMP plane. The simple use case is inputting and outputting character variants like å, ñ, etc. More ambitiously, I believe Dialog might be capable of parsing Japanese kana input (which is difficult because the language does not put spaces between words, “take the dog” -> 「いぬをとる」), although I’m also not sure if there is a way to do splitting of a dictionary ‘word’ into multiple smaller words (split いぬをとる into いぬ and とる). Maybe it’s not possible, I’m not sure.

Hi, and thanks!

That is an intriguing idea. I think it boils down to two new requirements. One, which I’ve been meaning to implement anyway, is to improve unicode support in the Z-machine backend. Like you say, the Z-machine standard supports using a custom character set based on arbitrary BMP characters, but the Dialog compiler doesn’t make use of this feature yet.

The second requirement, as you point out, is the ability to split a dictionary word into single-character words, and then join them back together. This is currently not possible in the language, but it could be added.

I’ve dabbled in Japanese grammar myself; it’s a fascinating subject. If I were to attempt to parse Japanese input in Dialog, I would start by converting it into a list of characters, as discussed above. Then, as a first approximation, I would probably try something like *(split $Input by [は を も に へ で が] into $Prefix and $Verb) to split off the verb at a valid particle. For each possible split, I would join the characters of $Verb back into a single dictionary word, and match that against the grammar rules.

Hmm. Now that I think about it, it makes more sense to break down the input into chunks of characters that each end with a particle. To do this efficiently, I think a good trick would be to first reverse the list, so the particle ends up as the head element of each chunk. Then one could write a recursive rule definition that backtracks over every possible parse.

So many possibilities, and so little time. I’ll have to leave this puzzle for somebody else to solve. But the two feature requests are duly noted.

Never thought of parsing a Japanese sentence in reverse, but that does seem like it might be a fruitful approach.

Dialog version 0h/01 (library 0.30) is out.

  • This version introduces support for embedded graphics, as well as links to feelies and external web sites, when compiling for the Å-machine. Read all about Resources in the manual.

    • Graphics and feelies are stored inside the .aastory file, and this part of the file format has been carefully designed to be accessible and malleable. This means that a build process could involve converting a large story file intended for the web into a small story file for 8-bit systems, and vice versa. It also means that external links can be kept up to date even if the source code to a game is lost.
  • A new built-in predicate called (interpreter supports quit) reports whether (quit) is handled in a way that is meaningful to the player. The predicate fails under the Å-machine web interpreter, for instance, because there’s no way for the interpreter to close the browser tab. The game-over menu in the standard library has been redesigned slightly, and no longer suggests QUIT when that action makes no sense.

2 Likes

Hello!

I am having trouble getting Dialog to understand that “pushing a button (switch)” means “switching the button (switch)”. What is the right way to do this?

(library links enabled)
(default actions enabled)

%%%%

(intro)
	(enter #your-room)

%%%%

#player

(current player *)

%%%%

#your-room

(name *)
	Your Room
(look *)
	It's your room.
(room *)
(singleton *)

%%%%

#the-button

(name *)
	button
(* is #in #your-room)
(descr *)
	(if) (switched on *) (then)
		It is switched on.
	(else)
		It is switched off.
	(endif)
(switchable *)
(understand [push | $Words] as [switch | $Words])

Thank you!