D&D

Stuff about this very unknown tabletop RPG

DelveForge L shaped rooms

- Posted in D&D by

Welcome to the L-shaped rooms in DelveForge! enter image description here Upcoming features on the horizon:

  • โ€œConfigurable procedural corridor width (1โ€“2 tiles) and width probabilityโ€ ๐Ÿก’ a breeze
  • โ€œMulti-level dungeonโ€ ๐Ÿก’ ouch, ouch, ouch
  • โ€œManual dungeon editorโ€ ๐Ÿก’ hurt me plenty

Will these new features be available in TorchBound?

Yes but ... not just yet :)

DelveForge can now:

  • export โ€œsimpleโ€ dungeons (v1.0) that TorchBound can handle
  • export dungeons with new features (v2.0) that TorchBound is still far from being able to handle :)

Peace. Out.

Torchbound - From a Rules-Coupled Engine to a Pluggable Rulesets engine?

- Posted in D&D by

Goal

Torchbound started as (and it still is, as I write this) an implementation of Five Torches Deep. I still believe that it was the right choice: implementing a real game gave me concrete rules, contracts, tests, persistence requirements, dungeon interactions, combat, progression, and UI behavior instead of designing an abstract RPG engine upfront.

As Torchbound grows, however, I am wondering if it could be possible to preserve an important architectural option (which is a new idea, it just crossed my mind, so I'm letting my uncontrollable ramblings flow here):

Torchbound Core should not assume that Five Torches Deep is the definition of an RPG.

The long-term goal is not to turn Torchbound into a universal RPG framework. It would rather be to make the ruleset an explicit boundary, so that another system could eventually replace 5TD without requiring Torchbound itself to be rewritten.

Possible future rulesets include Nimble and an adapted 2D6 Dungeon ruleset.


Torchbound today

The current architecture already contains a large amount of reusable infrastructure:

  • campaign and session management
  • SQLite persistence
  • commands and events
  • dungeon import from Delveforge
  • dungeon identity, provenance and spatial state
  • save/reload
  • navigation and UI
  • player-facing projections
  • world-state management

However, the Engine also directly knows about many concepts belong specifically to 5TD.

Examples include checks, combat rules, proficiency, Supply, death and stabilization, resting, progression, spells, treasure rules and other game-specific mechanics.

Conceptually, the architecture still looks roughly like this:

                         TORCHBOUND TODAY

                         โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
                         โ”‚     UI      โ”‚
                         โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
                                โ”‚
                                โ–ผ
                    โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
                    โ”‚  Campaign / Session  โ”‚
                    โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
                               โ”‚
                               โ–ผ
                    โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
                    โ”‚        ENGINE        โ”‚
                    โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
                               โ”‚
                โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                โ”‚              โ”‚              โ”‚
                โ–ผ              โ–ผ              โ–ผ
          โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ  โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ  โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
          โ”‚  Dungeon  โ”‚  โ”‚   State   โ”‚  โ”‚ Persistence โ”‚
          โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ  โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ  โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
                               โ”‚
                               โ–ผ
               โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
               โ”‚       5TD assumptions        โ”‚
               โ”‚                              โ”‚
               โ”‚  checks       combat         โ”‚
               โ”‚  Supply       death          โ”‚
               โ”‚  rest         progression    โ”‚
               โ”‚  spells       treasure       โ”‚
               โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
                              โ”‚
                              โ–ผ
                   โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
                   โ”‚ Five Torches Deep  โ”‚
                   โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

This does not mean Torchbound would have to be rewritten from scratch to use another system.

It does mean that changing rulesets today would still require invasive surgery because infrastructure, orchestration and rules responsibilities are not yet consistently separated.


The architectural constraint from now on

The new rule is deliberately simpler than "build a multi-ruleset engine":

New Torchbound Core code must not introduce an implicit dependency on a Five Torches Deep rule.

For every new feature, from now I want to distinguish four responsibilities:

Core: Torchbound infrastructure and orchestration.

Rules: Mechanics belonging to the selected game system.

Content: Authored Torchbound adventures, encounters, profiles and configuration that may intentionally use a particular ruleset.

External contracts: Delveforge and other external representations that describe things to Torchbound without defining its game rules.

Existing mixed code does not need to be rewritten immediately. I will first audit it and then separate responsibilities where there is a demonstrated architectural benefit.


Target architecture

The desired direction is approximately:

                          TORCHBOUND

                    โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
                    โ”‚         UI         โ”‚
                    โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
                              โ”‚
                              โ–ผ
             โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
             โ”‚        Campaign / Core         โ”‚
             โ”‚                                โ”‚
             โ”‚   state          identity      โ”‚
             โ”‚   commands       events        โ”‚
             โ”‚   persistence    projections   โ”‚
             โ”‚   dungeon        orchestration โ”‚
             โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
                             โ”‚
                             โ–ผ
                 โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
                 โ”‚ Explicit Rules API   โ”‚
                 โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
                            โ”‚
               โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
               โ”‚            โ”‚            โ”‚
               โ–ผ            โ–ผ            โ–ผ
        โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
        โ”‚    5TD     โ”‚ โ”‚   Nimble   โ”‚ โ”‚   2D6D*    โ”‚
        โ”‚ Rules Pack โ”‚ โ”‚ Rules Pack โ”‚ โ”‚ Rules Pack โ”‚
        โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

                 Interchangeable Rules Packs

            * adapted to use DF-provided dungeons

The Core should therefore know primarily about concepts such as:

  • identities
  • state
  • commands
  • events
  • spaces and positions
  • persistence
  • transitions
  • sessions
  • projections

It should avoid assuming that every RPG necessarily has:

  • STR / DEX / CON / INT / WIS / CHA
  • d20 checks and DCs
  • AC
  • Supply
  • spell slots
  • 5TD death mechanics
  • 5TD progression
  • 5TD treasure tables

Those concepts can exist in Torchbound โ€” but their owner is the Rules Pack, not necessarily Torchbound Core.


Delveforge remains a separate responsibility

This distinction is particularly important for dungeon generation.

Torchbound should not become a procedural dungeon generator merely because one supported ruleset normally includes dungeon generation.

The intended responsibility split is:

                       โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
                       โ”‚   DELVEFORGE   โ”‚
                       โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
                               โ”‚
                      describes / generates
                               โ”‚
                               โ–ผ
                       โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
                       โ”‚    DUNGEON     โ”‚
                       โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
                               โ”‚
                               โ–ผ
                 โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
                 โ”‚     TORCHBOUND CORE      โ”‚
                 โ”‚                          โ”‚
                 โ”‚  identity                โ”‚
                 โ”‚  spatial state           โ”‚
                 โ”‚  persistence             โ”‚
                 โ”‚  world state             โ”‚
                 โ”‚  orchestration           โ”‚
                 โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
                              โ”‚
                     interprets / resolves
                              โ”‚
                              โ–ผ
                       โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
                       โ”‚  RULES PACK  โ”‚
                       โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

In other words:

Delveforge says what the dungeon is.
Torchbound says what exists and what happens in it.
The Rules Pack says how actions and consequences are resolved.

This remains true even for an adapted 2D6 Dungeon Rules Pack.

2D6 Dungeon normally includes procedural dungeon generation as part of its gameplay loop. In Torchbound, I would deliberately remove that responsibility from the Rules Pack and replace it with Delveforge.

Torchbound itself should not gain procedural dungeon generation merely to reproduce that part of 2D6 Dungeon.


Three architectural tests

I can use three rulesets as conceptual tests without implementing any of them yet.

Five Torches Deep - baseline

5TD is the existing implementation.

The question is:

Can I identify and eventually remove the 5TD rules without removing Torchbound infrastructure with them?

This reveals the current Core/Rules coupling.

Nimble - substitution test

Nimble is another fantasy RPG, so it will share some concepts with 5TD while implementing them differently.

The question becomes:

Could I replace 5TD with Nimble without changing code that genuinely belongs to Torchbound Core?

This is important because otherwise I could accidentally create abstractions that are merely the common denominator of 5TD and Nimble and mistake them for generic Torchbound concepts.

2D6 Dungeon - partial-ruleset / DF-substitution test

2D6 Dungeon is structurally more different.

For Torchbound, I would deliberately remove its procedural dungeon-generation responsibility and replace it with Delveforge.

The question becomes:

Can a Rules Pack surrender a responsibility already owned by another Torchbound component while retaining its coherent resolution, combat, treasure and progression mechanics?

This prevents me from solving the opposite problem by making Torchbound Core absurdly broad.


What I am deliberately NOT doing

I am not building a generic RPG framework today and trying to predict every RPG mechanic I may encounter in the future.

Instead, I can use the existing 5TD implementation to discover the first real boundary.

Later, an actual Nimble implementation can challenge that boundary.

If Nimble exposes incorrect assumptions, I can adjust it.

A substantially different system such as adapted 2D6 Dungeon can challenge it again.

The abstraction therefore emerges from real implementations and failing assumptions, rather than speculative generalization.


Desired end state

Eventually, changing the game system should conceptually approach:

                    โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
                    โ”‚  Torchbound Core   โ”‚
                    โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
                              โ”‚
              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
              โ”‚               โ”‚                โ”‚
              โ–ผ               โ–ผ                โ–ผ
       โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
       โ”‚ Delveforge  โ”‚ โ”‚ Campaign / UI โ”‚ โ”‚  Rules Pack  โ”‚
       โ”‚   Dungeon   โ”‚ โ”‚ Saves / State โ”‚ โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
       โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ        โ”‚
                                                โ–ผ
                                     โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
                                     โ”‚ Five Torches Deep  โ”‚
                                     โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
                                                โ”‚
                                           swap rules
                                                โ”‚
                                                โ–ผ
                                         โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
                                         โ”‚   Nimble   โ”‚
                                         โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

rather than:

                     โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
                     โ”‚ Change ruleset โ”‚
                     โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
                             โ”‚
                             โ–ผ
                     rewrite engine.lua
                             โ”‚
                             โ–ผ
                 rewrite campaign_session
                             โ”‚
                             โ–ผ
                    rewrite dungeon logic
                             โ”‚
                             โ–ผ
                    rewrite persistence
                             โ”‚
                             โ–ผ
                        rewrite UI
                             โ”‚
                             โ–ผ
                    rewrite everything
                             โ”‚
                             โ–ผ
                            :(

That being said, I am far from being close to that yet.

But Torchbound is still early enough that adopting this constraint now is cheap compared with extracting 5TD assumptions after several more major gameplay systems have been built.

The immediate strategy is therefore:

Audit the existing coupling. Do not over-engineer it. Stop introducing new coupling today. Extract Rules boundaries only where real dependencies demonstrate that they are needed.

That keeps Five Torches Deep as Torchbound's first fully supported ruleset while leaving the door open for Torchbound to become, later, a game capable of running the same underlying campaign/dungeon infrastructure through genuinely different Rules Packs.


Yes, I know why you smile.

As if... this challenge wasn't already out of proportion to my technical abilities and my long-term commitment :)


Peace. Out.

Torchbound progress status

- Posted in D&D by

And... (drumroll) here's the first version of TorchBound, showing a player at the start of a DelveForge dungeon! enter image description here This is a god mode view, the dark squares are unknown to the player.
And the player canโ€™t go any further becauseโ€ฆ the next square contains a pit andโ€ฆ the โ€œobstacleโ€ handling isnโ€™t implemented yet, so the player is stuck :)
(Yes, starting with a pit right behind the dungeon entrance is pretty mean, but thatโ€™s how DelveForge generated the map, and I left it as is)
(Life is hard, especially for dungeon explorers.)

That said, itโ€™s nice to โ€œseeโ€ something after hours (and hours) of implementing rules and automated tests (1,723 and still counting).

Peace. Out.

DelveForge and Torchbound are on a boat...

- Posted in D&D by

DelveForge & Torchbound โ€” where are the boundaries?

The relationship between DelveForge and Torchbound became clear:
DelveForge creates places.
Torchbound makes stories happen inside these places.

They share a world, but they do not have the same responsibility.


DelveForge: the world builder

DelveForge answers one question:

What does this place look like?

DelveForge is an architect and decorator of an unexplored place. It generates:

DelveForge
|
โ”œโ”€โ”€ Spatial generation
|     โ”œโ”€โ”€ levels
|     โ”œโ”€โ”€ rooms
|     โ”œโ”€โ”€ corridors
|     โ””โ”€โ”€ connections
|
โ”œโ”€โ”€ Dungeon structure
|     โ”œโ”€โ”€ topology
|     โ”œโ”€โ”€ accessibility
|     โ””โ”€โ”€ constraints
|
โ””โ”€โ”€ Static features
      โ”œโ”€โ”€ doors
      โ”œโ”€โ”€ chests
      โ”œโ”€โ”€ skeletons (relics / remains)
      โ”œโ”€โ”€ pits
      โ”œโ”€โ”€ stairs
      โ””โ”€โ”€ other points of interest

A DelveForge dungeon is a coherent location.

Example generated by DelveForge:

Forgotten Chamber

  • ancient walls
  • locked door
  • forgotten chest
  • skeleton remains
  • dangerous pit
  • staircase leading deeper

DelveForge does not decide what happens there, it only says:

Here is a place with a history.


Who can experience a DelveForge world?

The generated world is not tied to a single consumer. The same dungeon can become:

A classic TTRPG adventure

Using:

  • printed PNG map
  • human imagination
  • a Game Master

A VTTRPG adventure

Using:

  • map export
  • structured dungeon data
  • virtual tabletop features

Torchbound

Using:

  • the modeled dungeon representation
  • game rules
  • persistence
  • gameplay systems

Torchbound: the world storyteller

Torchbound answers another question:

What happens here?

Torchbound gives life to the place. It adds:

Torchbound
|
โ”œโ”€โ”€ Characters
โ”œโ”€โ”€ Creatures
โ”œโ”€โ”€ Events
โ”œโ”€โ”€ Encounters
โ”œโ”€โ”€ Decisions
โ”œโ”€โ”€ Consequences
โ””โ”€โ”€ Progression

DelveForge creates:

There is a chest in this forgotten room.

Torchbound decides:

What is this chest?

It could contain:

  • a potion
  • a trap
  • a key
  • nothing

DelveForge creates:

A skeleton lies here.

Torchbound decides:

What does this mean?

It could be:

  • simple scenery
  • a fallen adventurer
  • a clue
  • part of a larger story

Same world, different experiences

The same dungeon can therefore live several lives. DelveForge exports a description:

{
  "room": 42,
  "features": [
    "chest",
    "skeleton"
  ]
}

A consumer interprets it according to its purpose:

  • a GM invents a story
  • a VTTRPG provides interaction
  • Torchbound creates an adventure

The simple rule

DelveForge creates the stage. Torchbound directs the play.

Or even shorter:

DelveForge builds worlds. Torchbound tells stories inside them.

Peace. Out.

Torchbound progress status

- Posted in D&D by

I'm proud to announce that Isometric Dungeon Generator is dead, long live Delveforge!
As Iโ€™m about to try to get Torchbound to load a dungeon generated by IDG, I figured it deserved a real name...
So, hereโ€™s Delveforge.
And its gorgeous future splash screen.
Delveforge
Yeah, sometimes I need to work on lighter projects to take my mind off things a bit :)
(yes, itโ€™s AI-generated)
(but a quick look at my artistic talents instantly exonerates me for this despicable misdeed)
(better pretty and cheated than ugly and completely homemade)

