L's blog

Twine macro: <<once>>

This little macro shows a span of text only the first time you encounter it - for all subsequent times you visit a passage containing it, it will be absent. This can be done with variables, but this form lets you use a single pair of macro tags. This can be good for, let's say, IF-style verbose opening descriptions of scenes or rooms.

Install my <<Replace>> Macro Set to use this macro.

You can use <<becomes>> or <<gains>> to specify text that should appear only on the second visit, or the third, and so forth.

Usage examples:
* <<once>>I'm going now. Goodbye.<<endonce>>
* <<once>>You arrive at the bathhouse.<<becomes>>You return to the bathhouse a second time.<<endonce>>
* <<once>>You arrive at the garage.<<becomes>>Back at the garage.<<becomes>>Third visit to the garage.<<endonce>>

Notes:
* If many <<once>> macros containing exactly identical text are used in different passages, seeing one of them will hide the others.

Version history

  1. 16-6-13 - Updated regarding Combined Replace Macro Set.
  2. 12-5-13 - Initial.

Feel free to report any bugs to @webbedspace.

Twine macro: <<hoverreplace>> and <<mousereplace>>

This set of macros is a mouse-driven counterpart to <<replace>> and are essentially a simpler form of <<hoverrevise>>. They cause a span of passage text to change into a different span when the mouse moves over it. It comes in two main varieties: <<mousereplace>> replaces the span outright when the mouse touches it, whereas <<hoverreplace>> simply displays the alternative span while the mouse is hovering over it, and will change back when it leaves.

For convenience, there are also the following variations:

  1. <<mousecontinue>> functions like the <<continue>> macro, causing a single enclosing span to disappear when the mouse touches it, and revealing all subsequent passage text.
  2. <<mouseremove>> creates text that simply disappears when the mouse touches it.

Install my <<Replace>> Macro Set to use this macro.

Usage examples:
Separate both versions of the span using <<becomes>>.

  1. <<hoverreplace>>You see here a clock.<<becomes>>It's 8:09PM.<<endhoverreplace>> causes the text "You see here a clock" to become "It's 8:09PM." when the mouse hovers over it, and go back when the mouse leaves.
  2. <<mousereplace>>A [[bird]]!<<becomes>>It flew away.<<endmousereplace>> causes the text to become "It flew away." when the mouse touches it.

The <<mousecontinue>> and <<mouseremove>> variations don't use <<becomes>>:
  1. <<mousecontinue>>Move here to begin.<<endmousecontinue>> hides all further passage text until the mouse touches "Move here to begin.", whereupon those words vanish and the text is revealed.
  2. <<mouseremove>>Don't touch me!<<endmouseremove>> causes "Don't touch me!" to vanish when the mouse touches it.

<<becomes>> vs. <<gains>>
If you use <<gains>> instead, then the second version is appended to the first version.
  1. <<hoverreplace>>[[End game|Quit]]<<gains>> Are you sure??<<endhoverreplace>> adds the words "Are you sure??" after the link while you hover over it.
  2. <<mousereplace>>You see a barrel. <<gains>>It is empty.<<endmousereplace>> adds the words "It is empty." when your mouse touches the words.

Version history:
  1. 16-6-2013: Updated regarding Combined Replace Macro Set.
  2. 12-5-13 - Initial.

Feel free to report any bugs to @webbedspace.

Twine: Jonah: Disable all links after leaving a passage

Update: The Javascript on this page is now built into Twine 1.4! It is no longer necessary to install it. You can enable this in Twine 1.4 by setting "Undo: off" in the StorySettings passage.

If you're using Jonah, and you're not using single-passage, then you may find this useful. It causes all internal links to behave like the <<choice>> macro.

Obsolete script removed: use Twine 1.4

This is designed to also work with approximately all of my link macros (<<cyclinglink>>, <<revise>>, <<replace>> etc.)

Version history:

  1. 9-5-13: Initial.

Feel free to report any bugs to @webbedspace.

Twine macro: <<else if>>, an improvement to <<if>>

Update: This macro is now built into Twine 1.4! It is no longer necessary to install it.

This is not strictly a new macro, but a replacement version of the <<if>> macro. You might have noticed that nesting the <<if>> macro can get a bit messy:

<<if $fire eq "warm">>
The fire isn't hot yet.
<<else>>
<<if $medal eq "water">>
You medal protects you.
<<else>>
<<if $dead gt 0>>
Not again!
<<else>>
You died!
<<endif>>
<<endif>>
<<endif>>

