One More Branch #2

The following story act was created through my lovely app One More Branch (link for the repo), which is a platform for interactive branching storytelling. In the case of this story, I didn’t explore alternative branches: just picked among the offered choices whichever sounded better. The result is quite good.

If you’re a veteran of reading whatever nonsense I post on here, you may recognize the trio involved in this story; they’re the same idiots from my short story from years ago named Interspecies Misdemeanours.

New changes in the app: I’ve implemented a complex feature that forces the LLM to actually structure a story in three acts and 2-4 beats per act, based on the character concept, worldbuilding, and tone/genre provided. The code passes the current act/beat, along with what’s necessary to know about upcoming ones, to the LLM so that it can produce the next page. That keeps it on track. However, this is an app for branching storytelling that necessarily would allow one to go off the deep end, so I’ve also implemented the ability for the LLM to determine if a choice has deviated too much from the pre-planned structure, which would trigger a re-plan of the story from the last concluded act/beat onwards. I haven’t seen that in action yet because the current test story was quite on point.

Perhaps this is not obvious, but there was an issue with my instructions to the LLM regarding when it should decide to conclude a story beat. The first act’s introductory beat was about the trio exploring the strange place and establishing what kind of trouble they were in. Well, the app still considered them to be in the same beat deep into the pages, where they were in serious fucking trouble. I fixed the issue; from then onwards, it concluded the beats appropriately (by page 18, it has entered the second act), but this issue has colored what has happened in about half of these pages.


Page 1

The ruined brick building squats in the woods like a corpse nobody bothered to bury—three stories of broken windows and poison ivy, the kind of place adults tell you not to fuck around in, which is basically an engraved invitation. You are Sam, fifteen years old, and you’re standing at the tree line with Betty Krommer and Frank Haimer, watching Frank bounce on his heels like a kid who just discovered his parents’ porn stash.

“I’m telling you, it’s not just a basement,” Frank says for the third time, pushing his glasses up. His nose is already running. “It goes down, like, way down, and then it opens up into these rooms. Tiled rooms. With pools.”

“Pools,” Betty repeats flatly. She’s in her pink polka-dot dress, arms crossed, one eyebrow doing that thing that makes you feel like an idiot even when you’re right. “In a condemned factory.”

“I’m not making it up!” Frank’s voice cracks. He pulls out his camera, waves it like evidence. “I got pictures, but they came out all—the light’s weird down there, okay? You have to see it.”

You can feel the buzz already, that electric itch under your skin that says this is it, this is the thing that makes today matter. Frank’s been weird for three days—jumpy, secretive, smoking again even though he swore to his dad he quit. Whatever he found, it’s real enough to scare him, and that makes it real enough for you.

Betty’s watching you now, waiting to see which way you’ll jump. The sun’s getting low, painting everything orange. Frank’s already moving toward the building, his backpack bouncing.

“If this is another fossil thing,” Betty says, “I’m gonna kick both your asses.”

Page 2

“Hold up,” you say, catching Frank’s shirt before he can disappear into the building. “Pictures. Now. You’re not dragging us into some bullshit without proof.”

Frank stops, looks back at you like you just asked him to solve calculus. “I told you, they came out weird—”

“Then show us weird,” Betty cuts in. She’s moved closer, close enough you can smell her shampoo—something fruity that makes your brain short-circuit for half a second before you shove it down. “Come on, Haimer. If it’s real, the pictures’ll show something.”

Frank’s face does this thing, this trapped-animal flicker, but he digs into his backpack and pulls out a stack of Polaroids. His hands are shaking a little as he fans them out.

The first few are what you’d expect—darkness, the flash catching brick and rebar, Frank’s thumb over the lens on one. But then there’s a shot of stairs going down, and the light in it is wrong. Not dark, not bright, just… off. Like the flash hit something that reflected it back in a color that doesn’t have a name. The next one shows a doorway, and beyond it, tiles. Clean white tiles, the kind you’d see in a hospital or a pool, except they’re glowing faintly, and the perspective makes your eyes hurt if you stare too long.

“What the fuck,” Betty breathes. She’s leaning in, her shoulder touching yours, and you’re trying to focus on the pictures but your skin is doing that shivery thing where it’s aware of every point of contact.

The last picture is the worst. It’s a room—square, tiled floor to ceiling, with a pool of water in the center. Except the water isn’t reflecting anything. It’s black, perfectly black, and the edges of it seem to curve up slightly, like it’s defying gravity. Frank’s flash caught something else too: a doorway on the far side, and beyond it, another room. And another. The perspective stretches back like a hall of mirrors, except there are no mirrors.

“That’s not possible,” you say, but your voice sounds thin even to you.

“I know,” Frank says. He’s wiping his nose with his sleeve, his eyes huge behind his glasses. “I only went three rooms in. I got scared. But Sam—” He looks at you, and there’s something desperate in it, something that needs you to believe him. “It keeps going. I could hear echoes, like… like it’s massive down there.”

Betty’s breathing has gone a little raspy. She’s still staring at the pictures. “This is fake. This has to be fake.”

“It’s not fake!” Frank’s voice cracks again. “Why would I fake this? Why would I—”

“Because you’re Frank,” Betty snaps, but there’s no heat in it. She’s rattled. You can tell because she’s not making eye contact, and Betty always makes eye contact when she’s tearing into someone.

The sun’s lower now. Maybe twenty minutes of good light left. The building looms, all broken windows and shadows. Frank’s already moving toward it again, like he can’t help himself, like it’s pulling him.

“We don’t have to go all the way in,” he says. “Just… just to the first room. So you can see. So you know I’m not crazy.”

Page 3

“Alright,” you say, shoving the pictures back at Frank. “I’m in. But we’re not going in blind.”

You scan the ground, spot a broken chunk of brick near the foundation, and grab it. The edge is chalky, crumbles a little in your grip. “We mark the walls. Every turn, every room. That way if this place is as fucked up as it looks, we can follow the trail back.”

Frank’s face lights up like you just solved world hunger. “Yes. Yes, that’s—that’s actually smart, man.” He’s already moving toward the building, backpack bouncing. “I went three rooms in last time and I swear to God the echoes—”

“Wait.” Betty’s voice cuts through, sharp enough to stop both of you. She’s still staring at the Polaroid with the black pool, and when she looks up, her eyes are doing that thing where they’re too bright, like she’s forcing herself not to blink. “We tell someone. We leave a note or—or we tell my dad where we’re going, because if something happens—”

“Your dad’ll call the cops,” Frank says, and there’s this edge of panic in it. “My dad finds out I’m back here, I’m grounded until college. Minimum.”

“Then we leave a note somewhere,” Betty insists. “We’re not just disappearing into some—some fucking nightmare dimension without anyone knowing.”

The sun’s almost gone now. The factory’s a black cutout against the purple sky, and the trees are close enough that their shadows feel like they’re reaching. You can see the doorway Frank’s talking about, the one that leads down. It’s just darkness from here, but you keep thinking about that picture, that wrong light.

Frank’s already got his flashlight out. Betty’s got her arms crossed, waiting.

You’re holding a chunk of brick and the night’s coming fast.

Page 4

You don’t give Betty time to argue. Three strides and you’re past Frank, shouldering through the doorway into the factory’s gutted interior. The floor’s unstable—chunks of concrete and rebar poking through like broken teeth—but you keep moving, following the path Frank must’ve taken, and yeah, there it is: a hole in the floor near the back wall where the foundation’s collapsed inward, except it’s too regular, too deliberate, like something carved it open from below.

“Sam, wait—” Frank’s behind you, flashlight beam bouncing wild.

You drop through before you can think better of it. It’s only a six-foot drop, and you land in a crouch on tile. Actual tile. Clean white tile that shouldn’t exist under a ruined factory, glowing with that sick pale light Frank’s pictures showed. The air down here tastes wrong—sterile and metallic, like licking a battery.

Frank lands beside you with a grunt, immediately fumbling his camera up. “Holy shit, okay, okay—” The flash pops, blindingly bright in the enclosed space, and for a second the walls look curved when they’re definitely flat.

Betty drops through last, landing harder than she meant to, and you hear it immediately—that hitch in her breath, the whistle starting. She’s already fishing for her inhaler, but her eyes are huge, scanning the room.

It’s exactly like the Polaroid. Ten feet by ten feet, perfectly square, tiles unmarred and impossibly clean. Two doorways: one ahead, one to the right. No door frames, just rectangular absences in the walls. The light’s coming from everywhere and nowhere, like the tiles themselves are luminous.

“Three days I’ve been thinking about this,” Frank whispers, and his voice multiplies, echoes layering over each other from the doorways, from deeper in. “Three days and I thought maybe I imagined how wrong it felt, but—”

“Mark it,” Betty says, voice tight. She’s got the inhaler to her mouth, takes a hit. “Mark the fucking wall, Sam.”

You’ve still got the brick chunk. The tile’s so clean it feels like vandalism to touch it.

Page 5

You press the brick’s chalky edge against the nearest wall tile, dragging it hard enough to leave a mark. Except there’s no mark. No scratch. Not even dust. The brick crumbles against the surface like you’re trying to write on diamond, leaving a gray smear that fades as you watch—actually fades, the tile absorbing it or rejecting it or something, until the surface is pristine again.

“Jesus Christ,” you breathe, and your voice comes back at you from both doorways, layered and wrong. You try again, harder, grinding the brick corner into the tile until your knuckles scrape. The brick disintegrates into powder. The tile remains perfect.

Frank’s got his camera up, flash popping. “Did you see that? Did you fucking see—” He’s practically vibrating. “It’s like, like self-healing, or the material’s rejecting contamination, or—”

“Or we’re in some fucked-up alien bathroom,” Betty cuts in. She’s moved to the doorway on the right, peering through without crossing the threshold. “Because that’s not tile. Tile doesn’t do that.”

You look down at what’s left of your brick—barely half its original size, crumbled to dust in your palm. Your path-marking plan just became a lot more complicated.

The echoes are still going. Not from your voices anymore, but from deeper in. A sound like water dripping, except it’s coming from multiple directions at once, and when you focus on it, it might not be water at all. It might be footsteps. Or something dragging.

Frank’s already moving toward the forward doorway, camera raised like a talisman. “We should go straight first. That’s what I did before. Straight, then right, then right again, and that’s where the big room with the pool is—”