By the way, there are some major updates in the works for Delveforge, but I'm taking it easy for now, Torchbound needs a steady stream of input if I want it to be able to import anything someday :) enter image description here

Peace. Out.

Torchbound progress status

- Posted in D&D by

Everyone in Europe saw the solar eclipse. Not me.
I was -and still am- too busy trying to make a playable pre-alpha version of Torchbound.

Right now, itโ€™s not exactly visually that impressive: enter image description here

Despite everything that has been done behind the scenes:

      +-----------------------------------------------+
      |                    SUMMARY                    |
      +-----------------------------------------------+
  Files                    258
  Modules                  -
  CodeGraph nodes          4044
  CodeGraph edges          13291
  Functions analyzed       469
  Call relations           1114

  Entry points
    LOVE callbacks         6
    Bootstrap              1
    Module APIs            463
    Root candidates        217
    Documented             687


And if I try to gauge how far along I am in this project -which seemed small and easy at first but is becoming a bigger and bigger thing every day- Iโ€™d say:

Rules / Engine foundations       โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ
Persistence                      โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ
Campaign aggregate / session     โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ
Playable encounters              โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ
Playable travel                  โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ
Interactive travel consequences  โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ
Playable exploration             โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘
Party management                 โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘
Generated encounters             โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘
Rewards / progression loop       โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘
Management UI                    โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘
Game UI                          โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘
Game tests                       โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘
Game assets                      โ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘
Game sounds                      โ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘

