My ‘daily driver’ USB drive gave up the ghost recently, and after having secured a replacement1, it was time for the always-fun task of formatting. I could’ve left things as-is, but the stock partition was FAT32 with 32K block allocations. While not the end of the world, I was really hoping to set the new drive up with smaller block allocations. The previous drive was partitioned with 32K allocations, which wasn’t ideal given that I tend to keep a lot of small files around. To make a point, the largest of my blog posts is the colorful release of decolletage.vim at a whopping 12K. The directory for my blog (including all templates, server logs, boring behind-the-scenes stuff) is under 25MB, yet consumed over 90MB on the drive. This is a trivial, petty thing to be bothered by when dealing with today’s drive sizes, but it bugged me, and I was hoping to get smaller blocks on my next drive. I also wanted to stick with FAT32 as the 4GB file size limitation is meaningless to me, and exFAT just isn’t as widely supported. As far as I know, FUSE is still the only way to get exFAT support in Linux, and, well… ew. Here were my initial attempts:

Windows 10 Format Utility
Won’t do FAT32 on a 64GB drive.
CMD/DOS2 format Utility (under Windows 10)
Also won’t do FAT32 on a 64GB drive. Of course, before it gets around to yelling at you for that it yells at you for choosing too small of an allocation size. Though I think it let me get to 16K before saying no to FAT32.
This is a neat little utility that will allow you to format large FAT32 volumes under modern versions of Windows. It will also seamlessly make the drive bootable into FreeDOS if you’d like, which is a nice perk. The lowest allocation size it seems to support is 16K, which isn’t ideal but I might’ve stuck with it just to be done. However, when I tried this, it actually formatted it with 32K blocks anyway.
macOS Disk Utility
Didn’t seem to want to do a drive of that size in FAT32.
macOS diskutil
I’m pretty sure you can force a FAT32 drive this way, but nothing in the manpages indicated that there was any way to adjust the allocation size (nor what the default was).
Seemingly no way to set allocation size. GParted, particularly in its live USB stick incarnation, is an incredibly useful tool though.
GParted’s CLI pal. I started flipping through the manpages and realized that using it as a one-stop shop to handle partitioning and filesystem creation is discouraged, and didn’t get around to finding out whether or not adjusting allocation size was even a possibility. Didn’t seem worth it.

So, this was discouraging. I figured I’d try one last-ditch effort, fussing around with tools I haven’t touched for… likely a decade: fdisk and mkfs. parted was essentially asking me to do the same thing – start with it and finish off with mkfs, and that may have been a smoother, less arcane process. I mean, starting up fdisk greets you with

Command (m for help):

Because of course ’m’ means help. Not that there’s an ‘h’ command. Anyway. fdisk or parted just handles the partitioning bit, and I probably didn’t need to do that again since I had already reformatted the thing several times with unsatisfactory FAT32 partitions, but I opted to clear the thing out anyway. The juicy bit is using mkfs.fat, and explicitly specifying -F 32 to ensure FAT32 and -s 16 which was a lucky-ish guess, giving me 8K blocks. Even reading the manpage, it’s tricky figuring out how -s and -S interact – -S 4096 -s 1 left me with a broken filesystem, but ignoring -S and guessing at -s got me to a happy place.

It’s probably a good thing that disk partitioning and formatting utilities are becoming more streamlined, though I think the mainstream OSes pushing folks to exFAT for large removable media is bound to lead to trouble. I sure didn’t need to go through all of this trouble to set up a small allocation size; I would’ve been fine with how the thing came, or how Rufus formatted it. It’s likely for the best that things like that aren’t generally exposed to users. But it’s worth noting that if you do want to do something funky, the old tools are there and they work.

  1. The old stick was a Transcend JetFlash unit that died after about 2 years. I’ve replaced it with a Corsair Flash Voyager Vega. I cannot speak to the Vega’s longevity yet (obviously), but I can say that the physical design is superior in every way: the metal feels sturdier (the aluminum had deformed and been reshaped a few times on the Transcend), the metal is grippier, there’s an activity light, and the bit that sticks out is raised just enough more to make it easy to pull from the port. Oh, and it also fits the port properly. I’ve been happy with other Corsair products, hoping this proves to be a winner. ↩︎
  2. There’s also a PowerShell formatting command or module or whatever the heck you call the things that you type into PowerShell. But PowerShell is the closest thing I have to evidence that hell is real, so… thank u, next. ↩︎

