Undead Signal: five days of rules before a line of code
Undead Signal was built for a Wavedash game jam, theme: Bad Connection. It’s an anti-poker zombie roguelike, live on Wavedash as a WebGL build with platform achievements, leaderboards, and cloud saves. My fourth shipped game and my second in Unity, after Spare Knight (Phaser 3), I Won’t Be Abducted (Godot), and ThunderBashers (Unity).
This one was a design-first project on purpose. The previous jams taught me to ship; this jam I wanted to prove I could make the rules the interesting part. So I spent roughly the first five days entirely on rules, in a design vault, before any build existed.
The pitch
You’re a radio engineer restoring the signal in overrun locations. The dead are networked by frequency: a lone zombie is just a body, but when they align into a lineup, a poker hand, they form a coordinated resonance that overwhelms you at the location’s exit. Each act deals more zombies onto the table; whatever you don’t remove survives to form the horde’s best five-card hand, and its threat hits your health.
Threat is one equation: the sum of the five zombie ranks times a poker-hand multiplier. That gives you exactly two levers. Drop the sum by killing or shrinking the big ranks, or break the structure by scattering a pair and splitting a straight. Breaking their hand is fixing the Bad Connection is restoring the signal. The theme and the core mechanic are the same sentence, which is the thing I’m proudest of in the whole design.
Killing three drafts
The honest history is that the first drafts were derivative. Draft one was a straight zombie card battler. Draft two leaned hard into Balatro: build your hand, stack multipliers, score big. On paper it functioned, and on paper it was boring, because Balatro already exists and a worse Balatro with zombies isn’t a game, it’s a reskin.
The unlock was inverting it. In Balatro you assemble the scoring hand. What if the enemy assembles it, and every verb you have subtracts from their hand instead of adding to yours? Suddenly the power fantasy flips from building a combo to dismantling one, the poker knowledge players already carry becomes threat literacy instead of a scoring manual, and the zombie fiction snaps into place: the horde is the hand.
There was a third draft between those, a corridor-crawl hybrid, and it died too. I kept every dead draft in an archive folder instead of deleting it, and I’d recommend that to anyone doing solo design work: the graveyard is what proves the final rule set was chosen, not stumbled into. Five days of this felt irresponsible mid-jam. It was the best production decision in the project, because the build phase never had to stop and redesign anything.
The rule that gave back
My favorite moment in systems design is when one rule starts producing depth you didn’t put there. In Undead Signal, a zombie’s rank is also its health. Hit it for less than its rank and it doesn’t die, it shrinks: a Mutated 9 hit for 3 becomes a 6.
Which means shrinking can backfire. If there are two 6s already on the table, you just completed three of a kind and raised the threat you were trying to lower. That interaction was never designed. It fell out of “rank is HP” colliding with “poker hands multiply,” and the first time it happened in testing I knew the ruleset was actually alive. We kept it, we tell the player to read the board, and it’s the single most quoted rule when people describe the game back to me.
Balancing with a bot
The other half of the jam was learning what “balancing on testing” means when you’re solo and the game is a twenty-five minute roguelike run. You cannot feel-test your way to a win rate. So the game got a balance lab: a headless harness where a threat-aware bot plays 300 seeded runs per configuration and prints the funnel, win rate, clear rate per location, how people die.
The first measurement was humbling. Win rate: 19 percent. And if the bot used the game’s own loot-digging verb naively, it dropped to 5 percent, meaning one of my core verbs was a trap. The numbers found root causes feel never would have: whole runs were passing without a usable weapon appearing before the first exit, and the average first-location exit damage was 60 against 100 health. The deadliest room in the game was the front door, before the player owned a single tool.
Two dial changes later (gear density up, plus a rule guaranteeing a weapon in the first few cards), the win rate hit 31 percent against a 30 to 40 target, and deaths migrated to the late-game wall where they belong. Then playtesting produced the opposite complaint: hands full at all times, loot stopped mattering. So weapons got durability, failed kills got bite-back, and the lab re-tuned the whole thing to 37 percent with weapons actually cycling. Every one of those numbers is a logged report I can re-run.
The meta-lesson: the lab also measured the dial I thought I understood. Gear density turned out to be two dials in one, because more gear also means fewer zombies in the deck, and the second effect was the stronger one. I would have tuned that dial wrong by hand forever.
Shipping on a platform
This was also my first release on Wavedash rather than a plain web upload, and the platform SDK work was its own small discipline: ten achievements, two leaderboards, player identity on the title screen, cloud saves for your settings and lifetime stats. The game had no native score, so the leaderboards run on a derived composite (progress first, kills as the tiebreaker) that had to be designed like any other rule. Launch day itself was a rhythm of building, pushing, and patching against live reports. Five updates went out on day one. That felt closer to live ops than to jam submission, and I want more of it.
What I’d keep
Spend the design days before the build days; the archive of dead drafts is the receipt. When a rule produces depth you didn’t author, that’s the ruleset telling you it works. And balance is a measurement problem: a bot that plays 300 runs will find the truth about your economy faster than a hundred feel passes, and it leaves you numbers you can defend later.








