Skip to content

Twine 1.4#

Game engine#


  • You can now mix HTML tags and passage syntax in your story, without needing the <html> syntax. (It still remains for backwards-compatibility).
  • You can now use variables in place of a passage name in the link syntax - [[Exit|$placeName]] now creates a link to the passage whose name is in the $placeName variable. You can also do [[Back|previous()]] to replicate the <<back>> macro.
  • Also, you can write [[link text|passage name][$var = value]] to make a passage or external link that changes a variable when it's followed! The code section is treated as if it were arguments to a <<set>> macro. This syntax addition should work with <<choice>> macros (but not the [img] syntax). You can set multiple variables by separating them with a semicolon.
  • As a shorthand for <span style="...">, the TiddlyWiki inline style syntax is available. Type @@, then list CSS style attributes separated and terminated with semicolons, then put the passage text (including any other formatting and macros) ending with another @@. Example: @@font-size:2em; text-decoration: underline; Hello there!@@
  • Ending a line with \ will cause that line break to be removed from the rendered text. This can be useful when dealing with long chains of <<if>> macros.


  • <<remember>> now uses HTML5 Local Storage, which means it can now work even in an offline HTML file. Also, it can remember multiple variables given in a compound statement (like <<remember $a = 1, $b = 2>>).
  • Added <<forget>>, which undoes the effects of <<remember>>.
  • <<choice>> can now accept arguments phrased using the link syntax, e.g: <<choice [[a trapdoor?|falling]]>>. This saves the trouble of having to account for its inconsistent argument order.
  • <<nobr>> and <<endnobr>> remove all the line breaks in the text between them. They should be used instead of <<silently>> to enclose groups of macros.
  • The <<else if>> macro, which can also be written as <<elseif>>, allows you to essentially have multiple <<if>> macros chained together, without needing to nest each of them within the <<else>> / <<endif>> tag pair of the other.
  • You can also use variables in place of a passage name in <<display>>. For instance, <<display $name>> is now valid.

Shorthand macros#

  • You can now write a shorthand form of <<print $variable>> like so: <<$variable>>. Note that this only works for printing just variables - not functions or anything else.
  • You can now write a shorthand form of <<display "Place">> like so: <<Place>>. Note that this only works for passages whose names do NOT contain spaces. Also, it can only be done with specific named passages - not variables or anything else.
  • You can supply additional arguments to the shorthand <<display>> macro - in effect, you can "call" passages as if they were macros. (Note: you cannot supply arguments to the longhand <<display>> because they will be interpreted as part of the passage name - for instance, <<display Cellar 2>> will try to display "Cellar 2" instead of "Cellar" with an argument of 2.)

Macro syntax/functions#

  • You may now use "to" in macros instead of "=", and "is" instead of "eq". I think we can all agree it's too easy to confuse "=" with "eq", so you can instead write <<set $darts to 4>> for more readable code.
  • Strings containing 'and', 'or', '$' and other Twine operator symbols can be used inside macros without them changing into Javascript symbols.
  • Now you can put greater-than signs inside macro tags, such as <<set $arrow to "-->">>
  • All new variables are now 0 by default, regardless of whether you've <<set>> them or not.
  • Added either(), a function that randomly picks one of the things given to it.
  • Added visited(), a function that returns the number of times you've visited the given passage.
  • Added previous(), a function that returns the name of the previous passage visited.
  • If this passage is being included by a shorthand <<display>>, the parameter() function returns one of the space-separated terms in the macro invocation, parsed to a value. The function's argument is a zero-based index - parameter() or parameter(0) returns the first parameter, parameter(1) the second, and so forth.

Macro coding#

  • setTransitionCSS() replaces the contents of the #transitionCSS \<script> element with the passed string. This allows you to completely override the default transition CSS without it cascading down. I'm offering this as a JS function because many transitions will also require some extra JS, and being able to provide the complete transition code in just a script is desirable.
  • prerender and postrender are new objects whose function properties are executed every time the passage is rendered. The functions added to them take one argument: the resultant .passage .content element. Their 'this' value is the Passage object being rendered.