Baba is Turing Complete (external)

Baba is You is a wonderful puzzle game that has been frustrating the heck out of me lately. Its primary conceit is that puzzles are solved by moving textual blocks around to form subject/predicate constructions that rewrite the rules of the puzzle. Matthew Rodriguez has, as explained in the external link above, implemented Rule 1101 in Baba is You, with a video of the automaton in action on his Twitter feed. Matthew Cook famously proved Rule 110 to be Turing complete, which means (given an infinite grid, blah blah) the grammar and mechanics that make for a puzzle in Baba is You also make for a Turing complete system.

Humorously, the first response on the Twitter post is along the lines of ‘can it play DOOM?’ which… Sure! A Turing machine can theoretically do all of the computations that DOOM makes! Ignoring how much processing power and RAM one would need for this (a convenient thing to ignore, but we’re talking hypotheticals here), folks always seem to jump right from Turing machine to something resembling a modern computer. The only thing on the table is computational ability, and at a bare minimum, one still needs a viable I/O interface in order to do anything beyond turning bits into other bits.

  1. Here’s an implementation of Rule 110 in CSS which both helps demonstrate the rules of 110 and shows Turing completeness in CSS. ↩︎

The avocado with legs

Avo is the first bit of media from British company Playdeo, whose lofty introduction describes the things they’re creating as ‘television you can touch’. A lot of the general buzz around Avo has described it as augmented reality with prerecorded video, which seems apt. Told over eight short episodes, Avo is a lightweight mystery that befalls the quirky scientist Billie and her sentient ambulatory avocado, Avo. The player controls Avo, walking the stubby-legged fruit around and picking things up while Billie explains the situation and tells you what she needs. At its core, it’s a typical adventure game mechanically – walk around, pick things up, bring them to a place. But it’s all done seamlessly in this fully video-based real setting.

“Seamless” is kind of a strong word, I suppose. While exploring, the video is simply short loops of, say, Billie working at her desk in the background. There are still cutscenes, but because you’re already in the world and bound to preset camera angles, they just kind of… happen in place. So despite there still being two distinct modes, they do blend together in a fairly seamless way. The story is cute and simple, there are fun nerdy jokes scattered throughout (I had a good chuckle at Billie’s large cardboard box labelled ‘Klein bottles with moebius strips inside’), and the core mechanic works well. Avo is enjoyable and potentially worthy of recommendation, albeit with some caveats.

For starters, the game requires you to agree to a privacy policy like… pretty much immediately. I definitely have issues with content (especially paid content) tracking me for marketing purposes, but unfortunately I am used to it. Actually having to accept a privacy policy before entering the game just (and this may be unwarranted) feels more ominous than usual. Perhaps requirements are tighter being based in the UK, but it feels extreme for such an airy game. I was going to play it regardless because I was curious about what Playdeo was doing with the format, but I would encourage folks to actually read through the thing and weigh the pros and cons.

The other weird thing to me is the matter of the beans. Beans are scattered throughout the game. They serve three purposes: they give you an idea of paths you’re supposed to explore, they make Avo move slightly faster for some reason, and they are also the in-game currency to buy the episodes. While I suppose you could simply replay each episode a ton of times and collect enough beans to get the next one, doing so would be wildly impractical. Episodes cost 1,000 beans, and there aren’t hundreds (much less a thousand) of beans scattered throughout any given level. Which makes sense, Playdeo wants you to actually spend money on the game. For this, I do not blame them, and I do not think the game is overpriced (the bean bundle at $6 will get you through the whole thing). I do think that forcing it into this free-to-play framework is just weird. Awkward.

Many negative reviews on the App Store are from folks who don’t want to pay and actually are going the bean-collection route. The alternative that they would prefer is lowering the cost of the episodes. I mentioned that I don’t think the game is overpriced. I do think that the complete undervaluation of mobile apps means that a great number of people will think it’s overpriced. Especially since it’s much more of a story than it is a game. I think these are challenges that Playdeo is going to need to overcome. First, either ditch free-to-play or come up with a far less clumsy approach to it. Second, make the content more of a game and less of a poking-the-television. Avo largely feels like a proof-of-concept. As proof-of-concepts go, however, it is an incredibly charming one. And I would still recommend it as an experience for folks who are comfortable with the data collection.

On Twine (and my first Twine project)

