Skip to content
borisvanschooten edited this page Apr 17, 2020 · 61 revisions

WOOL Logo

WOOL is a dialogue specification language and accompanying set of tools that allows you to quickly and dynamically script dialogues between characters and embed them within your application with ease.

The Repository

The WOOL repository consists of three parts:

  • /java/ - contains the core Java library for reading, and executing .wool scripts.
  • /test-dialogues/ - contains various test .wool scripts with increasing level of complexity.
  • /wooleditor/ - contains the web-based editor for .wool scripts (based on the Yarn Editor).

Language Definition

A WOOL dialogue definition is essentially a definition of a series of dialogue steps (that we refer to as nodes) linked together through user replies.

We define the following terms:

  • Node - A dialogue step that contains one Statement and a one or more Replies.
  • Statement - Something an agent says.
  • Reply - A possible reply that a user of the system can give.
  • Agent - A virtual speaker within a dialogue.

Nodes

A Node consists of two parts, a header, and a body.

Header

The header consists of a series of lines, each with a Key: Value pair. Required key-value pairs are:

  • title - a String that uniquely identifies this Node within this WoolDialogue.
  • speaker - a String that defines the name of the Agent speaking in this Node.

You are free to define other key-value pairs. The Wool editor uses the following additional ones:

  • colorID - a number between 0 and 9 specifying a colour. This is also used by the viewer to allow multiple backgrounds, one for each colorID.
  • position - used to position the nodes in the editor.

An example of what this looks like in a .wool file:

title: Start
speaker: Robin
position: -416,112
colorID: 3

Body

The body of a Node contains at least one Statement and zero or more Replies. A very basic example is given here.

Hello, my name is Robin!

[[Nice to meet you Robin!|NodeRobin2]]
[[Goodbye.|NodeEnd]]

This Node defines a Statement "Hello, my name is Robin!", uttered by the Agent "Robin" and two possible Reply options. When a user selects "Nice to meet you Robin!" he will be forwarded to a Node labeled "NodeRobin2", and when he selects "Goodbye." he will be forwarded to the Node labeled "NodeEnd".

File Format

A .wool files consists of a list of concatenated Nodes separated by === markers. The header and body of the node are separated by the --- line. For example:

title: Start
speaker: Robin
position: -416,112
color: cyan
---
Hello, my name is Robin!

[[Nice to meet you Robin!|NodeRobin2]]
[[Goodbye.|NodeEnd]]
===
title: NodeRobin2
speaker: Robin
position: -216,112
color: red
---
Nice to meet you too, how are you doing?

[[I am fine and you?|NodeRobin3]]
[[Goodbye.|NodeEnd]]
===
...

WOOL Dialogues

A series of WOOL Nodes is called a WOOL Dialogue. The following rules apply to WOOL Dialogues:

  • All Node title's must be unique within a WOOL Dialogue.
  • There must be one Node with the title "Start" (this is the default starting point of the dialogue).
  • WOOL Dialogue files may contain letters, numbers, dashes and underscores, and end with .wool
    • Valid Examples:
      • mydialogue.wool
      • my-dialogue.wool
      • my_dialogue-1.wool
      • 123dialogue_for-Robin.wool

Ending a dialogue

There are two ways a WOOL dialogue can end:

  • The user doesn't have any Reply options in the Node (the Agent has the last say).
  • The user chooses a Reply option that leads to a Node with title "End" (user has the last say).

Example 1:

It was nice talking to you, bye!

Example 2:

Do you have any other questions?

[[I have nothing left to say.|End]]

Comments

WOOL Supports line-comments, everything after a double-slash // is considered a comment:

Robin: Thank you very much. // Note: thank the user for the gift.

// If it was a nice gift...
<<if $giftNice >>
   ...

Statements

Basic

In the end, all Nodes should output something like this:

Hello, how are you?

Including variables

You can use variables within your statements. Variables start with a $ sign, followed by one of A-Z a-z and then any number of a-z A-Z 0-9 or _. In short: start with a letter, then use letters, numbers or underscores, for example:

  • $variableName
  • $variable_name
  • $var123

These variables can be used within statements to inject their values into a sentence, like so:

Hello $userFirstName, how are you?

Setting variables

WOOL allows you to set variables using the <<set>> statement:

<<set $userFirstName = "Bob">>
<<set $points = 0>>
<<set $hasReplied = true>>

<<set $points = $points + 1>>
<<set $name = $firstname + " " + $lastname>>
<<set $string = "String" + 12345>> // $string is set to "String12345"
<<set $string = 1 + 2 + "3">> // is parsed from left to right, $string = "33"
<<set $string = 1 + (2 + "3")>> // using brackets, resulting in $string = "123"

Special characters

What if you actually want to include a $ character in your text. If it's not followed by A-Z a-z, you can just type $. But otherwise you can escape it with a backslash: \$. And to include a backslash? Just escape it with another backslash: \\. In fact you can escape any character with \ and it will not be treated as a special character. Some more examples: \<< \>> \[[ \]]

Including markup

WOOL doesn't care about your markup, if you want to add HTML tags around text, please go ahead. The parser will ignore it.

Hello <b>$userFirstName</b>, how are you?

Conditionals

WOOL supports if-then-else statements. The simple example:

<<if $dayPart == "Morning" >>
   Good morning ladies and gentlemen!
