World map and portals
repo: land-of-lor (game + director) and this workspace (site/)
· depends on: server-architecture
Where this stands (2026-10-28)
Furniture for the houses (2026-10-28, deliverable #43) — on staging, ships with the houses.
Eight pieces of furniture and twelve Persian rugs, carried like the chest and put down facing back
at whoever put them down (a rug rolled up in the arms, unrolling away from you); Madame Zahra, a
wolf-faced rug seller who wants dyes, at a stall in the Bazaar; the villagers’ homes furnished;
and a step onto a cell takes everything on it, a full bag leaving the rest where it lay. Branch
furniture (from villagers); not yet tried on a phone. Next, from Kris’s brief: the dyes as
elements, the rug trade, dyes from the well, Zahra’s words; where players get furniture is not
decided. docs/handoff/furniture.md, rug-seller.md, pickup-all.md.
Your own house in the Village (#42, 2026-10-26) — signed off on staging; waits for Apple.
Kris and Rah’s design: every player’s home is a house in the Village of Lor, in their own colours
while they are in the game, knocked on by anyone, visited only by invitation. Drawn and voted on
(deliverable #41), built on the houses branch, tried over three rounds on Kris’s phone against
staging — knocking (replace, walk-away, a Keep-out cooldown), the white outline, your house on the
map, a warm brown backdrop in every room, unique player names — and signed off the same evening
(Kris: “I am totally happy with that — excellent work!”). Not live, on purpose: Kris waits for
Apple to approve 0.2.2 first, then a store release of the houses client, then — a couple of days
after both stores approve — the server rollout with a forced update. That needs a client-version
gate built into the houses app first (PROTOCOL_VERSION is an exact match and cannot do it); the
whole plan is on #42.
Decided: houses are a table the Area sends once and then its changes, never entities on the
ten-a-second broadcast; an offline owner’s house is scenery (a tap does nothing).
Area rules are a catalogue now (2026-09-15): an Area’s rules list was free text with one
string anyone read (quick-spell:<id>). There are three rules — pvp, harm, quick-spell —
in game/shell/rules.js beside the elements, each with a preset per areaType, and one shared
resolver (game/shell/area_rules.mjs) the director, the Builder and the editors share; an
Area overrides a preset by writing harm or no-harm in its own list, and a key that names no
rule fails load-world and the Builder’s publish. harm is real on the server (one gate in
area_server.gd’s combat tick) and on the client (no health bars where nothing can be hurt), so
the Village’s towers stand whole. The legacy descriptive strings (no_combat, open_combat, …)
were dropped from the world file: nothing had ever read them. docs/handoff/area-rules.md.
All earlier built work signed off on 2026-08-18: the Area model in the database, portals visible and
walkable, the authored world and its loader, both map surfaces, the entity class restructure,
and six rounds of what playing it found (009–016). The last piece — players stacking on the
arrival cell (was 008) — was fixed by the mini-games work on 2026-09-08: an arrival cell already
taken places the arrival on a free neighbour (area_server.gd).
Open issues: epic:world-map-and-portals — #42 your own house. Past task files (to 2026-09-13): workshop/historic-docs/epics/world-map-and-portals/tasks/.
What this is
Defined by Kris by voice on 2026-08-12, alongside accounts (server-architecture/010),
as the next significant build after the interface pass landed.
The world is organised into discrete areas — Kris’s working word is rooms, naming still open — linked to each other by portals. The public part of that graph is a shared, published thing: a village of Lor with portals out to a beginner battle arena, to the Badlands (desert), and onward. Every player also has a private part: their own home area, and portals to their friends’ realms. Both parts are one map with two layers, not two separate maps.
The map is a first-class artefact, not a UI convenience. Kris wants it in two places:
- On the public website, standalone — something people can look at without playing, showing how the world hangs together. A server picker sits above it, because there will be more than one server.
- In the game, reachable from the interface, showing the same public graph plus the player’s own private layer.
Kris has drawn a paper sketch of the Lor map. It is not yet in the repo — it needs to be photographed and added before the visual design of either surface is settled; the sketch is the source of truth for the initial public topology, not anything an agent invents.
Superseded, 2026-08-15. The sketch was never photographed in, and it is no longer
blocking: Kris commissioned the map’s design instead (three handoffs and two .dc.html
mocks, in land-of-lor/docs/design/ClaudeDesignWorldMapBrief/), and its nine-area world —
Village of Lor, Bazaar, Beginner Arena, The Badlands, Deep Cut, Wizard Battle Pit,
and three private homes — is the starting topology, now authored in
land-of-lor/game/content/spellgrove.world.json. If the sketch turns up it becomes an edit
in the world editor, not a rebuild.
Why it exists as its own epic
It sits across three existing epics without belonging to any of them: server-architecture
owns the transport and the authoritative state, public-site-and-comms owns the website,
world-traversal-and-ground owns what the ground under your feet is made of. None of them
owns the shape of the world at the scale of areas — which areas exist, what links them,
what rules each one imposes, and how a player reads that at a glance. That’s this epic.
The substrate that already exists
This is not a green field. The multiplayer work adopted into land-of-lor/game/ already
carries most of the primitives, and any plan should build on them rather than re-invent:
worldstable (game/director/src/schema.sql) — id, name,owner_id, a JSONB snapshot blob,last_played_at. An “area” is a world row today.world_members— membership as an explicit whitelist, owner included. This is already the mechanism for “my realm, and the friends I let in.”- Portals are implemented, not hypothetical:
PortalConfigSchema/SetWorldPortalsRequest(which grid cells are portals and where each leads) and theportal_transfer_*control messages that move an entity between world processes via Postgres, carrying its full state and a spawn token. Seegame/director/src/protocol.ts. - A public commons world —
JoinPublicWorldRequestfinds-or-creates it and auto-members the caller, so strangers land in the same place.
So the graph the map draws is, structurally, worlds as nodes and portal configs as
directed edges. What’s missing is: the graph is currently a test-scoped configuration
detail, not a designed, named, rule-bearing thing anybody can look at.
The offline requirement — stated now, deliberately
Kris’s explicit call, 2026-08-12: the finished game must be playable offline. He recognises it is probably not achievable on the current build, and is stating it now anyway so that nothing gets architected in a way that forecloses it.
Offline play does not mean the same game with the network removed. Shared areas are inherently unavailable offline, and resource rules may have to differ. But that is not a special case bolted on later — it belongs to a broader principle Kris raised in the same breath: different areas already impose different rules. A battle arena, for example, probably won’t let you bring your whole inventory in. Once “an area carries its own rule set” is a real, designed concept, “offline” becomes one more rule set rather than a second codebase.
Open, and deliberately not decided here: what happens to resources gathered offline, and
whether offline progress reconciles with the server on reconnect. The worlds table
already carries last_played_at from day one specifically to keep offline progression
possible without a migration.
Scope
- Naming the concept (“rooms”? areas? realms?) and settling it.
- The area/portal graph model: what an area is as a designed object, what rules it can carry, how portals are authored rather than test-configured.
- The public topology, from Kris’s sketch.
- The public/private split: home areas, friends’ realms, who can see what on whose map.
- Multiple servers, and what a server means to a player choosing one from a dropdown.
- Two rendering surfaces (site page, in-game screen) from one source of truth.
- Offline play as a stated end-state requirement that the model must not foreclose.
Non-goals
- Not accounts and login — that’s
server-architecture/010, which this epic depends on for any personal/private map to mean anything. - Not ground types or moment-to-moment traversal within an area — that’s
world-traversal-and-ground. - Not building offline play now. Stating it as a requirement, and not blocking it.
Key open questions
- What are areas called? (Kris: “rooms for now.”)
- Is the map authored (a designed, hand-laid topology) or derived (drawn from whatever
worlds+ portal rows happen to exist)? This is the single biggest fork for both surfaces, and it decides whether the site page is a static asset or a live view. - What does a “server” mean to a player — a shard with its own worlds and its own population, or something lighter?
- What does the private layer reveal? Do you see a friend’s realm on your map before they’ve let you in?
Deliverables (3)
- #43 — Furniture, twelve Persian rugs and Madame Zahra — and everything on a cell at once (2026-10-28)
- #41 — Your own house in the Village — the design sheet, and how Kris voted (2026-10-26, promised)
- #29 — The floating islands — a trial build where the neighbouring places float beside the one you stand in (2026-09-15)
Work on this epic
The granular work is GitHub Issues, one label per epic:
epic:world-map-and-portals
(private repository — sign-in required).
The dated Where this stands section above names the open ones.
The task files that carried this epic until 2026-09-13 are kept in the repo:
task files to 2026-09-13
.
Ask an agent about this epic
Paste your AI Task Runner API key once. It stays in this browser and is sent only to kris.ai-task-runner.com.
Also available as raw markdown.