Twine is, by its own definition, “an open-source tool for telling interactive, nonlinear stories”. I, personally, would call it a templating language for HTML-based interactive fiction. I have finally gotten around to experimenting with it, and… I find it to be missing the mark in the way that many templating systems tend to, and the way that many ‘friendly’ languages tend to.

Before I dive into my struggles with Twine, I’d just like to drop a link to the result of this experiment: yum yum you are a bread, which I guess I’ll just call a bread simulator? I don’t know. It’s silly, it’s fun, it’s bread. Also, minor spoilers in the rest of the post.

My biggest problem with templating systems is that they tend to just replace work with other work. For everything that’s made simpler or more concise, some simple programmatic task is made awkward and verbose. They also tend to lack necessary programmatic structures, leading to even more verbose workarounds. Twine, for instance, has no way of creating one’s own functions. For yum yum you are a bread, I needed to check a bunch of things against a bunch of other things to properly construct the variable $you. For instance, if you start in the fridge, you are stale bread. If you make a cheese sandwich with stale bread, you are a stale cheese sandwich. Grilling/toasting removes the staleness. There are a bunch of rules that need to be run whenever an action is taken, and this would ideally be done via a function.

Since Twine does not have user-defined functions, my initial plan was to create a passage1 that displayed nothing, it just generated the $you variable and then went to the appropriate destination passage. This was a bad idea; among other things it breaks the back button. The best solution that I could find was to essentially do the same thing, but with the (display:) macro. This simply runs a passage and inserts the result into the current passage’s text. It is an incredibly clumsy workaround.

Much like an older interactive fiction darling, Inform, Twine’s issues go beyond templating and into that of ‘friendly’ programming languages. I’ve only dealt with a handful of ‘friendly’ languages, but they all have one thing in common: they’re incredibly unfriendly to programmers experienced in more typical languages. I know plenty of folks will say that this is, in fact, the point – these languages are so much more accessible to non-programmers! I don’t believe that’s true. One still has to learn the fundamentals of branching, conditionals, variable and string manipulation, and one still has to learn a specific syntax. And while this syntax may be sort-of-kind-of human-readable, it is by no means perfect and is now nothing like anything else. Take array addressing in Twine: it’s handled like $array's 3rd2. Verbosity and uniqueness aside, is that truly easier to grok than $array[3]?3

The lack of functions ties in perfectly to how ‘friendly’ languages struggle to teach programming concepts. A tutorial for any more traditional language would almost immediately introduce ways to reuse code. Without that concept even properly existing in Twine, a user is unlikely to even know what to search for. They may, in fact, resort to simply copying and pasting code over and over, unaware that the concept even exists. If they do figure out the (display:) trick, they’ve now learned a clumsy strategy that they’ll have to unlearn if they want to branch out into more traditional languages.

It’s actually hard to say how much of this to blame on Twine, and how much to blame on Harlowe. This is another issue, Twine itself is more of a framework, and there are a bunch of different ‘formats’ that one can use for projects. The default4 is Harlowe, and to get answers to questions, one must bounce back and forth between the Twine documentation and the Harlowe documentation. None of this is really documented well5, and it took me quite a while to figure out that in order to do basic things like setting variables, I didn’t have to actually load any additional code – Harlowe was there by default.

For all of its issues, Twine does a great job working within constraints. Final projects are just single HTML files with the CSS and engine script embedded – there’s a limit to how much of this you really want to stuff into a single page. I definitely prefer the hyperlinked HTML format for interactive fiction over Inform and its need for an external interpreter. And as much as Twine’s code quirks annoyed me, they’re nothing compared to the ‘friendly’ absurdity that is Inform. I’m glad the world of interactive fiction seems to be having a comeback, and I think tools like Twine and hypertext experiences like those it provides are largely responsible for that. I intend to try a few more short narratives with it, and hopefully will retain some of its odd syntax in my mind as it matures.

Below is my (display:) passage for generating the bread’s description. I think yum yum you are a bread is a cute, quirky thing, and I’d recommend you play through it one or two or three times before looking at this (spoilers).

