Tethered post-mortem (and post-comp release!)

The post-comp release of Tethered is out! I did not update the game during the comp as a matter of principle, but I kept a close eye on the online transcripts, and made lots of improvements as a result. The overall playing experience should be much smoother now.

Post-mortem reflections in the box.

[spoiler]Tethered violates every rule of thumb about how to craft a successful parser-game for IFComp. It’s implemented in a homebrew system, it contains a rope that can be tied across rooms, its puzzles are difficult, and it plays tricks on the reader. The game contains not one, but two unbearably cliché settings: The cave crawl and the crappy apartment. I didn’t write in my native language, I didn’t write what I know, and the story ends in tragedy. It’s also sorted towards the end of the alphabet. But, well, it was a piece of interactive fiction that wanted to be written.

Narrative structure

The most defining aspect of Tethered, in my opinion, is its narrative form. After the opening scene, the player is clearly experiencing a series of events where Judith is exploring a cave system and begins to hallucinate. But towards the end, the player is exploring a different set of events, taking place much later: Charles pretending to be Judith, roleplaying the first series of events in his apartment. The switchover is gradual, and for a long time the player is arguably playing out both scenarios at the same time.

And yet, that is not the whole story: At the end, Charles removes his pyjamas and falls asleep in the room corresponding to the entrance of the cave. But, as we’re told at the end, this is the very place where Judith entered the final stages of hypothermia, removed her protective clothing and lost consciousness. So, as far as causality is concerned, the snake bites its own tail, and we really don’t know whether we are now Charles dreaming he is Judith, or whether we were then Judith dreaming she was Charles.

So although my blurb (the Chuang Tzu quote) has been denounced by more than one reviewer, I stand by it because I think it provides a neat bookends summary of the structure of the work.

Relationship with Shade (spoilers for Shade in this paragraph!)

Many people have remarked on the similarity to Shade by Andrew Plotkin. I was completely unaware of this game when I wrote Tethered, but I’ve played it since, and I heartily agree. There’s the same gradual reveal that things aren’t what they seem, and by an amusing coincidence both stories feature a vacuum cleaner in a closet. But note that the direction of discovery is reversed: In Shade, you start with the safe and mundane and move towards the perils of an unforgiving climate, whereas in Tethered you start with the outdoors adventure and move towards the crappy apartment simulator.

It is pitch dark

Tethered contains two darkness puzzles, both with unconventional solutions. Based on the online transcripts, I must admit that the first darkness puzzle ended up being too difficult. The tacit switch from Charles to Judith is appealing from an aesthetical point of view, but also inherently confusing: Both characters are wearing identical clothes, and therefore (by parser-game logic) they are essentially indistinguishable in the dark. Thus, for a little while, the player inhabits both of them simultaneously, which is a foreshadowing of the major reveal later in the story.

Alas, that’s not how the player sees it. First of all, the main difference between Charles and Judith at this point is that Judith doesn’t carry a tool belt and a knife. This distinctly looks like a bug, which makes a bad impression on the player. For the post-comp release, I’ve added shadow objects, so that referring to the belt or knife generates appropriate responses.

Second, and more importantly, the player approaches the darkness puzzle with preconceived notions of what is going on. I had hoped that they would explore their surroundings, using various senses, and quickly reach the conclusion that they were buried in snow. But, and this is obvious in hindsight, the previous scene has primed the player to understand the situation in terms of Charles’ predicament, and so they try really hard to find a way to go down the mountain, instead of up from the snowdrift.

Many players attempted to spit in order to orient themselves in the dark. Google confirms that this is a useful technique when one is stuck in a snowdrift, and I’ve added it as an alternative solution to the post-comp release. A few players attempted to pee, but after due consideration, I think this is a less reliable approach.

I’m particularly fond of the second darkness puzzle, because of the way it traps genre-savvy players, while potentially letting novices through. Of course, in Tethered it appears after a more taxing puzzle, so inexperienced adventurers might not even reach it. But it’s been amusing to see how this plays out in the online transcripts. As I suspected, people are strongly conditioned to immediately back out of a location when they see the “It’s pitch dark” message. They proceed to search the other rooms for a light source, and then they eventually return and stumble over the correct solution. In real life, of course, they would instantly know how to solve this puzzle.

Speaking of darkness, the luminescent fungus is a bit of a red herring. It was originally intended to explain how Judith can see deep inside a cave without a lamp. I thought it could correspond to patches of mould on the bathroom walls, but I changed my mind about that as the characters developed: Charles may live in an old, worn-down apartment, but he keeps it clean.

