Published by KnownBetter Studios → This page is the engineering case study.
Marjorie's Manor
In developmentA cozy game about running a Victorian rooming house, where helping each tenant move on with their life is the whole point, and it costs you their rent.
At a glance
- Outcome: You inherit a manor, its debts and its tenants. Building relationships moves each tenant’s story forward, finishing a story costs you their rent, and what you notice about the house is what the long arc turns on. The product page and art direction live at KnownBetter Studios.
- Status: In development. As of September 3, 2026 the 3D prototype has been retired and the game rebuilt as a 2.5D isometric Godot build: 21 rooms of gray blockout, tenants on schedules, talk and gifts, build mode, rent and bills, the attic, a journal, an observation system, four tenant arcs, an endgame, a tutorial and three save slots. Hand-drawn art by co-creator Sarah replaces the blockouts as it lands, and a Kickstarter is planned for 2027 once the vertical slice is playable.
- Role: Systems, data model, save format and the verifier discipline; implementation is AI-assisted and reviewed. The art direction is Sarah’s.
- Stack & libraries: Godot 4.6 with GDScript, Dialogic 2.0 alpha for dialogue. TileMapLayer floors and Y-sorted Node2D props in 2:1 dimetric, AStarGrid2D pathing, no physics. Eleven autoload managers read nine JSON content files.
- Source: Private.
- Validation: 35 headless verifier scripts, 6,173 checks in all, run by one shell script after a clean boot; the whole suite passed against the last commit on September 11, 2026. Verifiers are 11,385 of the 25,971 lines of GDScript. A balance sim drives the real managers through six months for four player archetypes, and its verdicts set the economy constants.
- Limitations: No art: every surface is a gray prism. No title screen and no builds. The featured arc has been walked headless from a new game, but the in-engine fresh-save playthrough on the roadmap is still unchecked. A local co-op layer (a second actor, workstation jobs, save v6) sits uncommitted in the working tree as of September 11. Rent, bills, the observation tier thresholds and Iris’s birthday are still constants in GDScript.
The mechanism the data model has to carry
Rent is the live tenant count times $300 a month against $600 of flat bills. It accrues into the mailbox until collected, and one odd job a day pays $25 to $50. Finishing a tenant’s story is the thing that costs you: three of the 22 quest beats mark a departure, and there is no separate move-out system, because leaving is the final beat’s effect.
Decoration decides who arrives. Every furniture item carries weighted style
tags, a room is scored as points and share per style, and leaving build mode in
a vacant apartment moves in the first un-housed tenant whose rule holds. The
rules are rows in tenant_data.json: Jasper wants half the room and six points
of vintage, Zoe the same in minimalist, Iris any room with three points of
anything. In the prototype those thresholds were constants; now a new tenant
with a new taste is a row.
Noticing as a third currency
The rebuild added a system the prototype didn’t have. Every room and every tenant is an observation subject, 21 in all, each with three to five facets that open under a window: an hour, a place, a finished objective, or another subject’s tier. Standing in a room pays one point a chunk; a watch spot or the tenant menu’s Pay Attention spends the chunk to mark a facet outright. Points and facets lift a subject through Noticed, Familiar and Understood. The permanent floor is saved; the session tier is rebuilt one lower on load, so a returning player re-sees the house.
A tier does three things. It is a quest trigger, observation_tier, on four of
the 22 beats, so a story can wait on what you noticed rather than what you said.
It grows a journal page stage by stage: 21 staged entries with 68 margin lines,
derived from the manager at draw time and never copied into the journal. And it
branches dialogue: 13 of the 37 Dialogic timelines carry an if on a tier or on
whether a noticing is waiting to be shared. One function, is_facet_in_window,
answers for both the passive and the active rate, so the two can’t disagree
about a gate.
Verified by scripts
There is no test framework. Each verifier is a SceneTree script that boots the
real autoloads, drives them through the real hooks and prints N checks, M failures; the runner reads that line rather than the exit code, because two
verifiers run real Dialogic timelines and crash on the addon’s teardown after
printing. Verifiers landed alongside the roadmap steps, 35 across the four
rebuild phases.
The acceptance verifiers are the ones worth naming. g4_acceptance_verify
starts a new game and plays the featured arc end to end with nothing forced:
furniture bought from the week’s thrift rotation, a gift picked from a tree,
items out of attic boxes, sixteen days standing in a hallway. It asserts the
whole thing costs 19 game days, connects debug_command_executed and checks it
never fired, and sweeps its own source for ten named shortcuts.
g4_prose_verify runs every timeline through Dialogic twice, once with nothing
noticed and once with every subject Familiar, so both sides of every branch
execute and every speaker resolves. The save verifier builds a v1, v2, v3 and v4
payload and pushes each through the migration chain to v5, asserting what each
step seeds and what it must leave alone.
What’s data and what isn’t
Nine JSON files hold the content: rooms (21 rooms, 55 props and the door table),
palettes, tenants, quests and objectives, attic items, forage, journal entries,
observation subjects and the furniture catalog. A prop’s behaviour is picked from
its type field, eleven types from mailbox to story_door, so the endgame’s
one-way doors and walk-in triggers are rows, and adding a room is one registry
entry plus a bare scene. A fourth tenant arc from the four existing trigger
types is content work; a fifth trigger type is still a code change.
The rebuild kept the manager layer and the tenant, beat and furniture schemas
from the prototype and threw away the scenes, the camera and the asset packs,
which were purged from history with git filter-repo.