Alabaster Open Beta

Okay — it’s much later than I would have liked, but Alabaster is now, I think, ready for beta.

This is an unusual sort of beta for IF. Usually I distribute a game file and collect information about how it plays. This time, because of the unusual origins of the thing, I’d like the beta to be more open, with contributors able to see how their materials were worked in and how the mechanics of the game function.

To that end, a) I am putting up the source, the conversation diagram, and the plot tree for people to work from. I have testing commands in place and have (I think) proven to my satisfaction that the plot tree works… which is exactly the sort of hubristic statement that guarantees the discovery of enormous bugs by tomorrow morning.

Also, b) I have left in a lot of the construction materials. You can, for instance, see in the status bar a bunch of stuff about Snow White’s mood and the current state of the conversation in terms of how many quips are used up / available / total in the game. We’ll naturally be getting rid of that in the final version.

How I envision this working:

— If you are testing, please keep a transcript and send it along with any bug reports. Without transcripts, it is nearly impossible to debug complex state-related bugs in conversational games. This is critical.

— The conversation builder is still turned on, and can still be used to generate new quips for inclusion. If you want to use it to fill in missing little snippets of dialogue, you may, but this is a good time to do it sparingly and with regard for what other people have written: the idea at this point is to fill in the remaining gaps in the game, not to add big glorious new plot threads. I reserve the right not to accept new conversation that would redirect things in massive, hard-to-code new ways.

— If you encounter something weird and want to go look at the code, you’re welcome to do that; I’m happy to receive actual patches as well as reports of things broken.

— I also welcome feedback about the way the story winds up being folded together, though I guess I welcome it more from people who had a hand in the first half of this project (or at least, I’m more likely to act on it). There were a lot of different ideas from the contributors that got combined into the final plotline, and I hope I achieved something coherent that doesn’t too terribly betray anyone’s vision. But… who knows. Tell me if I totally broke your idea.

— If you prefer to test in a black-box, how-would-the-player-really-experience-this way, that would also be very useful. In that case, ignore the source code and charts, and when you start up the game, type PLAYER MODE ON; this will turn off the conversation builder and create a somewhat more natural playing experience. Feedback about how the game is paced, how the endings are clued, etc., would all be useful especially from black-box testers.

Finally, re. performance: I’ve optimized somewhat, but at the expense of a longish load time. I’m working on further improvements, but for the time being, starting the game now does a bunch of work so that the lapsed time between turns will be shorter. Sorry about that. If you have access to a functioning version of Git, I suggest trying that.

Visualizing replay structure

A lot of my recent work on Alabaster has been to tie together plot threads from different contributors and try construct something that produces a coherent narrative. I’m a little nervous about this process, since I’m doubtless taking some of the contributions in a direction that the contributors didn’t expect; if anyone objects wildly, we can talk it out in the beta-stage. But I think I do now have a viable, consistent story and plot structure.

This level of organization is impossible to capture on the conversation tree, because some of the outcomes depend on other actions than conversation. So I need something else — another kind of chart — and this one can’t really be automatically generated from the game source. Here it is drawn by hand (though note that if you click through to the full thing it will necessarily be a bit spoilery):

Diagram of significant outcomes in Alabaster
Diagram of significant outcomes in Alabaster

Currently there are 18 ways the plot can end. Dashed lines indicated endings that aren’t fully implemented yet (so you can’t actually reach that outcome); a number in a box indicates that I’ve written a test command to test it. The ending test commands are named things like “end-1”, “end-2”, and so on, so one can go through and try all of them. The colors of the outcome boxes indicate how likely the player character is to survive that ending. Red endings kill you instantly; orange endings indicate that long-term prospects aren’t great; yellow endings are more optimistic. The one green ending doesn’t kill you at all, but it’s not optimal for other reasons. So the best endings from the story perspective are the yellowish ones down at the bottom center-left; they take the greatest amount of plot-traversal to reach, which (I think) is as it should be.

It’s possible that I would be able to autogenerate a puzzle and completion map if I were using Aaron Reed’s Intelligent Hinting extension. Since that explicitly tracks puzzles and the relationship between them, one might be able to create a .dot file for that as well. In fact I did a little preliminary experimentation with the idea, using Aaron’s hinted implementation of Adventure. It partly worked, but it wasn’t as clear as I would have liked; I think I was misunderstanding how he was using some of the relations. Nonetheless, that is something that could probably be done given some effort.

Something that’s always necessary to think about in a replayable plot where the player is unlikely to get the “good” outcome the first time around: how do we indicate after a failed playing what he should go back and do in order to get a better outcome?

Partly one needs to leave enough clues in-game that there are other options one hasn’t pursued, but I think a certain amount also depends on the hook-iness of the writing of the unhappy endings. They shouldn’t just be generic failures; they should be interesting failures that give enough information to reward the player for reaching even that far, while improving his understanding of the world and giving him some new directions to try once he gets back into the game. So the chart helps me think about this: in particular, a negative ending should point at the next thing the player could have done to get a more interesting outcome. Endings 1, 2, 3, and 6 could leave some hint about waking the hart. Endings 4 and 5 should suggest that there is more to know, that you didn’t find out everything from Happy after all. And so on. It’s pretty unlikely that the player will wind up hitting all the less-optimal endings before getting to the better ones, but I’m hoping that consciously structuring things this way will provide more impetus to keep going.

Visualizing conversation

When I was first working on Inform 7, one of the things I was a bit skeptical about was the map index. Yeah, it was cute, but did I need it? As a real IF designer, wasn’t I perfectly capable of keeping my own notes and maps? And wouldn’t it perhaps exert an undue influence on designers to use a square-grid map, just because that’s what indexes best?

