Baby steps

Covering the basics of where to begin and what is what.


Pre baby steps

What's twine for?

Having some DNA from an earlier wiki type format, twine is first and foremost a downloadable program with an online hosted version that lets a player use a story format to create a story using a grid of tiles that the developer (you!) can organize to personal taste.

Using the story format acts as a library that gives you access to the macros defined by the story format creator. This guide covers one story format, Sugarcube. To that end, most of the information provided only applies to Sugarcube, but as anyone whose learned a few programming languages know, there is a sometimes a common dialect, so you may still find information you find useful.

Why make interactive fiction over other formats?

Simplicity. There isn't an audio/graphics/gameplay balance to consider, only the basic stylings of the page and writing. You can optionally add much of it back in, with very few limitations beyond your own, but no one's going to expect them, so no one's going to demand them besides the most unreasonable out there.

I've seen everything from straight books to rpgs to open world sims, the limit is you, the individual, and your ability to learn the skills you wish to use. The Enemy with a capital E is burnout. Ease yourself into the workflow using smaller projects. You can make your Ideal, but you can't right now, probably. If you can cultivate yourself, you'll be suprised what you can make in the near future.

What does sugarcube/twine do and how do I start?

Were you able to use twine without a story format, you'd pretty much just have the ability to write text and html aswell as use [[links]]. Adding any story format on top of that expands your selection to include the story format's library of macros. In the case of sugarcube, it's main charms are being friendly with javascript, having simple to use audio macros, preconfigured save system, and having simple to use powerful general use macros.

While there's over a hundred to choose from, most of your problems are solvable using just 3, <<link>>, <<if>>, and <<set>>. <<set>> is able to save pieces of infromation for use later, mostly text and numbers, but also a few optional things we'll cover later. <<if>> and its child macros can be used to check those saved values against conditions to decide what content to show the end user, or run additional macros invisibly. It's not auto updating however, so refreshing the page is often necesary, but there's ways to avoid that that'll be covered later. Lastly, but easily the most used is <<link>>. It allows you to put a number of macros between <<link>> and <<link>>, those macros will be ran each time the link text is clicked. It is essentially the button that the player uses to tell the computer that they are done reading and would like more content, but even that's selling it short. Anything you've ever clicked on a website could be compared to a <<link>>.

If I had to break down my stories by macro usage, 7 in 10 macros would be the basic macros and their child macros. Even with all the other macros I could be using, the fact is, if you can use them to solve an issue, you are likely solving it in a logical way. I've got to emphasize that last bit however, child macros. <<link>> is handy, but it's designed for a certain range of applications, variations like <<linkreplace>> and <<button>> fill in the niches between. <<if>> is great for ranges of values, alongside <<elseif>> and <<else>> it can handle almost any combination of conditions, but if you have a set of known values, you probably want it's sibling, <<switch>>. Like a fan with a dial going from 0 to 3, it deals in exacts.

The rest any given author uses are simply up to the nature of the project. In my case, I often use <<replace>> to allow links more control over the page, but in a project with music, <<audio>> macros would likely fill in the last third. You may not even need other macros though, and there's nothing wrong with that either. Even if a macro is recomended to you, do not feel obligated to use it, though if a party is sure that it fixes your issue, I recomend at least trying it. People by and large do not hand out advise out of malice.


Baby steps

Now that we've covered all that, install the newest stable release of sugarcube into twine and lets look at what your first steps will look like.

After turning on the dark theme and starting a new project, we are greeted with one passage, untitled passage. That's always generated for every new project.

Hovering over the 'untitled passage' passage will reveal a few icons; trash, edit, demo play, and ..., the first two explain themselves, but demo play is a bit more involved. In somewhat simplified terms, it allows you to see what parts of the screen were the result of a macro, and what the macro was. The ... lets you change the size of your passage, at the cost of really ruining your ability to evenly tile your passages. That menu also allows you to change the starting point of your story. Any exported html starts on the starting point you define in this way, the play button on the bottom right also starts from that passage.

If you double click the passage you'll open the editing window, as well as some very memetic text, 'Double-click this passage to edit it.' . I recomend filling that with your heart and all its contents, then giving it a passage title that you'll be able to recognize and remember. Usually I name things with as few letters as would convey their utility, such as intro, but you can use whatever organizational method works for you. I also heavily recommend enabling snap to grid, It makes it much harder to layer passages on top of eachother. It also looks much fancier.

Now that its got some text, make a [[link]]. After you do that, you can close the popup by clicking outside the editing box. An arrow should now be drawn from the current passage to the new passage, titled whatever you had put in the [[link]]. [[link]] is part of twines functionality, so it is special in the ability to create a passage without going through the motions. Unfortunately, those arrays are a performance concern for the program itself. Without a few hundred passages, you should however be fine.

Opening that new passage, you'll once again see 'Double-click this passage to edit it.'. This time, let's make a <<link>>. copy this into your passage

<<link 'passage transition, wow' passage1>><</link>>

This is sugarcube code. Most macros look like similar to this, though not all have a <</link>> style closing tag. Here I type the macro I'd like to use, link. After that, I provide the text that the reader will see. It's important that it has quotation marks so that the engine knows where to start and stop reading. After that, I provide a destination, passage1, but it's a bit different, isn't it? I said quotes are required, but here I used none.

That's input coersion. Sugarcube wants you to succeed, so it tries to help you in little ways. Here it sees a singular word, so it assumes it's intentional and uses it in the macro. Coersion can't work with multiple words however, so try not to depend on it.

Here I'd like you to rename passage1 to something else of your own choosing, I'd also like you to change the first bit of text to something else. After that, make a new passage and give it the name you used in your version of the code and fill it out a bit. Once you've done that, hit the play button and see what happens.

At this point, you should see the passage you wrote earlier, some of the default UI, and at the bottom, a link of your own creation. Click that and you should move to the next passage. If at this point you have an error on your screen, it means sugarcube wasn't expecting something that you gave it, but you probably wont receive an error, link is very agreeable. If it's red, that means you need to double check that it's second argument is the exact same as the passage you created. Assuming you didn't receive an error, and the link is blue, click it. You should see the text from before.

You at this point should notice that there's an arrow from the [[link]] passage to the linked passage, but not the <<link>> passage to the passage it links to. It's a bit of a simplification, but that's because twine handles [[]] and sugarcube handles <<>>. Both are useful, so use whichever you prefer, but I recomend getting used to the macro link. It's more functional and lacks the performance implications. Further, it looks much cleaner when setting multiple variables at once using it.


Baby steps 2

Link's an excellent tool, but it's best used in combination with other macros. Let's look at <<set>> as an example.

<<set $integer to 5>>

<<set $string to 'vista point'>>
  
<<set $boolean to true>>
  
<<set _tempvar to 4>>

While not everything you could use, this covers most things you should be using at the start. First we have a number and a string. An overwhelming majority of variables will be one of these two types. Even more esoteric things like objects and arrays mostly exist for the delivery of strings and numbers. Under that we've got a boolean, as simple as a binary bit. It's either true or false, no quotes. Lastly we have a temporary variable, that's just a variable you can only use until you load the next passage.

Looking back at the link from earlier, you should notice a similarity, the quotations. Behind sugarcube is twine and behind twine is javascript. Naturally, that means sugarcube inherits javascript's rules, and javascript states that numbers must not have quotes, and text must. Let's see what happens if i violate those rule a bit.

<<set $notastring to this text>>
-> unexpected token, 'text'
  
<<set $twostring to 'this' 'text'>>
-> unexpected string
  
<<set $badstring to 'this text>>
-> invalid or unexpected token

