Rez v1.7.0 — open source tool for creating non-linear games/IF

You do!

This looks great, but I’m not interested in installing Elixir or Erlang. Would it be possible to host an editor and compiler online ?

1 Like

Thank you. That’s kind of you to say.

In terms of a hosted version it’s technically possible but somewhat unlikely because I have little interest in creating the kind of editor environment you’d need.

To your point about not wanting to install the dependencies though, the binary download packages for macOS, Linux, and Windows mean that you shouldn’t have to manually install or update any of the Elixir/Erlang dependencies if you don’t want to.

If you want to try it I am happy to support you.

1 Like

Oh, that’s great. Would it be possible to add state machines and behavior trees to a Rez game? Is there anything I will encounter (any issues) if I use the binary download instead of doing a manual install?

I’m reluctant to install more programming languages on my computer. A lot of them don’t interact well with each other (especially Python vs. anything else). I’m not sure whether the Rez binary auto-installs Elixir/Erlang or makes their installations irrelevant, but I’ll try either way.

I think you could consider making the README.md for Rez more visually striking if you want to have more people use it or care about that kind of thing. If not, you don’t have to! I just noticed that I instinctively kept looking for some kind of logo or image and couldn’t find one.

Also, I’m not sure if this is intentional? I don’t know if the source code for these pages is meant to be part of the preview.

Rez already has some support for behaviour trees although it needs more testing and refinement. It’s easy enough to build state machines (@plot is a vehicle for doing this) but what did you have in mind?

In terms of usage it shouldn’t make any difference whether you install it yourself or use the binary package. The Rez code is the same either way around.

The binary installer installs the Beam virtual machine, ERTS, and the compiled application code. But AFAIK it is not equivalent to installing Erland or Elixir on your computer.

In fact I have a great logo contributed by @HAL9000 which I haven’t gotten put on the site yet (except for the favicon).

I accept your criticisms. Rez being a side-project means that progress fixing this stuff isn’t necessarily quick.

To that end it’s probably worth noting some of Rez’s shortcomings before you dive in.

  1. The game file parser error reporting needs a lot of work
  2. The save/load system is broken.
  3. There is no local state preservation or undo support. If you reload the page you reload the game and you can’t go backwards in time.
  4. JavaScript run-time needs a bit of work
  5. Only image assets are supported.
  6. Documentation needs a bit of work

By “parser” here I am talking about the code that reads .rez files. The error messages it generates when you get syntax wrong aren’t brilliant. Because I am so familiar with the internals I can usually spot errors pretty fast so fixing this has been low priority up to now. Error reports from users/bugging me for support will probably force me to focus on improving this.

Save/load to/from JSON files used to work but got broken. This is probably next on my list to fix because I will need this to work soon myself.

Undo support and saving the current state to localStorage is planned but I am still considering how best to implement it. Rez actually stores deltas to the attributes so the underpinnings are there, I think it’s mainly detail.

The Javascript run-time has been some of the oldest code in Rez and some of it is showing its age. I’ve just this weekend gone back and rewritten all of it to a more modern standard (using class and private fields, etc…). This will be the 1.5 release.

Asset management works but presently only supports image assets. That’s largely because I haven’t been fussed to go back and fix audio/video assets because I don’t have any yet. The actual work involved work is relatively small.

Documentation is a bit patchy. I think it’s mostly decent enough but some areas definitely need work. The authoring guide was a good start but I’ve not gotten around to continuing it.

The net of this is, if you were thinking of doing some kind of game jam where you release something next weekend then it may not be fully baked. Lack of save/load for example might be a non-starter. But if your timescale is more along the line of weeks/months then I have time to fix some of these things. They’re mostly things I need anyway.

I don’t want to put you off, and I am working on the shortcomings, but feel it’s worth understanding where the project is right now before encouraging you to put your time into using it.

1 Like

I have finally figured out enough Hugo configuration to add the logo. My thanks to @HAL9000 for creating it.

1 Like

Okay I have fixed save/load.

Calling $game.save() will automatically download a JSON file containing all attribute changes since the game was loaded.

The standard lib contains a very basic scene $load_game which has a form to pick a save file and load it.

You can trigger this with:

$game.interludeSceneWithId("$load_game");

or

<a interlude="$load_game">Load Game</a>

It restores attributes to their saved values and then resumes the previous scene.

It’s a little basic but functional again.

From here to saving state to localStorage (so that reloading the page doesn’t reset the game stage) and implementing undo should be relatively small steps.

1 Like

That’s great progress. Are you interested in collaborators? I would like to redesign the GitHub README.md, spruce up the documentation (colors! interactive examples!), and learn how Rez works enough to add features that I need.

Although…that last idea might be difficult for me to execute as I lack Erlang/Elixir experience.

2 Likes

Definitely open to collaborations.

If you’re familiar with Git/Github you can create your own fork of the project and make any changes you like, then open a PR for me to incorporate them when you’re ready.

In terms of the code it’s about 9k lines of Elixir and 5.5k of Javascript. So experience with either is potentially relevant. The Elixir code is the parser and code generator, the Javascript is the Rez runtime library. Most of the actual functionality is implemented in JS.

But at this point just kicking the tyres would be a great help.

1 Like

I’ve just published Rez v1.5.0. This version fixes bugs, improves underlying systems, and adds a couple of QoL updates.