The <<else if>> macro 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:

<<if $fire eq "warm">>
The fire isn't hot yet.
<<else if $medal eq "water">>
You medal protects you.
<<else if $dead gt 0>>
Not again!
<<else>>
You died!
<<endif>>

The macro code is here:
Obsolete script removed: use Twine 1.4

You might wonder why I chose "else if" instead of "elseif"... I guess my mind flipped a coin and the 'natural language' side shone upward.

If someone else has already developed a similar macro, as I suspect they might, then do tell.

Feel free to report any bugs to @webbedspace.

Twine: Further remarks about <<cyclinglink>> and game choices

I've recently played the game Breakfast on a Wagon With Your Partner, which uses the <<cyclinglink>> macro, and it's inspired a few brief thoughts about the user interface of text choices.

Generally, the interface used for choice, especially dialogue trees, in videogames and Twine games, resembles the following:

Fig. 1: A doctored page from "Breakfast on a Wagon With Your Partner"
A list, usually exhaustive, of the possible choices one could make, usually in an egalitarian fashion. Its exact shape is highly variable, but the important aspect is that every choice is simultaneously visible.

However, the introduction of my <<cyclinglink>> macro has unwittingly introduced an alternative arrangement:

Fig. 2: An actual page from "Breakfast on a Wagon With Your Partner"
A single hyperlink that cycles between choices when clicked, displaying only the current choice. The choice is confirmed by clicking a proper link below.

This differs from the former in a number of interesting ways. Firstly, when you initially approach the page, all of the other options are concealed. Only by clicking the link successively does each option become briefly visible - the choices are presented in a temporal sequence, rather than a spatial sequence. And, not only are the choices themselves hidden, but their quantity as well - a list of 20 choices takes up the same screen space as a list of two.

I feel as if these differences slightly more closely resemble the actual human process of making a decision. Seldom do we, in our minds, see two drastically opposing options appear side-by-side, when confronted with a tough decision. Rather, our minds actively scour themselves for choices, possibilities - the few that appeal to our intuitions rise immediately, and others must be forced up to our conscious realisation, whereupon we focus intently on it. Neither of these link presentations can be said to truly capture this marvelous process, but I like to think that the cyclinglink presentation has more superficial similarities.

One other difference I feel is worth examining is the way in which cyclinglink, in this particular usage, reverses the usual meaning of clicking a hyperlink. Consider the text "I'm not opposed to settling down" in both illustrations. In the first one, the act of clicking it means to commit to the decision - to perform these words. But in the second, the act of clicking it is the act of revising the decision, replacing it with a different possibility. This strikes a somewhat discordant note within me.

Of course, usually a Twine hyperlink doesn't translate to the player verb "act according to these words" - most often it simply means "provoke the computer to delve further into this subject" or "continue a line of thought paused at this point", any of which could somehow revoke or reverse the link text's meaning, relevance or significance. Porpentine has previously called the hyperlink an "omniverb", commenting that its meanings within a game are as varied as the words you could put inside it, and the text that results when you click it. And, indeed, my original impetus for creating this macro was to extend the mechanical potential of links in a playful fashion - links that change unexpectedly when clicked, like a puzzle switch, or a toy, or an animate object in Windosill. Links that are multifaceted, multifarious, capricious. And, indeed, many uses of cyclinglink that I've seen thus far have used it for playful or cute subject matter, where rubbing and touching the story text, and seeing unexpected changes appear, is in keeping with the tone of the story.

I only came to think of cyclinglink as a genuine replacement for the 'choice list', and began considering the implications thereof, when I encountered the above choice in "Breakfast on a Wagon With Your Partner". This story, to its credit, does a very good job of establishing a "hyperlink vocabulary" - a link at the bottom of each page, reading "(o)", serves as the 'confirm choice' button, and is the only one that is used to advance to a subsequent passage. Nevertheless, the cyclinglink still runs contrary to the grain of the traditional hyperlink's meaning - its underline suggests a button waiting to be pushed, rather than a dial waiting to be turned. I hesitated conspicuously when I got to that page, for I had become quite invested in the path of the story, and of my performance as the player-character.

What shall we conclude from this? I believe that the cyclinglink is entirely in keeping with the standard interface of Twine games, and of the versatility that the hyperlink is afforded within a Twine game. I believe further that the use of a cyclinglink for choices, particularly especially mental choices, lends the selection some superficial resemblance to the human act of reaching and developing decisions. However, it is also important that they are sufficiently differentiable from normal links, in situations where it's important the player has full confidence in the presented hyperlinks. This could be through establishing a firm in-game vocabulary, or, more directly, it could be through CSS. (I do not include CSS within the cyclinglink script that forces them to appear differently to normal links, but I do provide CSS hooks that enable them to be styled differently from normal links.)