“The pool with the black water that doesn’t reflect,” Betty says flatly. She’s still at the right doorway, and her breathing’s evening out, but her hand’s white-knuckled around her inhaler. “The one in the picture that made me want to fucking puke.”

The forward doorway yawns open, perfectly rectangular, leading to another tiled corridor. The right doorway shows a glimpse of another room, but from this angle you can’t see how big it is or what’s in it. And behind you, the hole you dropped through is still there—you can see the factory’s broken ceiling, daylight filtering through gaps.

Still an exit. For now.

Page 6

You step toward Betty and the right doorway, leaving Frank frozen mid-gesture with his camera. “Fuck the pool,” you say. “Let’s see what’s behind door number two.”

“Sam—” Frank’s voice pitches up, but you’re already moving, and Betty shifts to make room as you join her at the threshold.

The room beyond is smaller. Maybe eight feet square instead of ten. Same white tiles, same sourceless glow, but the geometry’s wrong in a way that makes your eyes water. The far wall looks closer than it should be, but when you focus on it, it seems to recede, like you’re looking through the wrong end of a telescope. There’s no doorway on the opposite side. Just walls. A dead end.

Except there’s something in the corner.

A pile of fabric. Dark, crumpled, definitely not tile. Your heart kicks into overdrive because it looks like clothes, like someone took off their jacket and jeans and just left them there, except the pile’s too flat, too deflated, like—

“Is that a fucking shirt?” Betty whispers, and her hand finds your forearm, fingers digging in.

Frank crowds in behind you both, camera raised. The flash goes off and the room inverts for a second—black tiles, white fabric—then snaps back. “Holy shit,” Frank breathes. “Holy shit, someone was here. Someone else found this place.”

The clothes don’t move. They’re just lying there, bundled in the corner like laundry. A jacket. Jeans. Something that might be a sneaker, tipped on its side. No body. No bones. Just the clothes, arranged in a way that suggests a person was wearing them when they… what? Disappeared? Evaporated?

The echoes from deeper in the space suddenly sound a lot less like water dripping.

“We should check the pockets,” you hear yourself say, because your brain’s decided this is an adventure, not a horror show, and adventurers loot the environment. “Could be ID. Could tell us who—”

“Could be fucking cursed,” Betty hisses. Her breathing’s getting raspy again. “Could be, I don’t know, a trap, or contaminated, or—”

Frank’s already stepping past you both, camera dangling from his neck, reaching for the pile. “It’s evidence,” he says, like that settles it. “We need to document—”

That’s when you notice the second detail: the tiles under the clothes are darker. Not discolored, exactly, but shadowed, like the fabric’s casting a stain into the floor itself. And the stain’s spreading, creeping outward in a slow, organic way that makes your stomach flip.

Frank’s hand is six inches from the jacket.

Page 7

“Go ahead,” you tell Frank, stepping back to give him room. “I’ll watch the floor.”

Frank doesn’t need to be told twice. He’s already moving, camera swinging from its neck strap as he crouches beside the pile. His hand hesitates for just a second—you see his fingers twitch—then he grabs the jacket sleeve and lifts.

The fabric comes up stiff, like it’s been starched, and there’s a wet sound as it peels away from the tile. Not wet like water. Wet like something organic, something that’s been sitting too long. Frank makes a noise in his throat, but he doesn’t drop it. He’s shaking it out, checking the pockets with the methodical focus of someone who’s decided facts are safer than fear.

“Nothing,” he mutters. “No wallet, no phone, no—wait.” He digs deeper into the inner pocket and pulls out something small and white. A receipt. He squints at it, pushes his glasses up. “Gas station. Route 47. Date’s… shit, that’s from last year.”

You’re barely listening because the stain is moving.

It’s subtle at first—just a darkening at the edges, like the tile’s absorbing something it shouldn’t. But then it spreads, a slow creep of shadow that fans out from where the clothes were lying. Not black like the pool water. Darker than that. A color that doesn’t have a name, that makes your eyes try to slide away from it.

The stain reaches the wall and stops. Just stops, like it hit an invisible barrier. The tiles around it look… wrong. Puckered. Warped. Like skin around a burn.

“Frank,” Betty says, and her voice is thin, stretched. “Frank, put it back.”

“I’m not done—” Frank’s got the jeans now, shaking them out, and something falls from the pocket. A keychain. Car keys. Toyota logo. They hit the tile with a sharp clink that echoes wrong, bouncing off walls that shouldn’t exist.

The stain pulses.

It’s not spreading anymore, but it’s moving, rippling like water disturbed by something underneath. You can see the tile beneath it warping, buckling, and there’s a sound now—low, grinding, like stone on stone—and the temperature drops so fast you can see your breath.

“PUT IT BACK,” Betty shouts, and she’s backing up, hand fumbling for her inhaler.

Frank drops the jeans like they’re on fire. The fabric hits the stain and the rippling stops. Just stops. The grinding cuts off mid-note. The temperature normalizes so abruptly you almost stumble.

The three of you stand there, frozen, staring at the pile of clothes that’s now half-on, half-off the stain. Frank’s breathing hard, his glasses fogged. Betty’s got her inhaler to her lips, taking a hit. Your hand’s wrapped so tight around the brick chunk your knuckles are white.

“What the fuck was that?” Frank whispers.

The clothes don’t answer. Neither does the stain. But you can hear it now—that rhythmic sound from deeper in the space. Closer than before. Definitely closer. And it’s not footsteps.

It’s dragging. Something heavy, being dragged across tile.

Page 8

“Fuck that,” you snap, grabbing Frank’s shoulder before he can back away.” Get photos. All of it. The stain, the clothes, the keys—everything.”

Frank’s head whips toward you, eyes wide behind his glasses.” Are you insane? We need to—”

“We need evidence,” you cut him off, your voice harder than you mean it to be.” Nobody’s gonna believe this shit without pictures. You said it yourself—document everything.”

For a second, Frank just stares at you. Then something shifts in his face—that manic gleam he gets when his brain catches up to his curiosity. He nods once, jerky, and raises the camera.

The flash goes off.

The stain recoils.

It’s not a metaphor. The dark spreading across the tile actually pulls back, contracting like a living thing flinching from light. The warped tiles around it seem to flatten, smoothing out for just a moment before the darkness surges back, angrier, reaching farther than before.

“Holy shit,” Frank breathes, and he’s already winding the film, already lining up another shot.” Did you see that? It reacted to the—”

The second flash stops him mid-sentence.

This time, the stain doesn’t just recoil. It erupts.

Not physically—there’s no spray, no explosion—but the temperature drops so fast your breath mists in front of your face. The tiles beneath the clothes crack with a sound like breaking ice, spiderwebbing outward in jagged lines that glow faintly at the edges. And the dragging sound—the one you’ve been hearing from deeper in the space—stops.

Complete silence.

“Frank,” Betty says, and her voice is barely a whisper.” Frank, we need to go. Now.”

But Frank’s already taking another picture, the camera whirring as it spits out the Polaroid. He’s shaking, you can see it in the way the camera trembles, but he’s not stopping. He crouches lower, getting the angle on the cracked tiles, the keys, the stain that’s now pulsing in rhythm with something you can’t hear but can feel in your chest.

“One more,” he mutters.” Just one more and I got it all—”

Something moves in the forward doorway.

You don’t see it clearly—just a shift in the shadows, a shape that’s too tall and too wrong to be human but too deliberate to be anything else. It doesn’t step into the room. It just… stands there. Watching.

Frank’s finger freezes on the shutter button.

Betty’s inhaler hisses as she takes a desperate pull, her breathing ragged and wet.

The shape in the doorway doesn’t move. But you can feel its attention, heavy and cold, pressing against your skin like a physical weight.

Page 9

You throw yourself sideways, putting your body between the doorway and Frank’s hunched form. Your voice comes out louder than you intended, cracking on the edges.

“Back the fuck off!”

The shape doesn’t move. Doesn’t speak. It just stands there in the doorway, impossibly tall, and the longer you stare at it the less sense it makes. The proportions are wrong—arms too long, head tilted at an angle that makes your stomach lurch. It’s not quite blocking the light from the next room, but it’s not quite letting it through either, like it’s made of something that doesn’t interact with illumination the way solid things should.

Behind you, Frank’s camera whirs again. The flash goes off.

The shape flinches.

Not back. Sideways. It jerks to the left, and for a split second you see it clearly—a person, maybe, or something wearing a person’s outline like a coat that doesn’t fit right. Then it’s in the doorway again, and you can’t remember if it moved or if your eyes just lied to you about where it was.

“Sam,” Betty hisses, and her hand closes around your wrist, nails digging in. “Sam, it’s not alone.”

You hear it then. Not from the doorway ahead. From behind.

From the entrance you came through.

Footsteps. Slow. Deliberate. The sound of something heavy being dragged.

“Oh god,” Frank whispers, and you can hear the Polaroids fluttering in his shaking hands. “Oh god, oh god, there’s two of them.”

The shape in the forward doorway tilts its head the other direction. Watching. Waiting.

The dragging sound from behind gets louder.

You’re trapped in a dead-end room with a stain that cracks tiles and two things that shouldn’t exist closing in from both directions. The only other doorway is the one to your right—the one Betty was examining before Frank found the clothes. You don’t know where it leads. You don’t know if it leads anywhere.

But the dragging sound is getting closer, and the shape ahead hasn’t blinked, and Frank is hyperventilating so hard his glasses are fogging up.

Page 10

You don’t think. You just move.

Your hand shoots out and grabs Frank’s shirt collar, yanking him sideways. Betty’s already moving—she anticipated you, or maybe she just has better survival instincts—and the three of you stumble through the right doorway in a tangle of limbs and panic.

The room beyond is longer. Rectangular. The tiles here are the same sterile white, but the light is dimmer, like it’s coming from farther away or through something thick. There are three doorways: one directly ahead at the far end, one to the left about halfway down, and one to the right near where you’re standing.

Behind you, the dragging sound stops.

You spin around, chest heaving, and see the entrance you just came through. The dead-end room is visible beyond it—the stain, the cracked tiles, the abandoned clothes. But the shape that was in the forward doorway is gone. Just gone. And the dragging sound from the entrance has gone silent.

“Where—” Frank starts, then cuts himself off with a wet cough.

Betty’s breathing is ragged and wet, that familiar wheeze building in her chest. She fumbles for her inhaler with shaking hands, and you can see the pink fabric of her dress is dark with sweat at the collar.

