All posts

The Shadow That Did Nothing

A character class was fully built, fully tested, and never connected to the game

6 min read
game-systems
architecture
ai-narrator
shadowkin
Comic: the Warrior's lifeless shadow wakes up, grabs a key, and is denied the gold.
Comic: the Warrior's lifeless shadow wakes up, grabs a key, and is denied the gold.

Shadowkin is a playable class in Chronicles of Terros. A Shadowkin character shares their body with a bonded shadow that has its own name, moods, a pool of bond points, and combat abilities that grow as the character levels. All of it was authored, and all of it had passing tests.

During a playtest, the shadow did nothing. It had no lines, took no actions, and never reacted to anything the player did. Picking the class got you an ordinary character with a paragraph of flavour text about a shadow that was not mechanically or narratively present.

Built and Disconnected

I audited the class to find out why, and the answer was that every part of the shadow existed and none of it was connected. Character creation built the shadow and wrote it to the save. The combat math, the bond-point progression, the personality stages: all present, all passing their unit tests.

The game loop read none of it. Nothing turned the shadow on the character sheet into something the narrator could see or the combat system could use. The functions that calculated a Shadow Strike had no callers anywhere in the code. They were correct and dead.

The class was ninety-five percent built and zero percent wired.

This failure recurs in this project. A system gets built and tested on its own, the tests pass, and the single line that connects it to the running game never gets written. Passing tests prove the calculation is right. They cannot prove that anything calls it.

The Obvious Fix Was Wrong

The engine already knew how to make a shadow act. A Shadowkin who joins the party as a companion runs through the companion system, takes turns, reacts to the player, and shows up in the party roster. The player's own shadow did none of that, because it was never a companion.

The fastest fix was to register the player's shadow as a companion too. That would have worked, and it would have been wrong. The companion system is built for allies you recruit, bench, and dismiss, and it hands every member a slot in a party capped at three, a line in the party's emotional roster, and a place in the turn order.

A player's shadow is part of the character. It cannot leave, it has no body to stand somewhere else on the battlefield, and its bond points are a spendable resource closer to spell slots than to a measure of affection.

Registering it as a companion would make the game treat an inseparable part of the character as a recruit who might walk away. It would list the shadow as a peer in the party, which contradicts the one rule the setting is firm about: the shadow is anchored to its host and cannot detach.

Keep It on the Character

The shadow stays on the character sheet, where it was already stored, and two systems read it from there.

The narrator receives a block of context each turn: the shadow's name, its current mood, its bond points, and whatever it is holding. The block tells the narrator that the shadow has its own will and may act on its own when the moment fits its personality, and that it is a constant presence rather than a second party member.

The mechanics run in code. A new processor owns bond-point recalculation on level-up, bond restoration on a long rest, and combat resolution when the player uses an ability. A Shadow Strike now runs through the same attack resolution as a sword swing, using the shadow's die and the character's Charisma. The dead code has a caller.

What Happens When the Shadow Grabs Something

The question that took the most thought was what the shadow may do on its own. I want it to feel like it has a will, so during a scene it might recoil from a bright lantern or strain toward something it wants. That is narration, and the narrator can produce it freely.

The trouble starts when the shadow does something with a consequence. If the narrator writes that the shadow snatches a key off a table and nothing records that the shadow now holds a key, the fact evaporates on the next turn. This is the failure that defined Friends and Fables, where the story says one thing and the game state says another until the world stops making sense.

The line I drew is whether the action has a rules consequence. A shadow lifting a key off a table is a fact about the world. A shadow pinning an enemy is a combat condition with a saving throw. The first can be narrated and recorded; the second has to be resolved by code.

For the first kind, the narrator emits a small tagged signal when the shadow takes or drops an object. Code reads the tag, validates it, and stores it on the character's shadow state, which feeds back into the context block next turn. The shadow that grabbed the key is still holding it ten turns later, because the fact lives in the game state and not in the narrator's short memory.

The validation refuses anything with a mechanical cost. The shadow cannot pocket fifty gold this way, because currency is the code's to hand out. It can hold a prop, not mint a resource.

For the second kind, the shadow's real abilities are declared by the player and resolved by code. Shadow Grasp computes a save DC and spends a bond point. Shadow Step checks that the character is high enough level and has a point to spend before anything happens. The narrator describes the result rather than deciding it.

What Is Not Done

Three of the shadow's abilities are on the character sheet and not yet in combat. Shadow Defense is a reaction that fires when the player is hit, which is a different point in the flow than a declared action. Shadow Merge and Umbral Form are transformations that grant resistances for several rounds, and applying a temporary defensive buff mid-combat needs machinery the engine does not have yet.

I left them out rather than half-build them. A buff that a prompt announces but the code never applies is the exact story-versus-state problem the rest of this work exists to prevent.

Whether the rest holds up is a playtesting question. The unit tests prove a Shadow Strike deals the right damage and that a bond point is spent when it should be. They cannot prove the narrator honours the line between flavour and mechanics once it has a live shadow with a personality and permission to act.

If the shadow starts narrating restraints and wounds the code never applied, the boundary is being ignored, and that is a different problem than the one I just fixed.