Dungeon Crawl logic for Dialog

Ever since it was recommend to me in another thread, I’ve been poking at Dialog a bit to see what I can do with it.

Now, I can’t be the first to have thought of building a Dungeon Crawler with it, as that seems like one of the most classic types of interactive fiction to start with, so I was wondering.

Does anyone know of a set of predicates or adventuring actions that are useful to include? Just so I am not reinventing the wheel. Stuff like combat actions, lighting a torch, casting spells, collecting treasure, encountering traps or monsters, the real basic classic stuff.

Do you mean an RPG, or more of an adventure like Adventure, or Zork? I wouldn’t expect an adventure to have torches or whatever just because some game 40 years ago did, but maybe that would make some sense in an RPG.

1 Like

Afaik a dungeon crawler is an RPG. (Anybody correct me if I’m wrong about this.) And that means normally some stats like strength, intelligence, dexterity, maybe more. And a combat system, which can be very simple. A damage function, a value for armour protection, life points aka hit points.

Apart from that RPG stuff you need to design dungeon maps (or create them procedurally but that’s probably more work than drawing them on a sheet of paper.)

I think there are not many “must have” actions/commands.

There are many (partially complicated) ways to implement magic, but you can go for the simple solution: The player types the spell name to cast it.

You can simply use “attack orc” (or even simply “attack”) as a combat command.

1 Like

Dialog is very good at parsing commands, matching them to rules, and doing things to world state, but very bad at doing even simple math. It’s great when you have a story to tell, but may not be the best for creating an emergent narrative like an RPG.

3 Likes

Then the combat system must be even simpler than what I wrote.

1 Like

Yeah, while Dialog is very good at manipulating high-level data structures like lists, closures, and words, it’s very bad at manipulating low-level things like numbers. Inform (both 6 and 7) and TADS squarely have it beat in that regard.

(That said, if people have additional math predicates they want in Dialog, I’ve been considering adding some more. Just let me know what your use case is!)

On the other hand, people have built entire PRNGs in Dialog when they didn’t want to rely on the VM’s built-in one, so it’s far from impossible! It’s just tedious and verbose. It provides +, -, *, /, %, >, <, =, and rand, which is enough to implement the rest.

As far as RPGs, though, I’m not aware of any written in Dialog. I think it would actually be easier than Inform, because it’s easier to dike out the entire stock of built-in actions in Dialog and replace it with your own—or even the built-in handling of things like rooms and containment!—but it hasn’t really been done before.

So it comes back to: what exactly are you envisioning? Tara McGrew just published an entire roguelike on the Z-machine (though written in ZIL rather than Dialog), for example, and several different versions of the original Colossal Cave Adventure have been ported to Dialog, but none of those have a stats system.

3 Likes

Honestly, right now I wanted to see how far I could get with selecting a class out of three, having inventory and some stats be dependent on that (though the stats could likely be narrative properties, more than numbers) and pretty much have it function like a Roguelike, where you go from room to room and essentially do what you would do in AD&D 2e. The classic, high lethality type of dungeon crawling.

I did notice Tara’s efforts! So that’s cool to see. I am currently experimenting with a wrapper application for Dialog which is able to read out the world state through a JSON dump, which is then deserialised in the application, so I may be speaking heresy here, but if I want to do actual math, I can probably hack some way around that.

For reference, the current JSON dump logic:

(dump-eidolon-state)
    \{\" (no space)
    (current player $P)
    (if) ($P has parent $Loc) (then)
        location\":\ \" (no space)
        (name $Loc) (no space)
        \"\,\ \" (no space)
    (endif)
    visible\":\ \[ (no space)
    (exhaust) (dump-visible-json)
    null (no space)
    \]\,\ \" (no space)
    inventory\":\ \[ (no space)
    (exhaust) (dump-inventory-json)
    null (no space)
    \]\,\ \" (no space)
    narrative\":\ \{ (no space)
    (exhaust) (dump-narrative-json)
    \"_ignore\" (no space)
    \:\ null (no space)
    \} (no space)
    \} (no space)

(dump-visible-json)
    (current player $P)
    ($P has parent $Loc)
    *(everything $Obj)
    ($Obj is in room $Loc)
    ($Obj \= $P)
    \" (no space)
    (name $Obj) (no space)
    \"\, (no space)

(dump-inventory-json)
    (current player $P)
    *(everything $Item)
    ($Item is in room $P)
    \" (no space)
    (name $Item) (no space)
    \"\, (no space)

(dump-narrative-json)
    *(object $Obj has narrative $Fact)
    \" (no space)
    (name $Obj) (no space)
    \" (no space)
    \:\ \" (no space)
    (print words $Fact) (no space)
    \"\, (no space)

