Choice tricks of the trade

Hello all, first post here.

As far as making text games goes I know there are a bunch of ways to nail a hammer. I’m working on my own choice IF system as you do, and I’m interested in implementing good techniques/features/workflows from existing systems. My goal is to add things that are known to be helpful for authors/programmers (authgrammers ?). I assume my system will be stronger because of it. A few examples that come to mind:

Implicit choices in Undum.

Percentile Stats and Fairmath in Choice script.

Hooks in Twine 2.

Rollback in Ren’Py (not necessarily for authors but great for players IMO)

Story map in Twine.

If you know of any useful things along the same lines do share :slight_smile:

I think we would have more interesting choices (ehem) of tools to use if more tools had a clear focus instead of so many trying to support any type of game. There are already so many tools that can do anything, but if you can instead focus on making some particular type of game easy to make, that will be great for anyone interested in making that particular type of game. You can always add the ability to export to some popular format (Twine, Choicescript, whatever there is) to make it easier for authors to reach out to more players, while still work with a more specialized tool that actually supports (not just allows) the kind of game they want to make. (It should be noted that I don’t quite live as I teach when it comes to this, but I have tried to work on focusing gamebookformat more to make it great at a few things and ignore other things, like any good tool or framework should ideally do).

I may have been vague in my original post, but my point in this topic is to ask what are some of the things that we have learned to be helpful in making choice games. Since there are many systems and many games, I’m interested in finding useful gems that make the lives of game developers/authors easier.

Going back to one of my examples, in many digital choice games we track variables based on player decisions. If one of these variables is meant to be a player facing percentile stat, we have to do extra work in authoring to ensure the variable stays between 0-100. I don’t know how or when, but someone working on Choicescript picked up on the difficulty in managing that type of stat. They came up with the idea of using Fairmath to control changing the variable’s value and it makes the author’s life that much easier. On the surface this may sound like a feature that is beyond the scope of what a system should do, but I think it is significant enough that a good system should support something similar. (A sidenote is that I was working on a game in Twine 1 where I had a percentile stat that took a lot of effort to balance. I realize now that I could have had a better experience had I known that this was not a unique problem and was already solved in another system.)

No, your question was perfectly clear. I just deliberately did not answer exactly that, but wanted to point to a closely related problem, and that not doing all the great things the other tools do so well already can be considered a feature in itself for your tool.

Twine 2 hooks are a great idea, but Harlowe’s lack of support for new macros makes them really limited. I found that they ultimately aren’t better than something like the very popular <> macro set that is still available with Sugarcube.

I haven’t actually tried hooks yet, but my interest is in the idea that spans of text can be marked and modified elsewhere. One idea I have is to simplify formatting so that you could write something like a macro at the start of a source file, then use it anywhere.

[code]#myText if($myKey == 5) {#TEXT#}

:: A Passage
This is my #myText[uncreative ]example.[/code]
This would be replaced as.

:: A Passage This is my if($myKey == 5) {<b><i>uncreative </i></b>}example.

Indeed, though you can do that with Sugarcube widgets, but I found them pretty limited. I tried to implement a relatively simple hypertext effect in a passage and found that in Harlowe I simply couldn’t unless I wanted to dip into doing it by hand with jquery.

I looked into Sugarcube widgets and they look pretty helpful. I’m wondering in your case was the issue that the widget didn’t replace text properly or was it just a limitation in Harlowe? Actually the better question to ask is what would be an ideal way of writing hypertext effects? The most I’ve actually done visually is to change the background color of the page based on a link click, and it was pretty rough visually.

I really wish for something like Inform 7’s adaptive text resources, which are fantastic and far ahead of what Twine offers (As they have to be, because otherwise writing adaptive text to handle anything but the simplest world model would be a pain). So I would like to be able to write something semantically equivalent to:

A woman walking a [one of]poodle[or]chihuahua[or]ferret[or]cat[or]exceedingly small horse[as decreasingly likely outcomes] bumps into you.

You rummage through the box, finding [expand]your aunt's scarf[and], some old mittens[and],a box of ancient Drambuie-filled chocolates[and], and the papers you were looking for[on clicking].

