Sadako: a new hypertext adventure engine

I’ve spent the last few months working on a project that I’d like to share with the public. My goal was to create a scripting language that merged my favorite things about Twine and my favorite things about Ink into one package, and I feel like I’ve succeeded.

Sadako is written entirely in ECMAScript 5 compliant JavaScript and is meant to be included in an HTML page. However, I left the text output functions exposed so that they can be easily overridden with functions targeting a different UI, if anyone wants to include it in an Electron app or something similar.

You can see a demo game of it here: http://tayruh.thanatos.feralhosting.com/gamebook/

Some other links:

Here’s a snippet of what the script syntax looks like:

## remote
	It's the remote for the television. Erin is looking for this.
	
	+ [Use]
		~~ if ($.bookmark === "erin.remote")
			[:&
				sadako.closeDialog(true);
				game.move(null, "remote");
			:]
			You hand the remote to Erin.
			"Thanks, $:name!"
			She points it at the TV and turns the volume up a couple notches. "Ah. Much better."
			+++ {gave} [Back]
				>> #living_room
		~~ else
			You can't find a use for the remote here.
			
			[:& sadako.doLink("#inventory") @: Back:] ~:choice
			<< END
	+ [Back];; >> #inventory

One of the big features of Sadako is that you can either compile the source to a JS file to be included into your page, or you can write the script directly into an HTML page. The following is a fully functioning (albeit incredibly short) game.

<html>
    <head>
        <style type="text/css">
            .choice { 
                cursor: pointer;
                color: orange;
            }
        </style>
    </head>
    <body>
        <div id="output"></div>
        <textarea id="source" style="display:none">
            ## start
                Hello world
                + Choice one[] was chosen.
                    Maybe try choice two next time?
                + Choice two[] was chosen.
                    Maybe try choice one next time?
                - The End
        </textarea>
    </body>
    <script src="sadako.js" type="text/javascript"></script>
    <script src="kayako.js" type="text/javascript"></script>
	<script type="text/javascript">
        sadako.init();
        sadako.startGame();
    </script>
</html>

Anyway, I guess that’s it. Hopefully you guys will check it out and let me know what you think.

Edit: Rewrote the description and changed the title because I don’t think that I presented the information very well the first time around.

6 Likes

I was unsure whether to keep updating this thread as I add features, but I figured that it’d make sense if I added big ones that might be of interest. shrug

After realizing how useful scenes are for Inform and TADS, I decided to add them to Sadako. And so I did. As far as I’m aware, I managed to emulate their functionality almost exactly.

To be honest, it comes at a good time because I was trying to figure out how to prevent the game I’m working on from turning into spaghetti code. This will solve a lot of those problems. :smile:

Anyway, I updated the demo code in the first post (and also the demo itself, but the changes aren’t visible), and added the info on how to use it to the reference. There’s a direct link to the section right here.

1 Like

In case there’s any passing interest in this project, I finally managed to update the JavaScript reference for it.

Part of this delay was procrastination and part of it was because I was waiting for the project to become stable enough that I was confident none of what I wrote in the reference would change.

With exception of the init and startGame functions, it should possible to make a game in Sadako without using any JavaScript at all. However, you can enhance your game through JavaScript quite easily using a few functions and global variables that are provided for this purpose. And this is what the reference covers.

You can find the reference here: https://github.com/Tayruh/sadako/blob/master/javascript_reference.md

3 Likes

I just released a complex demo which I think would be very useful for anyone curious in this system. It’s basically chapter 1 of a game that I’m currently working on.

The game itself is written as hybrid fiction that attempts to emulate a parser-style game world by using hyperlinks as navigation and object interaction. Sadako can be used to write games in a typical Twine style or even an Ink style. This game blends the two styles together.

You can find the game here: https://tayruh.github.io/monster/

And the source is here: https://github.com/Tayruh/tayruh.github.io/tree/master/monster

An example image:

2 Likes

I can see how the scripting is like Ink-- what features of Twine did you replicate? The passage-based model?

1 Like

Yeah. Here’s a quick list of similarities:

  • The passage model (I call them pages, but same thing). I added labels inside pages though, so it’s like mini-passages inside a passage. I think it helps prevent using passages for only a few lines of text, which I personally found annoying. Pages also support tags like in SugarCube.
  • The embedding of variables values into the text. For example, if you have the character’s name stored as name, it’ll display with $:name in your text, similar to $name in SugarCube.
  • Simple span tag markup. @@bleh;Some text.@@ in SugarCube is <:bleh::Some text.:> in Sadako.
  • It has variables automatically saved to storage using the $ prefix and deleted after transition if prefixed with _, similar to SugarCube.
  • Simple text replacement based on true/false conditions (also present in Ink) with You have {:some_value > 0::some stuff::nothing:} left.
  • The ability to use javascript inside a page without it being defined ahead of time.
  • You can define a function as a macro and call it from your page with (:someFunction arg1, arg2:) without having to drop into JS to call it.
  • You can embed input textboxes and text areas into your script. [:> $.name @: What is your name?:] is a single line textbox and [:>> would be a large textarea box.
  • It also has history with a definable limit (including disabling). The back() function sends you back one history state.
  • Sadako also provides the functions for showing and hiding a dialog window. Unlike SugarCube, the HTML behind this is up to the user. You can see an example of how to do it in the demo I linked in the first post. Due to the way it’s designed, the “dialog” could also be another DIV (like a sidebar or something) instead of a pop-up.
  • There are before and after user defined functions that are called before and after every page transition. You can define them so that they are only called for a specific page, or you can use ALL to have it called for every page.

That’s about it, I think. Twine/SugarCube has a lot of high level features that I honestly have no intention of ever adding. But I love their passage model and their embedding stuff, so I implimented it.

Before I started Sadako, I originally tried just using Ink inside SugarCube, which I did actually get to work. But the two different engines had a really difficult time talking to each other. It was possible but incredibly cumbersome. And that’s why I developed this. It was mostly an engine I made for me, but then I decided to share.