A lot of players have attempted to eat the fungus, which got dismissed with a “No way!” response. I now feel that this was a missed opportunity, since Judith is going to start hallucinating later, and I like the idea that some players would link that to having tasted the fungus earlier, and regret their carelessness. So in the post-comp version, Judith agrees to taste the fungus once, before vehemently refusing to eat any more.

Dialog

The writing of Tethered has been highly intertwined with another project of mine, which is the development of a new IF authoring system for the Z-machine. The idea for Dialog came first, and I toyed around with prototype versions for several years, on and off. Then, as it all started to come together, I decided to put the language to the test by writing a comp-sized game, which would also be my first published work of IF.

What actually happened, of course, was that as soon as I tried to use the language in practice, I ran into lots of unforeseen problems with the design. So the language and the game evolved together for about a year. The first round of testing happened in early July. During the judging period, I’ve kept an eye on the online transcripts, and made improvements not just to the game (for the post-comp release), but also to my standard library. I’ve also been busy documenting the whole Dialog system, and this process has lead to further insight and consequent adjustments to the design.

Tethered contains a small in-joke for fellow authoring-system developers: The overcoat in the vestibule is “slightly splattered with raindrops” and hangs on a small brass hook. Perhaps you recognize it as the Cloak of Darkness. Of course, there is no real way to interact with the overcoat in the game and try it out, but I’m sure Charles is putting it to good use when we’re not looking.

Walkthrough

Like Inform, Dialog can parse sentences with multiple objects, such as TAKE APPLE, ORANGE, BANANA. I made the mistake of putting such a command in my walkthrough (PUSH BOULDER S, W), which turned out to be confusing. And I realized that as an author, when somebody is looking at your walkthrough, you’ve already failed to communicate with them in-game, using hints and nudges. At some point, there’s been a misunderstanding, and the player is attempting to go back and redo everything one step at a time, in order to pinpoint exactly where the misunderstanding happened.

So, walkthroughs aren’t necessarily about spoon-feeding the player with puzzle solutions. The person reading your walkthrough may in fact be thinking very hard, trying to debug their earlier thought processes, like a programmer single-stepping through a convoluted piece of code. And you are playing the part of their debugger.

The rope

Implementing a rope in a text adventure is notoriously difficult. One of my reasons for doing it was to prove to myself that Dialog was useful for complicated programming tasks. But a programming language cannot magically remove the essential complexity of the situation. Apart from implementing a myriad of special cases and custom responses, the main trick is to carefully shape the entire game world around the rope puzzle:

First of all, apart from the player character, there are very few objects in the early part of the game that the player might be tempted to tie the rope to. A trickle of water here, a patch of fungus there, a slippery floor. As hinted by one of the “amusing” items, there are hidden objects strewn all over the place. However, when Judith tries to tie the rope to an object from the apartment, a stock message is printed about the object not really being there. And when Charles tries to do it, a message is printed about the rope not really being there.

As for the player character, they’re permanently attached to the rope. This gives the narrative voice a plausible excuse for refusing to tie the rope to the player character—you’re already attached to it! Furthermore, the fact that there is only one loose end allows the implementation to get away with a limit of a single knot at any given time: Any attempt to tie a second knot triggers an innocent-looking “first untying the rope” action.

A lot of thought went into the geometry of the cave. The rope is exactly seven rooms long (although multiple segments can be located in the same room, forming a loop or pile on the floor). There are three different techniques for anchoring the rope to the upper level of the cave, in order to reach the lower level. Each technique makes the rope long enough to allow the player to climb down the pit, but too short to allow them to enter the northernmost room, regardless of what path they take through the cave system. When the rope is tied to the column by the cave entrance, it is possible to reach the boulder, in order to create an alternative way up. When the rope is merely held in a loop passing through the upper rooms, it can be dropped in order to reach the boulder.

And there are other, subtler things. For instance, the FIND command is part of my standard library, and it usually takes the player to a given object by the shortest path. However, attempts to FIND THE KNOT in this way could potentially lead the player to the cave entrance by a different route than they used going down, and this would have the side-effect of threading the rope through the upper rooms of the cave system. Such threading is a perfectly fine solution to the problem of reaching the lower caves, but when it is discovered by accident (as one tester did), it can be very confusing. To avoid this problem, I had to ensure that FIND THE KNOT makes the player follow the rope back to the knot, while avoiding any detours due to slack in the rope. So a lot of work went into curling the player through that special case, in a way that is hopefully completely invisible.[/spoiler]

Final words

Being part of IFComp 2018 has been an amazing experience. I’ve particularly enjoyed hanging out with my fellow authors in the private forum. The comp has been impeccably organized; I had to get in touch with the officials just before the submission deadline, and their responses were prompt and considerate. The web interface for submitting entries and ratings has worked flawlessly. Judges have judged, reviewers have reviewed, and my “reload” button has never seen as much action as during these last six weeks.

