# Build-A-Sophie
[2026-04-26_sophie]

Modified: 2026-05-27 @ 23:41:16 (Wednesday)
txt

#project #code

Here's the link up front for what I'll be rambling about: Build-A-Sophie

## § The Roundabout Path ^

I always seem to arrive at a project in the most indirect way. If I set myself a creative task, I'll ponder and ponder and... nothing happens. There's no spark. Then, when I stop pondering, something out of the blue will inspire me in a way that is inevitably totally orthogonal to the thing I wanted to do in the first place. I'm not sure if that's just how creativity works or if it's just me, but in any case, I follow wherever Eris leads.

I was pondering imagemaps. Imagemaps are an old HTML thing where you can make parts of an image into links. (If you're old enough, you might remember a time when image-based web interfaces were really popular and really annoying. Nowadays, websites don't really use images for navigation, at least not to the same degree. People talk a lot about all the ways the internet has gotten worse, but it got way better in others, and this is one of them. Yeah, it's fun to look at the old Space Jam website, but that's because you're doing it voluntarily. You can spend as few minutes on it as you want, and when you get bored, you leave. If you've ever been in a hurry looking for information you needed and had to waste time deciphering what each cute little picture meant, you intuitively know that these are inferior user interfaces.)

I didn't have any particular use for an imagemap. I didn't have any great ideas for how to revolutionize the art form of imagemaps. I just thought, huh, those are kind of interesting. They've been with us since 1997 and they'll probably be with us until 2057. There's something charming about their simplicity: you can pretty much only define regions of the image as links. A plain old imagemap is even more user-unfriendly than most image-based websites, because you can't even tell where the links are unless you hover your mouse over them (or tab to them). While this makes it a frustrating user interface for serious pursuits, this is also basically the UI for countless point-and-click games, many of which are excellent.1 The mysterious, unpredictable nature of the interface can encourage exploration.

### § Enter: Puzzle Castle ^

I was doing all that pondering up yonder when I happened to view my Puzzle Castle book/tote bag. I think it's super cute and I carry it a lot. (It has a castle with a maze on it. Be jealous.) I have no idea where it came from. I somehow hit the trifecta on Puzzle Castle as a kid: the book, the game, and the tote bag. Since it's a children's book, the puzzles aren't exactly compelling, but I still love looking at the art. I just find the style endlessly charming.

Actually, all the books in the Puzzle _____ (Island, Planet, Town...) series I've seen are lovely. But as far as I know, Puzzle Castle is the only one that got a video game. And with that, the cute thing from my childhood ran face first into my pondering: maybe I could take some of those lovely sprites and make an imagemap of... something? (Why is my brain like this?)