At least this timeโ€”I didn't start with the visuals :)

And of course, I have dozens of brilliant ideas every day that I meticulously log in my personal local instance of LineAgent (yes, Linear is great, but itโ€™s a non-open-source SaaS service, so I switched both the product and the hosting for my issues).
And since LineAgent doesn't expose a user interface -it is headless and REST only- well... I built a little interface on a small self-hosted server, just to take my mind off things for a bit.

enter image description here

(perhaps an english version on day)

So Torchbound will probably never be finished, but deep down inside Iโ€™ve always known that :)
Sticks and stones...
Yeah, I admit this post is a bit all over the place. But that's okay.

Peace. Out.

Torchbound

- Posted in D&D by

So I dove into developing my game, which will use the dungeon I now know how to generate.
After much thought, Iโ€™ve decided to call it Torchbound, since itโ€™s based on the rules of Five Torches Deep.

Version 1, aka โ€œOptimism and carefreeโ€

I thought to myself, โ€œOK, itโ€™s a simplified version of D&Dโ€”this will work easily,โ€ and of course, as always, I started playing around with the UI.
And I built a UI in Luaโ€”how should I put it?โ€”itโ€™s pretty old-school :)
And of course I created the logical sequence of screens for character creation: Race, Attibutes, Classes, Equipmentโ€”the usual stuff.
Then, of course, the inevitable happened: โ€œDamn, the rules arenโ€™t that simple,โ€ and โ€œHello, unmaintainable ifโ€ฆ thenโ€ฆ else statements.โ€
So, Iโ€ฆ stopped everything andโ€ฆ started over from scratch (which just shows that WIS doesn't necessarily come with age).
(Well, OK, Iโ€™ll probably keep some assets like logos, buttons, and sounds)

Version 2, โ€œWelcome to the Real Worldโ€

The UI will come later; I need to start with the game engine: the FTD rules.

Phase 1: The Rules
So I started by actually reading the rulesโ€”which, letโ€™s face it, Iโ€™d only skimmed before. Well, even though itโ€™s a minimalist version of D&D 5th Edition, itโ€™s not as straightforward as it seems. I ended up with a rules file thatโ€™sโ€ฆ 120 KB, including 24 reference tables. Plain text, mind youโ€”not a Word document with images.

Phase 2: Modeling the Rules
Then, after careful consideration, I settled on the following model:

      โ”Œโ†’ Specific item (AC) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ†’ Plain text 'Contract' โ”€โ”€โ”€โ”€โ†’ Lua 'Tests' โ”€โ”€โ”€โ”€โ†’ Lua 'Logic'
      โ”œโ†’ Specific item (Armor)โ”€โ”€โ”€โ”€โ”€โ”€โ†’ Plain text 'Contract' โ”€โ”€โ”€โ”€โ†’ Lua 'Tests' โ”€โ”€โ”€โ”€โ†’ Lua 'Logic'
RULES โ”ผโ†’ Specific item (Attack) โ”€โ”€โ”€โ”€โ†’ Plain text 'Contract' โ”€โ”€โ”€โ”€โ†’ Lua 'Tests' โ”€โ”€โ”€โ”€โ†’ Lua 'Logic'
      โ”œโ†’ ...
      โ””โ†’ Specific item (Weapon) โ”€โ”€โ”€โ”€โ†’ Plain text 'Contract' โ”€โ”€โ”€โ”€โ†’ Lua 'Tests' โ”€โ”€โ”€โ”€โ†’ Lua 'Logic'

And now I think I've covered everything with a little less than... 90 subdomains (from โ€œACโ€ to โ€œWeaponโ€). It's just huge compared to what I imagined, but at least the foundations will be isolated, well-defined, and their code and tests will be dedicated.

Phase 3: Implementing the Rules
For example, for AC:

Contract 'contract.md':

# CONTRACT: ARMOR CLASS

Every combatant, PC or NPC, has an Armor Class (AC).
AC is the number an attacker must meet or exceed to hit the target in combat.
AC is therefore the DC used to damage a target.
FTD defines, among others:
    Heavy Armor
        AC 15
    Light Armor
        AC 12 + DEX mod
A shield increases AC.
Further AC calculation details depend on the equipment and applicable rules.

## SOFTWARE INTERPRETATION
The contract receives the values required to calculate AC.
For heavy armor:
    AC = 15
For light armor:
    AC = 12 + DEX mod
The contract does not resolve the attack check, roll dice, select armor,
calculate the DEX modifier, or decide whether an attack hits.

## API
Module:
    Modules.Engine.ac

Entry point:
    ac.heavy()
    ac.light(dex_modifier)

## RETURN
The functions return:
    {ac = <valeur d'AC>}

## INVARIANTS
Heavy armor provides a base AC of 15.
Light armor provides a base AC of 12 before applying the DEX modifier.
The contract never modifies DEX, calculates the DEX modifier, or rolls dice.
It is deterministic for identical inputs.


## TEST CASES
The following cases must be covered:
- heavy armor
- light armor with a zero modifier
- light armor with a positive modifier
- light armor with a negative modifier
- determinism


## OUT OF SCOPE

The AC contract does not perform:
- RNG ;
- CHECK ;
(...)

## VALIDATION
The contract is considered validated when:
    lua Tests/run_tests.lua
returns zero failures and all contract cases are covered.

Tests 'test-AC.lua':

TestAC = {}
-- HEAVY ARMOR
function TestAC:test_heavy_armor()
    local result = ac.heavy()
    lu.assertEquals(result.ac, 15)
end
(...)
return TestAC

Logic 'ac.lua':

local ac = {}
function ac.heavy()
    return {
        ac = 15
    }
end
function ac.light(dex_modifier)
    return {
        ac = 12 + dex_modifier
    }
end
return ac

Phase 4: Writing All These Items All the {specifications, tests, code} for the 90 domains have been written, and I am verifying that:

  • the {specifications, tests, code} actually exist:
.\Specifications\Contracts\Rules_Check.ps1
 TORCHBOUND - RULES CHECK

===== COUNTS =====
Contracts             : 86
Contract modules      : 86
Contract tests        : 86
Infrastructure tests  : 5
Total tests           : 91

===== CONTRACT BIJECTION =====
Contracts          : 86
Modules            : 86
Contract tests     : 86
OK   complete 1:1 contract matrix.

 RULES CHECK : PASS
  • the tests are OK:
lua .\Tests\run_tests.lua
Ran 967 tests in 0.072 seconds, 967 successes, 0 failures

Nearly 1,000 unit tests are run with every change.

Phase 5: The engine that drives all these rules
The approach adopted is as follows:

                        +------------------+
                        |    INPUT / UI    |
                        +--------+---------+
                                 |
                                 | command
                                 v
                        +------------------+
                        | COMMAND VALIDATOR|
                        +--------+---------+
                                 |
                                 | valid command
                                 v
                        +------------------+
                        |  COMMAND QUEUE   |
                        +--------+---------+
                                 |
                                 | one command per update
                                 v
+----------------+      +--------+---------+      +----------------+
| ACTOR STATE    |<---->|      ENGINE      |<---->| COMBAT / TURN  |
| HP, SUP, class |      | orchestration    |      | current actor  |
| actions, etc.  |      +--------+---------+      +----------------+
+----------------+               |
                                 | selects resolver
              +------------------+------------------+
              |                  |                  |
              v                  v                  v
     +----------------+ +----------------+ +----------------+
     | ACTION         | | ATTACK         | | SPELLCASTING   |
     | RESOLVER       | | RESOLVER       | | RESOLVER       |
     +-------+--------+ +-------+--------+ +-------+--------+
             |                  |                  |
             |                  v                  v
             |          +---------------+  +---------------+
             |          | DAMAGE / HP   |  | SPELL CHECK   |
             |          +---------------+  +-------+-------+
             |                                     |
             |                             failure |
             |                                     v
             |                             +---------------+
             |                             | MAGIC MISHAP  |
             |                             +---------------+
             |
             +------------------+
                                |
                                | state changes
                                | and events
                                v
                       +-------------------+
                       |   EVENT BUFFER    |
                       +---------+---------+
                                 |
                                 | dispatch
                                 v
                       +-------------------+
                       | EVENT HANDLERS    |
                       +---------+---------+
                                 |
                    +------------+------------+
                    |                         |
                    v                         v
           +----------------+        +----------------+
           | COMBAT LOG     |        | FOLLOW-UP RULE |
           | observable     |        | death, etc.    |
           +----------------+        +----------------+

In practice, it looks something like this when you're playing around with a Goblin:

[CALL] PUBLIC engine.update(0)
[CALL] command_queue.pop
[RETURN] command_queue.pop
[STATE] queue 1 -> 0
[STATE] consumed command=Attack
[CALL] combat_command_resolver.execute
  [CALL] engine.use_action
  [RETURN] engine.use_action
  [STATE] Active false -> true
  [STATE] action accepted=true
  [CALL] combat_resolver.execute
    [CALL] attack.resolve
    [RETURN] attack.resolve
    [STATE] attack hit=true
    [CALL] damage.resolve
    [RETURN] damage.resolve
    [STATE] damage total=5
    [CALL] hp.apply_damage
    [RETURN] hp.apply_damage
    [STATE] hp result 5 -> 0
    [CALL] events.push
    [RETURN] events.push
    [EVENT] damage_applied
    [STATE] events 0 -> 1
  [RETURN] combat_resolver.execute
  [STATE] goblin.hp 5 -> 0
  [STATE] combat hit=true
[RETURN] combat_command_resolver.execute
[STATE] attack command success=true
[CALL] event_dispatcher.dispatch_all
  [CALL] event_dispatcher.dispatch
    [CALL] combat_log.on_damage_applied
    [RETURN] combat_log.on_damage_applied
    [STATE] logs 0 -> 1
    [CALL] death_handler.on_damage_applied
    [RETURN] death_handler.on_damage_applied
    [STATE] goblin.incapacitated nil -> true
    [STATE] goblin.dying nil -> true
    [STATE] death handler result=false
  [RETURN] event_dispatcher.dispatch
  [EVENT] dispatched damage_applied
[RETURN] event_dispatcher.dispatch_all
[STATE] events 1 -> 0
[STATE] logs 0 -> 1
[RETURN] PUBLIC engine.update(0)
[STATE] queue 1 -> 0
[STATE] logs 0 -> 1
[STATE] Active false -> true
[STATE] goblin.hp 5 -> 0
[STATE] goblin.incapacitated nil -> true
[STATE] goblin.dying nil -> true

So Iโ€™m still working on integrating all of this.

Once all the rules are properly implemented (especially since Iโ€™ve learned along the way that thereโ€™s an SRD for FTD, and of course it doesnโ€™t match my rules 100%), Iโ€™ll start working on more visual aspects, but weโ€™re not there yet.

A quick note on tools:

  • Itโ€™s obvious, but Iโ€™ll say it anyway: without Git, thereโ€™s no hope (Iโ€™m working entirely locally).
  • CodeGraph is simply indispensable as the code grows; it lets you generate things like this:
combat_resolver
โ”œโ”€โ”€ actor::get_ac
โ”‚   โ”œโ”€โ”€ actor::get_ac_bonus
โ”‚   โ”œโ”€โ”€ armor::ac
โ”‚   โ””โ”€โ”€ shield::apply
โ”œโ”€โ”€ actor::is_dead
โ”‚   โ””โ”€โ”€ actor::has_condition
โ”œโ”€โ”€ attack::resolve
โ”‚   โ””โ”€โ”€ check::resolve
โ”œโ”€โ”€ damage::resolve
โ”œโ”€โ”€ engine::get_actor
โ”œโ”€โ”€ engine::get_state
โ”œโ”€โ”€ equipment::get
โ”œโ”€โ”€ events::push
โ”œโ”€โ”€ hp::apply_damage
โ”‚   โ”œโ”€โ”€ hp
โ”‚   โ”‚   โ””โ”€โ”€ supply::max
โ”‚   โ””โ”€โ”€ supply::max
โ”œโ”€โ”€ weapon::attack_bonus
โ””โ”€โ”€ weapon::damage_bonus

and:

engine::rest_actor
โ”œโ”€โ”€ engine::get_actor [Modules/Engine/engine.lua:204]
โ””โ”€โ”€ rest_handler::apply [Modules/Engine/engine.lua:273, Modules/Engine/rest_handler.lua:12]
    โ”œโ”€โ”€ actor::clear_temporary_injuries [Modules/Engine/actor.lua:142, Modules/Engine/rest_handler.lua:12]
    โ”‚   โ””โ”€โ”€ actor.ensure_injuries [Modules/Engine/actor.lua:75]
    โ”œโ”€โ”€ actor::has_condition [Modules/Engine/actor.lua:201, Modules/Engine/rest_handler.lua:12]
    โ”œโ”€โ”€ actor::remove_condition [Modules/Engine/actor.lua:222, Modules/Engine/rest_handler.lua:12]
    โ”œโ”€โ”€ hp::apply_healing [Modules/Engine/hp.lua:34, Modules/Engine/rest_handler.lua:12]
    โ”‚   โ””โ”€โ”€ hp.normalize_amount [Modules/Engine/hp.lua:4]
    โ”‚       โ””โ”€โ”€ supply::max [Modules/Engine/hp.lua:4]
    โ””โ”€โ”€ rest::resolve [Modules/Engine/rest.lua:3, Modules/Engine/rest_handler.lua:12]

And, most importantly, to find out what I've already integrated and what I haven't:

Runtime call tree reachable from main.lua.

main.lua
โ”œโ”€โ”€ love.draw
โ”‚   โ””โ”€โ”€ engine.draw
โ”œโ”€โ”€ love.load
โ”‚   โ””โ”€โ”€ engine.init
โ”‚       โ”œโ”€โ”€ combat.create
โ”‚       โ”‚   โ”œโ”€โ”€ combat_round.create
โ”‚       โ”‚   โ”‚   โ””โ”€โ”€ combat_turn.create
โ”‚       โ”‚   โ””โ”€โ”€ combat_round.create
โ”‚       โ”‚       โ””โ”€โ”€ combat_turn.create
โ”‚       โ”œโ”€โ”€ combat.create
โ”‚       โ”‚   โ”œโ”€โ”€ combat_round.create
โ”‚       โ”‚   โ”‚   โ””โ”€โ”€ combat_turn.create
โ”‚       โ”‚   โ””โ”€โ”€ combat_round.create
โ”‚       โ”‚       โ””โ”€โ”€ combat_turn.create
โ”‚       โ”œโ”€โ”€ command_queue.new
โ”‚       โ”œโ”€โ”€ command_queue.new
โ”‚       โ””โ”€โ”€ event_setup.init
โ””โ”€โ”€ love.update
    โ””โ”€โ”€ engine.update
        โ”œโ”€โ”€ action_resolver.execute
        โ”‚   โ”œโ”€โ”€ engine.get_actor
        โ”‚   โ”œโ”€โ”€ engine.get_state
        โ”‚   โ”œโ”€โ”€ engine.use_action
        โ”‚   โ”‚   โ”œโ”€โ”€ actions.can_follow
        โ”‚   โ”‚   โ”œโ”€โ”€ actions.can_take
        โ”‚   โ”‚   โ”œโ”€โ”€ actions.use
        โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ actions.can_take
        โ”‚   โ”‚   โ”œโ”€โ”€ actions.use
        โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ actions.can_take
        โ”‚   โ”‚   โ”œโ”€โ”€ actor.can_act
        โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ actor.create
        โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ supply.load
        โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ supply.max
        โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ actor.has_condition
        โ”‚   โ”‚   โ”œโ”€โ”€ engine.build_used_actions
        โ”‚   โ”‚   โ”œโ”€โ”€ engine.get_action_key
        โ”‚   โ”‚   โ”œโ”€โ”€ engine.get_actor
        โ”‚   โ”‚   โ””โ”€โ”€ engine.set_action_used
        โ”‚   โ”œโ”€โ”€ events.create
        โ”‚   โ””โ”€โ”€ events.push
        โ”œโ”€โ”€ actor.has_condition
        โ”œโ”€โ”€ command_queue.pop
        โ”œโ”€โ”€ death_handler.resolve_deadline
        โ”‚   โ”œโ”€โ”€ actor.add_condition
        โ”‚   โ”œโ”€โ”€ actor.has_condition
        โ”‚   โ”œโ”€โ”€ actor.remove_condition
        โ”‚   โ”œโ”€โ”€ death.resolve
        โ”‚   โ””โ”€โ”€ events.push
        โ”œโ”€โ”€ death_handler.resolve_deadline
        โ”‚   โ”œโ”€โ”€ actor.add_condition
        โ”‚   โ”œโ”€โ”€ actor.has_condition
        โ”‚   โ”œโ”€โ”€ actor.remove_condition
        โ”‚   โ”œโ”€โ”€ death.resolve
        โ”‚   โ””โ”€โ”€ events.push
        โ””โ”€โ”€ event_dispatcher.dispatch_all
  • Last but not least, to keep from getting lost amid development, integration, bugs, and testing, Linear is a lifesaver too. enter image description here

Well, Iโ€™ve spent about half my vacation on this, but Iโ€™m having fun :)
That was a (very) long postโ€”sorry.
Have a safe trip, and don't forget your torches if you're going to seedy placesโ€”especially ones that aren't well-lit.
Peace, out.

The Return of the Dungeon Generator

- Posted in D&D by

So, no, I hadn't forgotten about it, but with my tendency to procrastinate as soon as life gives me a break, this project had been gathering dust for quite some time.
Against all odds, I dug it out from the depths of a folder on my hard drive with the idea of reworking it, or even (crazy and pretentious as I am) finishing it, trying at the same time to conquerโ€”for onceโ€”one of my most persistent demons: projects started but never finished. Thanks to global warming, I was able to spend a few days cooped up indoors to escape the heat and work on continuing this project.
Well, actually, I started it all over from scratch :)
Still built on Lua (which reminds me of my first love, Tcl) and its Lรถve framework (for doing 2D without reinventing the wheel).
So hereโ€™s a more or less stable version of Isometric Dungeon Generator (aka IDG). And yes, I know, itโ€™s not an isometric projection, but who caresโ€”itโ€™s just its nickname.

