davidn: (Jam)
davidn ([personal profile] davidn) wrote2013-01-13 03:41 pm

The science of Hatogate

I nearly called this entry "Technical coonsiderations" before realizing that that would put my life just too far over the edge.

The last three evenings spent on Hatogate were a great opportunity to start up MMF again and do a quick project, after not touching it for the last while (hopefully it'll lead into me completing the Xbox versions of Special Agent and Running Free). And it was an interesting exercise in doing something I haven't done with it before - I've experimented in writing adventure games, but this one felt like it really needed a scripting language running behind the game to make it easy to program reactions to commands. So naturally, I modelled it after the only language remotely mad enough to contain anything Hatoful-related.

I wrote it in ZZT-OOP.

That is, I based the syntax heavily on the scripting language that ZZT uses, as it gave me something to aim towards (writing a language from scratch at the same time as writing something in that language is like trying to handwrite two different sentences with each hand simultaneously) - and being familiar with it made it readable to me at the same time as being easily parseable, based on commands denoted by # and then another couple of tokens per line. The language is heavily based on a GOTO philosophy with programs jumping about between labels all over the place, but for small scripts it does its job very well - and this game is greatly simplified by the way that there's only one location you can be doing anything in, and one object that you can interact with on the screen ever, so it would never get too tangled.

So I borrowed most of the vocabulary - when the player builds a command with a verb and object (or two objects for USE), the game looks in the script for a label matching that command, then starts there and runs through the program. If it doesn't find one, it tries again with the object name replaced with ANYTHING, as a fall-through backup for places where you just need the same response for a variety of things (like using anything on the paintbrush).

Labels are labelled with :, comments with ', commands with # (and # followed by an unrecognized command is assumed to be a jump to the label of the same name) and everything else is assumed to be text to display onscreen. Like most good ZZT scripts, things tend to start with #END, which in this case stops running a script and hands control back to the player. #GIVE and #TAKE form a pair of commands to add or remove an item from your inventory - #TAKE has an unfortunately counter-intuitive name because it sounds like you're taking and therefore gaining an item, but I chose to live with this rather than think up a synonym. Similarly, #SET and #CLEAR are used to turn flags on and off - these are named on/off switches that just act like inventory items that you can't see or interact with. Unlike in ZZT, of course, there is no hidden flag limit, flag name length limit, or risk of detonating the flag pile by innocently setting a flag twice.

Syntax for #IF was a little more involved, mostly due to my own choice - I could have lived with just one variant, but to make scripting slightly easier, I came up with four different varieties of it. #IF followed by two tokens will check the flag list for token 1 and go to the label matching token 2 if it's found. #IF with only one token after it will check the flag list as above, but will then run the next line if it's found, and skip over it if not. This is useful for situations where you just want to display one alternative line of text depending on whether the player's done something before (I could have implemented #ZAP... but consciously chose not to). For situations where you want to check a flag isn't on, I threw in an #IFNOT command rather than force myself to think backwards. Supporting just one command or line on an #IF is still rather limiting, but it works here - and led to things like #IFNOT PUDDINGTHROWN SKIPLIZARDPUDDING, which is among the most surreal lines of code I've ever written.

Of course, I also had to make up a couple of commands specific to this type of game - #SHOW changes the screen shown, and #SPRITE followed by a name and show/hide toggles the sprites overlaid on the location on and off. #ACHIEVE turns on an achievement and #ENDING stops the game. The classic #DIE is present, but only as a label that shows the death screen and calls #ENDGAME, which displays the death text and sets the game up to restart on the next click.

It turns out that it's quite easy to create a bad language by just making it up as you go along, and I found myself putting things in to work around my own parser quite often - :END was set up as a label as well as a command for convenience at first, because the original three-token #IF lines could only go to labels and not call commands directly - and even now, you can't jump directly to a label with multiple words and have to duplicate them (:PECKMILLET). There are also a couple of special cases handled by the game and not in the code - the counter for turns before Okosan appears and the death achievement are two of them - but overall it turned into quite a neat little experiment, and I'd be interested to try making another adventure up in the same language to see if it holds together.

In doing the interface, I also noticed something very interesting about Shadowgate - the screen is arranged so that all the buttons are on an 8x8 pixel grid. Presumably for ease of laying them out?

[identity profile] xaq.livejournal.com 2013-01-13 09:17 pm (UTC)(link)
I feel I owe you an apology for this.
kjorteo: Glitched screenshot from Pokémon Yellow, of Pikachu's portrait with scrambled graphics. (Pikachu: Glitch)

[personal profile] kjorteo 2013-01-13 10:48 pm (UTC)(link)
You don't understand. He had his choice of how he wanted to lay out his own made-up scripting language and he based it on ZZT-OOP. He owes us an apology for this.

(No, but seriously, that is actually a perfect choice for "what could possibly be mad enough to make a Hatoful game." God help us all if Moa ever finds the ZZT community.)
kjorteo: Portrait of the Cactus Wolf from Mother 3, smirking. (Cactus Wolf)

[personal profile] kjorteo 2013-01-13 11:49 pm (UTC)(link)
What, if the ZZT community finds Moa? I'm pretty sure the end result of that happening was that we rounded up you, Kaye, and Raven to help us do some voices for the video playthroughs.

[identity profile] xaq.livejournal.com 2013-01-14 12:45 am (UTC)(link)
...Oh yeah. Never mind, then.

[identity profile] ravenworks.livejournal.com 2013-01-13 11:05 pm (UTC)(link)
Have you never seen under the hood of an NES (or an SNES for that matter)? The system can only display a small number of sprites (and further limit of 8 per row), so most of the graphics are drawn via the map, which is a grid of 8x8 tiles that all move together. In theory you could certainly load a full-screen bitmap that's been cut into pieces 8x8 big, but that would use up most of your cartridge (besides being more complicated to set up) so generally, the same tile is used in more than one place on the grid, hence all the UI elements being a multiple of 8x8 (or at least a multiple of 8x8 apart from one another).

Interesting challenge, writing your own parser...! I was tempted to say that going out of your way to make something more like ZZT when it doesn't have to be is the definition of masochism, but... stripped of all the legendary workarounds that it usually requires, the language itself seems fine! (Though ":END #END :DIE #SHOW DEAD" does seem like the sort of program Murderbeaks would write....)
kjorteo: Fanart of Shuu from Hatoful Boyfriend in bird form, scowling at the camera and looking menacing. (Hatoful: Shuu)

[personal profile] kjorteo 2013-01-14 02:22 am (UTC)(link)
You know, I just realized ... this game easily sets an all-time record for Hatoful series deaths that don't involve Shuu.

[identity profile] xaq.livejournal.com 2013-01-14 02:34 am (UTC)(link)
...I don't know if I should be proud of that. o_O

[identity profile] terrana.livejournal.com 2013-01-14 06:15 pm (UTC)(link)
I can't help but feel that coding in ZZT-OOP should be accompanied by the sounds of ZZ Top.

[identity profile] xaq.livejournal.com 2013-01-14 06:34 pm (UTC)(link)
...Thanks, now I have an 8-bit rendition of "She's Got Legs" stuck in my head.

(That was not a sarcastic "thanks," BTW. This actually sounds pretty sweet!)