I've included a bonus error to show that in this case, the errors are slightly different. In the first case, it didnt coerce the second text, as it only needed the one string, so instead of tried to access a javascript variable that didnt exist. In the latter, it had an extra value that it didn't know how to handle, so it discarded the whole line of code. Lastly we have an unclosed string. javascript couldn't figure out where it ended, so it stopped thinking about it and discarded the code.

While the finer details of that don't matter, it's important to be able to recognize errors. They are informative and can tell you exactly what went wrong if you know how to read them. I'll go into more detail later, but for now, just remember that the $var will be converted into whatever you saved to its name until you go out of your way to change the value. This can be within the context of a macro or just in plain text, as seen bellow.

<<set $var to 'passage'>>

<<link 'navigation' $var>><</link>>

Of note, while i didn't include '' for $var, it does not mean it was string coerced. outside of one specific line of macros, it's always incorrect to use '$var'. It causes a nasty error that causes all your values to text correctly, but fail any actual logic. Let's look at that now.

<<set $var to 1>>
$var -> 1
<<set $var2 to '$var'>>
$var2 -> 1
<<set $var3 to $var2 * 2>>
$var3 -> [number NaN]

In this situation, my math failed because I thought I had a 1 saved to that variable, but instead I had a variable's notation saved. It's like sending your friend a desktop shortcut of a game instead of sending them the '.exe'.


Baby steps 3

Now let's look at the last of the big 3 macros, <<if>>. <<set>> is great for keeping track of things, but <<if>> is why you keep track of things. For this, I'd like you to imagine a story in which you are asked weather you'd like to be a mage, a warrior or a rogue. Let's assume each is a link that sets $class to whatever you choose. How would you change the dialog of the first person you meet? Let's look at some examples.

<<set $class to either('wizard', 'warrior', 'rouge')>>

"Hello fair $class, I wish you luck on your journey"
/*this works, but can we make it a bit more personal?*/
  
"hello fair $class, I hope your 
<<if $class == 'wizard'>>
  worldly insight\
<<elseif $class == 'warrior'>>
  unrivaled might\
<<else>>
  silver tongue\
<</if>> 
brings you success in your adventures"
/*every time you hit enter, thats a new line, you can use \ to cancel out those extra 'newlines' or 'linebreaks'*/

While even I can admit that it's a bit ugly, and maybe even a bit excessive for this exact use case, It's still a matter of fact that it's a lot more personalized now. Even if it would be a bit more wasteful to have each conditition replace the entire scentence, it'd actually what I recomend. Visual clarity is very important in code. Let's see how that looks.

<<if $class == 'wizard'>>
  "Hello fellow $class, I hope your worldly insight serves you well in your journey."
<<elseif $class == 'warrior'>>
  "Hello fair $class, I pray your unrivaled might leads your enemies to ruin."
<<else>>
  "Hello my silver tongued $class, I hope for your safety that your every foe is single mother."
<</if>>

While it's handy swapping a few words, I am of the opinion that it's preferable to make the most of each macro usage. Speaking of, let's look at another link.

<<link 'wizard' seminar>>
  <<set $class to wizard>>
  <<set $skill to magic>>
  <<set _dice to random(1, 6)>>

  <<if _dice gte 4>>
    <<set $weakness to might>>
  <<else>>
    <<set $weakness to subterfuge>>
  <<if>>
<</link>>

You may have been able to intuit, but the reason that there's a closing <</link>> is so that you may fill it with macros. In this case I've saved a bunch of information all at once, but I've even taken the chance to roll a six sided die and assign a weakness for later in the theoretical story. You can do a lot in the span of one link. That's a bit of joke you'll get later.

With that, I think that I've covered everything you'd need to get your foot through the door. if you want to expand your understanding, You've got the rest of this guide to look forward to.


Glossary

Reference material.


I do NOT recomend reading this in its entirety before moving on to the next section, this is a reference material you should come back to as needed.

Value : A meaningful piece of data, can be numbers, words, Booleans, or even functions.

Argument : Each value that a macro requires is an argument. Providing too many arguments may cause an error.

Expression : A combination of values and operators that has a result. Adding two numbers is an example of an expression.

Setters : Anything that declares a new variable.

On Pageload: Refers to running code as a page is loading. Attempting to edit html elements while they are still loading will cause errors.

Event : Ised to refer to a moment of meaningful player interaction with the game. primarily click and onmouseover, but many others exist.

Onmouseover / onmouseout: An event that triggers when the cursor enters or exits the area an element covers. Comparable to hover.

Macro: a JavaScript function simplified for usage in SugarCube, the vast majority require an argument, and a healthy portion require a closing tag, which typically follows a pattern of <<macro>>, possibly an <<childmacro>> and a final closing <</macro>>.

Widget: a string of macros that have a shortened name that you yourself define. When called can accept any number of arguments including 0, after which it'll execute the macros inside. In the newest releases of sugarcube, the args array has had its syntax updated to _args[]. May now be defined to have a closing tag.

Single quotes: ' ' apostrophes ' ', outside of prose, they can be used to contain strings.

Double quotes: " " quotation marks " ", Functionally the same as single quotes, but you have to hold shift to type it.

Backticks : ` ` backtics ` `, Located next to 1 on most keyboards, they are occasionally used to indicate to twine that you'd like something to be processed as an expression.

@property : similar to backticks, placing @ before a CSS property will indicate to it that an expression needs to be parsed, allowing you to use variables in elements.

Boolean : a true false value. Some macros require true false values, they will convert any non true false value into a truthy falsy value. 0, '', and undefined are falsy values and will be treated as false, most other things are truthy. This is not a comprehensive list of falsy values.

Operators : All the ones talked about bellow will fall under one of three types,

  • Math operators: + - * / % ** , the signs you use for Math
  • Logical operators : || && ! , Or/And/Not respectively, used in conditionals. use parenthesis if you need to control the order.
  • Comparison operators : > < != == === and all the derivatives therein. May also be refered to as conditonal operators.

DOM elements : html objects. they all have a type and they usually have at least one class, ID or other property.

  • Class : a label applied to a DOM object to assign it traits, medium specificity, will overwrite the type but not the ID when it comes to stylings
  • Id : a unique ID that only one element on the page can contain, if you'd like to see no errors, often used in macros to target a specific element. max specificity, will overwrite both class and type stylings
  • Property : Instructions regarding how a dom element should look or operate. Inline CSS can be used to style single use elements, and functions can be used to give extra functionality to elements that is otherwise impractical to use on a sugarcube generated element.

CSS : Cascading Style Sheet, a special tab in the twine desktop app (tweego users have their own method) that you use to store your element stylings. The lower an item is on the list, the more priority it has, but that only exists to break ties. Otherwise it's always type > class > id. Priority can be inherited using modifiers that won't be explained here.

Naked Variable Markup : $var , when you display a variable using its name. At times you'll need to have a variable right next to a dollar sign for example, that can make the variable illegible to sugarcube. In that case use <<print $var>> or <<= $var>>.

Square Bracket Link Markup : a way to make a link using [[cosmetic name|passage]], a core twine functionality not from SugarCube. SugarCube expands its functionality to include the ability to modify variables as seen in [[cosmetic name|passage][$var to 1]]. unlike link, these automatically create passages and draw lines which may affect performance on all machines given enough lines.

Error : errors come in two varieties primarily, 'I didn't type that correctly' and 'I didn't think that entirely through' that is to say, syntax errors, which are relatively simple to fix most of the time, and logical errors, which are nightmarish to fix. Logical errors do not throw a red error message or a browser alert in most cases, that's because they are poor decisions more than they are legitimate errors. Flipping a > or adding a zero are logical errors.

