tiny-qbn

Getting Started with TinyQBN

Start by opening Twine. The quick way is to go to my TinyQBN blank-project generator, save the resulting page, and import that HTML file into Twine.


But you can also do it manually: create a new story in Twine and set its Story Format to SugarCube. Then we need to add the TinyQBN code. Go to the TinyQBN GitHub repository. Click on the link for the minified javascript, click “Raw”, then select all and copy it. Go back to Twine, open the Story Javascript from the menu in the bottom left, and paste it in. Then go back to GitHub, select and copy the stylesheet and paste it in to Twine’s Story Stylesheet.

Finally, go to GitHub again and select and copy the widgets. These are SugarCube code, so make a new passage in your Twine story and paste it in. Add a “widget” tag to the passage so SugarCube knows that it’s code which needs to be loaded immediately. Give the passage a name if you like (I usually call it “TinyQBN Widgets”).


Now we’re ready to start building the basic demo: a little setting where you can drive around and see what local seasonal food is available. We’ll start with some locations that you can drive between.

The starting passage will be your home. So give it a header: !Home. Also we need a way to drive somewhere else, so let’s add a link [[Drive->Car]].

To make it a “card” that the QBN engine can find, you tag it with “card” or “sticky-card”. “card” is for single-use passages which will be discarded after they are visited. But this is a physical location. We want to be able to visit it many times, so make it a “sticky-card”.

Right now this card has no requirements, no restrictions on when it is available. So it will show up every time we select cards and there will be no way to exclude it. So let’s add some requirements about when we can draw this card. Requirements are tags starting with req-. Add a tag req-driving to say that you can only get here if you’re driving.

This requirement will be satisfied if there is a non-empty story variable $driving or a temporary variable _driving. It doesn’t differentiate, mostly because tags can’t contain dollar signs (or spaces or any punctuation other than hyphens and underscores).

Home passage

In the car, we’re going to show you all the places you can drive to. So we’re going to say

<<set _driving to true>>\
<<cardrow `QBN.cards()` "linkbox">>\
<<unset _driving>>

QBN.cards will select all of the cards whose requirements are satisfied by the current story state and the _driving variable. The second argument is the name of a widget that will be used to wrap each card. If you leave out "linkbox" it will use “contentbox”, which shows the contents of the cards directly instead of linking to them by name.

If we play the game and get in the car, we should see that we can drive back home (even though we’re already there, but we’ll fix that later). Let’s add some other locations. Some small farmers like to give their farms cutesy names, so how about Fairweather Farm? This is probably a farm that sells organic vegetables and eggs from happy hens. Name the passage, give it a header and link to the car.

Now…Twine isn’t built to let you edit tags easily. If you make a typo, you have to delete the tag and try again. You have to click the new tag button each time: there isn’t an easy way to type in a bunch of tags. So I’ve set up a bypass mechanism that lets you put the TinyQBN markers in a specially-marked comment in the body of the passage.

/* QBN sticky-card req-driving */

This can go anywhere in the passage: it doesn’t have to be at the very top. Nor does it have to be on a single line: anything between the /* QBN and the */ will work.

Then another farm, maybe with the surname of the owners? Anderson Farm. Let’s say that this is a more conventional third-generation animal farm that produces beef and pork and some dairy products. Set up the card the same way.

And…maybe this town is on the ocean, so you can drive to the docks early in the morning and buy fresh fish from the boats which are coming in. Set up another card for the Docks.

Now if you run the game you should be able to drive between all the locations. Notice that they show up in a random order each time. That’s a little irritating, so let’s sort them. Change QBN.cards() to QBN.cards().sort(QBN.alphabetically) and try it again.

It’s a little silly to drive to the place where you already are, so let’s rule out driving to your current location. We’ll start with Home. Open the passage and add another tag: req-location-ne-home. This will compare $location (or _location) against the string "home". Then go in to the passage body and <<set $location to "home">>\. The backslash at the end will prevent it from sticking an extra blank line into your passage.

Do the same to the other locations. Since we can’t put spaces in tags, we’ll shorten some of the names: “fairweather” and “anderson”.

Anderson Farm passage

We’ll also add a link to the car so you can get out without driving anywhere:

<<return "Exit Car">>

Car passage

Now if you play it, you should be able to exit the car and return to your previous location, or drive to any of the other locations.

That’s the end of this section: we’ll continue in part 2.

The sample so far.