Revision of Twine code shortcuts and unconventional operators from Wed, 02/20/2013 - 21:12

Since everyone has read my summary of Twine's built-in macros, you'll notice that many other JavaScript operators can be used in the <<set>>, <<remember>>, <<if>> and <<print>> macros. Here is an incomplete list of a few that you may find useful. Many of these are not as "tidy" as the documented operators, and some of them are counterintuitive in their meaning. You can still use them, though, if you so wish.

No greater-than signs

Before we begin, a quick reminder: the greater-than sign can't be used inside a valid macro tag - the macro will not be recognised. That's why the "gt" and "gte" operators are provided to you instead.

Setting multiple variables in one <<set>>

You can set multiple variables in a <<set>> macro if you separate their equations with a semicolon:

<<set $green = "Rice" ; $gold = "Cheese" ; $ammo = 14; $score = 0 >>

Note: you should not do this using <<remember>>: the macro only remembers the first $variable used in it.

Modifying a number variable: +=, -=, *=, /=

A commonly known programming shorthand for arithmetic operations is available. Instead of writing <<set $strength = $strength - 1>> you can just write

<<set $strength -= 1>>

This sets $strength to itself, minus 1. The other operators +=, *=, /= also work for their respective arithmetic. These can only be used in situations where the = sign would normally be used.

(Do not accidentally write <<set $strength =- 1>>, because that will set $strength to -1. The arithmetic operator goes before the equals sign.)

The ternary operator ( ? : )

The ternary operator can be used as a condensed, specific version of <<if>> <<else>> <<endif>>. Whenever a statement calls for a value, you could instead put ( [an if-macro condition] ? [a value if the condition is true] : [a value if the condition is false] ).

<<print ($ammo gt 4 ? "Ammo OK" : "Ammo low" )>>

The above line prints "Ammo OK" if $ammo is greater than 4, and "Ammo low" otherwise. If you want to make things much less readable and comprehensible, you can nest ternaries in each other:

<<print ($ammo gt 4 ? ($ammo gt 16 ? "Ammo oversupplied" : "Ammo OK") : "Ammo low" )>>

If $ammo exceeds 4, then the value of the inner ternary is printed. You can also rewrite it like this, which is slightly more readable:

<<print ($ammo gt 16? : "Ammo oversupplied" : ($ammo gt 4 ? "Ammo OK" : "Ammo low" )>>

Show all the game's variables for debug purposes

All the story variables are accessible in the JavaScript object "state.history[0].variables".

This line of code will print the variables that have currently been set:
<<print JSON.stringify(state.history[0].variables)>>

This will print something like the following:
{"meal":"Rice","snack":"Cheese","ammo":14,"score":0}
As you can see, it features pairs of values - the variable name, followed by a colon, followed by the value of the variable.

Alternative to <<display>>

Since <<display>> doesn't interpret its parameter as code, you can't, for instance, specify a passage name inside a variable. Hopefully this will be fixed at some point, but until then, here's an alternative you can use right now:

<<print tale.get($variable).text>>

$variable can be any statement or valid series of operations, as long as it equals the name of one of your passages:

<<print tale.get($hp eq 0 ? "DeathEnd" : $race + "Ending").text>>

Of course, it'd be much better if you could just fix <<display>> so that you can use code in it.

Accessing information about the current passage

This could be useful if, for instance, you use <<display>> a lot, and want the displayed passage to know something about whatever's displaying it.

The JavaScript object corresponding to the current passage is accessible in state.history[0].passage. If you want to, for instance, get the title of the current passage, try:

<<set $title = state.history[0].passage.title >>

All of the tags are in the array state.history[0].passage.tags. You can use the array syntax to access them (but I do not recommend modifying them). To see if the current passage has a tag, try:

<<set $hasTheTag = (state.history[0].passage.tags.indexOf("tag") gte 0) >>

Putting non-printed space between macros

You can use the TiddlyWiki comment markers /% and %/ to prevent whatever is inside them from being printed or run. You can use this to give large blocks of macros some breathing room without having to use a <<silently>> macro.

<<set $red = 1>>/%
%/<<if $green gt 4>>/%
%/<<set $blue += 2>>/%
%/<<remember $white = 2>>/%
%/<<endif>>/%
%/Some actual passage text...

pensive-mosquitoes