Syntax errors : seen in either browser alerts or red error boxes. They have descriptive error messages and usually will tell you have to fix them. Occasionally having an unclosed '' or "" will cause errors that are less informative. Always check that every quote is correctly closed before fixing anything else.

A nonexhaustive list of common error examples include;

  • Using just = in if statements
  • Using == in setters
  • Flipping < and > in conditionals
  • Doing set $object to $object2 instead of clone($object2)
  • Trying to modify a DOM element on page load
  • Closing a link to soon
  • Refactoring code incompletely
  • Using the same temp var in nested loops
  • Changing a passage name without updating links
  • Capitalizing a var in one location but not another
  • Using logic in story caption that you need completed by the time the main passage loads
  • Reloading a page without the understanding that every macro will get ran again
  • Calling an array without the square brackets
  • Creating an object with [] instead of {}
  • Not using <<capure>> in situations involving loops and variables
  • Forgetting to close a string
  • Forgetting to escape single or double quotes when inside a string contained in the same quote type
  • Forgetting backticks around expressions in macros that use multiple arguments
  • Changing a link into a linkreplace but forgetting the closing tag


Chapter 0 - Fundamentals

Needed for the inner workings of a story.


Understanding the fundamentals

By and large, most things in life can be expressed as either a number or a word. The time? its 7. His name? John. That understanding is fundamental to most programming solutions. You take a larger idea of 'knowledge' and turn it into a number. Now that it's a number, let's say 100, it can be compared to other people, used as a chance of passing a text, or just a plain skill check. Though I covered the basics in baby steps, let's look at the set macro again.

<<set $integer to 5>>

<<set $string to 'vista point'>>
  
<<set $boolean to true>>
  
<<set $dice to random(1,6)>>

As before, we've first got a variable storign a number. It's possible to use it in expressions to calculate other values. Let's look at that in action.

<<set $math to $interger * 2>>
$math - > 10

<<set $math to $integer + $string>>
$math - > 5vista point

<<set $math to $integer + $boolean>>
$math - > 6

<<set $math to random(1, $integer)>>
$math - > a whole number between 1 and $integer

Let's look at some of these values a bit closer. Squaring went as expected. 5 squared is 25, simple as. Adding an array to the number placed it at the front of the array and stringified it. pretty logical. Adding a true to 5 resulted in six. Somewhat logical, a true is a 1 in binary. *don't add binaries to numbers, this is a demonstration*. Finally we have a simple function, it accepted the 5 as one of its parameters. None of it has any unpleasant variance. If you combine values, you get their sum. Let's do this again with strings.

<<set $stringx to $string + ' at moon rock'>>
$stringx - > vista point at moon rock

<<set $stringx to $string * 2>>
$stringx - > [number NaN]

<<set $stringx to $string + $boolean>>
$stringx - > vista pointtrue

<<set $stringx to (1, $string)>>
$stringx - > vista point

Clearly strings are a little less able to handle extra ordinary circumstances. While you can add a number to the start or end of a string, letters that look like numbers are not numbers as far as the javascript is concerned, meaning '5' + 5 becomes '55'.

It's not unusual to add togeather strings to make a complete phrase, but be aware that picking information out of arrays can be tedius. While it's easy to imagine taking the 5 from '5ivsta point' and passing it through num() to 'repair' it. In practice, it's hard to identify exactly where the number is. With that in mind, it's better to create combined strings on the fly than it is to use them as a long term store of information.

Now let's look a bit closer at the rules of strings.

<<set $string to "los compadres">>
-> valid, user sees los compadres without " "

<<set $string to ' "so i said to trust me" '>>
-> valid, the inner "" are visible to end user

<<set $string to 'ain't that just life?'>>
-> invalid, 'ain' is valid, but everything past that errors, so its all discarded

<<set $string to 'ain\'t that just life?'>>
-> valid, \ tells javascript that you've got an exception and you'd like it to bend the rules

When using "" inside strings, it's idea not to use them outside strings. The reverse is just as true. I favor '' over "" due to a writing style that favors quotations in links, but neither is 'correct'.


Math operations

Naturally, with any numbers, you need the ability to do operations. A majority of the time you'll be doing addition and subtraction, but occasionally you'll need something exotic. let's rattle off a few operations.

<<set $int to 5>>

<<set $exponent to $int ** 2>>
$exponent -> 25

<<set $divison to $int / 2>> ->
$division to 2.5

<<set $remainder to $int % 2>>
$remainder -> 1 (this performs division, but only keeps the remainder. in the case of 4 % 2 or 6 % 2, it would be zero)

<<set $int++>>
$int  - > 6 (add 1)

<<set $int-->>
$int - > 4 (substract 1)

These mostly explain themselves, it's just the same math you've been using in school for years. What they don't teach you in school is javascript functions, so let's look at those next. Some sharper readers may have been able to intuit them from earlier instances, but let's talk about them regardless.

<<set $random to either(1, 6)>>
$random - > 1 or 6, nothing else

<<set $random to random(1, 6)>>
$random - > 1 through six, inclusive, all whole numbers

<<set $random to Math.random(0, 1)>>
$random - > 0 to 1, decimals included

Here is your bag of dice. These handle randomness, and they handle it well. You can replace any number here with a variable that evaluates to a number. In the case of either, it even works with strings.

<<set $high to Math.max(100, 1)>>
$high - > 100

<<set $low to Math.min(100, 1)>>
$low - > 1

Self explanatory, keep the highest or lowest. Good for healthbars that cannot exceed values and wallets that dont go negative. Finally, let's rapid fire some simple ones. Remember, always capitalize Math!

<<set $var to 1.5>>
/*try to avoid saving decimals, they are floating points and have limited accuracy*/
<<set $truncate to Math.trunc($var)>>
$truncate -> 1, drops the decimal
<<set $round to Math.round($var)>>
$round -> 2, follows the rules of rounding
<<set $ceiling to Math.ceil($var)>>
$ceiling -> 2, rounds up, stops at zero
<<set $floor to Math.floor($var)>>
$floor -> 1, rounds down, stops at zero
<<set $fixed to $var.toFixed(2)>>
$fixed -> 1.50, for the significant digits minded individual, most commonly used in money

You can also nest as many functions as you'd like. Often your equation will look similar to a pumpkin ((())), just remember that the one at the center is the first to be evaluated.

<<set $var to Math.min(Math.trunc(Math.random(0, 10) * .5), 3)>>
$var -> 3, 4 or 5

Objects and Arrays

Objects and arrays are two sides of the same coin. They are two different ways of solving the issue of organized data. Let's look at two examples.

<<set $array to ['johnny', 'cache']>>
$array - > johnny, cache
$array[0] - > johnny
$array[1] - > cache
$array.length - > 2
  
<<set $object to {
  first : 'johnny',
  second : 'cache' 
}>>

$object - > [object Object]
$object.first - > johnny
$object.second - > cache
$object['first'] - > johnny
$object['last'] - > cache

That's a lot of information at once, so let's digest it a bit. Arrays use [] syntax, each entry has to be seperated by a comma, and each value has to be one of the datatypes we've talked about up to this point, which can include objects and arrays themselves. Arrays automatically number every entry from 0 to 1, in the order you provided.

Using $array[$key], you can access those saved values. The key can be any number up to the length of the array - 1. If you place an array inside an array, You will need to use a pair of $var[][]. Let's see that in action.

<<set $array to [['johnny', 'cache'] , ['sabrina', 'bytes']]>>

$array[0][0] - > johnny
$array[0][1] - > cache
$array[1][0] - > sabrina
$array[1][1] - > bytes

There's an order to it all, first javascript sees the outer array [x, y] with x and y representing the inner arrays, you access either the zeroith or the first using [0] or [1], then it looks at the value you picked and checks to see if it's an array, if it is, it'll see if you provided another [0] or [1], if you did, it'll fetch that value. Otherwise it'll return the entire array.