“They’re not following,” you say, but your voice sounds wrong. Too loud. The acoustics in this room are different—your words don’t echo, they just sort of die in the air like the space is swallowing them.

Frank wipes his nose on his sleeve, his glasses still fogged. “That doesn’t make sense. Why would they—”

“I don’t give a shit why,” Betty interrupts, her voice tight and high between pulls on her inhaler. “I don’t give a shit about any of this. We need to get out. Now.”

You look at the three doorways. Ahead. Left. Right. No way to know which one leads back to the entrance, or if any of them do. The room you came from had two doorways—forward and right. You took the right. But now you’re in a room with three exits, and the geometry doesn’t add up.

“Frank,” you say, “where did you go when you were here before? Did you see this room?”

He shakes his head, still trying to catch his breath. “No. No, I went straight. Forward through the first room, forward through the second. This is—we’re off my route. I don’t know this room.”

A sound echoes from somewhere. Not the dragging. Something else. A wet, sliding noise, like something moving through water. It’s impossible to tell which direction it’s coming from—the acoustics make it seem like it’s everywhere and nowhere at once.

Betty’s nails dig into your forearm again. “Sam. We need to move. Right now.”

Page 11

You point at the left doorway. “That one. If we went right before, left might take us back.”

“That’s not how geometry works,” Frank mutters, but he’s already moving, his flashlight beam cutting ahead into the next room.

Betty doesn’t argue. She just follows, one hand pressed to her chest like she’s trying to manually slow her breathing.

The doorway opens into another square room—smaller than the first, maybe eight by eight. The tiles here have a faint yellowish tinge, like old porcelain, and there’s only one other exit: straight ahead. No choices. Just forward.

“Shit,” you breathe.

Frank’s already at the far doorway, peering through. “Another room. Same size. One door.”

You move up beside him and look. He’s right. It’s like a hallway made of identical cells, each one feeding into the next. The yellowish tint gets stronger the deeper you look, and the light is dimmer, more amber.

“This is wrong,” Betty says behind you. Her voice is flat, drained of its usual bite. “We should’ve hit the entrance by now. We weren’t that far in.”

Frank pushes his glasses up. “Maybe the rooms… rearrange? Or maybe we’re moving parallel to the entrance instead of toward it?”

“Or maybe we’re fucked,” Betty snaps.

You’re about to respond when you hear it: a sound from back the way you came. Not dragging this time. Not footsteps. It’s more like… breathing. Slow, wet, deliberant. Coming from the rectangular room you just left.

Frank hears it too. His flashlight beam jerks back toward the entrance, and for a second you see something in the doorway—a dark mass, low to the ground, too many angles to make sense of—and then it’s gone, sliding sideways out of the light.

“Go,” you say. “Go, go, go.”

The three of you stumble through the next doorway, into the next yellow-tinged cell, and the one after that. Three rooms deep now, maybe four, and the amber light is getting thick, almost soupy. The air tastes stale and metallic.

Frank stops suddenly, his hand shooting out to grab your arm. “Wait. Listen.”

You freeze. At first you don’t hear anything except Betty’s wheezing and your own pulse hammering in your ears. Then you catch it: the breathing sound is still behind you, but now there’s something else. Ahead. A rhythmic tapping, like fingernails on tile, coming from deeper in the chain of rooms.

“We’re boxed in,” Frank whispers.

Page 12

“Keep moving,” you say, and your voice comes out steadier than you feel. “Whatever’s making that sound, it’s gotta be smaller than those tall fuckers behind us.”

Frank makes a sound that’s half-laugh, half-sob. “That’s your plan? Fight something because it might be smaller?”

“You got a better one?”

He doesn’t answer. Just pushes forward into the next room, and the next, his flashlight beam bouncing off yellow tiles that are definitely darker now, almost mustard-colored. The tapping is getting louder, more distinct. Not rhythmic like footsteps. More erratic. Like someone drumming their fingers on a desk, except the fingers are made of bone.

Betty’s wheezing behind you, each breath a wet rasp that makes your chest hurt in sympathy. She’s trying to keep up, but her legs are shaking.

“Sam,” she gasps. “I can’t—”

“You can,” you say, not looking back. If you look back you’ll see how bad she’s getting, and if you see it you’ll stop, and if you stop you’re all dead. “Just a little further.”

The tapping stops.

Frank freezes mid-step, his flashlight fixed on the doorway ahead. You can see into the next room now, and it’s different. Bigger. The tiles are almost brown, and there’s something in the center—a shape, maybe three feet tall, hunched over like it’s examining the floor.

It has too many joints. That’s the first thing your brain registers. Arms that bend in three places, fingers that curl backward, a head that sits at an angle no neck should allow. It’s not moving. Just… waiting.

“Back,” Frank whispers. “Back, back, back—”

But then you hear the dragging sound from behind you again, closer now, and the wet breathing, and you realize you’re out of rooms to retreat into.

The thing in the brown room tilts its head. Slowly. Like it’s listening.

Frank’s hand is shaking so bad his flashlight beam is strobing. Betty’s pulled out her inhaler but she’s not using it, just clutching it like a talisman.

You’re still holding the brick chunk. It’s pathetic—half-destroyed, barely bigger than your fist—but it’s all you’ve got.

The thing in the brown room makes a sound. Not tapping. Not breathing. Something between a click and a purr, like a cat with a mouthful of gravel.

Page 13

“Frank,” you hiss. “Flash it. Now.”

“What?”

“Like you did before—hit it with the flash!”

Frank’s hands are shaking so bad he nearly drops the camera. The thing in the brown room hasn’t moved, but its head is tilting further, further, the angle getting worse, and you can hear a sound coming from it now—a clicking, purring thing that makes your teeth ache.

You step sideways, putting yourself between Betty and the doorway. She’s pressed against your back, her breathing a wet rattle that’s getting quieter, which is somehow worse than when it was loud.

“Frank—”

The flash goes off.

The brown room explodes into white light and the thing screeches—a sound like metal scraping concrete—and launches itself backward, arms folding in ways that hurt to look at, fingers splaying wide. It hits the far wall and scrambles sideways, up the wall, across the ceiling, moving like a spider made of coat hangers.

But it doesn’t run. It just repositions. Crouches on the ceiling, head rotating to track you, and that clicking-purring starts again, faster now, angrier.

“Oh fuck,” Frank breathes. “Oh fuck, it’s still—”

Behind you, the dragging sound stops. Just stops. The silence is worse than the noise. You risk a glance back and there’s nothing in the doorway you came through, but you can feel something there, just out of sight, waiting.

The small thing on the ceiling makes a new sound. A chirp. High-pitched and questioning.

And from somewhere deeper in the brown rooms, something chirps back.

Betty’s fingers dig into your shirt. “Sam,” she whispers, and her voice is so thin you can barely hear it. “I can’t breathe right.”

The thing on the ceiling clicks three times, then goes silent. Watching.

Frank’s camera whirs as it spits out another Polaroid. His hands have stopped shaking, which is somehow worse—like he’s gone past fear into some kind of documentary autopilot. “There’s a doorway,” he says, flat and mechanical. “Right side of the room. Behind it.”

You look. He’s right. There’s another exit on the far side of the brown room, past where the thing is crouched. You’d have to go under it. Or make it move.

Behind you, something scrapes against tile. Once. Deliberately.

Page 14

You plant your feet and raise your voice, trying to make it sound steady even though your heart is hammering so hard Betty can probably feel it through your back.

“We’re not—we’re people, okay? We’re just kids. We didn’t mean to come here, we’re just trying to leave.”

The thing on the ceiling goes very still. Its head stops rotating mid-turn, locked at that impossible angle, and the clicking-purring cuts off like someone flipped a switch.

For one insane second you think it worked. That maybe there’s something in there that understands, that remembers what people are, that might let you pass.

Then it chirps again. Three sharp notes.

And the entire brown room answers.

They come out of the walls. Out of doorways you didn’t see, out of shadows that shouldn’t exist in this flat tile lighting. Four, five, six of them, unfolding from corners and ceiling edges, all clicking and purring and chirping in a rhythm that sounds horribly like laughter.

“Oh Jesus,” Frank says, and the camera flashes again on pure reflex.

The nearest one screeches and flinches, but the others surge forward, filling the doorway, their too-many-jointed arms reaching, fingers curling backward in ways that make your stomach flip.

Behind you, something massive scrapes across tile. The dragging sound, close now. So close you can smell it—something chemical and wrong, like burnt plastic and meat.

Betty makes a sound that’s barely a wheeze. Her inhaler rattles—she’s trying to use it but her hands are shaking too bad. The small click of the trigger, once, twice, and you can hear her trying to breathe in but nothing’s working right.

“Betty—” You spin, grabbing her shoulders, and her face is pale, lips starting to go blue at the edges. Her eyes are huge and terrified and she’s trying to say something but no air is moving.

The things in the brown room are clicking faster, coordinating, and Frank is backing up into you both, the camera clutched to his chest like a shield that won’t do shit.

“The doorway,” Frank says, and his voice cracks. “Right side, we have to—”

The massive shape appears in the entrance behind you. You catch it in your peripheral vision—tall, wrong, the same kind of thing that watched you in the dead-end room but closer now, so much closer, and it’s not stopping.

Betty’s knees buckle. You catch her weight, her inhaler clattering to the tile, and the small things chirp in unison like they’ve won something.

Page 15

You drop to your knees and grab the inhaler from where it’s rolled against Betty’s leg. Her hands are clawing at her throat, nails scraping her own skin, and when you shove the inhaler toward her mouth she tries to grab it but her fingers won’t close right.

“Frank, fucking flash them!” you scream, and wrap one arm around Betty’s shoulders to hold her steady while you jam the inhaler between her blue lips. “Breathe in, Betty, come on—”

The camera goes off behind you. The brown room fills with white light and the things screech, that horrible metallic sound that makes your teeth ache, but they don’t retreat. You can hear them repositioning, the skitter of too-many joints on tile, the clicking-purring rising to a fever pitch.

You press the trigger. Once. Betty’s chest hitches but nothing goes in—her throat is locked up too tight. You can feel her heartbeat against your arm, way too fast, fluttering like a trapped bird.

“Again!” Frank yells, and the flash goes off again. The dragging sound behind you stops. Just stops. Which is somehow worse than hearing it move.

