Sutori Project

A simple to use dialog system for websites, apps, games and more!

npmjs v0.0.7 nuget v0.0.2 forum

About Sutori

Sutori is a dialog engine that enables you to add an easy to customise dialog abilities to nearly anything that needs them. Here are some great examples of use cases:

  • A quiz/survey on a website.
  • Custom checkout process for buying things on a web shop.
  • Conversation system in computer game.
  • Visual novel creation.
  • Telephone switch board.

Dialog is written in XML files, with a structure that allows for multiple languages, option branches, multimedia (images, audio, video). Dialog is broken up into a list of moments in which the conversation can traverse.

Here is an example of a basic sutori XML document:

<?xml version="1.0" encoding="utf-8"?>
<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <moments>
      <moment>
         <text>Which door do you want to open?</text>
         <option target="door1">Door 1</option>
         <option target="door2">Door 2</option>
      </moment>

      <moment id="door1" clear="true" goto="end">
         <text>You picked door1</text>
      </moment>

      <moment id="door2" clear="true" goto="end">
         <text>You picked door2</text>
      </moment>

      <moment id="end">
         <text>This is the end</text>
      </moment>
   </moments>
</document>

Sutori closely mimics the way CYOA (choose your own adventure) Gamebooks work, with the small difference is that at the end of each moment, the user is asked what to do next.

For a more in-depth explanation on what XML sutori understands, visit the XML guide page for more information.

Getting Started

How To Use

The JavaScript version of Sutori is the most versatile version of the engine. You can build it into websites, or apps thanks to it's lack of dependencies.

Install into your project using NPM like this:

npm install sutori-js

Code Example

// load in an xml document.
const doc = await SutoriDocument.LoadXmlFile("test1.xml");
											  
// create a prompt engine.
const engine = new SutoriEngine(doc);
									
// handle challenges for a response.
engine.HandleChallenge = function(event) {
    // handler code goes here.
    console.log(event);
}
									
// ask the engine to start prompting challenges.
engine.Play()

How To Use

The .NET Standard 2.0 version of Sutori is the most appropriate version if you want to use Sutori in a desktop application, or a game that has the ability to communicate with .NET (Unity, Unreal Engine, MonoGame etc..).

With access to the .NET CLI, reference like this:

dotnet add package SutoriProject.Sutori

Code Example

using SutoriProject.Sutori;

// load the document & engine.
var doc = await SutoriDocument.LoadFromXmlFileAsync("test1.xml");
var engine = new SutoriEngine(doc);

// hook into the event system.
engine.HandleChallenge += 
   async delegate(object? sender, SutoriEngineCallbackArgs e) {

   Console.WriteLine(e.Moment.GetText(engine.Culture));

   var options = e.Moment.GetOptions(engine.Culture).ToArray();
   foreach (var option in options)
      Console.WriteLine(option.Text);

   // prompt & handle an answer.
   switch (Console.ReadKey(true).Key) {
      case ConsoleKey.D1: 
         await engine.GotoMomentIDAsync(options[0].Target);
         break;
      case ConsoleKey.D2:
         await engine.GotoMomentIDAsync(options[1].Target);
         break;
      default:
         await engine.GotoNextMomentAsync();
         break;
   }
};

// begin the game.
await engine.PlayAsync();

How To Use

The Python version of Sutori is designed to fit into places where you don't have access to powerful frameworks like JavaScript or .NET.

For example if you want to make a simple game on a PI or an Arduino this would be a good fit!

To use this version of the library, simply visit the Github link below to download sutori.py:

Code Example

import sutori;

# load document
doc = sutori.SutoriDocument()
doc.load_xml_file("example1.xml")

# init the engine.
engine = sutori.SutoriEngine(doc)

# choose a culture (language)
culture = sutori.SutoriCulture.NONE

# create handler for challenge events
def handle_challenge(moment):
   
   _options = moment.get_options(culture)
	
   if len(_options) > 0:
      for _option in _options:
         print("-- " + _option.text)
      response = input(moment.get_text(culture) + ' ')
      if response == '1':
         engine.goto_moment_id(_options[0].target)
      if response == '2':
         engine.goto_moment_id(_options[1].target)
      if response == '3':
         engine.goto_moment_id(_options[1].target)
   else:
      input(moment.get_text(culture) + ' ')
      engine.goto_next_moment()

# create handler for end event.
def handle_end():
   print('-- fin --')

# hook the events into the engine, then begin.
engine.challenge_event = handle_challenge
engine.end_event = handle_end
engine.play()

Sutori Studio (alpha)

Currently under construction, Sutori Studio is a cross-platform editor for Sutori XML files. Like the rest of the project it is completely free, and is written in Typescript and bundled in a new technology called NeutralinoJS.

If you wish to get notifications when release happen. Make sure to Star or Watch the repo on Github using the link below:

Visit on GitHub. Watch Star

The current alpha is actually available to use in browser, use link below to launch it:

A screenshot of Sutori Studio

Sutori Game Template

Want to build a visual novel using HTML, CSS and JavaScript? Why not try out the new Neutralino template we created called sutori-game. Couple it with Sutori Studio, and you could creating your first game in minutes!

Like with Sutori Studio, use the following links to get connected:

Visit on GitHub. Watch Star
A screenshot of Sutori Game Template