(set: $you to "bread")
(if: $stat's 3rd > 0)[(set: $you to "cheese sandwich")(if: $stat's 5th is 1)[(set: $you to "grilled " + $you)]](else-if: $stat's 6th >0)[(set: $you to "toast")]
(if: $stat's 3rd is 4)[(set: $you to "duper-super extra cheeserrific " + $you)](else-if: $stat's 3rd > 1)[(set: $you to "extra cheesy " + $you)(if: $stat's 3rd is 3)[(set: $you to "extra " + $you)]]
(if: $stat's 6th is 0)[(if: $stat's 1st is 1)[(set: $you to "stale " + $you)]](else-if: $stat's 6th is 2)[(if:$stat's 5th is 1)[(set: $you to "golden brown " + $you)](else:)[(set: $you to "toasty " + $you)]](else-if: $stat's 6th is 3)[(set: $you to "burnt " + $you)]
(if: $stat's 2nd > 0)[(set: $you to "buttery " + $you)(if: $stat's 2nd > 1)[(set: $you to "very very " + $you)]]
(if: $stat's 7th is 1)[(set: $you to "bisected " + $you)](else-if: $stat's 7th is 2)[(set: $you to "quadrisected " + $you)]
(if: $stat's 8th is 1)[(set: $you to "chatty " +$you)]
(if: $stat's 10th > 0)[(set: $you to "already-been-chewed " + $you)]
(if: $stat's 4th > 0)[(set: $you to "wet " + $you)]
(if: $stat's 9th > 9)[(set: $you to "oh-so vain " + $you)]
(if: $you's 1st is "o" or $you's 1st is "a" or $you's 1st is "e")[(set:$a to "an")](else:)[(set:$a to "a")]
(if: $grueTime > 3)[(set: $you to (uppercase:$you))]

  1. ‘Passage’ is Twine’s term for any given branched page, essentially. ↩︎
  2. Also, it’s 1-indexed. Vom. ↩︎
  3. Makes it hard to change these after the fact as well. Can’t just increment or decrement a number, you have to potentially change a suffix. ↩︎
  4. I’m sure some will disagree, but to me, being the default makes Harlowe the canonical (or at least blessed) format. Who knows how well-maintained any of the non-default formats will be down the line. ↩︎
  5. I could’ve gone on and on in the post itself, but really wanted to address the core issues that seem to present themselves due to being template-based and ‘friendly’. I do think it’s worth mentioning that the documentation is… not great, either. It feels very incomplete to me, and I ended up finding most of the answers I needed elsewhere. ↩︎

Tetris 99

I rather enjoy Tetris. Tetris has changed a lot from the pre-Guideline games I grew up with. I’m glad the Guideline exists and has made for a largely consistent experience among recent Tetris titles. But I still haven’t adapted perfectly to, say, a world with T-spins after no such moves existing in my formative Tetris years. Over the years, more and more multiplayer Tetris games have been released as well, the strategies of which are completely antithetical to the way I play solo. To put it lightly, I have never been good at multiplayer Tetris – some of the stronger AIs in Puyo Puyo Tetris’s story mode even frustrate me.

So when Nintendo announced Tetris 99, a battle royale match between (guess how many) players, I was skeptical. Not that I thought the game would be bad1, but I definitely thought I’d be bad at it, which would simply make it… not super fun for me. But, due to there simply being so many players and a large degree of randomness in how much you’ll be targeted for attacks (additional bricks), simply being decent can keep you alive for a considerable portion of the round. I’ve only played a handful of games, maxing out at 9th place (and dropping out nearly immediately at 74th once!), but I’m really enjoying it so far. Something about seeing 49 other players’ teeny tiny Tetris screens on either side of the screen is quite engaging (and honestly a bit humorous).

You can, either manually or according to four rule sets, choose who of those 98 others you are targeting. The mechanisms for this are not made entirely clear – in fact, they aren’t really explained at all, you just kind of have to stumble across them and suss out how they work by name. Likewise, because the rounds are short (and, to an extent, shorter the worse you are at the game) it’s hard to get into a groove, and there isn’t really a mechanism for practicing. If one didn’t already have other Guideline-era Tetris games, and particularly games with a multiplayer experience, I feel like they’d be a bit sunk here. Those minor quibbles are the closest things that I have to real complaints about the game. I’m curious how they’ll monetize it. The mobile Tetris games from EA have additional soundtracks that can be unlocked w/ coins won in-game (or purchased). Perhaps Tetris 99 will end up with a bit of this, or additional skins. Perhaps it’s just an incentive for Switch Online. For now, save for needing a Switch Online account, it is completely free… and it is a blast.

  1. If nothing else it was being made by Arika, known for multiplayer arcade Tetris games as well as the Cardcaptor Sakura-themed Tetris for PS1. ↩︎