(Do they still make video games out of children's books? Like besides Harry Potter?)

### § Oh Yeah, I Should Explain ^

It's like I Spy or Where's Waldo, basically. Actually, there's another incredibly dope game in this genre, I Spy: Spooky Mansion (1999).

### § This Game Fucking Rules, Okay ^

Puzzle Castle is basically a direct conversion from book form to video game form. Each level is a page from the book, faithfully recreated in extra-charming pixel art versions of the drawings. You can even turn the page with one of the giant arrows that are always in the corner if you want to replay a level or skip ahead. Hell yeah, reading!

But of course this is a video game, not an e-book, and the people who made Puzzle Castle understood their assignment. It's just like the book... but better! There's sound, for one thing, but that's not the main appeal. (The audio can get kind of annoying, honestly, if you're a kid and play it over and over.) What really takes it to the next level is all the animations. The opaque wall of potential mousing spots is a target-rich environment: anything that looks interesting can be clicked on, and then either you unlock part of the puzzle or... something goofy happens. (It blew my mind a little bit as a kid, like I was seeing a whole new dimension of the book. It's really cute.) There's no downside to clicking the wrong thing other than seeing the same animation again. You're either winning or being amused by the little animations.

The main character is named Sophie.2 She's a knight who's been sent to slay the dragon who's roaring in the castle's basement and scaring off banquet guests. After a long day of helping people find stuff, navigating a maze, and throwing buckets of literal shit on unwanted visitors (Sophie gives zero fucks), she finds the dragon. But he wasn't roaring, he was crying! He's jussa widdow baybay! Sophie cheers him up and saves the day, no murder needed. Isn't that nice? It's like Star Trek.

### § It Does Kick Ass, But... ^

Something that always bothered me about Puzzle Castle is that you can't dress up your character. (Well, you sort of can, in that you get certain items that include shoes and a helment, but you can't really "equip" them, they just come out once or twice in the story when they're needed.) Adding insult to injury, at least two of the puzzles are just you finding clothing for other people, and one of them is in this like, princess's bedroom with a big chest full of crowns and jewelry and stuff! Come on! Yeah, you can click on the crown and then it becomes a UFO and then the kid smashes it, and that is indeed Fucking Awesome. But I wanted to put it on! Why won't they let me Sophie dress up?

Admittedly, Sophie is already certified fresh and fully on fleek in her yellow polka-dot tights, spaceman boots, and plate armor. (Although I noticed the yellow polka-dots sometimes turn into green polka-dots. I don't think it works quite as well, but I added it as an option.) It's just the principle of the matter. Let us design our character! Let me make Sophie wear the UFO crown!

So that's what I decided to make, a little gift to my younger self: a character creator. Now Sophie can wear the crown! She can even have pink hair!

## § Deets ^

### § Imagemaps Schmimagemaps ^

Imagemaps are cool, but they're stubbornly resistant to CSS styling. Nothing I tried worked. Everything I came across about using them was actually about how to do fake imagemaps using JavaScript or SVGs or someshit. I regretfully parted with the pondered orb and zeroed in on the more fun goal: Make A Cute Thing With Puzzle Castle. I quickly decided to throw web design advice out the window and do everything with absolute pixel positioning. This is how Puzzle Castle works; it runs at 640x480 and nothing else. I settled on 300x300 for the full scene. This allows me to take chunks out of the background assets, which can't be used as-is because they have buttons and level guides and such.

I'm sure a million people have done this before, but I felt rather clever for alighting on this design pattern:

    <!-- input 0 -->
    <input type="radio" name="background" id="background-0">

    <!-- label and input 1 -->
    <label for="background-1">
    	<img src="bedroom.gif">
    </label>
    <input type="radio" name="background" id="background-1">

    <!-- label and input 2 -->
    <label for="background-2">
    	<img src="tower.gif">
    </label>
    <input type="radio" name="background" id="background-2" checked>

    <!-- label 0 -->
    <label for="background-0">
    	<img src="hill.gif">
    </label>

This simple, repetitive, easily generated HTML gets us most of the way there already, with just a couple CSS rules:

    /* hide the radio buttons, which are only really being used as a hack */
    input {
    	display: none;
    }
    /* hide labels (images) by default */
    label {
    	display: none;
    }
    /* show label immediately following currently selected option */
    input:checked + label {
    	display: inline;
    }

Putting it all together, we have a stack of images which advances to the next image when clicked and loops around when you get to the end:

- In the initial state, the last option (`<input>` 2) is checked.
- All labels are hidden by default. The `input:checked + label` rule means that only the label immediately following the checked option will be visible.
- Because we put the label for the first option (`<input>` 0) after the last option (`<input>` 2), when the last option is checked, it's really the first option that's visible --- or at least, the first option's label, which consists of an image.
- When you click on the visible label, `checked` rolls around to the first option; now, it's the second option (`<input>` 1) whose label is visible.

Hopefully that made sense to you. Email me if not.

Now we can cycle through images by clicking on them, using only CSS and HTML, compatible all the way back to at least Netscape 7.2 (2004), and it's easy enough to generate all the verbose and repetitive HTML rules with a shell script. But how do we design the thing? Where are we getting the images that we're stacking up with invisible radio buttons? That's the main event.

For this I turned to trusty old GIMP which I'm very comfortable with. I can just build up the doll in layers and use layer groups to organize the layers into components --- eg, all the hat options are layers in a "hat" layer group --- then export them, rerun my shell script, and refresh. GIMP is the development environment.

And... that's pretty much it. There isn't much to see here, code-wise. It's just stacking up and arranging gifs. Some of them need to be layered in a certain order, and you need to make sure all the items in a layer group have an identical canvas. Then you just line them up in CSS. I wrote a little readme, for what it's worth.

### § That Was Fun ^

And now it's basically done. After dumping in, touching up, and arranging the assets, I added a few fluorishes: the sword-and-shield mouse cursor and a favicon based on it; 10 minutes of music from the game; a postage stamp border inspired by one of the levels; background color options. I made sure to add the monster protection helmet, run-faster shoes, and everything from the princess's bedroom that could reasonably be pasted onto Sophie. I added new colors for hair, skin, tights, and skirt. I added non-clothing images you can put in the scene, mostly various animals. I think I would have really enjoyed this if I'd come across it as a kid. I actually have vague memories of trying to do something like this in MS Paint.

### § But It's Still Kinda Shit ^

The backgrounds were kind of rushed; I wanted this to be a one-day project. I'd like to redo them. Some of them don't line up right at all. And it's tricky, because your objects have to line up with all the possible backgrounds.

Really the fundamental limitation here is that everything is positioned beforehand, by me. The user can't drag stuff around however they please. They can have a dragon in one place, or nowhere. It would be difficult to work around this with CSS, but I've been pondering... you'd have to generate a fuckload more `<input>`s and `<label>`s, but you could add controls to nudge stuff around without any JavaScript.

There are other limitations, like the user can't set an arbitrary color for an item, it has to be chosen specifically beforehand. (I did find a way to add a color slider in pure CSS, but it isn't backwards compatible and only works in Chromium, so fuck that.) There's no screenshot feature built in; I would have been fine with a small snippet of JavaScript, but it seemed pretty involved and annoying, so I skipped it.

My simple --- dare I say elegant? --- solution for moving through the radio groups limits my ability to add more complex logic to the image selectors. Mostly this just means that I can't easily recolor any part of Sophie that moves (she has two poses), because then I'd have to select the color mask that fit the specific pose that was selected. It would be pretty easy with `:has()`, and it could still be done with `~` and IDs and whatnot, but it would be a pain.

I also think it's kind of a shame that I don't have any animations! These are the most compelling part of the game, but I'm only using still frames. There's nothing stopping me from using animated gifs, I'm just not sure how I'd approach putting them together with GIMP. The Batcher plugin might have an easy solution here, or I could do some more scripting.

Unfortunately, the tool I found for dumping the assets isn't fully compatible with Puzzle Castle so I'm missing some stuff I'd have liked to include. Still, I was of course delighted to find it and this project wouldn't have happened without it! That same developer is adding support for this game engine to ScummVM, and it worked almost perfectly when I tried it.

## § Conclusion ^

If nothing else, Sophie definitely cutens up my website. I like my site --- I think it's both functional and cute in its own way --- but I definitely get jealous of those beautiful pastel sites I come across on places like NeoCities. I don't usually do a project solely because it's nice, much less child-friendly; it was good to mix it up.

Messing with pixel art is always a calming activity, and getting to look at and remix someone else's art in the process is a big plus. I feel the same way about this as I do about Tarot cards. Any activity where you focus intently on the details of art that you like is good for you.

Still, the fact that it's copyrighted and I could hypothetically be forced to delete it takes a little bit of the wind out of my sails as far as developing it further. I might like to reuse this idea with some wholly original art sometime.

Email me if you, your kid, your aunt, or your roommate likes Puzzle Castle. I know you're out there, somewhere.

## § Footnotes ^

1. If you like this sort of game, I highly recommend the Samorost series. <-|

2. Aside: Oh how I love the name Sophie. It means "wisdom". I sometimes wish I'd named myself that. (I guess I still could? It felt a little narcissistic.) Before I landed on the paper doll thing I came dangerously close to making a twine about how the autogynephilia conspiracy theory not only denies our actual life experiences, it also is really creepy and implicitly sexualizes wholesome nice things. Like by saying "no you don't know your own feelings, it's all sex" they are telling me that I identified with Sophie as a kid for sex reasons even though I was a small child literally reading fucking picture books. Thankfully I had no solid ideas in this direction, just an inchoate rage about how that concept is embedded into a lot of transphobic narratives and it just won't die and... anyway, this result is way better. <-|

## § Backlinks ^

## § See Also ^