Pivoting back to objects, they instead have keys instead of indexs. While that sounds complicated, its the difference between a number and a word. Objects can also be nested. Let's see what that looks like.

<<set $outer to { inner : {
  first : 'johnny',
  second : 'cache' 
}}>>
$outer - > [object object]
$outer.inner - > [object object]
$outer.inner.first - > johnny
$outer.inner.second - > cache

Like before, there's an order to everything. the first {} is outer; it's got one key, inner. Since inner was an object, that means the process starts again. This time we have two keys, first and second. You can repeat the process till you finally reach a value, though you don't always want the values, sometimes the object itself is useful.

An example of when that's useful is when you are using functions. Let's look at some.

<<set $array to [1, 2, 3, 4]>>
$array - > 1, 2, 3, 4
$array.length - > 4

<<run $array.push(5)>>
$array - > 1, 2, 3, 4, 5
$array.length - > 5

<<set $pluck to $array.pluck(1)>>
$pluck will be one entry from $array, $array will no longer have that entry.

<<set $index to $array.indexOf(4)>>
$index - > 3
$array[$index] - > 4

<<set $array2 to $array.delete(1)>>
$array2 - > 2, 3, 4 /*every 1 will be deleted*/

<<set $array2 to $array.deleteAt(1)>> -> 1, 3, 4
$array2 - > 1, 3, 4 /*2 was in index 1, due to being the second entry*/

<<set $random to $array.random()>>
$random - > one value from $array chosen at random

<<if $array.includes(1)>>
true if the value is found in the array <</if>>

That's a health set of tools for arrays, but what can an object do? The answer is, 'it depends'. Without a greater framework, objects aren't useful. Arrays are different in the fact that they are much more useful out of the box. Objects are ideal for situations involving complex frameworks wherein a variety of things have similar properties. An early stage programmer does not need to worry about objects.

Meanwhile, arrays lend themselves incredibly well to being the solution to a large variety of problems. Even without any advanced framework, contains() allows them to be inventories, pluck() let's them be dice that cannot roll a result twice, random() let's them be regular dice. While objects will very quickly superceed them in utility, at this moment, you should be able to use them to solve any number of problems out of the box.

As a final note, not every variable needs to last forever. you can use _ instead of $ in any of the examples above to create a temporary variable. Whenever the player clicks a link, every temporary variable is unset. Let's look at a few.

 <<set _int to 1>>
_int - > 1

 <<set _string to 'vista point'>>
_string - > vista point

 <<set _array to [1, 1, 1, 6, 6, 6]>>
_array - > 1, 1, 1, 6, 6, 6

Chapter 1 - More commonly used macros

Covering most of the commonly used macros that most stories in the wild utalize.


Clickables

While I covered this is some detail in baby steps, I'd like to hone in on link before any of the other macros.

Sugarcube as an engine is very event driven. While games like minecraft have a logic loop they constantly perform, calculating physics, ai, and other block updates on a cycle, in a vacuum, a sugarcube game will not do any constant function. It will perform instructions as you instruct it to, but it will not go out of its way to automatically do things without being programmed to follow that kind of behavior.

With that in mind, how do we instruct sugarcube to take an action? The non exhaustive list is macros and javascript. Every macro can be seen as a means of interacting with the engine, but the primary thing that a player would use to interact is the humble link. Let's look at two links, one simple, one slightly more verbose.

<<link 'click me'>>
<</link>>

<<link 'click me, again' 'passage'>>
  <<set $var to 5>>
<</link>>

The first link is clickable and nothing else. It has a name, but not a passage to navigate to, nor a variable to set. It's the minimum version of itself. Under it we have a link that both sets a variable and navigates to a passage. While humble, it's the backbone of many projects.

That's not all it can do however. Let's simulate a situation in which a few variables are used to make a more complete link.

<<set $location to 'bus stop'>>

<<link `'exit the ' + $location` >>
<</link>>

In this case, I've used an expression, combining a hardcoded string with one saved in memory. That's not however all i did. Those `` are backtics. They tell sugarcube that an expression is being used. Why would we need that? parsing. Link accepts 2 parameters and will discard the rest. The issue is string coersion. The + gets coerced into a '+' stringified plus sign. Remove the `` and you should find the link turns red and navigates you to a passage that says 'error: the passage "+" does not exist'.

That mostly covers the functions of links, so let's look at some of its decendants, starting with my favorite, linkreplace.

Something you may have noticed about link is it's inability to produce additional text without using a dedicated macro. Any raw text between its <<>> is simply discarded. Linkreplace instead replaces itself with that content, while also running all the macros contained. Needless to say, that renders it unclickable. Let's look at an example.

<<linkreplace 'lootbox'>>
  very underwhelming loot
<</linkreplace>>

In this case, clicking lootbox will yield 'very underwhelming loot,' that removes the lootbox clickable element, so a player may not click again to try and receive multiples until the page is reloaded and the element resets. That makes linkreplace somewhat ideal for conversation options. It can convert itself to a responce, though you will need another macro to clear out additional options.

Taking maybe a step back instead of forward, let's talk about presentation. A link is good and all, but what about a button?

Well, in that case, you've got two options, button and clickable images, but to that end, I need to explain some things about how the twine client works. A file on your local desktop can be seen in your project, but only if a number of conditions are met. Namely, there are 3 different standards, embeds, absolute file paths, and relative file paths.

Relative flie paths are by and large, the thing you should be using in a release project. Assuming your game is in a folder named 'game', the images would go in either that same directory, or in another folder within the game folder. Let's lool at how that might look.

/game
  |-> project.html
  |-> images
      |-> bread.jpeg

in this case, your relative file path would be url(images/bread.jpeg), in theory at least. In practice, your project isn't going to be in that folder during testing. Instead it'll be in some temporary folder in %appdata%, with that in mind, durring testing, you should probably use an absolute file path.

While I could be a bit more technical here, to get an absolute file path, drag the file onto your web browser. After the web browser opens the file, the url bar should be full of the absolute file path. Using that, the image will always work so long as that file exists on your computer and your web browser isn't some xenophobic privacy nightmare. There's a catch however, it works on your machine. Only your machine. Further, it reveals your user profile name if you share that code with other parties, as well as your file structure, which may be information you consider private. With the understanding that this specific code only works on your machine and may consider private information, please avoid giving it to strangers or even friends.

Lastly we have embeds, server hosted files. Hotlinking files without permision should be avoided, though everyone who has ever said not to do it has probably done it once or twice for testing at at least one point in the past. That is to say, I cannot condemn you without being a hypocrit, but I can request you use it sparingly, and absolutely never use it in a release build. You will find your image stops working impresively fast.

With that all in mind, let's look at some examples.

<<button 'clicky'>>
  <<set $value to 'expression'>>
<</button>>

<<link '<img src="images/bread.jpeg">' bakery>>
<</link>>

<<link [img['images/bread.jpeg']]>>
<</link>>

The button has a rounded rectangle appearence by default, you can customize that to taste using css. The latter two are a two ways to insert the same image. They are just as capable as any other type of link, though you should consider how they might look on the page.


Conditionals

While links handle a majority of the interactive functionality of sugarcube, often you'll want the interaction to be more of a two way street. While every link could lead to a distict passage, it's often more advisable to use an if statement to selectively display content. Let's look at a basic example right now.

<<set $var to random(1,6)>>

<<if $var > 3>>
  4, 5, 6
<<else>>
  1, 2, 3
<</if>>