You tilt Betty’s head back the way you saw in some health class video, trying to open her airway, and press the trigger again. This time you feel her chest expand slightly, a tiny desperate sip of air and medicine, and she makes a sound like a broken vacuum cleaner trying to start.

“It’s working, come on Betty, one more—”

Something touches your shoulder.

Not a hand. The texture is wrong—smooth and cold and slightly wet, like a salamander’s skin, and when you jerk away and look up there’s one of the small things right there, its head tilted at that sickening angle, and its mouth is opening.

Not opening. Unfolding. Like a flower made of teeth.

Frank screams and the camera flashes so close the light burns purple ghosts into your vision. The thing flinches backward but two more are coming through the doorway you need to exit through, and the massive shape is finally moving in the corridor behind you—you can hear it now, a wet sliding sound accompanied by breathing that sounds like hydraulics failing.

Betty gasps. Actually gasps. Air moving in, ragged and thin but moving, and her hands close around your wrist with surprising strength.

“Can’t—” she wheezes. “Can’t stay—”

The exit doorway has two of them in it now, blocking the way. The things from the brown room are advancing from the other direction. Frank’s flashlight is shaking so badly the beam looks like a strobe light, and you can see the massive shape now at the edge of the light—something that takes up the entire corridor width, something that glistens.

Betty takes another hitching breath and tries to stand, using you as leverage. Her legs are shaking but she’s up, and the inhaler is still clutched in her fist.

Frank backs into both of you, the camera raised like a weapon. “Sam, what do we do, what the fuck do we do—”

Page 16

You lunge sideways and rip Frank’s flashlight out of his hand—he yelps but doesn’t fight you—and swing the beam straight into the faces of the two things blocking the exit.

They screech and recoil, arms folding over where their eyes should be, and for one beautiful second the doorway is clear.

“GO!” you scream, hauling Betty up by her armpits. She’s gasping now, each breath a wet ragged sound, but she’s breathing and that’s all that matters. Frank grabs her other arm and you’re moving, half-dragging her between you, her feet barely touching the tile.

The things recover fast. You hear them scrambling back into position, the skitter-click of joints bending wrong, but you’re already at the doorway and Betty’s through and Frank’s through and you’re diving after them—

Something grabs your ankle.

Not a hand. Too many fingers. They wrap around your leg like a fist made of cold wet worms and you go down hard, chin cracking against tile, flashlight skittering away across the floor. The thing is pulling you backward, back toward the brown room where that massive shape is still dragging itself closer, and you can smell it now, that burnt-plastic-and-meat reek that makes your stomach heave.

“SAM!” Frank’s voice cracks high and terrified.

You twist and see it—the small thing has your leg, its flower-mouth unfolding wider, and there are others coming through the doorway behind it, three or four of them, moving in that horrible spider-crawl.

Betty is on her hands and knees in this new room, inhaler clutched in one shaking fist, trying to breathe. Frank is frozen in the doorway, camera raised but not firing, his face white as paper.

The thing pulls harder. Your fingers scrape across tile, finding no purchase, and you’re sliding backward inch by inch. In the brown room behind, the massive entity’s breathing fills the space like a broken furnace, getting louder, getting closer.

Your hand closes around something. The brick chunk. Still in your pocket, jabbing into your hip.

You could smash it into the thing’s face—if it even has a face. You could scream for Frank to flash them all at once, hope it stuns them long enough to break free. Or you could do something really fucking stupid and kick backward with your free leg, try to connect with something vital, bet everything on one shot.

Page 17

“FRANK! FLASH THEM! FLASH ALL OF THEM!”

Your voice rips out raw and desperate, and thank Christ, Frank actually moves. His thumb jams down on the button and the camera erupts with light—once, twice, three times in rapid succession, the whine of the flash recharging between bursts filling the room like a dying alarm.

The things screech. All of them at once, a chorus of metallic shrieking that makes your teeth ache, and the grip on your ankle loosens just enough—you yank your leg free and scramble forward on hands and knees, tile cold and smooth under your palms, the brick chunk still clutched in one white-knuckled fist.

Behind you the entities are repositioning, you can hear the skitter-click of their joints, but they’re slower now, disoriented, and you’re through the doorway and Frank is grabbing your shirt and hauling you sideways.

This room is different. Bigger. The tiles here are a pale sickly green, like hospital walls left to mold, and there are four doorways—no, five—spaced unevenly around the walls. The air tastes worse here, metallic and sharp, like licking a battery.

Betty is still on her knees, inhaler pressed to her mouth, her whole body shaking with the effort of breathing. Her pigtails have come half-undone and her dress is soaked through with sweat.

“We gotta move,” Frank gasps, and he’s right, because the clicking sounds are getting organized again, coordinated, and you can hear that wet hydraulic breathing from the massive thing getting closer to the brown room you just escaped.

But Betty can’t run. Not like this. And you don’t know which doorway leads out versus deeper, and Frank’s flashlight is still back there on the floor where you dropped it, and you only have the brick and Frank’s camera has maybe two flashes left before the battery dies.

One of the doorways—the one to your far right—has a draft coming through it. You can feel it on your face, cool and carrying a smell that’s almost like outside air, like dirt and leaves and rain.

Another doorway, straight ahead, shows a room beyond that’s brighter, the tiles there almost white again, like the first room you landed in.

The doorway to your left shows only darkness. No glow at all. Just black.

One More Branch #1

Two nights ago I endured the kind of insomnia that forces you to roll around in bed under a barrage of intrusive thoughts, but also receiving some compelling ideas from the girl in the basement. And a new idea excited me immediately. In case you’ve been following my blog, which likely only a couple of people worldwide do at the most, you may have read recent posts about a project about evolving board games. Well, I’m growing out of it already. Don’t know what to tell you. Thankfully we’re in the era of Codex and Claude Code, and you can program whole new apps in a couple of days, which is what I’ve done for the new one.

In summary: as a kid I loved those “Choose Your Own Adventure” books. I devoured them. I resent the fact that I lent one to a guy I ended up hating, and I never saw that book again; it was my favorite of those kinds of books, too (it was about a guy, a knight or something, exploring a vast subterranean complex of caves. I don’t remember much of it other than he fought monsters and at the end there was a gorilla. I never found out the title of that book again). We’re in the era of large language models that can write better than 99% of writers, so why not task it with producing such interactive branching stories in a structured manner?

Well, it’s done. Here’s the repository: https://github.com/joeloverbeck/one-more-branch . You give the system a character concept, some worldbuilding details, the tone/genre, and it creates the first page of narrative, with 2-4 meaningful, distinct choices at the end. You click one, and the corresponding page gets generated. If you restart, you can navigate already explored branches without generating anything, but any new branches will be generated and stored. I have let the AI decide when branches end. Haven’t seen that yet.

There’s currently an issue: I store information about the characters involved, the canon facts about them, globally. And I found out that the information can bleed from branch to branch when I didn’t mean it; for example, in one branch a character gave the other a map or something to that effect, and it was registered globally, which would have contaminated new branches. Such issues are the kinds that you routinely fix while working on an app. It will involve distinguishing between global canon facts about characters and state changes involving characters.

Anyway, I present you some branches of a test narrative. You can click the choices that have been explored, and they will lead you to the appropriate header, like in one of those “Choose Your Own Adventure” books but automatically. Other branches haven’t been explored so they aren’t clickable.


Page 1

The Drowned Serpent tavern reeks of canal-water and desperation, which means the crowd is perfect. You are Vespera Nightwhisper—at least, that’s the name you’re wearing tonight—and you’ve been working this room for two hours, your hybrid lute-viol singing melodies that make dock workers weep into their ale while their coin purses grow lighter. Your whiskers twitch slightly as you modulate your voice into something breathy and inviting, finishing a ballad about star-crossed lovers. The amber-gold eye catches firelight while the ice-blue one tracks the room’s exits. Your tail sways in time with the final chord. The applause comes with the satisfying clink of copper and silver hitting your open instrument case. But it’s all… fine. Competent. Safe. The music isn’t reaching that place you need it to reach—that breakthrough you can taste but can’t fucking touch.

You’re prowling through the crowd afterward, ears decorated with silver charms catching the lamplight, when a hooded figure intercepts you near the bar. Beaver-folk, you note instantly—the broad flat tail is unmistakable beneath the cloak. His breathing is shallow, panicked. Prey behavior.

“You’re the bard, mmh?” His voice cracks. “The one who takes… contracts?”

Your whiskers perk forward with interest. He slides a leather pouch across the bar—it clinks heavily. Gold, not copper.

“My business partner, Greaves. He’s been… changed. Cursed item from a dredger haul. The Ash-Seal company says it’ll take two weeks to dispatch someone, but he’s—” The beaver-folk’s voice drops to a whisper. “—he’s killing people at night. Doesn’t remember it come morning. I need someone who can track him, stop him, and keep it quiet before the constables get involved.” His eyes are desperate, searching your face. “They say you don’t flinch.”

You can already hear it—the chord progression that would capture this moment. Minor key, building tension, the way his breath hitches like a string about to snap. Part of you is cataloging his tells: the way he won’t meet your heterochromatic gaze, how his fingers drum against the bar—guilt rhythm, not just fear. He knows something he’s not saying. The other part of you feels that familiar clarity starting to crystallize. Danger. Blood. The prospect of something that matters. Your hand rests casually on your theatrical rapier’s pommel.

What do you do?


Page 2

The beaver-folk’s whiskers flatten against his muzzle. “You want to see it? The thing that’s turning my partner into—” He cuts himself off, glances around the tavern. Too many ears. “Not here. Come.”

You follow him out into Brinewick’s fog-thick night, your tail swishing with anticipation. The canals reflect lamplight in fractured gold as he leads you through three twisting streets to a cramped warehouse office that smells of timber and wet fur. He bolts the door behind you.

From a locked chest beneath his desk, he produces a wooden box wrapped in chains. Your whiskers twitch involuntarily—even through the wood and iron, you can feel something wrong radiating from it. Not sound, exactly. More like the absence of sound, a void where music should be.

“Greaves pulled this from a canal dredge two weeks ago,” the beaver-folk says, his paws shaking as he sets it on the desk. “Thought it was just an old mirror. Looked into it once. Just once. Now every night when the moon rises, he… changes. Becomes something else. Hunts.”

