Skip to main content
Back to Articles
2026 / 02
| 6 min read

Deep Dive: Building a Canada Goose Simulator

How a deadpan text adventure about mild chaos became the BBS system's most extensively tested game—79 tests, procedural honk audio, and a migration ending instead of game over.

emulator games text-adventure testing audio
On this page

The bug was in the desensitization curve. Picnickers who’d been honked at twice should shrug; they were still fleeing. I logged every honk, every NPC reaction, every decay tick—and found the counter was resetting on zone transitions. Fixing it took one line. But understanding why that counter mattered forced me to articulate what makes a goose simulator actually feel like a goose: the honk should lose power over time. The fantasy isn’t unlimited chaos; it’s chaos with diminishing returns, which makes you work for it.

That debugging session crystallized the design. A goose simulator is a time budget wrapped around a single verb: honk. The player has 600 total time units (30 per day, 20 days), six zones, and five victory paths. The system became clear once I stopped treating it as a comedy game and started treating it as resource management with deadpan narration laid on top.

Time Units: The Smallest Truth

The core constraint is time, not health or inventory. Every action costs units: waddling costs 1, honking costs 1, flying costs 4, resting costs 5. When the budget ends, the run ends. This single rule makes the goals legible.

The five victory contracts:

  • The Nested Life: collect 15 specific nesting materials
  • Agent of Chaos: annoy 50 unique NPCs
  • Dynasty Builder: raise 3 goslings to independence
  • The Hoard: stash 30 food items in your nest
  • Territorial Supremacy: claim all 6 zones simultaneously

The names are flavour. The numbers are the contract. Each goal shapes which zones you visit, which NPCs you target, and how aggressively you spend time.

Honk As Protocol

Honking is the main verb, so I treat it like a small protocol instead of a flavour text toggle. Each honk affects NPCs within a 3-tile radius—up to 4 targets per honk, depending on crowd density. But reactions depend on context: who you’re honking at, how many times you’ve honked them before, and whether they happen to enjoy it.

The desensitization system tracks per-NPC honk counts. Fresh targets flee or drop items. Repeated targets shrug. This turns “honk everyone constantly” into a losing strategy and rewards zone-hopping to find fresh victims.

Some NPCs flip the response entirely. Children, elders, other geese, and ducks like being honked at—they honk back, or laugh, or drop food out of friendliness. The system handles this with a likesHonking flag on the NPC definition. It’s a small inversion, but it prevents the interaction model from becoming monotonous.

The honk mechanic is doing three jobs: moving the numbers (ferocity, notoriety, NPC annoyance counts), setting the comedic tone, and creating a reason to keep honking even when optimizing would suggest silence.

Procedural Goose Audio

I wanted the honk to feel like a honk, not a synthesizer demo. The audio generator is built on Tone.js with deliberately retro constraints:

  • Honk: descending sawtooth (320 Hz → 220 Hz → 180 Hz) with 8 Hz vibrato and a bandpass filter at 600 Hz for the nasal edge
  • Flap: white noise through a 400 Hz lowpass, quick attack and medium decay
  • Waddle: 80 Hz sine wave, barely audible soft thump
  • Splash: pink noise through a resonant bandpass, frequency sweep from 1200 Hz down to 400 Hz
  • Peck: white noise through a 2000 Hz highpass, 30 ms envelope
  • Victory: three ascending sawtooth honks (220 → 280 → 350 Hz)
  • Damage: square wave descending from 500 Hz to 200 Hz

The pitch drop and nasal filter on the honk carry most of the character. The audio is a mechanic cue as much as an effect—it tells you the action landed even when text scrolls past too fast.

Goslings As a Loop

Goslings are not decoration; they’re a daily loop with real constraints. A gosling hatches after 2 days of incubation. It ages each day, gets hungry (+15 hunger per day), and can only become independent after 5 days if it has learned at least 3 behaviours and its HP is above 20.

The learning system watches what the player does. After observing a behaviour twice, a gosling learns it. Behaviours include honking, flapping, stealing, swimming—anything the player models while the gosling is following. Personalities (aggressive, resourceful, brave, cautious, aquatic) give bonuses to related behaviours, which creates minor narrative flavour without changing the core math.

The “raise 3 goslings” goal is a planning problem: you need to hatch enough eggs, keep them fed, and demonstrate enough varied behaviours before day 20 runs out. It’s the slowest path to victory and the most vulnerable to time pressure.

Migration Instead of Death

The end state is framed as migration, not a corpse. When day 20 ends without victory, the game prints a migration epilogue and picks a destination from a list of 100 Canadian town names and goose puns: “Happy Valley-Goose Bay,” “Honkerton,” “Bread or Consequences,” “Peace Was Never An Option.”

HP reaching zero also ends the run, framed as the goose fleeing rather than dying. The tone is dry, not tragic. The loop is meant to be replayed.

The Test Harness

This game has 79 unit tests. That number sounds excessive for a text adventure, but the tests exist to lock in the mechanics so I can freely change the narrative and pacing without breaking the foundation. The tests guard goal completion (can I actually annoy 50 NPCs? can I actually hoard 30 food items?), action costs, stat bounds, state transitions, NPC spawning, save/load consistency, and edge cases like waddling into walls or eating from an empty inventory.

The stress tests run 500 random commands and 5 full day cycles to confirm nothing crashes. The deterministic tests confirm each goal is achievable through gameplay, not just theoretically possible.

It’s the same constraint as the game itself: once the smallest truths are fixed—time costs, stat bounds, goal thresholds—everything else can move around them.

What This Enables

A text adventure can carry humour, but it still needs a model. The model here is a time budget, a fixed map, and a handful of verbs with real consequences. If those are clean, the jokes land on top instead of propping up the whole system. The tests let me rewrite the flavour text, adjust NPC dialogue, or add new items without regression.

What surprised me was how much the desensitization system changed the feel. Early playtests with unlimited honk power felt like a power fantasy—mildly funny, quickly boring. Forcing the player to move, to find fresh targets, to balance aggressive actions against time costs, made the comedy earned. The goose isn’t overpowered; the goose is just persistent. That’s closer to the truth.

See also: Deep Dive: Bell 103 Audio Modem — for when you need to understand how the honk reaches the line.