While you may not consider it peak game design, here we've got a coin flip. Random(1, 6) will yield one of six results, chosen completely randomly. Any that are above 3 will yield a true, while those that are under will yield a true. While a simple idea, this is a simplified version of how every game handles randomness. Sure most games have weighted randomness, seeds, and other dressing, rolling a die and flipping a coin are still at the core of a healthy majority of games on the market.

Let's look at this in terms of applications in sugarcube.

<<link 'explore'>>
  <<set _var to random(1, 3)>>

  <<if _var == 1>>
    <<goto 'beach'>>
  <<elseif _var == 2>>
    <<goto 'park'>>
  <<else>>
    <<goto 'mall'>>
  <</if>>
<</link>>

This type of code is common as sand in a desert in my experience, and it's honestly perfectly fine conceptually. It's only true issue is being hardcoded, but that's a general issue of if statements in general. The sum total of their possibities is hardcoded. You cannot use a macro to add another condition to check against, you can only try to qualify for conditions that you setup before running the program. Another limitation is priority. Let's look at example of priority in action.

<<set $var to 1>>
<<if $var < 4>>
  under 4
<<elseif $var < 8>>
  under 8
<<elseif $var < 2>>
  under 2
<</if>>

Given an infinite set of values, how many times do you think each statement would trigger? Think about that for a second before continuing.

With 3 conditions, it's clear that they are all possible in a vacuum. Whith $var is 1, they'd all read true, but what happens when they are all true? I think a reasonable person could make 3 guesses; Either nothing triggers, all trigger, or one triggers. All triggering sounds reasonable, but it's not the case. Nothing triggering is counter intuitive and a bit contrarian, needless to say, it's not the case either.

With those eliminated, we can determine that one triggers, which which one? It's a bit anticlimactic, but the first. The first true is the only one that matters. This also means that you can never trigger two conditions. As an example where this might matter, let's imagine you have a skill check that checks for the presence of skills that would prevent a trap from going off. Ideally, every skill you have in the thief school should reduce it's chance to go off by 33 percent. Let's look at what someone might code for that.

<<set $chance to 100>>

<<if $skills.includes('lockpicking')>>
  <<set $chance to $chance - 33>>
<<elseif $skills.includes('sneaking')>>
  <<set $chance to $chance - 33>>
<<elseif $skills.includes('pickpocketing')>>
  <<set $chance to $chance - 33>>
<</if>>

<<if random(1, 100) <= $chance>>
  <<goto 'sprung trap'>>
<</if>>

While not code that will produce an error, this actually isn't going to work as desired. Chance will only ever be decreased once. To fix that, individual if statements could be used. Alternatively, you could put yourself in a position to not have to manually check each possible outcome.

Say we've got an array for just thieving skills, we could simply count the number of skills in the array and use that in the conditional. Let's see how that looks.

<<set $thieving to ['lockpicking', 'sneaking', 'pickpocketing']>>
<<set $chance to $chance - ($thieving.length * 33)>>
  
<<if random(1, 100) =< $chance>>
  <<goto 'actual trap'>>
<</if>>

While it's a bit ironic that the problem that uses less if statements is more elegant, it's important to remember that we've avoided tedium. A constant battle goes on between the functionality you'd like and the time/desire you have to impliment those ideas. Using mode code to solve problems does not make your solution better, it makes it longer.

While possibly not conditionals, let's take a look at a sibling macro of if, switch/case. While if statements are ideal for ranges, they are actually rather tedius when it comes to checking for hardcoded individual values. If you can believe it, that's where switch/case comes in. Let's see it in action.

<<set $var to either(1, 'one', 11, 0)>>

<<switch $var>>
  <<case 1 11>>
    one
  <<case 'one'>>
    the cooler one
  <<default>>
    not one?
<</switch>>

Looking at this, you can probably intuite how it works. Whatever the input equals will be checked against the cases. If it matches one, that one triggers. While that sounds rather brief, that's primarily because it's that simple.

As a final note, remember that the page NEVER has an if statement on it. The engine writes the contents of the if statement to the page. The logic remains in the mystical back end. If you change a variable that affects the conditional, it will not reflect those changes until you reload the page. It's not unlike a recipe. The engine will cook whatever recipe you provide, but changing the recipe will not affect food it's already made.

You can however assume links ignore this rule. Links process a new version of the code they contain on every click, meaning they'll always reflect the current version of the state.


Loops

Often you'll need to do recursive work, there's two main ways of doing that type of work, repeat and for. Repeat is simple, so let's look at it first.

<<set $impatience to 0>>
<<repeat 1s>>
  <<set $impatience++>>
<</repeat>>

It simply takes a valid unit of time, typically seconds, and runs the code after that period of time. It's got a sibling called timed that has the exact same syntax, but only runs once. It's got its uses, but in my opinion, there is no reason to rush someone's ability to read. Some people read slow and they should not be punished for it. Further, the repeat will continue indefinately, so consider the ramifications of how large and memory consuming the values you save could be. Even I have crashed my own chrome using repeat.

The other loop macro is for. It's not unlike repeat, but with a few pieces of dressing and a means of ending the loop. Let's look at its syntax along side an array, which is the overwhelming majority of its use cases.

<<set $array to [1, 2, 3, 4, 5]>>

<<for _v to 0; _v < $array.length; _v++>>
  $array[_v] /*this will print the contents of the array in order, seperated by a line each*/
<</for>>

While a bit indimidating at first, it's all very logical. There's a variable declaration, usually zero, a conditional, usually _v /= something, and then a math operation to do every loop, usually the incriment or decriment operation. While thats all very complicated, in short, in normal speak, you are just doing an if statement till it stops being true in a loop, and usually that if statement is as complicated as _x < $array.length.

Of note is the fact that execution seems to be halted while a loop is looping, so an infinite will lock up till sugarcube manually interupts it at arround a thousand cycles of nothing productive happening. Another consideration is to avoid calling loops within loops without considering the posibility of infinite recursion. I've in many cases refered a loop in itself and caused it to go completely infinate.

Next, let's talk about scope. In simple terms, variables cannot be accessed outside of their intended scope. Sugarcube story variables have an extremely wide scope normally, being accessable from javascript directly and other macros easily, though not necesarilly in the same way, but thats a thing for later. In this moment just note that the variable you define in the for macro is only scoped to the contents of the for macro.

Moving past that, lets look at a more complicated for loop.

<<set $spots to ['park', 'pier', 'beach']>>
  
<<for _v to 0; _v < $spots.length; _v++>>
  <<link `'travel to ' + $spots[_v]` $spots[_v]>><</link>>
<</for>>

Looking at this, you may be thinking 'that looks fine', and to some extent, you'd be correct. It 'looks' perfect. The links will form perfectly, but thats because the string is parsed immediately, the second $spots[_v] is parsed on click. Given that the for look runs 3 times, ending on beach, you could come to the conclusion that the value of $spots[_v] at the end of execution is beach, and you'd be correct. Every link will send you to beach. Let's fix that.

<<set $spots to ['park', 'pier', 'beach']>>

<<for _v to 0; _v < $spots.length; _v++>>
  <<capture $spots[_v]>>
    <<link `'travel to ' + $spots[_v]` $spots[_v]>><</link>>
  <</capture>>
<</for>>

Capture is now forcing $spots[_v] to be parsed immediately and passed to the link as a string. Many variables can be captured using commas to seperate each value. Capture is also not dependant on for, rather its a general use macro for any time you use variables that you'd like to fix to a certain value. Those situations are very sparse without for loops, but they do crop up.


Accessing Passages

Consider this more of a warning than a tutorial, I've been using this macro without explaining it since chapter zero. It makes you 'go to' a passage based on a string input. as seen bellow.

<<timed 10s>>
  <<goto 'die'>>
<</timed>>