In a few days, I’m going to post more information about Dialog under “Other Development Systems”. Stay tuned!

I only have a few finishing touches left to do now, so please bear with me for another day or so.

In the meantime, here is a teaser:

[rant][code]
(story title) Cloak of Darkness
(story author) Linus Åkesson
(story noun) A port of Roger Firth’s reference game

(story ifid)
%% This is the IFID for the Dialog port of Cloak of Darkness:
A5AA4F02-8F50-4649-A4BD-B1B5C5408B67

(scoring enabled)
(maximum score 2)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

(intro)

            Hurrying through the rainswept November night, you're glad to
            see the bright lights of the Opera House. It's surprising that
            there aren't more people about but, hey, what do you expect in
            a cheap demo game...?

            (banner)
            (enter #foyer)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#foyer

(room *)
(singleton *)
(name *) foyer of the Opera House

(look *)

            You are standing in a spacious hall, splendidly decorated in
            red and gold, with glittering chandeliers overhead. The
            entrance from the street is to the north, and there are
            doorways south and west.

(prevent [leave * #north])

            You've only just arrived, and besides, the weather outside
            seems to be getting worse.

(from * go #west to #cloakroom)
(from * go #south to #bar)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#cloakroom

(room *)
(singleton *)
(name *) cloakroom

(look *)

            The walls of this small room were clearly once lined with
            hooks, though now only one remains. The exit is a door to the
            east.

            (notice #hook)

(from * go #east to #foyer)

#hook

(supporter *)
(name *) small brass hook
(dict ) peg
(
is #in #cloakroom)

(descr *)

            It's just a small brass hook,
            (collect $Obj) ($Obj is #on *) (into $List)
            (if) (nonempty $List) (then)
                    with (a $List) hanging on it.
            (else)
                    screwed to the wall.
            (endif)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#bar

(room *)
(singleton *)
(name *) Foyer Bar
(look *)

            The bar, much rougher than you'd have guessed after the
            opulence of the foyer to the north, is completely empty. There
            seems to be some sort of message scrawled in the sawdust on the
            floor.

            (notice #message)

(from * go #north to #foyer)

(inherently dark *)
(#cloak is in room *)

(instead of [look #down])
(current room *)
(try [examine #message])

#message

(name *) scrawled message
(dict ) floor sawdust
(
is #in #bar)

(descr *)
(if) (message has been trampled) (then)
The message has been carelessly trampled, making it
difficult to read. You can just distinguish the
words…
(par)
(bold)*** You have lost ***(roman)
(else)
(increase score by 1)
The message, neatly marked in the sawdust, reads…
(par)
(bold)*** You have won ***(roman)
(endif)
(game over)

(prevent $Action)
(current room #bar)
~(player can see)
~(command $Action)
($Action = [$Verb | $])
~($Verb is one of [go leave enter look])
(select)
In the dark? You could easily disturb something.
(or)
Blundering around in the dark isn’t a good idea!
(now) (message has been trampled)
(stopping)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#player

(current player )
(
is #in #foyer)

#cloak

(name *) velvet cloak
(dict *) dark black satin
(wearable )
(
is #wornby #player)

(descr *)

            A handsome cloak, of velvet trimmed with satin, and slightly
            splattered with raindrops. Its blackness is so deep that it
            almost seems to suck light from the room.

(prevent [drop *])
(when dropping outside cloakroom)

(prevent [put * $ $])
(when dropping outside cloakroom)

(when dropping outside cloakroom)
~(current room #cloakroom)
This isn’t the best place to leave a smart cloak lying around.

(perform [put * #on #hook])
~(hook point awarded)
(increase score by 1)
(now) (hook point awarded)
(fail) %% Fall back on default behaviour now.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

(understand [hang | $Words] as [put $Obj #on $Dest])
*(split $Words by [on] into $Left and $Right)
*(understand $Left as object $Obj preferably held)
*(understand $Right as single object $Dest)
[/code][/rant]

Tethered was one of my favorite games from the IFComp, yet somehow I never manged to give it the attention I thought it deserved. Mostly because I found no way to seriously tackle the fascinating narration techniques and the very gripping (almost) story it tells. I really loved the subtle changes… this must have been the first time that I started looking at myself and wondering who I am in an IF game. :wink:. Plus it has some of the most natural puzzles I saw this year – so lifelike! Yet what I loved the most about it is the overall mood: That feeling of loss and not letting go, so fitting to the scenario.

Anyway: Thanks for this great game and the interesting experience it was playing it!