<<elseif $dayPart == "Afternoon" >>
   Good afternoon peoples!
<<else>>
   Good evening everyone!
<<endif>>

Please note that "==" is treated as strictly-equals.

WOOL also supports nesting these if-statements, if you really have to:

<<if $dayPart == "Morning" >>
    <<if $userFriendly == true>>
        Good morning, sir! How are you today.
    <<else>>
        Mornin'.
    <<endif>>
<<elseif $dayPart == "Afternoon" >>
   ...

Note that in the case of boolean variables ($userFriendly), you can leave out the " == true" part. E.g. the following is valid and will work as expected if $userFriendly is an actual boolean value:

<<if $userFriendly>>

However, if $userFriendly is actually a String with value "No, he is not friendly.", this expression will still evaluate to true.

User Interface Actions

Sometimes you might want to couple some event or action to a statement uttered by a speaker. WOOL supports specifically images, video or generic actions.

The image example:

And here you can see a picture of a dog.
<<action type="image" value="dog.png">>

The video example:

I would like to show you this cool video I found.
<<action type="video" value="https://www.youtube.com/watch?v=dQw4w9WgXcQ">>

The "generic action" example:

Let me show you something in this book I found.
<<action type="generic" value="OPEN_RECIPE_BOOK">>

An example with specified delay:

Okay, I'll take you to the puzzle game, just a second...
<<action type="generic" value="LAUNCH_PUZZLE_GAME" delay="10">>

In this example, the delay parameter defines that the action should be executed with some delay (whether you interpret this as 10 seconds, 10 milliseconds or 10 days is up to your UI developer).

Finally, you may want to add some other parameters, so as long as you don't call them type, value or delay you should be fine:

Okay, I'll take you to the puzzle game, just a second...
<<action type="generic" value="LAUNCH_PUZZLE_GAME" delay="10" difficulty="medium" background-color="#0000FF", num_players="2">>

In this last example, the contents of the value parameter are completely up to you, and up to the user interface developer to interpret. Optionally you can pass parameters along with the action, using the parameters tag.

Replies

Every Node can define zero or more (indefinite, but please consult your UI designer) Reply options, the different types are defined below.

Basic

The standard Reply option defines a "Statement" and "Node Pointer":

[[Are you sure, Robin?|NodeConfirm]]

The user should be forwarded to the Node labeled NodeConfirm when selecting the "Are you sure, Robin?" option.

Auto-forward Replies

You can leave out the statement, but you can only have one of these:

[[NodeConfirm]]

This should allow your user to go to the NodeConfirm node when selecting e.g. a default "Continue" button, or automatically after some time (up to you UI design). As said, and as obvious, you can not have two of these options in the same Node, but you can mix them with Basic replies, as so:

Would you like me to sign you up?

[[Yes, please do so!|Confirm]]
[[No, let's not.|Cancel]]
[[UserInDoubt]]

Input Replies

You can ask a user to add various types of input alongside a chosen reply. The easiest way is just some text input:

What is your first name?

[[None of your business Robin.|RobinInsulted]]
[[My name is <<input type="text" value="$userFirstName" min="5" max="30">>, why do you ask?|RobinInputGiven]]

The general format of this statement is: (optional)beforeText, InputStatement, (optional)afterText.

Very similar is numeric input:

[[I am <<input type="numeric" value="$userAge" min="0" max="120">> years old.|RobinInputGiven]]

In both cases the min and max parameters are optional (you can have none, either, or both).

Then we support time input in hours and minutes:

[[I ate my breakfast at <<input type="time" value="$breakfastTime" granularityMinutes="15" startTime="09:00" minTime="06:00" maxTime="12:00">> this morning.|BreakfastTimeGiven]]

This results in variable $breakfastTime being set to something like "07:45". There are four optional parameters:

  • granularityMinutes: In the example this is 15, meaning that you can enter 00, 15, 30 or 45. You can use any value between 1 and 60. The default is 1.
  • startTime: The time that the input widget should show initially. For example "09:00", but you can also write "now", or even a variable: "$breakfastTimeYesterday". If you leave it out, then the input widget will start empty.
  • minTime: The minimum time that the user can enter. The default is "00:00".
  • maxTime: The maximum time that the user can enter. The default is "23:59".

Setting variables in replies

Yes, that's something you can do as well, as such:

Do you prefer meat or fish?

[[Meat please.|NodeMeat|<<set $likesMeat = true>>]]
[[Fish for me.|NodeFish|<<set $likesFish = true>>]]

Adding actions to replies

Just like you are able to link a set-statement to a reply, you can also add action-statements to replies, like so:

[[Please show me the recipes.|RecipesStart|<<action type="generic" value="OPEN_RECIPE_BOOK">>]]

Linking to other dialogues

There's only so much you want to put into one WOOL dialogue definition before you start losing track (and/or sanity), so WOOL allows you to link between different dialogue definitions, like so:

What should we talk about now?

[[Know anything about cars?|CarsDialogue.Start]]
[[What about fishing?|FishingDialogue.Start]]

In this example, the first reply option would take the user to the Node labeled Start of the Dialogue labeled CarsDialogue. So, in this case, your application should be aware of a file named "CarsDialogue.wool".

License

WOOL is available under the MIT License:

Copyright (c) 2019-2020 Roessingh Research and Development

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.