But yes, I was mostly referring to, player goes to room X, does a few things there, advances to room Y and encounters a Troll. The player now needs to act, otherwise they turn into a fine red mist. That type of deal. I could write every room as an individual puzzle, but these sound like the the type of logic you could declare at the top level.

Could you point me in that direction, please? My IFDB-fu, search for her last name, proved insufficient! I remember her Moby Dick (that… sounds wrong, somehow) and that’s the latest work of hers I can find.

Of course! Here is the release page and here is some more discussion.

1 Like

Oh wow! Writing JSON in Dialog may be a bit of a struggle, since it’s not good at the sort of string manipulation you’d need for escaping illegal characters, but far be it from me to dissuade you!

Are you trying to dump the entire world state into JSON every turn? If so, you might want to talk to @hlship , who’s doing something similar parsing the output of the @dynamic command in the debugger every turn.

Haha, trust me, I was very close to having a frustrated breakdown. But, I succeeded!

Sort of. I was building an experimental wrapper called “Eidolon” to see if I could intercept failed commands, and instead parse those as a special command called eidolon_fallback, which emits a JSON of the current world state for an LLM to evaluate, and formulate an appropriate response to. The idea is, once it works correctly, that it updates the world state. However, I only have it functional to the point it updates the narrative world state, not the tangible game rules yet.

(dynamic (object $ has narrative $))

%% eidolon_note: called by the LLM to attach a narrative fact to a game object.
(grammar [eidolon_note [object] [any]] for [eidolon_note $ $])

(perform [eidolon_note $Obj $Words])
    *(object $Obj)
    (now) ($Obj has narrative $Words)
    [ACK_INJECTION] (line)

%% eidolon_force: called by the LLM to execute an arbitrary game command.
(grammar [eidolon_do [any]] for [eidolon_force $])

(perform [eidolon_force $Words])
    (try $Words)
    [ACK_INJECTION] (line)

%% Fallback action: catches any input the parser cannot understand.
%% Marked very unlikely so Dialog only selects it as a last resort.
(understand $Words as [eidolon_fallback])
    ($Words = [$ | $])

(very unlikely [eidolon_fallback])

(allow [eidolon_fallback])
    (true)

(perform [eidolon_fallback])
    (line)
    \[EIDOLON_FALLBACK\]
    (dump-eidolon-state)
    \[\/EIDOLON_FALLBACK\] (line)
    (stop)

%% After every successful action, emit a state snapshot for the sidebar.
(after [any $Action])
    ($Action = $Action)
    \[EIDOLON_STATE\]
    (dump-eidolon-state)
    \[\/EIDOLON_STATE\] (line)

But that aside, since I got that functional, I think it could be reasonably possible to create a fallback command much like eidolon_fallback such as skillcheck_resolve which, instead of letting Dialog handle the resolution, leaves that logic to a wrapper application to perform.

Expanding on this, you could even fire a command every turn that communicates the current room to a wrapper application, which then helps visualise the chamber or the dungeon map. But, I wasn’t planning to dedicate that much time to an experiment quite yet. I just want to see how far I can get with building an adventure module that feels reasonably like playing an old-school fantasy TTRPG.

1 Like

Are you compiling for Z-machine or Å-machine (or using the debugger)? Dialog actually has a feature to redirect a block of output into something that’s not the screen; this is currently used for the status bar and inline status bar, but it could easily be expanded to write a particular bunch of output lines somewhere else instead. That’s how Vorple sends lines of JavaScript to the browser to evaluate.

(I’m currently working on this because one of my WIPs is in a non-English language, and I want to show the vocabulary you’ve encountered in a separate panel.)

Since this would require a new builtin, I wouldn’t use it as a first resort, but if this project ends up taking off, it’s technically feasible.

1 Like

Currently the Z-machine, which I probably shot myself in the foot with. I basically insert [EIDOLON_STATE] and [EIDOLON_FALLBACK] tags which are picked up by the wrapper, and then stripped from the final output so they can be handled elsewhere. Might want to consider swapping to the Å-machine, but I fell down this rabbit hole first.

1 Like

Anyway, this got a little side tracked in wanting to gush about my little experiment.

Perhaps it’s better to ask: What current parser games implement some degree of Dungeon Crawling or classic fantasy that I could draw inspiration from?

Not exactly dungeon crawl but Little Match Girl 3 has a JRPG-style combat system.

I haven’t finished that one yet so I don’t know if this continues in the later games in the series (although I have the impression maybe yes?)

2 Likes

Cheers! I’ll give it a look!

I don’t know if they fit the bill exactly, but you could check out The Reliques of Tolti-Aph, Kerkerkruip, Treasures of a Slaver’s Kingdom, and Black Knife Dungeon.

2 Likes

Since the OP is interested in using Dialog, some of these might be useful:

4 Likes

I love these, thank you. I’ll give them a look! These are precisely the references I needed.

1 Like