He unwraps the chains with the care of someone handling a venomous snake. Inside the box: a hand mirror, its silver surface tarnished black except for veins of sickly green that pulse with their own light. Your heterochromatic eyes widen—the amber one burns, the blue one goes cold. The reflection it shows isn’t the room. It’s something moving. Writhing.

Your fingers hover over your lute-viol’s case. Part of your brain is already cataloging this—the way the green light pulses in 6/8 time, the subsonic hum that makes your teeth ache. But another part, the part that stays sharp when blood starts flowing, is calculating. This isn’t just a curse. This is a weapon. And the beaver-folk’s breathing has changed—faster now, excited beneath the fear.

“The music of the curse,” you murmur, and your voice has gone flat, dangerous. The cute affect has vanished entirely. “Interesting phrase for someone who just needs his partner stopped, mmh?”

The beaver-folk’s tail twitches. “I don’t—”

“You’re lying.” Your whiskers are arrow-straight, reading every microexpression. “Your breathing shifted when you opened that box. Not fear. Anticipation. So let’s try this again, and this time don’t waste my fucking time: what do you actually want?”

What do you do?


Page 3

The beaver-folk’s pupils dilate. His breathing shifts—shallow now, caught. You watch his paws clench and unclench against the desk edge, claws scraping wood. He’s calculating whether to lie, and you can see the exact moment he realizes you’ll know.

“Smart cat,” he mutters, and his voice drops the desperate merchant routine entirely. What’s left is sharper. Hungrier. “Fine. Yes. Greaves needs to be stopped—that part’s true. But the mirror…” His eyes flick to the pulsing green light, and there’s reverence there. Want. “Do you know what Ash-Seal pays for functional cursed items? Not the broken ones they have to dispose of. The ones that still work.”

Your tail goes still. “You want to sell it.”

“I want to profit from two weeks of my business partner trying to eat dock workers, yes.” He leans forward, and now you can smell it—not just fear, but excitement, the musk of someone who’s found an angle. “But here’s the problem. Ash-Seal won’t pay premium unless they can verify it’s functional and contained. Which means I need someone who can demonstrate control. Someone who can look into it, trigger the transformation, and prove they can handle what comes after.”

The mirror pulses. Six beats. Rest. Six beats. Your mind is already turning it into a waltz in a minor key, something that would sound beautiful if it weren’t so wrong.

“You want me to become the monster,” you say, and your voice is flat as a blade. “To prove it works.”

“I want you to show you can survive it.” His whiskers twitch—he’s lying about something, but not about the core truth. “You’re a bard who fights. You’ve got discipline, control. If anyone can look into that thing and come back unchanged—or at least, come back in control—it’s someone like you. Do that, help me negotiate with Ash-Seal, and I’ll split the sale. Sixty-forty.”

Your amber eye burns. Your blue eye stays ice-cold. Part of you—the part that chases the crystalline clarity that comes after violence—is already wondering what kind of music would pour out of you if you let that curse in. What you could compose if you survived it. The rest of you knows this is the kind of choice that draws a line you can’t uncross.

The beaver-folk mistakes your silence for negotiation. “Seventy-thirty. Final offer. And I’ll throw in information about where Greaves hunts tonight. You can stop him, play hero for the constables, build your reputation. Then we do the demonstration for Ash-Seal tomorrow. Everyone wins.”

Your fingers drift to your rapier’s pommel. The mirror keeps pulsing. Six beats. Rest. Six beats. Like a heartbeat. Like a song you haven’t written yet.


Page 4

You lean in close enough that your whiskers nearly brush his cheek, letting your tail curl around his wrist where it rests on the bar. The beaver-folk goes rigid—prey instinct warring with something else. Good.

“Mmh, they say a lot of things about me,” you purr, tracing one claw along the edge of the coin pouch without opening it. “But ‘cheap’ isn’t one of them, sweetness.” Your heterochromatic eyes lock onto his—amber-gold and ice-blue pinning him in place. You can read him like sheet music: the way his breath catches, pupils dilating despite the fear-scent rolling off him. Desperate, yes. But there’s something else underneath. Anticipation?

“Triple,” you say, voice dropping into that register that makes people forget how to negotiate. “Your partner’s killing people, you need discretion, and you need someone who won’t run screaming when things get messy.” You let your fingers walk up his forearm. “That’s specialty work, darling. Premium rates.”

He swallows hard. “I—I don’t have that kind of—”

“Mrow, don’t lie to me.” Your whiskers flatten slightly, just enough to shift from seductive to dangerous. “You’re not coming to a tavern bard with a cursed-item problem because you’re poor. You’re coming because you need this handled quietly, and quiet costs.” You tilt your head, studying the micro-expressions dancing across his face. “So either you pay what I’m worth, or I walk, and you explain to the constables why you waited two weeks while bodies piled up.”

The beaver-folk’s breathing changes—faster, shallower. But he’s not breaking. He’s… calculating. Your ears swivel forward.

“Seventy-thirty,” he says suddenly.

“What?”

“The mirror—the cursed item. It’s functional. Controllable, in a sense.” His voice gains confidence, which sets your whiskers twitching. “Ash-Seal pays premium for items they can study and demonstrate. We contain it, prove what it does, I sell it to them. Seventy-thirty split. You get thirty percent.”

Your mind catalogs this instantly: He’s not trying to destroy the curse. He’s trying to profit from it. And he needs you to—what? Demonstrate it? Contain Greaves while he still transforms? The chord progression in your head shifts to something darker, more complex.

“You want me to help you sell the thing that’s turning your partner into a killer.” You don’t phrase it as a question. “While he’s still useful as proof of concept.”

The beaver-folk meets your eyes. “Greaves doesn’t remember anyway. And the money would set us both up for years. I know where he hunts. I know the pattern. We just need… documentation. Containment. Someone who can handle the dangerous part.”

Your tail lashes once. The dangerous part. The part where you’d be close to something curse-twisted and violent, where blood would likely spill, where that crystalline clarity might finally arrive and the music you’ve been chasing would bloom perfect and terrible in your skull.

Your whiskers are already trembling with something that isn’t quite fear.

What do you do?


Page 5

You pull back like he’s venomous, tail snapping away from his wrist. The predatory warmth drains from your expression, leaving something colder, clearer. “No.”

The beaver-folk blinks. “What?”

“No.” You stand, smoothing your tail fur with one hand—the nervous gesture betraying what your voice doesn’t. “I’ve crossed lines, sweetness. Plenty of them. But this?” Your whiskers flatten completely. “You’re not trying to stop your partner. You’re trying to profit off him. Off the people he’s killed.” The words taste wrong in your mouth, and that wrongness is what decides it. “That’s too fucking twisted even for me.”

You can see the calculation die in his eyes, replaced by panic. “Wait—you can’t—”

“Watch me.” You’re already moving, slinging your lute case over your shoulder. The rapier’s weight at your hip feels necessary, grounding. Your mind is racing, converting the situation into rhythm—6/8 time, the mirror’s pulse, the pattern of a trap you almost walked into. The melody forming is discordant, unfinished, and it makes your chest tight.

The night air hits you as you push through the tavern door. Brinewick’s canal-smell wraps around you—brine and rot and fish. The constabulary station is three blocks west, near the merchant district. You know because you’ve made a point of knowing where law enforcement operates in every city you work.

Your ears swivel back. The beaver-folk hasn’t followed. Smart. But now you’re walking toward the constables with a story about cursed mirrors and nighttime killings, and you’re a traveling bard with a reputation for not flinching at violence. They might listen. They might arrest you for wasting their time. They might already know about the bodies and wonder why you know details.

Your whiskers twitch. The smart play would’ve been taking the contract, documenting everything, then selling both the mirror and the evidence. Control the narrative. Instead you’re about to hand your leverage to people who don’t owe you anything.

But the alternative was becoming part of something that made your skin crawl, and apparently you still have limits. Who knew?

The constabulary station’s lamplight glows ahead. You can see two constables outside—a tall human woman and a tortoise-folk man, both armed. This is the moment. Once you walk up those steps and start talking, you’re committed. No take-backs, no negotiations, no performance that lets you slip away clean.

Unless you don’t. Unless you find Greaves yourself first, before the beaver-folk can move the mirror or disappear. Unless you handle this your way—not for profit, but because someone should, and the constables are slow and the bodies are real.


Page 6

You slide onto the bar stool beside him, close enough that your tail brushes his leg—calculated intimacy, the kind that makes people spill secrets. “I’m listening, mrow,” you purr, letting your voice do that thing where it sounds like an invitation and a threat at the same time. Your whiskers angle forward, reading the micro-tensions in his posture. “But I need details. When did this start? What does he become? Where does he hunt?” Your clawed finger taps the bar in rhythm—already your mind is converting his panic into tempo.

The beaver-folk glances around nervously before leaning closer. His breath smells like fear and wood shavings. “Two weeks ago. Greaves bought a dredger haul—mostly junk, rusted tools, broken pottery. But there was a mirror.” His voice drops further. “Ornate thing, silver frame with strange engravings. He looked into it once, just once, and that night…” He swallows hard. “He came back covered in blood. Didn’t remember leaving the warehouse. Said he’d slept through the night.”

“And the pattern?” you press, your ice-blue eye fixed on his face while your amber one tracks the tavern’s crowd. Your tail coils around the stool leg—anchoring yourself while your mind races ahead to chord structures, to the way terror sounds when you pluck it just right.

“Every night since. Always between midnight and dawn. He goes to the canal district—the old warehouse rows near Southwick Bridge. Three bodies so far that I know of.” The beaver-folk’s paws tremble as he slides a folded paper across to you. “This is where we store the timber. The mirror’s there, locked in my office. I… I haven’t destroyed it because—” He hesitates, and something flickers across his face. Not just fear. Anticipation? “—because Ash-Seal pays premium prices for functional cursed items. If you can prove it works, prove it can be controlled or contained, we split the sale. Seventy-thirty, your favor.”

There it is. The real melody beneath the desperate harmony. He wants to profit from this. Your whiskers twitch—not quite a lie, but not quite honest either. “Show me the mirror first,” you say, your voice dropping the sultry performance into something flat and surgical. “Then tell me everything about how Greaves hunts. Does he track by scent? By sound? Does he remember his victims come morning, or is it complete blackout?” Your claws drum against the bar—six-eight time, you note distantly. Everything is music if you listen right.