Passage tags#

  • An alternative Tag CSS approach! Now, taking a stylesheet passage and adding an extra tag to it (in addition to "stylesheet") will cause that stylesheet to only be applied for passages with that given tag. (This, I feel, is a bit tidier than the old Tag CSS method - the [data-tags] selector need not be repeated dozens of times in a stylesheet, and applying only to the 'body' or '.passage' selectors. Although, it is slightly less flexible w/r/t tag hierarchies - the :not[data-tags] selector can't really be replicated.)
  • Twine now uses CSS transitions for passages appearing and disappearing. Giving a stylesheet passage the tag "transition" will cause that stylesheet to replace the default "fade-in" transition CSS, letting you define your own transition without having to override the other one's properties.
  • The special "nobr" passage tag removes line breaks from the whole passage.


The StorySettings passage enables a number of special story options to be set.

  • 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.
  • Obfuscate: obfuscates the story's HTML source to prevent people from spoiling themselves by reading it. Off by default.
  • jQuery: set this on if you are using custom scripts that rely on the jQuery library. Otherwise, leave off. Note: Twine 1.4 relinquishes control of the "$" variable, so jQuery can now use it without $.noConflict().
  • Modernizr: set this on if you are using custom scripts that rely on the Modernizr library. Otherwise, leave off.


  • All passages are now added to the bottom, regardless of where you click the link.
  • Clicking a link that leads to a previously displayed passage will display a new version of the passage at the bottom, instead of scrolling up to the old version.
  • Clicking a link in a past passage in Jonah now rewinds the game state to that passage before following the link. This gives the author a greater level of control over the game state - it's no longer possible to re-use old links from earlier in the story that no longer make sense in the current context. (Note: Switching off the "Undo" StorySetting disables all links in past passages.)
  • <<back>> is now usable in Jonah. When used in Jonah, a <<back>> link removes the contained passage, plus any prior passages (as given by the "steps" argument or a passage name argument).


  • Removed the "Share" menu.
  • The "Rewind" menu is only visible if any passage has been tagged with 'bookmark'.
  • Added a "Bookmark" menu item, which produces a link to the current passage.
  • HTML5 History is now used to control the browser's Back and Forward buttons, and the <<back>> and <<return>> macros, in Sugarcane. This means that several bugs related to these are now fixed, and they should now work alongside random macros, player-input macros, and other such things.
  • <<choice>> is now usable in Sugarcane. It now creates a link that can only be clicked once in the whole story.
  • The sidebar now has position:absolute instead of position:fixed.


  • Added a <noscript> tag to alert the reader that Javascript is off.
  • Made it so that raw HTML <a> links in stories are styled as if they were proper externalLinks, in case the author unwittingly used the former in ignorance of the latter (a not uncommon occurence).
  • The passage content element, formerly classed "body" in Jonah and "content" in Sugarcane, now has a class of "body content" to match legacy CSS for both.

Development program#


  • Special passages (Start, StoryAuthor, stylesheets, etc.) have different-coloured title bars. I've tried to stick with earthy hues in keeping with the colour scheme of the Twine icon, with redder hues used for stylesheet and script passages.
  • Passage tags are displayed in a peach ribbon along the bottom of the passage box.
  • Annotation passages are non-playable passages tagged with "annotation" that hold text to display on the story map, to annotate, comment or document the source code of the game. They have a different colour and size to normal passages.
  • Connection lines representing <<display>> macros are drawn with a bluer tint.
  • The position of newly created passages is much less arbitrary - passages will be placed closer to the expected area.
  • Altered the Greeking of zoomed-out passages to reflect the actual passage text length.
  • Selected passages now have their link arrows thickened to visually offset them.
  • Passage tooltips now display a preview of the passage's text (up to 840 characters).
  • Tagged stylesheets have arrows linking them and any passages with the same tag.


  • Added "Import From Compiled HTML" option, letting the author recover passages from built games.
  • Importing .twee source code no longer discards all the passage tags in the imported passages.
  • The "Proofing Copy" export option renders a few more markup styles better.


  • The "Test Play" menu item builds the game to a temp file, letting you run the story without having to have saved it to a specific filename first.
  • You can also right-click a passage and select "Test Play From Here" to start playing from that particular passage.
  • The "StoryIncludes" passage allows the passages inside other .tws or .twee files to be imported into this passage during building. If your game is particularly huge, you can divide it into a bunch of smaller .tws/.twee files, then add the filenames of these partial .tws/.twee files to one "main" file's StoryIncludes passage. All the passages in those files will then be copied into the main story at build time.
  • Added "Auto Build", a menu option that is only available when used with a StoryIncludes passage. If this is set, then when any one of those smaller .tws/.twee files is modified, the story is automatically rebuilt and can be tested in-browser. This requires both files to be open at the same time, though.

Passage editing#

  • Passage titles must now be unique. The passage title input will turn red to indicate non-uniqueness.
  • Passage titles may no longer contain the | and ] symbols, due to such names being difficult to link.
  • Vastly improved the passage syntax highlighter.
  • Added very basic stylesheet CSS syntax highlighting.

Images and fonts#

  • You can now add image files to the story file. These are stored as 'image passages' which can be included in passages using the image syntax: [img[imageName]] displays the image. Images are also embedded in the final HTML file, and don't need to be hosted elsewhere. Supported image file extensions are GIF, PNG, JPEG, SVG and WebP.
  • You can now embed font files, which can then be used in stylesheets, or, if you don't know CSS, the \<font> element. Fonts are simply imported as stylesheet passages containing the font file in base64 encoding. Supported font file extensions are TTF, WOFF, OTF and SVG.