So, what exactly does this revenant from beyond the grave do?
It lets you:

  • randomly generate dungeons with square rooms and straight corridors with turns
  • scatter doors (possibly secret ones), pillars, traps, pits, skeletons, and of course treasures throughout them
  • influence all that randomness by adjusting the weights that govern the spawning of these objects
  • render all of this using sprites that I half-stole (shh) and half-made myself
  • export a superb .png of the whole thing
  • and also export a .json file

What does it look like?
A zoomable overview of the dungeon:

A zoomable โ€œinternalโ€ view of the dungeon that lets you visualize the underlying logic behind object generation:

A configuration window to control (to some extent) the parameters of the generated dungeon:



So, in the end, whatโ€™s the point of all this?

  • Well, for starters, so I can look at my screen and say out loud: โ€œDid you see that? I did it!โ€ (and, incidentally, to post here once every two years)
  • To accept that Iโ€™ll always be light-years away from the quality of projects like Dungeon Map Generator (acceptance's always the first step)
  • And itโ€™s the first step toward my original idea: coding a single-player dungeon crawler, in the style of 2D6 Dungeon, even though lately Iโ€™ve been eyeing 5 Torches Deep more (I love the tension of managing torches)

See you in 3 years. And remember:

None of us are promised tomorrow. Life is uncertain. So... eat your dessert first.

Peace. Out.

(yes, the last sentences were a bit Matthew Colville influenced. Just a bit)

Dungeon generator

- Posted in D&D by

I recently stumbled upon this awesome free online Dungeon Map Generator, which gives you really nice ready to use maps like this:
enter image description here

While trying to build such a generator from scratch, I quickly came to the conclusion that this one is in fact much more complete and complex that it appears at first sight (and you realize that once you've tried to build your own):

  • Maps are not just orthogonal, they're nicely rotated
  • Walls are sexy
  • Rooms can be round
  • Rooms have notes

So yes, I'm trying to build my own map generator (got the idea while playing the solo Dungeon Crawler 2D6 Dungeon, which is by the way as cheap as excellent) and after a few hours of Lua, right now my generated maps look like this (beware, it's all but as sexy as above): enter image description here

There's a French proverb that says โ€œwhen I look at myself I feel sorry, when I compare myself I feel comfortedโ€.
Well, right now I'm much more sorry than comforted :)
So now I've got some work, first debug (the doors are badly placed, the corridors too numerous), rooms should be numbered in a clever way, and then make the output a little prettier (as far as the look is concerned there's definitively room for improvement).
And then generate levels interconnected by stairs :)

