Trizbort.io: Build adventure game maps in your browser

Trizbort.io is a browser-based tool that lets you easily map adventure games. Drag rooms into your map and link them up using connections in all compass directions. Add a list of objects present in each room. Finally, export your map straight to your adventure game toolkit of choice: TADS, Inform, Quest or Alan.

Trizbort,io is inspired by Trizbort, a desktop-based mapping tool originally created by Genstein and enhanced and maintained by Jason Lautzenheiser.

Edit room details quickly

Trizbort,io lets you edit the properties of your rooms using a quick and intuitive editor. Room name and description, room colors, room borders, elliptical or octagonal rooms are supported.

Add named objects with descriptions to your rooms, and create containment relationships - which will be included in your code generation later.

Generate code from your map

Trizbort,io can export your map to various adventure game development system. It supports TADS 3, Inform 7, Quest and Alan 2/3, among others. Code is generated for your rooms, connections and objects, and you can feed it straight into your compiler.

If you’d like to dive straight in, here is a link that opens Trizbort,io with a map preloaded:

2 Likes

Here are two more maps to play with in Trizbort,io:

Even more maps:

This is pretty great, but I can’t seem to export to Inform 7. Also saving a map gives me a .json file that won’t open again. It shows up in the load dialog but is not selectable.

I’m on Mac btw.

Thanks for trying things out! Your using a mac might be a clue for what’s going wrong. Are you using the Safari browser?

I am moving this issue to Trizbort’s Github repository since there are now several contributors working on this project.

If you have any additional info about this issue, please let us know!

Hi again, I was actually using Google Chrome.

Thanks again for reporting this. I have confirmed that code export indeed did not work as it should. A downloadable file was never offered. This has now been fixed; you should be able to export and save a file to local disk, in all code flavors.

I haven’t yet been able to replicate the issue where you can’t reopen a map file you just saved.

@Hanon: The map-loading issue on Chrome has now been solved.

Also, a host of new features were added to Trizbort.io: a help system, keyboard shortcuts, better Quest export, better TADS export, TextAdventure.js export, image export.

I love this! Non-linear stories deserve non-linear editors!

Some issues:

Tutorial says I can drag and drop objects on top of each other to specify the container relationship, but it doesn’t seem to work. I’m running Chrome on Windows 10.

Also, although it’s pretty easy to zoom, I can’t figure out how to pan.

Panning is done by holding down your mouse wheel. That may be have been a bad design choice (not all mouse wheels are clickable), so I think I’ll add a right mouse button + drag feature as well.

I will look into the dragging issue. It is probably Chrome-related.

Yes, holding down the mouse wheel works. I had forgotten that trick. You may want to consider adding controls for pan and zoom like google maps. You can leverage the fact that everyone is already familiar with that UI.

Lot’s of folks, myself included, are experimenting with DSLs for IF. It would be great if you could write up a tutorial on how to extend Trizbort to provide output for a custom DSL.

1 Like

Following the google maps convention is a good idea. Google uses the left mouse button for panning, but Trizbort.io needs it for object selection. I have changed the code to allow for panning by holding down the right mouse button; that should cater for everyone who does not have a clickable mouse wheel.

I’ve also fixed object dragging on Chrome. You can now drag objects using the handle on the side of the object box to create container relationships.

Domain-specific languages

Regarding DSLs: Trizbort uses the Handlebars template language to expands its models into a language like TADS or Inform. It is quite easy to add a new Handlebars template to the codebase, provided you know how the models are structured. The relationships are very simple: A map has rooms, and connectors exist between rooms. There are also notes and blocks, but these are generally not interesting for export. Handlebars allows for writing little JavaScript helpers that make it easier to encapsulate complex bits of code generation. It also allows recursion, which is important for object containment relationships.

For example, the code for TADS generation works as follows. It starts off with TADS boilerplate, where several values are filled in use Handlebars expressions ({{{...}}}). A reference is made to the main model element map.

#charset "us-ascii"

#include <adv3.h>
#include <en_us.h>

versionInfo: GameID
  name = '{{{map.title}}}'
  byline = 'by {{{map.author}}}'
  version = '1.0'
  desc = '"{{{map.description}}}'

gameMain: GameMainDef
  initialPlayerChar = me

Further down, the player actor is placed in the start room. TADS requires that a room name has CamelCase notation, so there is a Handlebars helper className that converts a name to a class name, i.e. “West of house” becomes WestOfHouse.

+ me: Actor
  location = {{{className map.startRoom.name}}}
;

A list of rooms follows, generated using Handlebars’s default #each block helper. For each room, the template goes through a list of its connections, and uses a custom helper to convert the connection’s compass direction to a string TADS understands.

{{#each map.rooms}} 
{{className this.name}}: Room '{{{this.name}}}'
  "{{{this.description}}}"
  {{#each this.connections}}
  {{ dirToStr this.startDir }}: {{{className this.room.name}}}
  {{/each}}
;

{{#each this.objects}}{{buildObject this}}{{/each}}
{{/each}} 

Within each room, the template processes the objects present. Since this requires recursion, I wrote a custom helper buildObject to produce the code. Helpers are written in JavaScript:

  protected buildObject(obj: Obj, level?: number) {
    if(!level) level = 1;
    let str = "";
    for(let i = 0; i < level; i++) str += "+";
    str = str + Handlebars.templates.tadsObject({ obj: obj });
    obj.content.forEach((o) => {
      str = str + this.buildObject(o, level + 1);
    });
    return new Handlebars.SafeString(str);
  }

The helper uses a subtemplate named tadsObject to export each object. Here kindToStr is another helper than converts an object type (actor, item or scenery) into a TADS class (Actor, Item or Decoration):

{{kindToStr obj.kind}} '{{{obj.name}}}'
 "{{{obj.description}}}"
;

It is quite easy to build new Handlebars template. The tricky part is usually getting the indentation right.

Current state of DSLs

Trizbort supports export to several domain-specific languages, in varying states of completeness. All DSLs export rooms and connections, some add objects, and some add containment relationships. Missing features are easy to add, but may require better knowledge of the DSLs themselves. I’m a TADS user, and I dug into Inform 7 to get the export right. A github user kindly helped with some of the Quest implementation, but it needs attention. There’s also Alan 2/3, but I am not sure too many people use that.

Trizbort has features for dark rooms, but no template uses that feature yet. I’m currently adding support for (locked) doors, and I’ll be adding export to TADS for that. For Inform - input very welcome.

Adding new DSLs

Currently, adding new export languages to Trizbort requires fiddling with the code. There is no feature for uploading new templates. If you’d like to experiment:

  • A package of Handlebars templates and JavaScript helpers are stored under /src/codegen.
  • To make a new code generation option available, it must be added to the main menu (/src/panels/menuPanel), where you can just copy-paste one of the existing options.

Making DSLs dynamic, i.e. where you upload a new specification to Trizbort would mean parsing Handlebars templates on the fly. That is possible to do. However, it would not be easily possible to parse JavaScript helpers, so it might be better to express these in some sort of template language as well. That seems a big task.

Thanks, nice write up.