back to work

case study

Yapoleon's Court

An AI game the LLM can't game.

visit sitecourt.yapoleon.com
Yapoleon's Court screenshot

01 the problem

A competitive game backed by an LLM the player is actively trying to game — running on a paid API, in front of minors — is a stack of production hazards. The model can be prompt-injected. It can be flattered into a high score. A bad actor can burn through your API bill. And the model can say things a family audience shouldn't hear.

02 the solution

Built the game so the model *can't* be gamed — structurally, not with hope. The Gemini call returns taste only (five bounded axes plus one in-voice line). The favor delta is derived server-side by a pure function the model can't see or reach. Prompt injection, sycophancy-gaming, and denial-of-wallet are handled at the architecture layer. A deterministic red-line pre-filter runs before any model call, so flagged input costs zero.

03decisions & tradeoffs

Model returns taste, server derives the score

Making the favor delta a field the LLM can output makes it a field the LLM can be talked into inflating. Removing the field entirely is stronger than any prompt hardening.

Structured, low-temperature output only

Predictable schema across every turn, cheaper to reason about, easier to write invariant tests against. Voice comes from prompt, not temperature.

Deterministic pre-filter before model call

Red-line content should never spend a token. Rules-based short-circuit is faster, cheaper, and auditable in a way an LLM classifier isn't.

Cached degrade mode over hard failure under load

Concurrency damper serves an in-voice cached reaction with zero model calls when spend or load spikes. Still routes a neutral score through the same derive-favor function. Meter never breaks, character never breaks.

04 tech stack

Google Gemini

Server-side proxy, low-temperature structured taste-only output

React + TypeScript

Web app, share-card generator, favor meter UI

Vercel serverless

API routes with atomic-slot concurrency damper (TOCTOU-safe)

Supabase

Auth, standing and rivalry persistence across days

05 results

  • The model never emits the score — favor delta is derived server-side from clamped, weighted taste axes
  • Denial-of-wallet bounded five ways: 3-turn daily cap, per-IP + per-user rate limits, atomic concurrency slot, cached degrade mode, Vercel spend hard-stop
  • Content pre-filter short-circuits red-line input before any model call — zero cost on flagged requests
  • Prompt injection handled structurally (player reply rides as data being judged, never in the system instruction)

Want something like this?

Let's talk about your project.

start a project →