Search Results for: dreamhold

Zarfplan: Progress report about progress

If I want to call this the "June report", I'd better get it posted in the next couple of hours... That is, if you're in the US. Everyone else can blame the leap-second.

Last month, I was saying I had a complete picture of the puzzle structure. I can now add to that:

  • An update of PlotEx which can handle the puzzle structure. (I wasn't kidding about it needing optimization, woo boy.)
  • A map! (Not complete in detail -- I may split up some rooms and shift closets around -- but complete in structure.)
  • A rough list of where everything in the game belongs on the map. (Again, not yet fixed in terms of what goes in what closet.)
  • The basic Inform code for the ritual engine.
  • The first three rituals.
  • A unit-testing script for testing new rituals as I implement them.
  • A Secret Project.

The ritual engine has been the fun part. Of course I've already implemented a version of this, for the Hadean Lands teaser that I posted with the original Kickstarter project. But that was built to handle just one ritual (ignoring the starting "lamp" puzzle, which is a one-off set of actions). Generalizing it to support the giant branching ritual tree I've got in my notes -- that's what we call fun. But I've got three rituals in there now, and they all work, so I must have gotten it right.

To make sure I've gotten it right, I built a little unit-testing script. (One can eyeball code for three rituals, but in the course of the next umpty-um rituals, mistakes will be made. I can smell 'em coming.) It's just a bit of Python hooked up to an interpreter -- I wrote the whole thing this afternoon. But for every ritual, I can now write down a list of commands and the expected outcomes (following the engine's state machine). Plus, I can write down a list for every way to do a ritual wrong, and all of those expected outcomes. (Interesting, informative failures are key to interesting IF.)

(For I7 experts: yes, this is similar in nature to the I7 Skein facility. However, I've never had good luck with the skein -- whenever I try to use it, the IDE eats my data. So I wrote my own thing. Yes, it is a personal failing. But my script is nicely tuned for HL, and more compact, and it's also easier to check into Git, so there.)

And the secret project? I won't lie -- it's not IF-related. It was a wild idea that popped up early in the month, when WWDC was coming up and everybody was agog with rumors about an SDK for AppleTV apps. It was a good idea. More importantly, I could have finished it fast, submitted it, and been one of the first apps in its category in the new AppleTV App Store.

As a developer, I have to pay attention to those sorts of opportunities. I am obligated to finish HL, but I am also obligated to keep an eye out for other paths to success. So I spent a few days on the Secret Project, and no apologies.

Well, WWDC went by and those rumors -- turned out to be rumors. Tim Cook didn't say a word about AppleTV apps. No SDK, no AppleTV App Store. So the Secret Project is back on the shelf, and I've been back on HL.

I do intend to finish the Secret Project, for iPhone. It's still a good idea! But in the iOS App Store it will be about the hundredth app in its category, and there's no advantage to finishing it right now. That makes it lower priority than the IF work. Maybe by the end of the summer, I'll get it done.