See, the problem isn’t really writing JavaScript code to generate adaptive text; frankly what I’d love is just something that would take a JS function and, every time the player performed some interaction (Such as clicking a link), it would then change some text to whatever that function returned. With closures, this could be used to create a functionally arbitrary text generator. I can already do that, except it would involve manually writing all the JQuery code to handle changing the contents of the page and so on, which makes it cumbersome. It’s the main reason I’m not using Snowman in the first place: It feels like a poor use of my time to reinvent the wheel so much.

The thing that made me feel Harlowe isn’t mature or extensible enough right now was a pretty simple thing: I had a passage in which the player character is in a place filled with curious objects, and as a small detail I wanted the player to be able to click a hyperlink to reveal more and more of the contents of the room. This is doable in Harlowe, but very uncomfortably:

Harlowe doesn't have an equivalent to the old "nobr". It has another way of stripping whitespace, {},
but that will only collapse whitespace into single spaces, meaning that '\n' becomes ' '. For reasons
that will become apparent, that means I can't put line breaks where they would be intuitive and
reasonable; I have to put it where a space would normally go, otherwise it'll insert an unwanted space.
On the shelves, you see a number of |o1>[odd items](transition: "fade-in"[(click: ?o1)[: a |o2>[dog] in a
wire mesh box]](transition: "fade-in")[(click: ?o2)[, a |o3>[crow] in a
cage]](transition: "fade-in")[(click: ?o3)[, a rabbit's foot]].
<!-- In the actual version of this, there were something like 30 items. -->

Doing this isn’t hard, it’s just vaguely shudder-inducing and I know that when I come back to it in two months my eyes are going to glaze over. Moreover it was indicative that doing anything slightly playful or odd with hypertext was going to be like pulling teeth; and sort of the value of Twine is that it gives you the whole text as a canvas to play around with hypertext. If I wanted to write a very conventional gamebook, where the only links are always at the end of every passage, I would use inklewriter or choicescript. Because Sugarcube is extensible, I have access to the <> macro set that makes the above passage much more tolerable to write.

Still, I find that none of the systems for developing choice-based games hit a good place for me in terms of usability versus power. Twine with Sugarcube comes closest. Choicescript and inklewriter are very usable, but they’re also very much married to one particular format; this is fine, but it’s not useful to me if I’m not interested in working within that format for a given project. Harlowe, quite frankly, seems like a step backwards. I find Snowman interesting, but I also fear it would lead to messing around with $(), which feels like a poor use of my time. Undum isn’t so much a game engine as a game with a moderately documented source code and an invitation to hack it.

That Harlowe example is really unworkable. My first impression of the gift tag syntax for named hooks was that it just won’t work in practice. Even before the rest of the brackets and such it just doesn’t look maintainable to me. Not that I have a better alternative to accomplish the same task in mind.

Your Inform examples look really clean. I’ll have to look into Inform 7’s adaptive text resources. I admit every time I look at Inform documentation I get distracted, but I really should take some time to focus on it.

In my system the best I can currently do is use something like a display macro to provide a different piece of text each time the section is visited. My design goal has been to separate logic from text as much as possible so it ends up being pretty verbose overall in cases like these. The benefit (in my mind anyway) is that in the actual place where you are trying to create variation it is clear how it is happening.

[code]:: Some passage 1
A woman walking a display($display = enum.somePet) bumps into you.

:: fill, poodle [rule($display == enum.somePet)]

:: fill, chihuahua [rule($display == enum.somePet)]

:: fill, ferret [rule($display == enum.somePet)]

:: fill, cat [rule($display == enum.somePet)]

:: fill, exceedingly small horse [rule($display == enum.somePet)]
exceedingly small horse

:: Some passage 2
You rummage through the box, finding display($display = enum.findingThingsInTheBox).

:: fill, stuff in box 1 [rule($display == enum.findingThingsInTheBox)]
set($boxCheckedCount += 1)
your aunt’s scarf

criteria($boxCheckedCount == 1)
set($boxCheckedCount += 1)
your aunt’s scarf and some old mittens

criteria($boxCheckedCount == 2)
set($boxCheckedCount += 1)
your aunt’s scarf, some old mittens and a box of ancient Drambuie-filled chocolates

criteria($boxCheckedCount > 2)
your aunt’s scarf, some old mittens, a box of ancient Drambuie-filled chocolates, and the papers you were looking for[/code]

To be honest, all of this nonsense could be avoided if only JavaScript had text interpolation like a real programming language. Alas, though. Maybe I should just learn Undum and then write everything in CoffeeScript and not cry so much. Or, really, just use Underscore templates in passages. The real problem is, of course, that all of the adaptive text generator stuff should live in a library, not get written again and again for each project. Especially when that text generation involves interactivity, because there is so much half-boilerplate half-implementation code that has to be written to allow for a seemingly simple thing like clicking a link here to change some text there. If a system doesn’t provide that functionality out the box I’m essentially setting off to write such a system if I want to use it.

By the by, my first example was actual Inform; the second was pseudo-inform meant to suggest what I would like out of a hypertext-based system.

Javascript has nothing built-in; that’s why people write libraries. Without even looking I can tell you that there are a dozen Javascript text-templating libraries out there and a couple of them are good.

There’s Mustache and Underscore that will do exactly that, yes. If I recall correctly, Snowman actually uses one of them by default. The problem is however that then you have to write all of the JQuery text-modifying code yourself, which is basically like writing a significant part of a Twine story format yourself.

Mm, I see.

I’m curious what people think of Seltani’s system in this regard. ( … he_Example)

Obviously it has its own limitations (no jQuery access, can’t be run offline) but I’m pretty happy with how the text-display engine came out. The relevant bit is that you can put double-brackets in your text – [[xyzzy]] – and the system will look up the “xyzzy” property and insert its text there. If the “xyzzy” property is code, it will run it and insert the result. And any state changes will redraw the text if necessary.

This turns out to require quite a bit of infrastructure. As you say, it’s not just about templating. I had to nail down a model of world state (both for storage, and so I could track changes and dependencies). I also had to force a distinction between display panes (always up-to-date, text adjusts as needed) and the event pane (scrolling list of recent events, no hyperlinks, text cannot adjust once printed).

I’m not at all familiar with Seltani (I thought it was really interesting, but my unfamiliarity with the Myst mythos sort of kept me away from investigating too hard). If it’s possible to change system state (In response to a hyperlink being clicked, for instance) and see text that references that state change in real time in a way that is transparent to the programmer, a la Meteor, that’s really impressive.

Actually, it turns out that JavaScript just developed a new templating feature called “template strings” in EcmaScript 6. … te_strings

It’s available in the latest Firefox and in Chrome 41 (planned release in early March). There’s no support in IE or Safari, but you can use a transpiler like babel (formerly 6to5) to convert template strings into ES3 JavaScript, which works in any browser.

At this stage, until ES6 is properly out and well-supported and safe, if you’re going to use a transpiler you might as well use CoffeeScript and get a rid of a lot of JS’ petty annoyances on the way too. But hopefully a year from now we’ll all be happily using ES6 at least in projects that don’t care too much about being usable to Mr Hasn’t Updated His Browser In Five Years.

I prefer ES6 to CoffeeScript. The only bugs I really cared about in JS were “this” pointer being weird (fixed with Arrows), hoisting (fixed with “let”), and undeclared variables automatically defining globals (fixed with “use strict”).

In CoffeeScript I feel very conscious of the generated code; indeed, the docs for CoffeeScript define a loto f CoffeeScript constructs in terms of plain JS. 6to5/babel transpilers are very safe/basic compatibility fixes. It’s the “same language” before and after transpilation.

I really should go look at what’s going on with ES6, I haven’t followed up with it at all.

That is what it does, yes.

I’ve always said “There’s no point to making Seltani single-player; that’s what Twine is for.” But it sounds like there’s room for something in that space.

(Tangential but relevant: Emily’s IF Theory Chat is in Seltani this Saturday: Happy to talk about the programming model in more detail.)

(Or you could ask me here.)