The reason for this chapter is to caution against using it as the page is loading. Never use the macro just on the page itself. We have a macro for that, it's called include. Let's look at it.

<<include 'extension'>>

Assuming a passage named extension exists, this will parse it's text before rendering the rest of the page. This can also execute macros, making it rather versatile.

Often the reason you'd want to use goto on pageload is to highjack the current page and lead somewhere else, perhaps an event. Let's look at a way to not-do that.

<<if $event == 5>>
  <<include 'event5'>>
<<else>>
  the actual page text.
<</if>>

While a bit uglier, and a bit longer, it's arround 5 seconds faster for the end user. While you can crunch a few thousand numbers and go unnoticed, double navigation is extremely costly and noticable.


Inputs

So a quick advisory, if you allow user input, expect it to be abused. Any time text is put onto the screen using a macro or the wiki javascript function, it will be ran through a parser that will filter out and trigger any macro text passed through it, meaning players can use text input to cheat and worse, but any player knowledgable enough to do that can cheat in other ways, so dont bother stopping them, you can't. Beyond that, if i name your female love character interest Black Dynamite, you have to just accept it. Cheating and stupidity are up to the user, not you.

So most inputs follow a formula, they require the string version of a variable, that is to say '$name' instead of $name. From there, either they require a default, or they require a selection of values as options. Let's look at the former first.

<<set $name to 'jonathan moestar'>>

<<textbox "$name" $name>>

This gives the player a simple textbox, not unlike the google search bar. While it can accept an extra parameter to be used as page navigation, I HEAVILY recomend against that. Mobile users often have trouble with getting it to register, so most developers don't use it ever, which has the effect of making the user's mostly unaware of its ability, even more seasoned ones. A final note before switching to the collection style inputs, the MOMENT that the value inside the textbox changes, the value is saved. there is no wait period, you do not need to manually save it.

These next two look a bit intimidating, but they are mostly two takes on the same idea, let's see them both first.

<<set _array to ['scandalous socks', 'unsightly hat', 'lascivious police baton']>>
<<set $headslot to ''>>
  
<<listbox '$headslot' autoselect>>
  <<optionsfrom _array>>
  <<option "steamy, scalding hot towel" 'Ouch!'>>
<</listbox>>
<<set $verse to 'rhythmic'>>

<<radiobutton '$verse' 'no rhythm' autocheck>> no rhythm
<<radiobutton '$verse' 'rhythmic' autocheck>> rythmic

First we have listbox. Either you can provide several options, or it can automatically generate some options from an array. As with most, the second value is the one thats acted upon, and the first is simply cosmetic. Clicking a listbox opens a list of the values you've provided, the user can select one. I recomend against trying to print text based on that without a link. It's much harder and not dramatically more functional.

Under that we've got a pair of radio buttons. They've got some complicated behavior in theory, but in practice, you've almost certainly used them before, so they should be intuitive. Listboxes that are attatched to the same variable become mutually exclusive, allowing only one to be clicked, they offer no visual indiciation of the value stored within, so you must attach your own.


Passage features

While most passage names are available, a few are reserved. This will server as a brief reference of the ones that matter. Note that all are case sensative.

StoryDisplayTitle: This is the story's name, if provided. Otherwise it'll default to the project name.

StorySubtitle: this controls the slightly smaller text that appears under your story's title. if unset, there will be no text.

StoryCaption: This controls the space that spans from the StorySubtitle to the save button. You don't need to worry about how much space you use vertically, the save button will be pushed down under the content of StoryCaption regardless of length. This loads after the passage itself. Do not update variables here if you want them reflected on the main passage. Use store header for that.

StoryInit: this loads invisibly before the story starts, specially its pre appended to the first passage that's loaded. though you can set a start point, that's a twine starting point, sugarcube handles storyinit and it'll be placed before whichever passage you start, debug or otherwise.

PassageHeader: this loads its contents before the current passage.

PassageFooter: this loads its contents after the current passagae, but before PassageCaption

There are others, but these are the ones that you'll use most often. Moving on, passages can also have tags. 3 exist, but I'd say two matter at this stage. the first is nobr, it removes the auto newline thats inserted when you hit enter. the second is widget. It makes the passage unloadable, instead its used to store widgets, which are sequences of code saved for later. Let's quickly look at a widget.

<<widget navigation>>
  <<if $time > 3>>
    <<link 'home' home>>
    <</link>>
  <<else>>
    <<link 'outside' outside>>
    <</link>>
  <</if>>
<</widget>>

While not a very useful widget, this captures much of the essence of widgets. They are code you'll be rewriting often. By defining a widget, you can instantly call the entire block of code using just <<navigation>>, or whatever you supplied as the argument to the widget macro.

This next part is new to the more recent major versions of sugarcube, _contents and the renamed _args array. Let's see how that looks.

<<widget color container>>
  <<set _inline to "color:" + _args[0] + ';'>>
  _contents
<</widget>>

<<color 'red'>>red text<</color>>

You may be able to intuit that _args[0] is what carries the value provided when i do <<color 'red'>>, but what about _contents? It's dynamically generated based on whatever you provided in between the closing and opening tags of the widget. It's still newish, so even I had trouble making an original demonstration, but it's a nice new feature and I look forward to finding new ways to use it.

I fully planning on skipping the third special passage tag, init, but you may look into it if you plan to import a javascript library. For everyne else, let's take a look at the un-special passage tags.

<<if tags().includes("blue")>>
  blue
<</if>>

tags() returns an immutable array that has every passage tag you've applied to the passage, primarilly its used with includes to check for the existance of a tag and handle it apropriately.


Chapter 2 - CSS, JS and HTML

The root of SugarCube and how to continue developing your story.


CSS and HTML

You might have been able to intuit some info about the span earlier, but now's the time to take a deep dive into the basics of css and html elements. What i used earlier was a span, it had one property, the style property. Attatched to that property was @, which can be used to tell sugarcube that a variable is being provided. Without that, the element will read the variable markup instead of the contents of the variable. The style property was being used to assign another property, the color property, which just controls the text color.

While that sounds like a complicated mess, It's only complicated because I was doing on the fly css. You could give it a 4/10 complexity rating. Let's look at some more basic examples.

text
text

Here we have two of your most common elements. Div is a block element that occupies its entire line, while span is much closer to a highlighter since it just covers the affected text. The div has an ID, which is a unique identifier, while the span has a class, which is a catagory identifier. I can only have one of each ID, but i can have any number of class members.

That's fine and all, but if you tested the code above, you'd notice very quickly that they didnt do anything I didnt mention. That's intentional, while each element type has its own special features, the overwhelming majority are left for you to define. Let's look at some css defintions.

#heading {
  background: #ffffff17;
  text-align: center;
  border-radius: 25px;
  padding: 0.3em;
}

.dialog {
  color: violet;
}

body {
  background: #14181a;
  font: 14px sans-serif;
  color : white;
}

That's a lot isnt it? There's a reason for that, these are fairly realistic looking. The heading has a slightly transparent background, center aligned text, rounded corners, and some padding. A sharp person could intuit a lot of that, except maybe the color. No one can really read color codes with much accuracy. It's not all obvious however. the only way to figure out what em is would be to be told. It's a percent of font size, in this case .3 of a font size. That makes it a scaling unit, compared to px which is hardcoded. Finally, the # is just the Id designator.

As for the dialog class, it's a bit minimal isn't it? Well, classes usually are simple. They aren't one highly customized element, they are a very broadly useful catagory. Where i making a project that required purple text, my purple text class would not be dramatically more complicated. I admit that it'd likely be called the speakers name or simply purple however.

