# Hachibake: a tanuki stealth game for the web

> Hachibake (八化け) is Brad Anderson's stealth game for the web, live at hachibake.com: Hachi, a tanuki who knows two of his eight shape changes, sneaks into farms, estates and shrines at night to steal food for Granny Matsu. Four seasonal chapters and a finale, built in TypeScript with three.js WebGPU, deterministic Rapier physics and Blender-scripted models.

Hachibake (八化け) is a stealth game I made for the web, and you can play it at hachibake.com on a computer, a tablet or a phone. You play Hachi, a tanuki ronin in a samurai outfit who sneaks into farms, a lord's estate and a fox shrine at night to steal food. No human dies or is shown hurt. The stealth is in the style of Tenchu: Wrath of Heaven, but the tone is closer to Fantastic Mr. Fox.

The name comes from the proverb 狐七化け狸八化け: the fox has seven changes, and the tanuki has eight. The title screen counts his: "The fox has seven changes. The tanuki has eight. This tanuki has two." Hachi earns the rest by stealing a moon supper for Granny Matsu, an old tanuki.

## The story

The game runs in four chapters of three nights each, then a finale:

- **The Moon Feast:** Mosuke and Ume's farm, the lord's estate, and the Inari shrine, where Kon, a vixen, is Hachi's rival.
- **Mochi for the New Year:** a town in the snow, where people follow your footprints; a hot-spring inn, where the steam hides you; and the lord's castle on New Year's Eve, where the temple bell covers your noise while it rings.
- **Dango under the Blossoms:** a tea house by the river, where gusts of petals cut people's sight; a temple blossom fair; and the lord's garden party.
- **In Summer, the Night:** Obon at a temple gate, where fireflies light you up the way a lamp does; a fishing village with cormorant boats; and a hunter's cabin on a moonless night, with his dogs and his traps.

After the summer the game ends on a beach, with the family around a fire and fireworks over the sea. The story is told on illustrated cards rendered in Blender from the game's own models, and I recorded all 152 lines of narration myself.

## How it plays

Humans see and dogs smell. How far a guard can see you depends on how lit you are: the game casts rays toward the moon from two points on Hachi's body and adds the light of nearby lamps, lanterns and fires, and a guard's sight range runs from about 7 meters in shadow to 17.5 in lamplight. A mark over each head fills as someone notices you, guards say what they're thinking, and you hear them walking.

Hachi moves upright or on all fours, carries folklore tools (sake, a kaginawa grappling hook, a leaf, his belly drum, makibishi caltrops and kusaya), can lift things from a guard's belt and play dead. Each night has a ladder of missions with stars. Four more animals open as you play, each with its own moves: a weasel that slips through gaps, a cat that climbs and sees in the dark, an otter that swims and dives, and a badger that digs and sniffs out food through walls. A sixth, a silver fox whose foxfire lures guards, is sold in the store.

The first chapter is free. Each later chapter opens with stars earned in the one before, or early from the store, which also sells animals and outfits. Nothing for sale is random, and the game's luck rewards (finds, gifts from Granny Matsu, a daily omikuji) are never sold. Signing in is optional, by an emailed link or code, and a signed-in player's progress is saved to the cloud and merged across devices. The site shows no ads, runs no analytics and sets no cookies.

## How it's built

It's TypeScript and Vite, with three.js's WebGPU renderer and TSL shaders, falling back to WebGL2 where WebGPU can't draw it. Physics is Rapier's deterministic build, and navigation is recast-navigation.

- **A determinism wall.** The simulation uses no DOM, no clock and no unseeded random numbers, and the linter enforces it, so the same seed and inputs always produce the same state hash.
- **One thread.** The simulation runs on the main thread rather than in a Web Worker, because the camera sphere-casts against the simulation's physics every frame, and a worker would add at least a frame of input lag.
- **Models from scripts.** The characters and levels are built by Blender Python scripts. Hachi's body is a signed distance field sampled on a 5 mm grid and decimated to about 6,000 faces, and all six animals share one 29-joint rig and its animation clips. Textures are CC0 from Poly Haven, and the music and sound effects are synthesized in the browser.
- **Safari and phones.** Safari's WebGPU refuses a shader whose private variables pass 8,192 bytes, so the game picks at most 12 point lights from all the lamps in a level. Where a browser has WebGPU only in compatibility mode, the game draws with WebGL2 instead.
- **A store with no database.** Stripe holds the purchases, and the server reads what an email bought back from Stripe. Cloud saves are the one thing kept in Postgres, and they merge so nothing earned is lost.
- **Offline play.** A service worker caches the game, and asset URLs carry content hashes.

I started it on September 27, 2026, the first playable slice was built the next day, and the finale landed on October 16. As with my other recent work, I made the design calls, and Claude wrote the specs from them and much of the code.

## Details

- **Category:** Projects
- **Tags:** Hachibake, 八化け, hachibake.com, game, games, video game, browser game, web game, stealth game, tanuki, Japanese folklore, yokai, three.js, WebGPU, Rapier, Blender, TypeScript, Claude Code

**Also read:** [All writing](https://bradanderson.org/writing?format=md) · [About Brad](https://bradanderson.org/about?format=md)

---

**Navigate:** [Home](https://bradanderson.org/?format=md) · [About](https://bradanderson.org/about?format=md) · [Work](https://bradanderson.org/work?format=md) · [Projects](https://bradanderson.org/projects?format=md) · [Breeds](https://bradanderson.org/breeds?format=md) · [Writing](https://bradanderson.org/writing?format=md) · [LLM guide](https://bradanderson.org/llms.txt)

_Ask BradBot directly: POST https://bradanderson.org/api/agent/ask with {"question": "..."} (details in https://bradanderson.org/llms.txt)._