The beaver-folk nods rapidly. “Complete blackout. He wakes up in his bed, no memory of leaving. But there’s always blood under his claws, dirt on his feet. And the mirror—” His voice catches. “—it glows. Sickly green light, pulsing like a heartbeat when the sun goes down.”

Your breath catches. Not from fear—from recognition. That’s the rhythm you’ve been chasing. The one that arrives right after violence, right after the kill, when everything becomes crystalline and clear. You can already hear it: the pulse of cursed light translating into bass notes, the transformation into a crescendo, the hunt into a bridge that builds and builds until—

You realize you’ve been silent too long. The beaver-folk is staring at you, uncertainty creeping into his expression. Your whiskers flatten slightly as you force yourself back into the moment. “The warehouse,” you say simply. “Take me there. I want to see this mirror before I commit to anything.”

What do you do?


Page 7

You lean back slightly, letting your heterochromatic gaze bore into him—amber and ice reading every microexpression. Your whiskers flatten just enough to signal you’re not buying the full story. “Seventy-thirty sounds lovely, mrow,” you say, voice silk over razors, “but I don’t commit to hunting cursed problems without seeing what I’m actually dealing with.” Your tail uncurls from the stool, tip flicking in that particular pattern that means you’re calculating angles. “Tonight. I watch the transformation from a safe distance. See what your partner becomes, how the curse actually works, whether this is a containment job or a mercy killing.”

The beaver-folk’s whiskers twitch—there, that tells you he was hoping you’d just take his word for it. “That’s… reasonable,” he admits slowly. “But if Greaves catches your scent while he’s changed, I don’t know what he’ll do. The transformation makes him… wrong. Predator-wrong. His eyes go black, his teeth sharpen, and he moves like something that learned to hunt before it learned to think.”

“I can handle myself,” you say flatly, though your mind is already composing—6/8 rhythm, that green pulse he mentioned, the way terror sounds different when the monster used to be someone you knew. “Where exactly should I position myself? Rooftop? Alley? I need sightlines and escape routes.”

He pulls out a second scrap of paper, sketching quick lines with a charcoal nub. “The warehouse district near Southwick Bridge. There’s a three-story grain storage building with a flat roof—here.” He marks an X. “You’ll see the timber yard from there, and the route Greaves takes toward the old canals. He leaves around midnight, returns just before dawn.” His paw hesitates over the sketch. “The mirror stays in my office. It glows when the curse activates—sickly green light, pulses like a heartbeat. You’ll know when it starts.”

Your ears swivel forward. That rhythm again. Your fingers itch for your lute’s strings. “And you’ll be where during all this?”

“Safe in my quarters, door barred, pretending I don’t hear him leave.” The beaver-folk’s voice cracks slightly. “Same as every night for two weeks.”

You study him a moment longer—the way his shoulders hunch, the slight tremor in his webbed fingers, the calculating gleam buried under the fear. He’s not just desperate. He’s invested. This curse is worth money to him, and you’re the instrument he’s hoping will make it profitable. Fine. You can work with that. You’ve been worse things than someone’s profitable tool.

“Midnight, then,” you say, sliding off the stool with feline grace. “I’ll be on that roof. And beaver?” You lean close enough that your whiskers nearly brush his cheek. “If you’re lying about any detail that gets me killed, I’ll haunt you so thoroughly you’ll beg for whatever Greaves does to his victims. Understood, mrow?”

He nods quickly, and you catch the genuine fear there—good. You take the sketched map and the warehouse address, tucking both into your hidden pockets. The night air outside will be cold, and you have hours to kill before midnight. Your lute case feels heavy on your shoulder, and part of you wants to find a quiet corner to play, to chase that 6/8 rhythm that’s been circling your mind since he mentioned the mirror’s pulse. But another part—the part that keeps you breathing in dangerous cities—knows you should prepare. Scout the location in daylight. Check your medical kit. Maybe sharpen your rapier. Or you could visit the constabulary, see what they know about the bodies. Information is leverage, and leverage is survival.

The Drowned Serpent’s door swings shut behind you as you step into Brinewick’s lamp-lit streets, the canal-smell thick in the air, your mind already three moves ahead.

Life update (02/02/2026)

These last four days I’ve felt the darkness gathering at the edges of my being. Losing any intention of going outside. Lying in bed and hoping I wouldn’t get to wake up and endure any more.

A couple of hours ago I lay down, put on my VR headset, and tried to concentrate on watching a movie from the seventies (concretely Serpico). The other day was The Conversation. For whatever reason, I’ve always felt a pull toward the 1970s, even before Alicia Western. A feeling that somehow I belong to that time. Experiencing things from that era fills me with a nostalgia that hollows out my chest. The strong notion that I should have been there, should still be there. Another one of the many things in my life I haven’t understood about myself.

I’ve always felt uncomfortable among human beings, likely due to autism, and that doesn’t change much when I have to see people on a screen. To focus on a movie I have to get over a base ickiness, a discomfort. So much of what I see on a screen feels alien to me: how people interact with each other, how they react to things. Watching stuff from the 1970s adds a layer on top of that; it’s already been fifty fucking years, but it feels like it a whole different era. As if everyone from back then had been dead for a long, long time. And there are the absurd pains, like a moment when Al Pacino as this Serpico dude walks down the street and touches a girl’s head, and I wonder what happened to that person’s life. Her next fifty years of enduring on this earth. Is she alive or is she dead.

I haven’t been able to watch any of the movies I’ve tried recently for more than twenty minutes at a time or so. Maybe it’s depression-induced anhedonia. Maybe I’ve genuinely been losing my ability to enjoy things. Novels haven’t said much to me in a long time, and the only ones I cared for in the last few years or so were McCarthy’s works, someone whose soul was tragically anchored in the seventies. I’m no longer at an age in which I can lose myself in videogames; I know there are great stories waiting for me in stuff like Red Dead Redemption 2, but whenever I reinstall it, I play it once for like four hours, and then I can’t bring myself to launch it again.

I was born in Spain but I’ve never felt like I belong here. Technically I was born in the Basque Country region, but I’m not a separatist. I don’t connect with the locals. Things are so fucking bad here; we’re easily the most retarded country in Europe, that in no time will get even worse than the UK, France and Belgium when it comes to ethnic cleansing of the indigenous people. I have no hope for Spaniards, as I’ve had to work with your average one; all of them hooked to the state-sponsored media. They smugly spout the socialist garbage they’ve been fed as if they couldn’t conceive anyone thinking differently. They don’t even see it as politics; for them, that’s the natural state of things, and if you disagree, you’re a freak. The few times I’ve made the mistake of giving them an inch, hearing their thoughts beyond work-related matters reminded me again why I shouldn’t have.

In general, I feel like I’ve been dead for a long time and my body is taking decades to figure it out. Whenever that actually comes, I don’t think I’ll miss or feel any particular attachment to the stuff that at the time seemed so important to me: the stories I’ve written, the music I’ve loved, other projects of mine. It served its purpose while they happened, then they ceased being mine. I’m around because I’m around, then at some point I’ll cease to be and that’ll be that.

In a month or so I’ll have to start looking for a job. I don’t believe I’ll get hired as a forty-year-old programmer in this new era in which AI can do the work of a whole office of programmers. I’ll probably have to look for protected job as someone with a 52% disability. And I won’t do it for any other reason than the money. It seems there are people out there that get other benefits from the job: interacting with people, dealing with responsibilities… I want none of that. Working has always been a hell I had to get through merely to receive money at the end of the month.

Last time I spoke with my mother she asked me about work. I told her again that I don’t care about any of it. These “normal” people always try to deceive you, maybe because they deceive themselves, by going on about how jobs are more than things you endure because of money. And maybe it is for some people, but not for me. The last time they called me for a job in IT, which ended up falling through, I suffered a panic attack, my whole body telling me that I couldn’t return to that hell that put me thrice in the ER for heart and brain issues. I can’t allow myself to suffer the levels of stress I endured. No amount of money is worth that.

I guess that’s all I had to say at the moment. Not sure why I felt like saying any of it, who do I think is reading any of this, or why they would care about it.

LudoForge #4

Now that the evolutionary process to grow game definitions is progressing at a steady pace in my app, named LudoForge, I fed the architectural docs to ChatGPT so that it would write a good explanation on how it works. It may be interesting to those curious about how complex systems can grow organically through an evolutionary algorithm that mimics biological evolution.


Teaching a computer to invent tabletop games (and occasionally rediscover the classics)

If you squint, evolving game designs is a lot like evolving creatures: you start with a messy ecosystem of “mostly viable” little organisms, you test which ones can survive in their environment, you keep the best survivors—but you also keep a diverse set of survivors so the whole population doesn’t collapse into one boring species.

In our system, the “organisms” are game definitions written in a small, strict game DSL (a structured way to describe rules: players, state variables, actions, effects, win/lose conditions, turn order, and so on). Each candidate game definition is wrapped in a genome: basically an ID plus the full definition.

From there, the evolutionary loop repeats: seed → simulate → score → place into niches → mutate elites → repeat.

1) Seeding: where the first games come from

Evolution needs a starting population. We can generate seeds automatically, or import them from disk, or mix both approaches. The important bit isn’t “are the seeds good?”—it’s “are they valid and diverse enough to start exploring?”

So seeds must pass two kinds of checks before they’re even allowed into the ecosystem:

  • Schema validation: does the JSON structure match the DSL’s required shape?
  • Semantic validation: does it make sense as a playable ruleset (no broken references, impossible requirements, etc.)?

And there’s a third, subtle filter: when we place games into “niches” (more on that below), seeds that land only in junk bins like unknown/under/over are rejected during seed generation, because they don’t help us cover the design space.

Think of this as: we don’t just want “a bunch of seeds,” we want seeds scattered across different climates so evolution has many directions to run in.

2) Playtesting at machine speed: simulation as the “environment”

A human can’t playtest 10,000 games a day. A simulation engine can.

For every candidate game, we run automated playthroughs using AI agents (simple ones like random and greedy are enough to expose lots of structural problems). The engine repeatedly:

  1. Lists the legal moves available right now
  2. Checks termination (win/lose/draw conditions, cutoffs, loop detection)
  3. Lets an agent pick an action (with concrete targets if needed)
  4. Applies costs and effects, recording what happened
  5. Advances the turn/phase according to the game’s turn scheduler

Crucially: when a complex game definition tries to do something illegal (like decrementing below a minimum, or targeting something that doesn’t exist), the engine records skipped effects/triggers instead of crashing, so the system can observe “this design is broken in these ways” rather than just failing outright.