That was class and ID, but what's body? body is an element. That is to say, it isn't a feature of an element, it's the actual element. span and div would also be valid identifiers. This applies to every element of that type. In the case of body, there's only one body, and due to inheritance, most elements on the page will inherit the features you define here, though not all, such as background.

About now, you may be wondering what happens if a conflict happens. The answer is suprisingly simple, specificity. The less of something that there is in theory, the more priority it gets, and if you have a tie on that level, the one lower on the list is the winner. Id is the most specific, following that is class, then lastly we have elements. While it seems counter intuitive that the one and only body has less specificity than the one and only heading, in practice, most elements aren't that unique. If you take the route of having colored text for every speaker, you'll find you have an army of spans in no time at all.

Classes go in the css tab in twine, tweego users will have to cite the relavent documentation to figure that one out. The elements themselves go in the passage, not unlike macros.


CSS and SugarCube

Needless to say, some macros can interface with elements. Let's cover those now.

The two macro sets essentially control the two parts that go into an element. That is to say, one set controls classes, and the other controls the content. In other words, one set controls the apperance and the other controls the text.

Of note, these macros cannot be used while the page is rendering. You can do things in that instant by putting them inside the done macro. That in mind, let's look at replace and append, perhaps the most useful of the whole lot.

<<done>>
  <<replace '.insertion'>>
    <<include 'a big passage'>>
  <</replace>>
<</done>>



<<linkreplace vanishing link>>
  <<append '#postamble'>>
    

it's like a preamble but at the end. <</append>> <</linkreplace>>

Between these two examples, we've got most of the use cases narrowed down. Let's start from the top.

If you remember what i said earlier durring the bit on include, any macro that produces text will process the text for additional macros, that means replace, which processes text, can be used to trigger macros such as include. I generally do this when I'd like to include a lot of text that I would prefer to keep out of the current passage.

Under that, we've got a linkreplace with append inside it. While this may seem a bit redundant, linkreplace is actually great for single use links. If its content is solely macros, it just disapears without a trace. In this case, i use that to prevent append from being abused and clicked multiple times.

A second note, while i demonstrated how to access classes with replace, namely the .class notation, it's a much better idea to use #id notation and ids. You may have multiple class members, making the macro reflect over a number of elements.

Moving onto the second set of element macros, we have the macros that control classes. Though there are a fair few macros that can do this, I'll narrow things down to just the ones I consider useful. Let's see them in practice.

inner-text
<<addclass '#demo' 'first'>> the item with id #demo gains first class <<removeclass '.dialog' 'second'>> all items with dialog class lose second class <<toggleclass '#header' 'dialog second'>> the item matching the id will have dialog and second either removed or applied, whichever they weren't before.

Mostly self explanatory. Don't use these on pageload without the done macro either.


JavaScript and SugarCube

While this sounds like a sudden leap, let's look at some basic javascript before getting any impresions.

window.mouseoverFunction = function() {
  console.log('yata'); /*this is a debug command that just puts a message in the console seen via f12*/
}
hover here

Here's an extremely simple function. While i could try to explain things in fine detail, let's more look for patterns. Patterns are at the heart of everything.

mouseoverFunction is seen both in the top and bottom sections, while nothing else is shared between them. Given that, we can assume it's how the div knows what code to active. In the div it has a (), and while that has two matches in the top code, we can discount the console.log() line, as it's optional. That leaves us with the function() bit of code.

It should be a bit familiar, thinking back to earlier, I've been using random() and either() from the begining. Given that, we can assume that mouseoverFunction sets the name, but MouseoverFunction() is how it's called, and that assumption is indeed correct. Let's look at another function to see why that () is there.

window.truetest = function(y) {
  if (y) {
    return true;
  } else {
    return false;
  }
}
<<= truetest($var)>>
/*return is what gets printed here, if nothing is, it'll be undefined*/

here's a simple bit of code that tells you if the value you provided evaluates to true or false. While I haven't shown the javascript version of an if statement, you should be able to see the similarities. Looking back at the function declaration, you see this one has a Y where the other had nothing. That's the argument. Looking back at most macros, they overwhelmingly take at least one argument.

Combining all that, we can assume that just truetest would be incomplete, but truetest(5) would be a complete call, and that would be 90 percent true. If you exclude the (), it still finds the function, but it doesnt have the arguments to execute it, even if it isn't designed to take any, so it just returns the whole function, because the function is an object too. Let's compare these functions to another line of code.

State.variables.var = 5;
variables().var = 5;

These two lines are javascript syntax for <<set $var to 5>>. One uses the verbose method, the other uses the variables() method to shorten the call. That all settled, let's compare them to the code from before.

Something you should immediately notice is that they all use =, that's because they are all assignments. Given that, you can assume that on one side is the name and opposite that is a value. While a bit intimidating, function() {} is entirely swappable with 5. Let's look at a function in a variable.

<<set $var to function() {console.log('konosuba')}>>
<<run $var()>> -> works

So I'll emphasize that you don't need to do this, this is stupid. it screams of bad save compatibility. What im trying to demonstrate is that there's no difference between a scary variable declaration and those sets that you've been using since page one.

Of note however is that the window.name part is necesary for the code to work. that is your scope. Window scopes the variable that has the function to the entire browser tab, in simple terms at least.

This isn't a perfect comparison, you can declare functions in the javasccript and use them within sugarcube easily, you can't very easily save values to javascript and have them be usable in sugarcube *in the same way that you'd use a sugarcube variable.* Let's look at what I mean,

setup.clothes = {
  'red shirt' = {
    price: 40,
    type: 'costume'
  }
  'swimsuit' = {
    price: 20,
    type: 'underwear but socially acceptable'
  }

}
<<= setup.clothes.swimsuit.type>>

this is called a setup variable. This is information that isn't saved to the actual save, this comes with the html file itself. As you might be able to guess, if this is stored on the html file, you have limited influence over it. While you can change it in the moment, those changes are always reverted after a new page is rendered.

While that sounds limiting, you already have variables that can be changed at will and reflect those changes. That in mind, what's the best use of setup? static data. If you dont plan to change values outside of major updates, they should probably be in setup. Looking back at that thing I mentioned earlier, I said the data is stored with the html. Each release would naturally include a new html. That means every new release, you can update the values and the changes will reflect immediately without relying on old saves. As a result, anything that depends primarilly on setup should be fairly resistant to breaking with old saves.

Expanding on that, setup is not the only thing that comes with the html, the functions do too, meaning much of what I said about seutp applies to functions aswell.


JavaScript and JavaScript

That's most of the fundamentals, let's look at some specific functionality.

I mentioned earlier that there were 3 ways to interact with elements, javascript forms the third. Let's look at a more advanced verison of the code from earlier.

window.mouseoverFunction = function(y) {
  $(y).addClass('red')
}
window.mouseoutFunction = function(y) {
  $(y).removeClass('red')
}
/*these dont go in the same secton*/

.red {
background: red;
}

/*neither do these*/
hover here

Sugarcube stock does not have a macro that handles hover, so to do hover effects, you have to use javascript or css. In this case, we've got css. One function triggers when the mouse enters the area of the element, the other when it leaves. While functional, it's clearly verbose for what it is. To that end, i recomend using CSS for this type of issue. Let's take a tangeant to look at that.

.redh:hover {
  background: red;
}
hover here

Clearly, this is a superior solution. It's shorter in short long and medium term, so why know the other solution? The answer is vision. Let's use it for something css can't immitate.

window.flipflopF = function(x) {
  if (x.classList.length == 0) {
    $(document.getElementById("right")).toggleClass('blue');
    $(document.getElementById("left")).toggleClass('red');
  }
  
}
hover here

