An Oral History of Twee

Twine (2009) celebrates its 10th birthday this year. Created by Chris Klimas in 2009, it has exploded in popularity from its beginning as hypertext-creation desktop software to being one of the most popular interactive fiction authoring tools on IFDB. It has had a profound impact on the narrative games field, and continues to allow people to create projects and games with very little programming knowledge.

Twine 1 Functionality, File -> Import -> “Twee Source Code…”

However, lost among the transition between Twine 1 (2009), a desktop application, and Twine 2 (2014), a web and desktop application, was a small part of core functionality. Something that was both notation and Twine source code: Twee.

What is Twee?

Twee (2006) was first. According to Chris Klimas, Twee was created as a derivative version of the TiddlyWiki (2004) code for creating interactive fiction. A few years later, an interactive version of Twee, Twine (2009), was created that was based on its ideas and used a graphical interface.

Between 2009 and the introduction of Twine 2 (2014) in 2015, Twine had two formats: HTML and Twee. Whenever a story was created in Twine, it could be imported or exported in either a format a web browser could read, HTML, or one that was much more human-readable, Twee.


:: Start
The story starts here.

[[What happened to Twee?]]

:: What happened to Twee?
It became part of the Twine ecosystem!

:: StoryTitle
An Oral History of Twee

:: StoryAuthor
Dan Cox

The building-blocks of Twine, passages, were represented in blocks of content in plain-text. A passage would start with two colons and then the name of the passage to the end of its line. Starting from the next line to an empty line, the content of the passage would follow. As both “encoded” and more human-readable, it provided an easy way to read the code and also exist as a way to write outside of the Twine program itself.

When Twine 2 (2014) dropped support for it, other tools began to immediately take it up as a way to create works within the Twine ecosystem that did not use Twine itself as the tool for compiling the works. Cradle (2015) (formally UnityTwine) became one of many tools for taking Twee output and using it in Unity. Yarn (2015), a tool based on Twine 1 (2009) that could understand Twee, was created to use the format and expanded in its own direction to be used to make games like A Night in the Woods (2017).

Tweego

Since 2013, Thomas M. Edwards has worked on Tweego (2013), a Twee-compiler written in the programming language Go that works with Twee directly. Instead of using Twine itself, Tweego (2013) takes the source code (Twee) and combines it with a story format to create a Twine-compatible HTML file. It works with both Twine 1 (2009) and Twine 2 (2014)-compatible story formats.

Separate from the editing aspect of using the graphical interface of Twine, Tweego (2013) allowed for authors to continue to create Twine-compatible projects without needing the software itself. Authors could write their own Twee code in whatever editor or tool they wanted and then simply “compile” the project into a HTML file that used the same story formats that Twine used but was not dependent on it.

Twee2

Starting in 2015, Twee2 (2015) was created by Dan-Q. Written in Ruby, Twee2 (2015) attempted to push the Twee notation in new directions. Using tags, functionality that had dated back to Twine 1 (2009) to differentiate if a passage was CSS, JavaScript, or text content, Twee2 (2015) added its own new ones, haml and twee2.

Since it was its own compiler, it could handle text in different ways that Twine did and could not. Using the @include directive functionality, for example, Twee2 (2015) added the ability to quickly include the content of other files without needing to use story format-specific code for the same task.

In an attempt to make its own version of Twee more compatible with Twine 2 (2014), Twee2 (2015) also added some optional metadata, position information. Encoded as part of the HTML, Twee2 (2015) was able to help those authors moving Twee2 (2015) and Twine 2 (2014), even if full support of all functionality was not possible.

Drifting Back

Several years went by while Tweego (2013), Twee2 (2015), and Twine 2 (2014) co-existed separately. Tweego (2013) and Twee2 (2015) could convert back and forth between HTML and Twee, but for those wanting to use Twine 2 (2014) and export out, Michael McCollum created Entweedle (2015). Wanting a better process, M.C. DeMarco created Entwee (2016) as an alternative. As story formats that exported Twine “source code,” Entweedle (2015) and Entwee (2016), allowed for people to continue to use Twee in the newer, Twine 2-era as they moved between the graphical interface and the command-line tools.