I should also mention another Secret Project, on which I spent no time at all, because it wasn't mine. Jason McIntosh has just released an iOS version of The Warbler's Nest, his short award-winning IF work from 2010. Jason is the first IF author to pick up my IosFizmo framework. (The first one who isn't, you know, me.) If you haven't played The Warbler's Nest, and you have an iPhone/iPod/iPad, drop a buck on it. Jason's cat needs kibble.

Posted in Zarfplan | Tagged , , , , , | Leave a comment

Anatomy of a bug hunt

As my loyal followers know, I released Dreamhold on a Friday, and then spent most of Saturday trying to figure out why it was crashing for some players. Nobody ever wants a software release like that, but I did find the bug, so it's as much of a win as one can hope for. The bug fix just hit the App Store.

I thought it might be interesting to detail the whole sequence of events. Or maybe it'll be as dull as ditch dirt! I don't know. It seems like a good narrative to me, but I was dere, Charlie.

Friday, 5:30 pm: I get the notice that The Dreamhold has been released to the App Store. I immediately update my web sites, and tweet about it. Then I head off to a Game of Thrones party. (Last three episodes of season 1. We're the non-HBO-having crowd.)

I have my blog post mostly written up, but I don't have time to finish it before I have to leave. I figure I'll post it before I go to bed. Good thing, as it turns out.

7:30 pm: Around the time Drogo's manly chest is sliced up, I get a tweet with a screenshot of a Dreamhold crash. Oops. Several more soon arrive. I tweet that fact. Guess I know what I'm going to be doing the next day.

1:45 am: Home now, I finish up my blog post, adding the embarrassing admission of the bug.

I have not yet done any investigation, or even seen the problem myself. But I think, what could be different about the people who are afflicted? If it's crashing on startup, everyone should be in exactly the same state. Well, one thing might be different: some people are signed into Game Center, some aren't. (The game logs into Game Center on start up, so that it can notify achievements.)

So I pull out my phone, log out of GC, flip on "airplane mode" so that I can't possibly be logged in, force-quit Dreamhold, and relaunch it. Presto. Crashy-crashy, just like people said.

Now I have a handle on what might be happening -- at least I can reproduce the problem. I go to bed, vastly less worried than I was three hours ago.

Saturday, 11 am: I wake up to email from Christoph Ender, the author of the Z-machine interpreter engine I'm using. He says he thinks the problem might be in the "blockbuf" module, and he recommends that I comment it out -- that prevents the crash he's seeing in the iPhone Simulator.

Wait. What? The app crashes in the iPhone Simulator? I've never seen that. How is he doing that?

1:20 pm: Christoph explains that he just checked out a fresh copy of my IosFizmo source, created a new Xcode project, and ran it. It crashed immediately. I try this myself, and behold, it crashes immediately.

(Christoph is testing Colossal Cave, not Dreamhold, because that's the sample game that IosFizmo ships with. This means that he's not testing the Dreamhold-specific features like Game Center. But this is good! Demonstrating the bug with a simpler setup means I can debug with a simpler setup.)

Why haven't I seen this before? Well -- honesty time -- I did see it once, several weeks ago. I couldn't reproduce it, and it never happened on a real iPhone, so I eventually forgot about it. This is one of those things that you Really Shouldn't Ignore; I have no excuse. Anyhow, I can't ignore it now.

As with all flaky bugs, the first priority is to figure out a magic chicken dance to make the error appear. After a certain amount of screwing around, I settle on this: delete the app from the Simulator, quit the Simulator, launch the app. Boom. (Naturally I never did this during normal development.)

I have no idea why this works; nor do I care. When launching from a fresh start, the memory blocks line up in such a way as to demonstrate the crash. (This is why it's good to be able to reproduce it in the Simulator. Much easier to restart than a real iPhone.)

I shall repeat this dance about five hundred times over the next few hours.

2:00 pm: (Times from here out will be approximate. Also, interrupted by meals, games of Ascension, and general staring at the ceiling. The ceiling is an important work surface.)

You might think, Christoph already found the problem! Just get rid of the blockbuf module.

True -- when I do that, the problem goes away. But that doesn't mean it's fixed. Anything can make the memory blocks line up differently. (Like not being logged into Game Center, for example.) Until I find the bug, any change is just a way to ruin the magic chicken dance, not a true fix.

Instead, I turn off Fizmo's signal handler. "Signal 11" is a Unix signal; the OS sends it to kill a process when it tries to access a bad memory address. But, as everybody noticed, the app doesn't actually die. Instead, it prints a polite message about "signal 11" and waits for the player to quit.

Why? Because Fizmo is set up to catch signals and report errors this way. But, really, I don't want that. It seems like the graceful thing to do, but in fact the report tells me nothing useful. If the app just flat-out crashed, players wouldn't be any unhappier. Furthermore, if the app flat-out crashed, then the OS would have a crash log that might be forwarded to me. (If you have your device set to do that.) The signal-catching doesn't make debugging any easier either; like I said, a simpler setup is better.

So now I've got the app crashing, in the iPhone Simulator, and it's hooked up to a debugger so I can see where it dies. As it happens, it dies on this line of code:

... [win isKindOfClass:[GlkWindowGrid class]] ...

This is gibberish if you're not familiar with ObjectiveC -- sorry about that. Basically, it checks what kind of window a particular window ("win") is. It's straightforward code which should work (return YES or NO) for any valid reference.

Since it doesn't, then I know that at some previous time the "win" reference stopped being valid. Of course, I have no idea when that happened, much less why. This is why programmers hate memory errors. (And languages that permit them.)

2:30 pm: Time to investigate the blockbuf module. This is the part of Fizmo that remembers what the status line looks like.

Here's the joke: IosFizmo doesn't even use the blockbuf module. It has its own module to track the status line. (The "GlkWindowGrid" class mentioned above.) The Fizmo part of the software sets up blockbuf, and I never got around to turning it off. In fact, for several weeks I had "Disable blockbuf?" on my to-do list! But the one time I tried it, I ran into some picayune problem -- not a crash, I think it was a compiler error -- and so I decided that it was important for some reason. So I crossed it off my list with a big fat "whatever".

Sigh. If only.

Anyway, blockbuf is a simple piece of code. I go through and stick in tests that will alert me if any blockbuf function writes past the end of a memory block. Unfortunately, when I run the app, none of the alerts go off. So much for that theory.

3:00 pm: I know that the crash occurs while the game is trying to draw the status line. Maybe I can pin that down more precisely.

I go through my status-line code, putting in "isKindOfClass" calls every time the window is updated. These calls don't do anything -- I'm checking the kind of a window that I already know what kind it is, and then throwing away the answer. The point is to see when the call starts crashing.

This is tedious, but it seems to be crashing... at the same point it was before. That is, the first time the cursor (the printing location) is relocated. (To draw the status line, the game moves the cursor to the top left corner, and then starts printing text.)

3:30 pm: Okay, the heck with that. I'm going to put in an "isKindOfClass" call after every single Z-machine opcode. That'll pin it down.

It works! The app crashes -- after the very first opcode. Huh.

For good measure, I put in another "isKindOfClass" call before every single opcode. And indeed, the app crashes before the first opcode.

Well, that certainly narrows it down. Memory is getting corrupted in the interpreter setup code! I put in more calls in the middle of the setup sequence. Nope, it's earlier than that. I try the beginning of the sequence. Nope, the problem has already occurred by then.

This is not what I expected. This is really odd.

Then I realize that my test call itself has a bug. I haven't been tracking down the bug, I've been crashing the app with my own test code. Oops. Throw away everything I've learned in the past half-hour.

4:30 pm: My test code does the right thing now, so it's back to the salt mines.

The app appears to be crashing after a "print character" opcode. (In fact it's printing a space character.) This isn't too surprising. Printing means adding new data to memory, and that could be corrupting something if it isn't handled right. (If the app crashed after adding two numbers, or something like that, I'd be surprised.)

How shall I deal with this, though? I can't set up alerts on every single memory-write in the printing path. Half the code in the app deals with printing text, one way or another. (It's a text adventure engine.)

5:00 pm: Bright idea time. The app always crashes after the same printing opcode. It's at address 56790. (Or something like that. I don't remember the exact number.) Fine -- I'll stick in a line that pauses execution right before address 56790. And then I'll single-step through the app and see if it does anything funny.

(You wanted to know why the magic chicken dance is so important? I really need the app to crash exactly the same way every time I test it. Because of moments like this.)

So, delete the app (again), quit the Simulator (again), start it up...

5:30 pm: This is a lot of single-stepping.

Fizmo converts the space character to Unicode. (Which is the same character value as before, but it still has to go through the function.) No overflow there.

Fizmo passes the character off to my iOS printing code.

My code passes it off to the GlkWindowGrid class, which stores it in a new memory block. All properly handled. (As far as I can tell. I'm going to feel really stupid if memory gets squashed in front of my eyes and I miss it...)

My code checks to see if transcripting is on. (It's not.)

Back to Fizmo.

Fizmo hands the character over to blockbuf.

Blockbuf passes my overflow alert (remember the overflow alert?) without a peep.

Blockbuf goes to write the space character at coordinates (-1, 0). Hold it right there.

Why is the X coordinate less than zero? Actually, I don't even care. This is the problem spot. Also, I'm an idiot. Hours ago, I stuck in an alert that would go off if blockbuf tried to write after the end of its memory block. I forgot to check for writing before the beginning of the memory block. If I had done that, I would have found the problem immediately.

6:30 pm: I suppose I should figure out how blockbuf got into that state.

It's not hard to see, now that I look. The way I'm setting up the interpreter (on iOS) leads to Fizmo thinking that the window width is zero, at first. Then, right after that, it gets resized to the "real" width.

But before that happens, it hits a line that tries to ensure that the current X coordinate is non-negative, but less than the width. Well, there is no integer which is non-negative but less than zero. It checks the conditions in that order... so the second one wins, and X winds up as -1.

7:00 pm: Time to unwind all the alerts and debugging code I've piled into this thing.

In the end, the right plan was the first plan: I have to get rid of the blockbuffer module. (But now I know that will fix the problem, not just sweep it under a rug.) The changes for Dreamhold 1.0.1 are just two lines of code:

#define DISABLE_SIGNAL_HANDLERS 1
#define DISABLE_BLOCKBUFFER 1

7:30 pm: Test in the Simulator. Test on my iPhone. Test on my iPad. No crashes.

7:46 pm: BUG FOUND..

(Then of course it took a week for Apple to review it, because of their usual queue plus the holiday weekend. No, we don't need to get into App Store control issues here.)

Posted in Zarfplan | Tagged , , , , | Leave a comment

The Dreamhold for iOS

It is up on the App Store! Go take a look.

(If you have an iPhone or iPad or whatever, I mean. If you don't, you can still play Dreamhold on my web site or however you like. For old time's sake.)

(The Dreamhold cover art is based on a photograph by Trey Ratcliff: The Festival of Lights in Lyon (CC by-nc-sa).)

I know most of you have already played Dreamhold -- it's a 2004 game, after all -- but it's been a fun game to revisit. This iOS release has a nifty map and some nifty (if cliche'd) trophy achievements, so maybe that will spark some competitive spirit or speedrun hijinks out there in Internet-land.

Unfortunately, I managed to ship the thing with a crashy bug. Several players have reported "Fizmo fatal error: Caught signal 11" messages. It isn't happening to everybody, and some people have gotten past it simply by quitting and restarting several times. (The problem seems to be showing up only on iPhone 4 and 4S, so far.)

I apologize for the bug, of course, and I hope to hunt it down this weekend. (EDIT-ADD: I have submitted a bug fix, as of May 27th. It is awaiting App Store review.) (June 4th: Bug fix is available; grab the 1.0.1 update.)

Bugs aside, what does this mean for the greater world of interactive fiction?

First, this Z-code interpreter (an iOS port of Fizmo) is available on GitHub now. Do you have a Z-code game that you want to put in the App Store? Now you can. (I mean, when the bug is squashed.) Free or for money, it shouldn't be a problem either way.

(You'll have to be a registered iOS developer, though. Also, I haven't documented the build process in any useful way -- sorry. This will improve over time. For the present, just install the project and its submodules from GitHub, replace Game.z5, and fire up Xcode.)

Some answers for the IF author contemplating an App Store release:

  • Can I customize the display style?

Yes. I put in hooks for game-specific fonts and color schemes.

  • What about that awesome map?

The map is Dreamhold-specific, so it's not included in the interpreter release. The same goes for the Game Center achievements. I think I'm going to keep those as private extensions. (I'm pretending to do this for a living, so I have to have some kind of, whaddayacall, "value add".)

If you're good at iOS coding, you are of course free to write your own interpreter customizations. The source is under a BSD-style license.

  • Is this a fully functional Z-code interpreter?

Urm, mostly. It only handles V5 and V8 at this time. (The V3 status line code might work, but is untested.) Timed input works, but the color opcodes do not. There are undoubtedly some bugs -- I know the status line height can go wonky at startup in some games. (Fortunately not Dreamhold! I know what's going on with this bug, I just haven't gotten around to it yet.)

  • What about Glulx? (Hadean Lands will be a Glulx game, after all.)

I have most of the Glulx interpreter working (see iosglulxe), but it's missing one key feature -- the ability to launch the game where you left off. This is critical for iOS, obviously. Follow my GitHub progress to see when that's ready.

  • Can anybody use this? What if someone goes and posts all of your IF on the App Store?

The App Store has a lot of cloning and shovelware floating by. This is a sad fact of the app world. It is possible that somebody could take this opportunity to flood the world with games using my name -- or, for that matter, start uploading the entire IF Archive.

I hope that doesn't happen, though. I would like to build up a small selection of Zarf IF games on the App Store, both free and for-money, with nice game-specific bonus features. That would be good for the Zarfhome label.

(I have nothing against iOS Frotz, which is awesome -- it's not an app that features particular games. Flooding the App Store search results with a bunch of cloned IF is entirely different.)

(Note: if you are this sort of shovelware bozo, and you're posting other people's games from the Archive for free, you're a bozo. If you do it for money, or put ads on, you're a bozo who is probably violating a bunch of software licenses. All my games say "Do not distribute commercially without permission," for example. Don't go there.)

Well, we'll see what happens, right? Enough of that mess.

  • And Hadean Lands?

I turned Dreamhold over to the App Store review queue a week ago. Since then, I've been chewing through the pile of HL design documents that have been accumulating for the past oh-so-many months.

I now have a complete picture of the puzzle structure -- every ritual and special action, major and minor. It's... somewhat terrifying. Remember I said "53 major puzzles"? It's up to 72 now. There are 98 distinct spell components on the list.

Inform's parser isn't really optimized for carrying around 98 objects. I mean, you can't actually carry all 98 at once, because some of them are made from each other. But it's still way too many. Inform allows it, but I suspect the parsing will bog down on slower machines -- like phones.

But then, why should the player have to do all that inventory management at all? Expect a lot of attention to shortcuts and automatic object-fetching. "You run over to Herbarium and pick some rosemary..."

Anyhow, the next step will be typing all of these puzzles and components into PlotEx, to make sure I haven't completely broken the plot. (I'm sure the first thing I'll discover is that PlotEx isn't optimized for 98 objects either, and then there will be some more optimization. Whee!)

After that? My usual IF implementation strategy is "start with the first room, work forward until done." That is absolutely not going to work here. What will I do instead? Stay tuned...

A couple of other IF-related links from the past month:

The Bundle in a Box charity promotion is offering seven Windows adventure games in a pay-what-you-choose bundle. This includes six graphical adventures (by Jonas Kyratzes, Wadjet Eye Games, and Size Five Games) and one text game: Peter Nepstad's 1893: A World's Fair Mystery. Proceeds support indie developers and charitable causes.

Is it time for a text game revival? (Gamasutra article by Leigh Alexander.) Runs through several sorts of text-based games, from Infocom's heyday to modern e-literature, the Kickstarter revival of many old fan favorites, Emily Short's new project at Linden Labs, and so on. Includes the splash banner for Hadean Lands, so I'm in favor.

Interactive Fiction Communities: From Preservation through Promotion and Beyond (Article by Nick Montfort and Emily Short.) Introduction to IF (which I'm sure you don't need) but also a history of the genre and the community, in some detail. Worth reading if you haven't been immersed in the stuff for the past few decades.

Posted in Zarfplan | Tagged , , , , , | 5 Comments

It is the (mostly technical) progress report

I commented on Monday that I would get an update posted "in a couple of days". That wasn't procrastination; I wanted to be able to say I'd hit an interesting milestone before I headed off to a week of GDC. Didn't happen! Sorry. So, here's the somewhat-less-than-a-mile marker of progress I've got.

First, the game: the game is progressing. That is all I have to say about it. (Yes, there will be more detailed reports before the "It's done" report. But not right now.)

First and a half: Let's assume that if I had a release date to announce, I'd announce it, okay? (I wish I didn't have to explain that every time.)

But here is what I can say, because this is the open-source part: I have made great progress this month on the technical end of the project. That is to say, the iOS port of the IF interpreter.

I started writing this a full year ago, and I got the basics of an IF interface working: the status window, the story window, text input, scrolling. But I put it aside in the spring -- I wanted to get Secret Hideout and Meanwhile out the door. Now that HL is in progress, I decided to make sure the interface was up to snuff.

Turns out I made some mistakes back then; it was, after all, nearly my first iOS project. (Alas, poor KLD.) So the past couple of weeks have been spent ripping out inadequate code and hammering on it. If you follow my twitter feed, you'll have gotten some hints of this. Text scrolling is no longer stupid. The "more" flag works. The threading model is no longer a disaster waiting to happen. Also, I have a nice preferences menu for fonts and colors.

The biggest chunk of work remaining is to save and restore properly. The IF system that I'm using goes back to Infocom's design, which saved and restored the game only when the player typed "save" and "restore". There was no notion of the modern app world, which barely acknowledges that programs start and stop at all -- an app is expected to have your data ready the moment you look at it. This is possible in IF (iOS Frotz does it), but I've never integrated the feature into my own IF toolset. That'll be the big job for after GDC.

Anyhow, here's an interpreter snapshot, running my 2004 game The Dreamhold. Not fancy, but think ebook reader -- you want the UI to get out of the way of the text, not to distract from it. It still needs some icon work, mind you, and the menus are ugly. Not done yet; but greatly improved.

(IF mavens will note that The Dreamhold is a Z-code game, whereas Hadean Lands will be Glulx. True! The interpreter you see here is based on Fizmo, a Z-code interpreter. But nearly all of the interface code will be shared with the iOS Glulx app. The text windows, input, scrolling, menus, and so on are exactly the same.)

Now, this interpreter will certainly be finished before the game. (Sorry!) My plan is to release The Dreamhold as a free iOS app. I'm aiming to do that in early April, although that's not a firm date. I want to get the interpreter out there, both for real-life testing and for some eyeballs (in the "never heard of IF but what's this free app?" camp).

After that? Well, once the interpreter is done, it will be easy for me to release the rest of my existing IF catalog. They might be free apps, or I might charge a few dollars. Of course these games are available for free now, in iOS Frotz! So I'm not going to put the screws on. Maybe I'll add a little bonus content. You know the drill. Not life-changing work, but if it makes some money, it'll aid the cause.

Furthermore, anybody will be able to release an IF game using the same interpreter. Everything I've got is posted on my Github page. (The IF interface library is iosglk; the interpreters are iosfizmo and iosglulxe. Yes, iosglulxe is a couple of weeks behind.)

And Hadean Lands will follow, eventually, on a date to be announced.

Posted in Zarfplan | Tagged , , , , , | Leave a comment