Here's something a bit more novel. I did a lot here, so let's explain it step by step. The function declaration was fairly typical, It's got one argument, looking back at the mouseover functions, 'this.classList.length' is a bit esoteric looking, but in short, it's a shortcut for the getElement javascript. getElement is comparable to looking up any page number, while this is the page you are already on. Adding to that, classList will return an elements classes in an array. Combining all that, this passes the number of classes that the element in question has, in this case a 0 or a 1.

While I admit that the code itself is a bit pointless, I'll quickly spoil what it does. Mousing over the div with a colored background will remove the colored background and give it to the other element, permanently. The reason I want the number of classes is simply to check if it's the colored div. If the div has zero classes, it runs toggleClass on both elements, flipping them. As you might imagine, toggleClass in javascript is not fundamentally different from the sugarcube macro of similar naming.

Starting off, let's think of what that would take to do. The only thing I need to know is if the moused over element has the class already, needless to say, that's something we already have. Let's see what that version of the code would look like.

window.keephighlighted = function(x) {
  if (x == 0) {
    $(document.getElementById("right2")).toggleClass('blue');
    $(document.getElementById("left2")).toggleClass('red');
  }

}
hover here
hover here

It really is as simple as that, reverse the conditional and you get new behaviors. Keep this in mind when debugging, unexpected behavior can start from the smallest of errors. > versus >= has been enough to completely ruin the usability of my very own code in the past. Let's do a bit better though, we've managed to get the color changed, but how would this interface with sugarcube?

To do that, we'd need a bit more certainty. Currently the code just checks if the element has a class, it can't actually tell which element is making the request. Also, it's a bit hardcoded, with the way it uses ids, it can only be used once in a page. Let's see how that can be solved.

window.noclick = function(active, saveto, saveas) {

  variables()[saveto] = saveas;
  var contain = active.parentNode; 
  /*remember,  active  is the  hover'd element and contain is box*/
  active.classList.add('active');

  if (contain.tagName == 'BOX') { 
    /* tagName checks the elements type, it can also work for div and span*/
    for (let i = 0; i < contain.children.length; i++) {
      var deactivate = contain.children[i]; /*this make an array of all 3 spans*/
      if (!(deactivate === active)){
        deactivate.classList.remove('active');
      }
    }
}

$("#output").empty();
$("#output").wiki('$color'); 
/*just debug output so you can try the code on your own, also this is how to use javascript to write text to elements, but remember that this syntax and the above don't always work togeather, this is jquery markup*/
}
.active {
  background : #ff00002b;
}
.active:hover {
  background : #ff00003d;
}

.fixedsize {
  min-width: 10em;
  display:inline-block;
  text-align: center;
  border: 1px solid #ff00003d;
}

  green
  blue
  red

  
$color

Oh wow, isn't that a complicated piece of code? this is generally the cost of expandable design, occasionally its longer, but at the same time, this actually interacts with the engine. I had the goal of making a button you only had to hover over, and yes i could have solved that extremely easily. Giving each it's own function, it would have been simple. Even just making it less pretty would have saved an hour. The main point of showing you this is to understand that you can make a problem much harder by nudging it in certain directions.

That in mind, let's look at what it does, step by step, as always.

Up to this point, the box element has not been mentioned once. Why is that? That's because I made it up. No where does it say that you have to use elements from a list. This is a custom element. I needed a custom element for two primary reasons. The first reason is that I needed all 3 to be in one element so i could use the parentNode command to get the parent. The second is, i wanted to be sure if there was a parent in the first place, parentNode would fetch the entire passage-passagename element had i made one button but no box. This allows it to operate as one button, a fanciful thing i didn't need to add that required more effort than it was worth.

Moving past that, let's look at variables()[saveto] = saveas. as we mentioned earlier, variables() is the '$' that goes before story variables in its true form, in as many ways as matters at least. the [] is the same [] we use in arrays, but it actually works for objects too. so in this case, it's just variables().color = another variable;. Thats very digestible. Another goal was to make it work with any variable.

Moving on, we've got the parentNode code i mentioned before, this let me go from the inner spans to their parent, box. Afterwards I verify that it is indeed, a box element, then i get all it's children elements in an array using the children command, i looped through that just like you would any other array, using classList.remove to remove the active class from all elements but the one that === the element that triggered the function.

Now that it's all explained, barring the css which i think i'm not amazingly well equiped to explain in any useful detail, let's ask the question again, why does it look like that? Expandability. I wrote code designed to be used in multiple places. It can change any variable, it can be used any number of times on one page, none of it interfears with other css you could use. Lastly, it can handle any number of paired elements.

That's all well and good, but should you write code like this every time you have a problem? No. you'll never finish anything if every problem becomes a fancy Shiny Thing you have an obligation to reuse. The only time you should feel obligated to write code that iterates through arrays of any size without issue, that can handle a variety of situations without issue, that can be used in multiple different places to multiple effects, is when you actually will need it multiple times in the future.

The goal is always to finish your game, or at least version 1, dont get caught up on making fancy pretty code for every problem.

Moving forward, let's look at how to run javascript from a macro.

<<set $var to returnFunction()>>

<<run $(body).wiki('<<set $money to 10000>>')>> 
/*don't actually code like this please*/
  
<<link 'link'>>
  <<script>>
    var menu = document.getElementById("story-caption");
      $(menu).empty();
      $(menu).wiki("<<include 'StoryCaption'>>");
  <</script>>
<</link>>
  
<<script>>
  Dialog.setup("Shopping list:");
  Dialog.wiki("celery 
celery
celery
celery
celery
celery
celery"); Dialog.open(); <</script>>

Here's a bunch of different ways you can access javascript from the passage and macro level. Taking things from the top, just about any time you could be giving a 'value', you could be using a function with a return value. Let's quickly take an asside to check out one of those.

window.range = function(y, x, z) {
	if (y < z && y >= x) {
	  return true;
	}
  return false;
}
<<if range($var, 1, 10)>><</if>>

Here I've opted to use a function to create a true/false instead of a conditional. I recomend doing the same if you find yourself typing something all too often. Javascript should be used to save time, flashy vanity projects are secondary to not having to type the same mundane line of code a thousand times.

Moving on, we see run, it executes the line of code you give it. Ideal for running functions without returns. Following that, we have two uses of script. One in a link, one outside. Either is acceptable. The link on click updates the sidebar by clearing and reincluding it. Remember that wiki'd text executes any macros that are included. The script pops up a little window with the text provided, in this case, a normal shopping list. Ideally you'd want to use an include macro as the javascript does not allow itself to take multiple lines, hence the manual linebreaks.

About now is the time to mention all the quarks of javascript. Set and run can both accept $var arguments without issue, as any naked variable markup within a <<>> is converted unless it has already been stringified. Script cannot use that markup, you'll need to use the variables() markup or any equivilents. Another exceptin is seen in Dialog.setup(), in short, it isn't wiki'ing the text, so naked variable markup and macros wont work inside it.

Moving on from that, let's talk about methodology.

I don't know the totality of javascript. That much should be painfully obvious to any of the wizards that may be fact checking this guide. That in mind, how do you find new javascript? Google.

By and large, if you can properly phrase your question, google will lead you to stack exchange, the read-only twine forum, developer.mozilla, w3schools, or any number of other information repositories. Just try to break down your question into it's parts. 'How to turn string into all lowercase letters', 'Find elements from parent div', 'apply change to all elements in array,' these types of questions have a very high chance of being answered in one search. Why is that?

It's because they clearly state both what you have and what you need to do. You won't get good results if you ask complex questions like 'how to program conversation' or 'making a time system'. Assume the minimum, be clear, start from the smallest parts. Needless to say, that helps when talking to other people as well. Make sure to include javascript in your google search too.


Chapter 3 -