For the most part, if an author wanted to write in Twee, they could. While newer developers were not as aware of the existing command-line tools like Tweego (2013) and Twee2 (2015) unless told of them, authors could, with some work, move between writing in the graphical interface of Twine 2 (2014) and use story formats such as Entweedle (2015) or Entwee (2016) to export their content out of Twine 2 (2014). Moving back, however, was not as easy and usually involved importing the compiled HTML file instead of its textual parts.

The introduction of the Twine Cookbook (2017) complicated things even more. In order to represent the “code” of a Twine project, Twee had to be used. There were no other formats to show the “source code” of a Twine project. Yet, Twine 2 (2014) did not have support for Twee directly. The “code” of an example in the Twine Cookbook (2017), then, existed in a format that was more human-readable but was not usable in the tool itself. Most users could “read” it, but needed to copy and paste sections of it back into Twine 2 (2014) editor or use the ability to import HTML directly to get the whole example project as one unit.

Twee 3

While others had been discussing what to do with Twee for years, the introduction of the Twine Cookbook (2017) and my own role as managing editor put me directly into contact with the ongoing debates about its future. A small group had been talking about what a new version might look like that combined aspects of Twee 1 (Twine 1 (2009)) and the unofficial standard that was introduced with Twee2 (2015) for many months already.

For nearly a year after I joined this group, internal conversations moved from possibly using various formats, syntax, and what might be best to support for a more forward-looking Twee version. Different parsing approaches and errors were discussed, tried, and examined. During active moments of discussion, wildly different versions of Twee 3 existed and were rewritten on nearly a daily basis as ideas were tried, rejected, or incorporated as part of the design process.

Yesterday, the draft of the Twee 3 specification was released. Right now, it is not supported by many compilers. (Mine does, and Tweego (2013) support is planned to roll out soon.) However, it represents the first major attempt to re-unite a notation that has had over a decade of drift as other tools, users, and developers have tried to expand and push it in new directions since 2006.

State of Twee (Pre-Twee 3)

Notation

The notation is written as a series of three parts for the header of each passage:

  • Sigil: Two colons (“:”) followed by a single space
  • Passage Name: The name of the passage followed by a single space. Passage Names can contain spaces, alphanumeric characters, and punctuation. Meta-characters such as curly braces or square brackets should be avoided.
  • Tags: One or more tags separated by a single space each within square brackets
  • Coordinates: Currently exclusive to Twee2, coordinates can be given in the following format: <123,456>

The content of a passage continues until the next sigil of a passage is found or the input ends with at least a single empty line between passage headers.

Example Twee Notation:

:: Snoopy [dog peanuts]
Snoopy is a dog in the comic Peanuts.

:: Charlie Brown [person peanuts]
Charlie Brown is a person in the comic Peanuts

Special Passage Names

Many compilers understand and process certain case-sensitive keywords differently. The following is a common set of reserved passage names.

Start

The first passage.

Example:

:: Start
A beginning!

StoryTitle

The title of the story.

Example:

:: StoryTitle
A Named Story

StorySubtitle

Twine 1.4.2:

The subtitle of the story.

Twee2:

Ignored during HTML compilation process.

Example:

:: ```StorySubtitle```
The subtitle of this story

StoryAuthor

Twine 1.4.2:

The author of the story.

Twee2:

Ignored during HTML compilation process.

Example:

:: ```StoryAuthor```
John Smith

StoryMenu

Twine 1.4.2:

Corresponds to the menu that hovers in the upper-right corner of the page in the Jonah story format, or on the left side of the page in the Sugarcane story format.

Twee2:

Ignored during HTML compilation process.

Example:

:: StoryMenu
Content of the story menu!

StorySettings

Used to specify certain options and settings depending on the compiler used.