The most noticable is the inclusion of the <.embed_card /> component into the stdlib, while also allowing user components to accept ‘dynamic assigns’. This means you can write content like:

@card my_card {
  bindings: [
    player: #player
    location: player.location
  ]

  content: ```
  <p>Some fixed content here.</p>
  <.embed_card card={location.card} />
  <p>Some more fixed content.</p>
  ```
}

While I implemented user components on a whim they’ve turned out to be transformative and are generally pretty easy to write. The <.embed_card /> component, as the name suggests, embeds the content of any referenced card into the current card.

The addition of dynamic assigns (using the {} delimiter) allows passing expressions to the component. In this case location is a local binding with a card property.

Previously the way to incorporate other content was using a blocks: attribute but this only allowed for including named cards. It remains to be seen whether blocks: still has a purpose, or whether it could be phased out in a future release in favour of embed_card.

For example I commonly implement a two column layout for a @scene as follows:

@scene s_foo {
  blocks: [#c_sidebar]
  layout: ```
  <div class="columns">
    <div class="column is-two-fifths">${c_sidebar}</div>
    <div class="column">${content}</div>
  </div>
}
  ```

But this would work just as well by removing the blocks: attribute and using <embed_card card="c_sidebar" /> into the first column.

There are numerous fixes added since v1.4 including bringing save & load back into a working state. It’s not perfect but it’s usable. A basic “game load” scene is included in the standard lib and can be triggered with the following:

<a interlude="$load_game">Load</a>

But it’s mainly there to show how you could implement your own much nicer load-game screen.

The JS code that forms the basis of the stdlib has been completely rewritten to use class instead of prototypes and to employing private properties wherever possible. Whatever your views of class in a prototype based language it certainly reads clearer now.

Lastly, although not part of the release itself, I’ve created a version of the Cloak of Darkness game for Rez.

CoD doesn’t make a huge amount of sense as a choice game given that it’s primary puzzle is verb discovery. But it does seem to be a right of passage for any game system so I made one for Rez.

What I’ve tried to do with this is explore a number of Rez’s features that aren’t strictly necessary in a game of such low complexity:

  • It makes heavy use of @inventory, @item, @effect, @plot, and @actor.
  • It uses multiple @scenes including triggering an interlude (a scene within a scene) using a @keybinding
  • Custom objects with defaults, e.g. @location
  • Including custom Javascript (e.g. using Tippy.js for dynamic popovers on links)
  • Significant amounts of dynamically rendered content

Lastly it utilises my in-progress “storylet lib” which sits atop Rez and makes choices available dynamically. Any element can provide a generate_storylets: function attribute that can return one or more Storylet objects. In the game both @scene, @actor and @locations all generate options this way.

While this CoD definitely needs more work, it’s a start. Here’s the source.

All-in-all Rez has now reached a level of maturity where you can use it to build real, complex, games. I don’t have any further planned features and remaining work required is about improving event handling, optimising the compiler, and improving parser error messages which are — I won’t deny it — pretty poor.

I hope you’ll give Rez a try and welcome all constructive feedback.

2 Likes

I’ve just released v1.5.1 of Rez to Github.

This includes the fixes I made to the RezList bag implementation on stream the other day and some optimisations to the parser.

These cut parsing times for my game file from 2.9s to 1.7s which is appreciable although ~2s is still pretty slow (the smallest possible game takes about 0.5s to compile). I may need to bust out some profiling to work out why.

1 Like

Something like this the reason why I love Rust, but creating UI in Rust is a pain - the long compile times even for small changes. When I change a line in a TypeScript file, Webpack applies the changes instantly. Sadly, Web dev is still the platform with the best dev experience for UI.

I did explore a re-write in Rust but I couldn’t get on with it for the amount of time I had available. I suspect profiling and rewriting what I have will get me better results.

I could also explore a different structure that would support incremental compilation.

Incremental compilation is great - Rust already uses it and is still slow to compile. A technique used for language servers is to surgically change the existing AST when a file is changed. If I ever get around to creating my own programming language, I’ll take this a step further: incremental compilation for each function. Only modified functions will get recompiled, the rest is cached and just assembled to the new binary.

If you’re done changing the language for the most part, you could rewrite the compiler in a statically-typed compiled language for speed gains. If not, a few seconds are by far not the worst compile times I’ve seen lol. For something still in development that’s completely fine. Most non-trivial C applications take longer to compile.

1 Like

Yep that’s what I was considering. I did a spike with Rust and while I didn’t really give it long enough I wasn’t digging it and the advice I was getting was that I’d bitten off (in terms of the data representation) something that wasn’t a beginner level problem.

I’m 25+ years from being fluent in C++ so if I was going to do a performance rewrite now I think I’d try OCaml.

But I figure that I can still get decent performance and stay with Elixir by optimising what I have.

I’m ready to start coding! Can you explain how @plot is a vehicle for building state machines?

2 Likes

Hm. I wonder what this error means? I renamed the executable rez from rez_macos, do you think that’s the issue?

Also, please let me know whether you prefer to have this kind of discussion on intfiction, GitHub, or somewhere/thing else.

Nothing formal but each @plot has a current stage that can be advanced and you can have as many plots as you like and intertwined them in as complex a pattern as you like using the on_advance handler to create side-effects.

I suspect that this means you have another rez binary in your path. I’m on a Mac and rez refers to /usr/bin/rez (IIRC, an old Apple developer tool). My solution was to rename it to rc (for Rez compiler).