For a time after adding the variable-alteration functionality to cyclinglink, I wondered if I had perhaps erred by making it produce a Javascript-augmented link - perhaps a more familiar interface element, like a dropdown menu, would be more appropriate for the use cases of this macro. But, I committed to the justification that the hyperlink is the player interface element in Twine games, far more so than even familiar website navigation elements. They are, after all, not web sites, but videogames. So, let the hyperlink's scope be extended so.

Twine: visited(), a function to find how often a passage was visited

Update: The Javascript on this page is now built into Twine 1.4! It is no longer necessary to install it.

I've noticed that a good deal of variable usage in Twine is simply employed to track whether or not you've visited a certain passage previously, or done so a number of times. This script code provides you with a function that can give this value straight, without needing to use the <<set>> macro.

Obsolete script removed: use Twine 1.4

To use it, use "visited("Passage")" as a value in a <<set>>, <<if>> or <<print>> macro. It will equal the number of times you've visited the passage whose name is between the quotes and parentheses. For instance:

  1. <<if visited("Store")>>You've been to the store.<<endif>>
  2. <<if not visited("Firepit") and not visited("Maggotpit")>>You've not yet been to the fire pit or maggot pit.<<endif>>
  3. <<if visited("Trap Floor") gt 2>>Your repeated stomping is making the floor weaken.<<endif>>
  4. You've visited the chasm <<print visited("Dark Chasm")>> times.<<endif>>
  5. <<set $count = visited("Jewelers")>>You've visited the Jeweler's <<print $count>> times.<<endif>>

Also, instead of a passage name, you can put a variable.
  1. <<if visited($bossPassage)>>If only you'd had this when you'd fought the boss!<<endif>>
  2. <<set $beenToMyHome = visited($myHome)>>

New: If you just put visited(), then it will count visits to the current passage, without you needing to include the passage's name.
<<set $beenHereBefore = visited()>>

In addition, here is a function called "visitedbefore" which can be used to tell you if a passage has ever, in the course of the game, been visited before another passage.

window.visitedbefore = function(e,f) {
	var h,c,ret;
  	for(ret=c=0; c<state.history.length; c++) {
		h = state.history[c].passage;
		if(h && h.title == e) {
			return true;
		} else if (h && h.title == f) {
			return false;
		}
	}
	return false;
}

This only returns true or false. Use it like so:
  1. <<if visitedbefore("Firepit", "Maggotpit")>>First the fire pit, then the maggot pit, now this?!<<endif>>
  2. <<if visited("Armory") and visitedbefore("Firepit", "Maggotpit")>>First the fire pit, then the maggot pit, now this?!<<endif>>

Again, variables can be substituted for passage name strings:
  1. <<if visitedbefore("Dragon Hoard", $myHome)>>You must've left it at home after meeting the dragon.<<endif>>

The two passage names must be separated by a comma.

Some notes:

  1. This doesn't count use of the <<display>> macro as a visit.
  2. If neither passage has been visited, visitedbefore() will return false.

Feel free to report any bugs to @webbedspace.

Twine: escape line breaks with backslashes

Update: The Javascript on this page is now built into Twine 1.4! It is no longer necessary to install it.

As you know, one of the most prominent difficulties with mixing code and prose in Twine games is the handling of line breaks. If you have a bunch of macros interspersed in your prose, especially <<if>> macros, then the temptation is to leave them on separate lines from the text, for readability. However, the line breaks adjacent to these macros end up appearing in the rendered passage.

The <<silently>> macro is the 'official' solution...

<<silently>>
<<set $hp -= 1>>
<<set $dead = true>>
<<endsilently>>
Wrap up all of the macros in it and the line breaks will be suppressed. But, it seems to me to be a half-effective solution, requiring two large macro tags enclosing each block, and disallowing <<print>> macros within it.

I've previously advocated a different solution, involving the TiddlyWiki comment syntax:

/%
%/<<set $hp -= 1>>/%
%/<<set $dead = true>>/%
%/
This has the advantage of allowing the use of <<print>> macros. But it, too, is authorially and visually unwieldy, requiring both the end and beginning of lines to be tagged with one of two similar-looking tags.