Twee2:

Ignored during HTML compilation process.

Optional Tweego Settings:

  • ifid: the story’s IFID (Interactive Fiction IDentifier)

Optional Twine 1.4.2 Settings:

  • undo: enables the player to “undo moves.” In Sugarcane, this means being able to use the Back button in the browser. In Jonah, this means being able to use the “Rewind to here” link, and being able to click links in previous passages.

  • bookmark: enables the player to use the “Bookmark” link in Sugarcane and Jonah. On by default.

  • hash: this causes the current passage’s bookmark URL to be automatically placed in the player’s browser address bar whenever they change passages. This is off by default because the URLs can become very long and ugly quickly.

  • exitprompt: If the player tries to reload or close the page, the browser will prompt for confirmation. This is useful for long games – it would be unfortunate if the player lost a lot of progress due to an idle key-press.

  • blankcss: This removes most of the CSS used by the story format, allowing CSS programmers to write their own stylesheet redesigns more easily. Off by default – but including the text “blank stylesheet” in a stylesheet will set it on automatically.

  • obfuscate: obfuscates the story’s HTML source using ROT 13 to dissuade people from spoiling themselves by reading it. Off by default.

  • jquery: if the jQuery library should be included or not

  • modernizr: if the Modernizr should be included or not

Example:

:: StorySettings
undo:on
bookmark:on
hash:on
exitprompt:on
blankcss:on
obfuscate:rot13
jquery:on
modernizr:on

StoryIncludes

A list of any local or remote files to combine with the story during the HTML compilation process.

Tweego:

This passage is ignored, as Tweego will bundle any JavaScript source files automatically as it detects them.

Twee2:

Other Twee2 compiled files (.tw2) can be used.

Twine 1.4.2:

Both Twine Story (.tws) and Twine Source (.twee) files can be used.

Example:

:: StoryIncludes
localfile.tws

::@include

Twee2:

Include the contents of another file at that point in the code. Does not work recursively.

Example:

::Garden [haml]
%p
  The garden winds around decorative trees.
%p
  ::@include description-of-house.tw2

Special Tag Names

Passage headers can contain any collection of tags. Two of the most common are stylesheet and script, but some Twee compilers such as Tweego and Twee2 also recognize and use others.

stylesheet

Any additional or overriding CSS rules for the story.

Twine 2″

This is the equivalent of Story Stylesheet and is often translated as UserStylesheet[stylesheet].

Tweego:

Unnecessary. Tweego automatically incorporates all CSS (.css) files it finds.

Example:

:: UserStylesheet[stylesheet]

script

Any additional or overriding JavaScript code for the story.

Twine2:

This is the equivalent of Story JavaScript and is often translated as UserScript[script].

Tweego:

Unnecessary. Tweego automatically incorporates all JavaScript (.js) files it finds.

Example:

:: UserScript[script]

scss stylesheet

Twee2

Any additional or overriding CSS rules written in SASS.

Example:

::MyCoolStylesheet [scss stylesheet]

body {
  background: #eee;
}

tw-passage {
  tw-link {
    color: red;
  }
}

coffee script

Twee 2

Any additional or overriding CoffeeScript for the story.

Example:

::SomeAwesomeCode [coffee script]

alert 'This message will appear when the adventure starts!'

haml

Twee 2

Any additional HAML code.

Example:

::NicksBar [haml]
%p
  Nick's Bar is exactly the kind of nightspot that helps you remember why you quit drinking.
%p
  %strong What would you like to do?
%ul
  %li [Nick<-Talk to the bartender]
  %li [BarToilet<-Go to the bathroom]

twee2

Twee 2

Additional configuration options or Ruby code to run during the HTML compilation process.

Example:

::Configuration [twee2]
Twee2::build_config.story_ifid = '41AB7776-D198-40F5-BD54-0493D49DA58C'
Twee2::build_config.story_format = 'Snowman'
view raw preTwee3.md hosted with ❤ by GitHub