This is the equivalent of an organism interacting with the world and leaving tracks: “it tried to fly, but its wings didn’t work.”

3) Turning playthroughs into numbers: metrics, degeneracy, and fitness

After simulation, we compute a set of analytics that act like proxies for design quality—things like:

  • Agency: did players have meaningful choices, or were they railroaded?
  • Strategic depth (proxy): how large is the typical decision space?
  • Variety: do many different actions get used, or does one dominate?
  • Interaction rate: are players affecting each other or only themselves?
  • Structural complexity: is this a tiny toy, or something richer?

These are not “fun detectors.” They’re sensors.

Then we run degeneracy detection: filters that catch the classic failure modes of randomly-generated rulesets:

  • infinite loops / repeated states
  • non-terminating games (hits max turns/steps)
  • games with no real choices
  • trivial wins, dominant actions, excessive skipped effects, etc.

Some degeneracy flags cause an outright reject (hard gate), others apply a penalty (soft pressure), and too many penalties at once can also trigger rejection.

Finally, all of this becomes a feature vector, and we compute an overall fitness score—the number evolution tries to increase.

4) “Growing in niches”: why we don’t keep only the top 1%

If you only keep the single highest-scoring game each generation, you get premature convergence: the population collapses into one design family and stops surprising you.

Instead, we use MAP-Elites, which you can picture as a big grid of “design neighborhoods.” Each neighborhood is defined by a few chosen descriptors (think: agency bucket, variety bucket, etc.). Each candidate game gets “binned” into a niche based on its descriptor values, and then it competes only with others in that same niche.

  • Each niche keeps its best resident (the “elite”).
  • Over time, the map fills with many different elites: fast games, slow games, chaotic games, skillful games, high-interaction games, and so on.

This is how you get a museum of interesting survivors, not one monoculture.

5) Reproduction: mutation (and why mutation is structured, not random noise)

Once we have elites across niches, we generate the next generation by mutating them.

Mutation operators aren’t “flip random bits.” They are rule-aware edits that make plausible changes to game structure, such as:

  • tweak a number (thresholds, magnitudes)
  • add/remove/duplicate actions (with safety guards so you can’t delete the last action)
  • add/remove variables (while rewriting dangling references)
  • change turn schedulers (round-robin ↔ simultaneous ↔ priority-based, etc.)
  • add triggers and conditional effects
  • modify termination rules (win/lose/draw conditions)

The key is: the operator library is rich enough to explore mechanics, not just parameters.

Mutation retries (because many mutations are duds)

Some mutations do nothing (“no-op”), or produce something that can’t be repaired. The runner will retry with a different operator a few times; if it still can’t produce a productive mutation, it falls back to keeping the parent for that offspring slot.

This keeps evolution moving without pretending every random change is meaningful.

6) Repair, rejection reasons, and staying honest about failure

After mutation, we may run repair (optional), then validation and safety gates. If a candidate fails, it’s not just dropped silently—the system classifies why it failed:

  • repair failure
  • validation failure
  • safety failure
  • evaluation error
  • evaluation returned null fitness/descriptors

And it persists these outcomes for observability and debugging.

This matters because “evolution” is only useful if you can tell whether the ecosystem is healthy—or if you’ve started breeding nonsense.

7) Adaptive evolution: learning which mutations are actually useful

Not all mutation operators are created equal. Some will be reliably productive; others will mostly create broken genomes.

So the runner tracks per-operator telemetry every generation: attempts, no-ops, repair failures, rejection counts, and how often an operator actually helped fill a new niche or improve an elite. evolution-runner

Those stats feed into adaptive operator weighting, so the system gradually shifts its mutation choices toward what’s working in the current region of the design space—without hardcoding that “operator X is always good.”

8) Optional superpower: motif mining (stealing good patterns from winners)

Sometimes an evolved game contains a little “mechanical phrase” that’s doing real work—like a neat resource exchange loop, or a repeating pattern of effects that creates tension.

When motif mining is enabled, we:

  1. select elites (top per niche + global best)
  2. re-simulate them to extract trajectories
  3. mine repeated effect sequences (“motifs”)
  4. convert those motifs back into DSL effects
  5. feed them into a special mutation operator that can inject those motifs into new games

That’s evolution discovering a useful mechanic, then turning it into reusable genetic material.

9) Human taste enters the loop (without turning it into manual curation)

Metrics are helpful, but “fun” is subjective. So we can add human feedback:

  • ratings (“how good is this?”)
  • pairwise comparisons (“A or B?”)

Rather than asking the human to judge random games, the system uses active learning to choose the most informative comparisons—especially cases where its preference model is uncertain, and it tries to include underrepresented niches so taste is learned across the map.

Under the hood, the preference model is an ensemble trained online (so it can update continuously) and its uncertainty controls how much feedback to request per generation (adaptive budget).

Fitness can then blend:

  • “objective-ish” signals (metrics/degeneracy)
  • “human preference” signals

So the system doesn’t just breed games that are non-broken—it breeds games that align with what you actually enjoy.

10) Why this can rediscover known games and invent new ones

If your DSL is expressive enough to describe the rules of an existing game, then in principle there exists a genome that encodes it. Evolution doesn’t need to “know” the game—it only needs:

  1. Search operators that can reach that region of the rulespace (structural mutations, not just numeric tweaks)
  2. Selection pressure that rewards the behaviors that make that game work (choice, balance, interaction, clean termination, etc.)
  3. Diversity preservation so the system keeps exploring many styles instead of collapsing early

Once those are in place, rediscovery becomes a side-effect of searching a huge space under the right constraints. And invention is what happens when evolution stumbles into combinations nobody tried on purpose—then keeps them because the ecosystem rewards them.

The simplest mental model

If you want the non-technical version in one breath:

We generate lots of small rulesets, machine-play them thousands of times, score them for “does this behave like a real game?”, sort the survivors into many different “design neighborhoods,” keep the best in each neighborhood, then make mutated children from those survivors—occasionally learning from human taste and reusing discovered mechanics—until the map fills with strong and varied games.

That’s the evolutionary process: not magic, not random, but a relentless loop of variation + playtesting + selection + diversity.

LudoForge #3

If you don’t know about LudoForge, you should probably read the previous posts. In summary: I’m developing an app to evolve tabletop game prototypes according to a “fun” factor made up of plenty of fun proxies like player agency, strategic depth, etc. The code is now mature enough to run X evolutionary generations on demand, produce shortlists of the best games, and finish. That’s great because it means the code works well, although there’s always room for improvement. But the shortlist of four winners is absolutely terrible in a way that has had me giggling for a while. I’ll let ChatGPT explain these “games.”


Game 1: “The Shared Counter Chicken”

Two players take turns. There’s a shared number on the table that starts at 0 and can be increased up to 15. The “win condition” is simple: whoever makes it hit 15 wins instantly.

The game also includes a couple of other buttons that change other numbers… but those numbers can never actually produce a win. They’re basically decorative dials. One of them always gets set to 12, but the victory threshold for it is 20, so it’s like having a “Launch Rocket” button that always fuels you to 60% and then stops forever.

So what do players really do? They increment the shared counter… and then start playing a tiny psychological game of chicken: “I could push the counter closer to 15… but then you might get the final move.” So the game hands them some useless actions that function as “stalling.” If both players are stubborn, they can just keep stalling until the match times out.

It’s not strategy so much as who blinks first.

Game 2: “The Game Where You Can’t Move”

This one is my favorite kind of failure because it’s so clean.

The game defines two counters. The only action in the entire game says: “Decrease both counters.”

But the action is only allowed if both counters are greater than zero.

And the game starts with both counters at zero.

So on turn one, a player looks at the rules and… there is literally nothing they’re allowed to do. No move exists. The game doesn’t even fail dramatically. It just sits there like a vending machine with the power unplugged.

In other words: it’s a tabletop game prototype that begins in a stalemate.

Game 3: “First Player Loses: The Speedrun”

This one actually runs, which makes it even funnier.

There are two counters. One counter is the only one that can possibly lead to a win — the other one only goes downward forever, so its “win condition” is a permanent lie.

The “real” counter starts at 0, and there’s an action that increases it by 2. The victory threshold is 4.

Here’s what happens:

  • Player 1 goes first. Their only sensible move is: 0 → 2.
  • Player 2 goes next and does the same move: 2 → 4.
  • Player 2 instantly wins.

So the entire “game” is basically:

“Player 1 sets up the win for Player 2.”

It’s like a sport where the first player is forced to place the ball on the penalty spot and then politely step aside.

Game 4: “The Unwinnable Ritual”

Three players this time. There’s one shared counter. Winning requires the counter to reach 4.

But the rules only let you do two things:

  • Set it to 2.
  • Decrease it by 2 (if it’s above zero).

Notice what’s missing: any way to make it bigger than 2.

So the win condition is a castle in the sky. The game is a ritual where players take turns setting the number to 2, or knocking it back down toward 0. It can never, ever reach 4. No amount of cleverness changes that.

It’s essentially a machine that cycles between “2” and “less than 2” until you get bored or the turn limit ends it.


ChatGPT finished its report with this note: “The first evolutionary run didn’t produce brilliant board games. It produced life, in the same way early evolution produced algae and sea foam. These were rule-sets that technically existed… but didn’t yet deserve to.”

These idiotic games already provided fun by existing, so as far as I care, this app has already been a success. The good thing is that I have code to handle degeneracy, fitness, etc., so I simply have to tighten that code so some of these nonsensical points would either kill a genome or penalize its fitness.

By the way, earlier tonight I was playing tennis in VR with people across Europe while I waited for Claude Code to work through the tickets of one of the app’s new features. And yet the world is terrible. We live in the lamest cyberpunk dystopia imaginable.

LudoForge #1

Two nights ago I was rolling around in bed trying to sleep when a notion came into my head, one that has returned from time to time: some of the most flow-like fun I’ve ever had was playing tabletop games. I’m a systems builder by nature, and I love to solve problems with a variety of tools. Tabletop games are complex problems to solve with specific series of tools. My favorite tabletop game is Arkham Horror LCG, although I’ve loved many more like Terraforming Mars, Ark Nova, Baseball Highlights: 2045, Core Worlds, Imperium, Labyrinth, Renegade… But none of them fully captured me. Like some potential game exists that has exactly every feature my brain yearns for, but that game doesn’t exist. I’ve cyclically thought that I should create that game, but I never know where to start. I don’t even know what exactly I want, other than knowing that what I’ve experienced isn’t enough.