Why spend hours trying to do this when very nice free tools already exist?
Because โ€œIts the not the destination, it's the journey.โ€
Peace out.

More than images, ideas

- Posted in D&D by

Recently I played quite a bit with Stable Diffusion, a program for generating images from text, and it's amazing.
I'm not going to try to show here some unmatched ability (that I don't have) to generate extraordinary images, the Internet is full of tutorials on the subject (I recommend for example Sebastian Kamph's YouTube channel, he is both talented and educational).
However, let's talk about the unexpected fact that these images ... stimulate my imagination.
Indeed, in order to illustrate in an original way the textual descriptions of my imaginary world of Gilianar, I played with Stable Diffusion and besides the quality of the images produced, I discovered with surprise how this tool gave me new ideas.
Let me explain.
Let's say I want an image of a dragon perched on an old tower. With the following prompt

ancient yellow and green dragon with a large wingspan perched on an old broken stone tower

I get this for example:
enter image description here
Not bad for a start.
Stable Diffusion's modus operandi is to generate a lot of images, then once you like one of them, to modify it in a loop until you get a satisfactory result.
So let's modify it, but this time starting not from the textual description of the beginning, but from the image above (yes, Stable Diffusion is amazing, I already said it).
By playing with the enigmatic parameter Denoising strength, one introduce more or less chaos in the following images and so that's where magic happens, it's as if a part of a story was written without us.
After a few generations, an image clicks in my head.
"Oh yeah, that's cool, it looks like a forgotten tomb, let's keep this one!"
enter image description here
So much for the grave, now it looks more like she has boobs and she is instead near the entrance to her nest, on which she watches fiercely.
What if she protects her eggs? Deal!
A few random images later with guarding her eggs added to the description, this one fits my mood:
enter image description here
Definitely a good start for a place and the history that goes with it!

Thank you Stable Diffusion, I was just looking for original images to illustrate my texts, but I actually found more than that, now I own an iterative idea machine!