However, I believe it's on the right track. Right now, my proposal is to directly borrow the syntax of the C language's preprocessor - a single backslash at the end of a line suppresses the line break:

<<set $hp -= 1>>\
<<set $dead = true>>\
You are \
<<if $hp gt 1>>
hale
<<else>>
almost dead
<<endif>>.
In my opinion, this has much more convenience compared to the other two.
Here is the script code to enable this in your stories:

Obsolete script removed: use Twine 1.4

To recap, when you install this script:

  1. A line that reads:
    You have \
    twenty dollars.
    ...will be rendered as "You have twenty dollars."
  2. A line that reads:
    You have \
    <<set $cash = "twenty">>\
    <<print $cash>>\
    dollars.
    ...will be rendered as "You have twenty dollars."

Feel free to report any bugs to @webbedspace.

Twine: example uses for <<revision>>

The <<revision>> macros provide a good deal of expressive power, though some potential uses may not be immediately obvious. Here are a few examples which may provide some inspiration.

An extended form of <<cyclinglink>>

This combination of <<cycle>> and <<set>> changes a variable every time you cycle the passage using the link.

<<cycle attire>>
<<set $shirt="red">>[<img[redshirt.png]] You eagerly slip on a red shirt.
<<becomes>>
<<set $shirt="blue">>[<img[blueshirt.png]] No! Clearly, a blue shirt is required.
<<becomes>>
<<set $shirt="vermillion">>[<img[yellowshirt.png]] Nope, it ''has'' to be vermillion! Or so you think...
<<endcycle>>
<<revise attire "Reconsider shirt">>

A music picker

This uses my HTML5 sound macros to create a link that changes the currently playing music when you click it. (If the music isn't meant to loop, of course substitute <<loopsound>> with <<playsound>>)

<<cycle music>>
<<stopallsound>><<loopsound "piano.ogg">>Piano music
<<becomes>>
<<stopallsound>><<loopsound "chiptune.ogg">>Chiptune music
<<becomes>>
<<stopallsound>><<loopsound "acapella.ogg">>A capella music
<<endcycle>>
<<revise music "Change current music">>

More info / Less info

This functions similar to <<replace>> but also provides a link to hide the inserted text after it's been shown.

<<revision info>>You see here a spotted stripe frog.<<revise info "(More info)">><<gains>>
Poisonous in 3 countries and illegal contraband in 7, this fearsomely shaded amphibian is an aesthetic and biological terror.
<<revert info "(Less info)">>
<<endrevision>>

More examples to come...

Twine: loading jQuery without editing the HTML

Update: Twine 1.4 now lets you load jQuery via a StorySettings option, so this page is no longer necessary.

You can load jQuery into your Twine game via Google Hosted Libraries using this simple script code:

Obsolete script removed: use Twine 1.4

Change whatever you want the function passed to ready() to do.
Notes:
* Since Twine's engine uses '$' for something, jQuery must sadly relinquish that convenient abbreviation.
* Due to a minor bug, Twine's runtime currently doesn't work at all in IE 8 or below, so there's not much reason to use jQuery 1.9 over 2.0
* Using Google Hosted Libraries of course means that people can't play your game without a live internet connection - which, in the extremely rare chance you intend your Twine game to be available offline, should be borne in mind. Nevertheless, it can be more convenient for you, the author, due to not having to provide the jQuery file yourself.
Feel free to report any bugs to @webbedspace.

Twine bugfix: "and" and "or" in strings in <<set>>, <<print>> and <<if>>

Update: this has been fixed in Twine 1.4, so this is no longer necessary.

As you know from reading my macro reference, code parameters passed to <<if>>, <<set>>, <<print>> and <<remember>> have their operators ("and", "or", "$", "not", etc.) converted to Javascript equivalents ("&&", "||", etc.) when they're executed.

But, due to a bug, this conversion is also applied to "operators" that are inside strings passed to these macros. So, <<print "Vast and large">> will print "Vast && large", and <<print "You find $10">> will print "You find state.history[0].variables.10".

Now, I've sent out a pullreq to the Twine GitHub repo that fixes this, but in the meantime, if you're stymied by this bug, you can fix it with this script:

Obsolete script removed: use Twine 1.4

Again, note that in some versions this will be loaded after the Start passage has rendered.

Version history:
* 2/7/13 - Bugfix for "She's cute" string.
* 5/5/13 - Bugfix.
* 25/4/13 - Initial.
Feel free to report any bugs to @webbedspace.

Syndicate content