These past few weeks I’ve been implementing extremely-complex analytics reports generators for my repository Living Narrative Engine. I was surprised to find out that it’s feasible to mathematically find gaps in extremely complex spaces (dozens of dimensions) as long as they’re mathematically defined. I guess Alicia was justified to be obsessed with math. So I started wondering: what makes a tabletop game good? Surely, the fun you have with it. Can “fun” be mathematically defined? Is it the agency you have? The strategic depth? The variety? If any of such metrics could be mathematically defined, then “fun” is a fitness score that combines them.

And what if you didn’t need to design the game yourself? If you can map a simulated game’s activity to metrics such as the agency per player, the strategic depth, the variety… Then you can evolve a population of game definitions in a way that, generation after generation, the “fun” score improves. If you can turn all game mechanics into primitives, the primitives will mutate in and prove their worth throughout the generations, composing coherent mechanics or even inventing new ones. Initially, a human may need to score game definition variants according to how “fun” the playthrough of those games were, but in the end that could be automated as well.

Because this is the era of Claude Code and Codex, I’ve already implemented the first version of the app. I’ve fed ChatGPT the architectural docs and told it to write a report. You can read it down below.


LudoForge: evolving tabletop games with a deterministic “taste loop”

I’m building LudoForge, a system that tries to answer a pretty blunt question:

What if we treated tabletop game design like search—simulate thousands of candidates, kill the broken ones fast, and let a human “taste model” steer evolution toward what’s actually fun?

Under the hood, it’s a seeded-population evolution loop: you start with a set of game definitions (genomes), run simulations, extract metrics, filter degeneracy, blend in learned human preferences, and then evolve the population using MAP-Elites and genetic operators. Then you repeat.

The big picture: the loop

LudoForge is structured as a pipeline with clean seams so each layer can be tested and swapped without turning the whole thing into spaghetti. The stages look like this: seed → evaluate → simulate → analytics → (optional) human feedback → fitness → MAP-Elites → (optional) mutate/crossover/repair → next generation. pipeline-overview

A key design choice: the core expects a seeded population. There’s no “magic generator” hidden inside that invents games from scratch. If you want a generator, you build it outside and feed it in. That keeps the engine honest and debuggable. Note by me after rereading this part of the report: this will change soon enough.

Games as genomes: a DSL that can be validated and repaired

Each candidate game is a genome: { id, definition }, where definition is a DSL game definition. Before any evaluation happens, the definition goes through schema + semantic validation—and optionally a repair pass if you enable repair operators. Invalid DSL gets rejected before it can contaminate simulation or preference learning.

Repair is deliberately conservative: it’s mostly “DSL safety” (e.g., clamp invalid variable initial values to bounds). Anything that’s “this game is technically valid but dumb/unplayable” is handled by simulation + degeneracy detection, not by sweeping edits that hide the real problem.

The simulation engine: deterministic playthroughs with real termination reasons

The simulation layer runs a single playthrough via runSimulation(config) (or wrapped via createSimulationEngine). It builds initial state from the definition, picks the active agent, lists legal actions, applies costs/effects/triggers, advances turns/phases, and records a trajectory of step snapshots and events.

It’s also built to fail safely:

  • No legal actions → terminates as a draw with terminationReason = "stalemate".
  • Max turns exceededterminationReason = "max-turns" with an outcome computed in that cutoff mode.
  • Loop detection (optional hashing + repetition threshold) → terminationReason = "loop-detected".

Most importantly: runs are reproducible. The RNG is a seeded 32-bit LCG, so identical seeds give identical behavior.

Metrics: cheap proxies first, expensive rollouts only when you ask

After simulation, LudoForge summarizes trajectories into analytics: step/turn counts, action frequencies, unique state counts, termination reasons, and sampled “key steps” that include legalActionCount.

From there it computes core metrics like:

  • Agency (fraction of steps with >1 legal action)
  • Strategic depth (average legal actions per step)
  • Variety (action entropy proxy)
  • Pacing tension (steps per turn)
  • Interaction rate (turn-taking proxy)

Extended metrics exist too, and some are intentionally opt-in because they’re expensive:

  • Meaningful choice spread via per-action rollouts at sampled decision points
  • Comeback potential via correlation between early advantage and final outcome

Here’s the honest stance: these metrics are not “fun”. They’re proxies. They become powerful when you combine them with learned human preference.

Degeneracy detection: kill the boring and the broken early

This is one of the parts I’m most stubborn about. Evolution will happily optimize garbage if you let it.

So LudoForge explicitly detects degeneracy patterns like:

  • loops / non-termination
  • stalemates
  • forced-move and no-choice games
  • dominant-action spam
  • trivial wins metrics-and-fitness

By default, those flags can reject candidates outright, and degeneracy flags also become part of the feature vector so the system can learn to avoid them even when they slip through.

Human feedback: turning taste into a model

Metrics get you a feature vector. Humans supply the missing ingredient: taste.

LudoForge supports two feedback modes:

  1. Ratings (1–5) with optional tags and rationale
  2. Pairwise comparisons (A/B/Tie) with optional tags and rationale

Pairwise comparisons are the main signal: they’re cleaner than ratings and train a preference model using a logistic/Bradley–Terry style update. Ratings still matter, but they’re weighted lower by default.

There’s also active learning: it selects comparison pairs where the model is most uncertain (predicted preference closest to 0.5), while reserving slots to ensure underrepresented MAP-Elites niches get surfaced. That keeps your feedback from collapsing into “I only ever see one genre of game.”

Fitness: blending objective proxies, diversity pressure, and learned preference

Fitness isn’t a single magic number pulled from the void. It’s a blend:

  • Base composite score from metrics (weighted sum/objectives)
  • Diversity contribution (pressure toward exploring niches)
  • Preference contribution from the learned preference model (centered/capped, with bootstrap limits early on)

Feature vectors are keyed by metric id (not positional arrays), which matters a lot: adding a new metric doesn’t silently scramble your model weights. Renaming metrics, though, becomes a migration event (and that’s correct—you should feel that pain explicitly).

Evolution: MAP-Elites + mutation/crossover that respect DSL validity

Instead of selecting “top N” and converging into a monoculture, LudoForge uses MAP-Elites: it bins candidates into descriptor niches and keeps the best elite per niche.

Descriptor binning is explicit and deterministic (normalize → floor into bin count; clamp to range), and niche ids serialize coordinates like descriptorId:bin|....

Then you can evolve elites with genetic operators:

  • Mutations like numeric tweaks, boolean toggles, enum cycling, duplicating/removing actions, nudging effect magnitudes, adding/removing phases, rewriting token/zone references safely, etc.
  • Crossover via subtree swaps of state.variables or actions, followed by DSL re-validation.

Optional “shortlisting” exists too: it picks a diversified subset of elites for human review using a max-min distance heuristic over descriptor coordinates.

What’s already proven (and what isn’t yet)

This isn’t vaporware; the end-to-end tests already prove key behaviors like:

  • the ordered phases of the pipeline
  • invalid DSL rejection before evaluation
  • safety cutoffs (max-turns) and deterministic seeded outputs
  • human prompt loops and legality enforcement
  • deterministic state transitions
  • MAP-Elites producing stable ids
  • active learning selection behavior
  • mutation + repair at scale, including crossover

And there are explicitly documented gaps—like extended metrics aggregation and worker-thread batch simulations.

The point of LudoForge

I’m not trying to build a “game designer replacement.” I’m building a design pressure cooker:

  • Simulate hard
  • Reject degeneracy ruthlessly
  • Measure what you can
  • Ask humans the right questions
  • Let evolution explore breadth, not just a single hill

If you’re into procedural design, evolutionary search, or just enjoy the idea of treating “fun” as something you can iteratively approximate with a human-in-the-loop model, that’s what this project is for.

Living Narrative Engine #19

I have quite the treat for you fuckers. I’ve recorded myself playing through my test scenario involving Alicia Western. More than an hour of me speaking in my accented English even though I rarely speak in real life, and showing off a fun, frustrating playthrough that made me hungry.

This is, of course, related to my beloved Living Narrative Engine. Repo here.

Living Narrative Engine #18

I’m building a browser-based app to play immersive sims, RPGs and the likes. In practice, I use it to set up short story scenarios or elaborate gooning sessions. I dared myself to build the most comprehensive psychological system imaginable, so that Sibylle Brunne, a 34-year-old orphan living in her parents rustic home somewhere in the Swiss mountains, while controlled by a large language model, would realistically bring her blue-eyed, blonde-hair-braided, full-breasted self to seduce my teenage avatar who is backpacking through the country, eventually convincing me to stay in her house so she can asphyxiate me with her mommy milkers.

Here’s a visual glimpse of the current complexity:

Alicia has become my test subject, as if she didn’t have enough with freezing to death. The system works like this: at the base you have mood axes (like pleasant <-> unpleasant), which change throughout a scene. Actors also have permanent biological or personality-based traits like aversion to harm. Together, mood axes and affect traits serve as weights and gates to specific emotion prototypes like disappointment, suspicion, grief. Delta changes to those polar mood axes naturally intensify or lessen the emotions. I also have sexual state prototypes, which work the same as the emotional states.

These emotional and sexual states serve as the prerequisites for certain expressions to trigger during play. An expression is a definition that tells you “when disappointment is very high and suspicion is high, but despair is relatively low, trigger this narrative beat.” Then, the program would output some text like “{actor} seems suspicious but at the same time as if they had been let down.” The descriptions are far better than that, though. The actors themselves receive in their internal log a first-person version of the narrative beat, which serves as an internal emotional reaction they need to process.

It all works amazingly well. However, to determine if I was truly missing mood axes, affect traits or prototypes, I had to create extremely complex analytics tools. I’ve learned far too much about statistical analysis recently, and I don’t really care about it other than for telling a system, “hey, here are my prototype sets. Please figure out if we have genuine gaps to cover.” Turns out that to answer such a request, some complex calculations need to map 20-dimensional spaces and find out diagonal vectors that run through them.

Anyway, I guess at some point I’ll run my good ol’ test scenario involving Alicia, with her now showing far more emotion than she used to before I implemented this system. That’s a win in my book.