The latter point may be a fair complaint (though at the same time I am kind of in favor of comprehensible map layouts). But I was totally wrong about the first point. When I wrote the early speed-IF version of Bronze, I was able to put it together quickly only because I could add rooms, refer to the map, see where the holes still were, add, recompile…

Primitive as it is, the graphing ability of Alabaster is proving reasonably useful too. The graph isn’t especially pretty — I don’t know whether I’d get something better out of Graphviz than I can get out of OmniGraffle and a .dot file — but it conveys a lot of useful information. In particular, it’s possible to glance at the graph and find bugs that might take hours of testing to detect in the game. Colored nodes show where conversation dead-ends. Lines that go to the wrong places show where some connection has been screwed up in the system.

The main problem is that this image is (a) insufficiently eye-candy-ish and (b) too big. With Alabaster we’re approaching 300 conversation quips, and I suspect we’ll exceed that number before it’s done. Which isn’t really surprising — that’s about on a scale with Galatea, and though Alabaster has fewer avenues of conversation, each individual one can be pursued in more depth, so the balance comes out similar. I think this will turn out to be a fairly normal, not-at-all-extraordinary size for a conversation game. So clearly the fact that the graph is getting ugly is a problem.

I’ve been thinking on and off about what I want to do about that. I’m eager enough to finish primary coding on the game that I haven’t gone off to investigate new graphing options — the current graph provides enough diagnostics to do what I need it for — but I’ve been thinking on and off about what I think it a conversation-visualizer should look like and do in an ideal world. The fact that Processing 1.0 was just released has also been affecting my thinking. Wouldn’t it be neat to be able to view a conversation tree as a dynamic structure, something you could zoom into or away from; or to be able to pull one piece of the conversation tree away by itself to view it in more detail; or to switch visualization modes and instead see a chart of which facts and subjects were most important, or which quips functioned as gate-keepers by providing access to large portions of the rest of the conversation tree? In fact, mightn’t such a tool actually be useful for optimization problems too (since it would make it easier to discover where the conversation tree could profitably be broken into chunks for the purpose of limiting the search range)?

But I’m focusing on finishing the primary coding, oh yes.

LICK TREE. PURCHASE ANTLERS.

This is mostly to put in a plug for Juhana Leinonen’s new extension “Object Response Tests” (linked from here). The extension implements an ANALYZE verb that systematically runs through standard rules actions (and new actions, if you choose) on any object in your game, exposing infelicitous responses, incorrect plurals and articles, and all those other little flaws that can escape even a good human beta-tester.

I spent a lot of yesterday evening thus: extract a complete list of in-world objects from the world index of Alabaster; write a test script to run through and ANALYZE each of them in turn; revise responses I didn’t like; run the test script again…

Unsurprisingly, this is a lot more thorough than even (what tried to be) a fairly rigorous testing by hand. It’s also a lot more fun. (Though I find it has the perhaps-unhealthy effect of making me lavish a lot more time on commands no one is ever going to try, like DRINK UNDERGROWTH or STAND ON CHIN or TIE FACE TO SKY. There’s something about seeing the same library messages over and over that makes me want to spice them up with randomized elements.)

More seriously: the huntsman seems to be getting a bit more character as I go along. I picture him as a loner who has never been quite comfortable with the other villagers or with the court, who doesn’t feel at home anywhere, and who has not much left to lose. (This justifies a wider variety of endings for him, of course — he’s more likely to be willing to run away from his home kingdom if he hasn’t got a wife and kids he’s leaving behind, say.)

Speed, speed, speed

Lately I spend a lot of my time wrestling with performance issues under Glulx.

This is partly because most of what I’m working on is, in one way or another, a test of the big conversation library I have in progress, and this is necessarily very code-heavy. But if I’m wrestling with it, that’s not good, because it means other authors using it are likely going to have to do the same — and they may have less patience with the problem, or just find that the whole thing is too irritating. For small projects, the system works fine, but for Alabaster (ca. 250 quips now) even after a fair amount of work, there is a 1-3 second delay on a lot of the moves. That is Just Not Okay.

There are three points of attack here, as I understand the problem:

Optimizing Inform so that it compiles code that will run faster. Several things have come out of my (or other people’s) performance problems in the past — Graham has sped up pathfinding and handling of large “Instead…” type rulebooks, and our recent conversations might conceivably lead to speeding up the performance of object-based rulebooks (which are one of the key pieces of the conversation library, since every piece of conversation has to be consulted to see whether it can be said at the moment).

Optimizing my own source. I’m working on that: finding more ways to cache needed information, minimize the scope of loops, etc. (And, since I mean this to be a released extension down the road, figuring out how to give authors of other work help optimizing their stuff, where those optimizing tricks cannot be folded into the core library but require some per-game customization.)

Speeding up interpreters so that any speed problems that remain are minimized for the end-user. Here Git seems to have a clear advantage over its competitors, but I haven’t had luck so far building it for OS X. (That might be because I have no ****ing idea what I’m doing. I am not exactly an old hand with gcc.) Has anyone else had luck with this? Is there an already-compiled OS X Git (using the latest, January 2008 version of the code) out there that I just don’t know about?

It looks as though Git might be what’s under the hood in Spatterlight (at least, Spatterlight seems to play faster than Zoom, at least a bit) — but if I actually open the Spatterlight package, it doesn’t list Git, only Glulxe. And I don’t see anywhere within the Spatterlight application to find out what version of interpreter it’s using. Which I guess doesn’t matter too much if it does, in fact, play faster… but this is all kind of mystifying.

Alabaster Interim Status Report (Release 18)

I am still working on Alabaster’s edited beta; in case anyone is interested, I’ve posted the latest build (18), but this should be regarded as just an interim thing while I continue to work on a release candidate that can be sent around to testers.

Continue reading “Alabaster Interim Status Report (Release 18)”