Migration: consolidate Echo6 docs to cortex with full infrastructure cleanup sync
- Documents recent infrastructure cleanup (8 CTs destroyed, 35 DNS records removed, Headscale cleanup) - Adds 24 new runbooks covering Authentik, PeerTube, Meshtastic, RECON, Proxmox, Mailcow, Internet Archive, GPU routing - Adds project documentation for headscale, vaultwarden, peertube, matrix, mmud, advbbs, arr stack - Updates services.md, environment.md, caddy.md, authentik.md to match live infrastructure - Removes 4 deprecated runbook duplicates (canonical versions live in projects/) - Adds .gitignore for binary archives and editor temp files Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
89834796ff
commit
e9231ac24a
93 changed files with 51223 additions and 254 deletions
152
projects/mmud/mmud-prompts/mmud-prompts/01-update-planned.md
Normal file
152
projects/mmud/mmud-prompts/mmud-prompts/01-update-planned.md
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
# Task: Update planned.md with new design sections
|
||||
|
||||
Edit `/home/zvx/projects/mmud/docs/planned.md` in place. Three additions plus resolved decisions updates.
|
||||
|
||||
---
|
||||
|
||||
## Addition 1: The Last Ember — Town Hub
|
||||
|
||||
Find the `## Atmosphere & Writing` section. **BEFORE** the `---` divider that separates Atmosphere from `## New Player Onboarding`, insert this new section:
|
||||
|
||||
```markdown
|
||||
---
|
||||
|
||||
## The Last Ember — Town Hub
|
||||
|
||||
The Last Ember is the one room that never changes. Epochs wipe the dungeon, reskin the narrative, randomize everything — but players always wake up in the same bar, with the same people, who remember them. The lanterns don't burn oil — they just burn. Nobody lights them. Nobody replaces them. The dungeon reshapes itself every 30 days but the Last Ember sits at the mouth of it like a tooth that won't come loose.
|
||||
|
||||
The Last Ember is the constant across every epoch, every server, every wipe. It is the frame for the entire game.
|
||||
|
||||
### Grist — The Barkeep
|
||||
|
||||
Has never left the bar. Not once. Players who've been around for dozens of epochs start to wonder if he *can*. He knows everything that happens in the dungeon — not because he goes there, but because everyone who comes back tells him, and he never forgets. He speaks in short, deliberate sentences. Never wastes a word. He pours drinks that are always exactly what you needed, even if you didn't order.
|
||||
|
||||
His recap isn't a service — it's a compulsion. He *has* to tell you what happened. Like the information would burn him if he held it.
|
||||
|
||||
He's the bard token system. He trades in stories, not gold. Bring him something interesting — a secret, a discovery, something nobody else knows — and he gives you something back. Information, a temporary edge, a nudge in the right direction. He doesn't trade because he's kind. He trades because he *collects*.
|
||||
|
||||
**Mechanical role:** Recap (free), bard token exchange, hints, epoch vote ballot, bounty board.
|
||||
|
||||
### Maren — The Healer
|
||||
|
||||
Used to be an adventurer. Went deeper than anyone. Came back wrong — not injured, just *done*. She won't say what she saw on the lowest floor. She heals with her hands, not magic, and it hurts. She's efficient, not gentle. She charges gold because she says free healing breeds carelessness, and she's tired of patching people up who didn't respect the dungeon.
|
||||
|
||||
She's the only NPC who will occasionally refuse to talk to you if you died doing something stupid — but she still heals you.
|
||||
|
||||
She has a scar across her left palm that she got "the last time." She won't say the last time of what.
|
||||
|
||||
**Mechanical role:** HP restoration for gold.
|
||||
|
||||
### Torval — The Merchant
|
||||
|
||||
Doesn't go into the dungeon either, but somehow his inventory matches what's down there each epoch. Nobody asks how. He appraises items by weight and sound — taps gear on the counter, listens, names a price. He's cheerful in a way that feels slightly wrong given where he operates. He tells bad jokes. He calls everyone "friend" and means it exactly zero percent. He'd sell you a cursed sword and sleep fine.
|
||||
|
||||
But his prices are fair and his stock is real, which is more than you can say for most people in a town built around a hole full of monsters.
|
||||
|
||||
He keeps a ledger that goes back further than the bar. The pages at the front are in a language nobody can read.
|
||||
|
||||
**Mechanical role:** Buy, sell, item appraisal.
|
||||
|
||||
### Whisper — The Sage
|
||||
|
||||
Nobody knows if Whisper is her name or a description of how she talks. She sits in the corner of the Last Ember, always the same corner, and she knows things about the dungeon that change each epoch — lore, history, connections between rooms, what the symbols mean. She speaks in fragments and riddles not because she's trying to be mysterious but because that's how the information comes to her. She describes it like listening to a conversation through a wall.
|
||||
|
||||
Her clues are genuine but filtered through whatever broke her ability to just *say things plainly*. Players who pay attention to her exact phrasing find secrets faster. Players who dismiss her as flavor text miss half the game.
|
||||
|
||||
She has been the same age for as long as anyone can remember.
|
||||
|
||||
**Mechanical role:** Lore hints, secret clues, puzzle guidance (via bard tokens).
|
||||
|
||||
### NPC Live Conversations — LLM at Runtime
|
||||
|
||||
The "zero LLM at runtime" rule has one exception: talking to NPCs in the Last Ember. Walking up to Grist and having an actual conversation, asking Maren about her scar, trying to get Whisper to speak plainly — these interactions use a live LLM call.
|
||||
|
||||
The 150-character limit IS the NPC's personality. Grist is terse by nature. Maren doesn't waste words. Whisper speaks in fragments. Torval talks fast. The constraint is the flavor.
|
||||
|
||||
**Command:** `talk <npc>` or `talk <npc> <message>` — free action (in town only). Opens or continues a conversation.
|
||||
|
||||
**System prompt per NPC includes:**
|
||||
- Full backstory and personality card
|
||||
- Current game state injection: active bounties, recent deaths, Breach status, epoch day, floor control percentages, raid boss HP — whatever is relevant. The NPC *knows what's happening.*
|
||||
- Hard rules: respond in character, NEVER break character, response MUST be under 150 characters, never reveal exact secret locations or puzzle solutions (hints only), never acknowledge being an AI, never discuss anything outside the game world.
|
||||
|
||||
**What each NPC brings:**
|
||||
- **Grist** — gossip and world state. Knows everything from broadcast logs. Ask about another player and he'll tell you what they've been up to. Dry, factual, slightly unsettling in how much he knows.
|
||||
- **Maren** — the human element. Comments on your injuries, your play pattern, your stubbornness. Has opinions about the dungeon. Will never talk about what she saw on the lowest floor no matter how hard you try.
|
||||
- **Torval** — comic relief and commerce. Banter about items, terrible jokes, comments on your gear. "You're wearing THAT to floor 3? Bold." Embellished sales pitches.
|
||||
- **Whisper** — lore oracle. High-skill conversation. Speaks in fragments. Ask the right questions and get real, useful information about secrets. Her cryptic style is the LLM prompt, not a gimmick — talking to Whisper IS a puzzle.
|
||||
|
||||
**Guardrails:**
|
||||
- Conversation memory is session-only — NPCs don't remember yesterday's chat. Keeps context windows small and prevents exploit accumulation.
|
||||
- If the LLM fails or times out, fall back to a random pre-generated dialogue snippet from the batch pipeline (20 per NPC already generated at epoch start).
|
||||
- No rate limit on NPC conversations. Players can talk as long as they want. The NPCs are storytellers and historians — extended conversation is a feature, not abuse.
|
||||
- Uses the same pluggable LLM backend as the epoch generation pipeline (Anthropic, OpenAI, Google, or Dummy).
|
||||
|
||||
**Server History Seed — 2 Years of Lore:**
|
||||
|
||||
Before the server goes live, generate 24 epochs (2 years) of simulated history. Each epoch gets: number, endgame mode, Breach type, narrative theme, win/loss result, 3-5 notable players (generated names, classes, what they did), 1-2 memorable moments, hall of fame entries, titles earned. Stored in the persistent tables. When the real server starts on epoch 25, the NPCs have 24 epochs of stories to tell. A compressed lore packet (20-30 sentences of highlights) is injected into every NPC system prompt and regenerated each epoch as real player history accumulates and blends with seeded history.
|
||||
|
||||
**Cost math:** At Haiku-tier pricing, ~500 tokens per turn. Even heavy usage (50+ turns/day across all players) is ~$0.006/day. Unlimited conversation is essentially free.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Addition 2: Command Discovery
|
||||
|
||||
Find the `## New Player Onboarding` section. After the "Daily Tips" subsection and before the `---` divider that separates it from `## Resolved Decisions`, insert:
|
||||
|
||||
```markdown
|
||||
### Command Discovery — No Guessing on Slow Radio
|
||||
|
||||
On a 45-60 second radio round-trip, guessing a command and getting "Unknown command" is unacceptable. Every interaction point should make available commands visible.
|
||||
|
||||
**First connect message:** Include core commands explicitly. Not "type H for help" — actually list them. `Move:N/S/E/W Fight:F Look:L Flee:FL Stats:ST Help:H` fits in 150 chars and gives a new player everything for their first session.
|
||||
|
||||
**Smart error responses:** Never just "Unknown command." Always suggest valid commands based on current player state:
|
||||
- In town: `Unknown. Try: BAR SHOP HEAL BANK TRAIN ENTER H(elp)`
|
||||
- In dungeon: `Unknown. Try: F(ight) FL(ee) L(ook) N/S/E/W H(elp)`
|
||||
- In combat: `Unknown. Try: F(ight) FL(ee) STATS`
|
||||
- Dead: `Unknown. You're dead. Type RESPAWN.`
|
||||
|
||||
**Context-sensitive help (H command):** `H` alone shows commands available in current state. `H <cmd>` gives specific help. All fits 150 chars. Help output changes based on player level — only shows unlocked commands.
|
||||
|
||||
**Barkeep nudges:** When a player visits Grist but hasn't used a system yet, the recap appends a tip: "Tip: try BOUNTY to see active hunts" or "Tip: use MSG to leave notes in rooms." One tip per visit, rotating through unused systems. Stops once the player has tried everything.
|
||||
|
||||
**Progressive unlock announcements:** When a command unlocks at a new level, announce it explicitly with usage: "⬆ Level 3! New: SHOP(buy gear) BANK(save gold) MAIL(send messages)"
|
||||
|
||||
**Last Ember quick reference:** The spectator web page includes a printable command cheat sheet — a one-page reference players can keep next to their Meshtastic device. Physical reference for a physical radio game.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Addition 3: Resolved Decisions
|
||||
|
||||
Find the `## Resolved Decisions` section. Add these lines at the end of the list:
|
||||
|
||||
```markdown
|
||||
- Town hub: The Last Ember — persistent bar across all epochs, all servers. Four permanent NPCs: Grist (barkeep), Maren (healer), Torval (merchant), Whisper (sage).
|
||||
- NPC live conversations: NPCs are sim nodes on the mesh (GRST, MRN, TRVL, WSPR). Players DM them directly. Three rule layers: unknown node gets static onboarding, known player not in bar gets static rejection, known player in bar gets full LLM conversation. No rate limit. Session-only memory. Falls back to pre-generated dialogue on failure. 24-epoch history seed provides 2 years of lore.
|
||||
- Command discovery: smart error responses show valid commands for current state, barkeep nudges for unused systems, explicit command listing on first connect.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Addition 4: LLM Content Pipeline update
|
||||
|
||||
Find the `## LLM Content Pipeline` section. Find the line that says `### Decision Rule` and the text `Use LLMs for content that can be validated offline. Use deterministic templates for anything that must be correct in real-time.`
|
||||
|
||||
Replace that with:
|
||||
|
||||
```markdown
|
||||
### Decision Rule
|
||||
|
||||
Use LLMs for content that can be validated offline. Use deterministic templates for anything that must be correct in real-time. **One exception:** NPC conversations in The Last Ember use live LLM calls — the 150-char response constraint, personality cards, and session-only memory make this safe, cheap, and in-character. See The Last Ember section for details.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Commit
|
||||
|
||||
```bash
|
||||
git add -A && git commit -m "Design doc: add Last Ember NPCs, live NPC conversations, command discovery"
|
||||
```
|
||||
102
projects/mmud/mmud-prompts/mmud-prompts/02-npc-nodes.md
Normal file
102
projects/mmud/mmud-prompts/mmud-prompts/02-npc-nodes.md
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
# Task: Add NPC sim node architecture and rules to planned.md
|
||||
|
||||
Edit `/home/zvx/projects/mmud/docs/planned.md` in place.
|
||||
|
||||
---
|
||||
|
||||
## Edit 1: NPC Sim Nodes section
|
||||
|
||||
Find the `### NPC Live Conversations — LLM at Runtime` subsection inside `## The Last Ember — Town Hub`. Replace the **Command** line and everything after it in that subsection (from `**Command:**` through the end of `**Cost math:**`) with the following:
|
||||
|
||||
```markdown
|
||||
**Network Architecture — NPCs as Mesh Nodes:**
|
||||
|
||||
The NPCs are literal Meshtastic nodes on the mesh network. Five sim nodes, all backed by the same game database:
|
||||
|
||||
- **EMBR** — The Last Ember. The game server. All game commands go here.
|
||||
- **GRST** — Grist. DM this node to talk to the barkeep.
|
||||
- **MRN** — Maren. DM this node to talk to the healer.
|
||||
- **TRVL** — Torval. DM this node to talk to the merchant.
|
||||
- **WSPR** — Whisper. DM this node to talk to the sage.
|
||||
|
||||
Players don't issue a `talk` command — they DM the NPC's node directly. The game server sees inbound on the NPC node ID, checks the rules below, and routes the response back through that NPC's node. The NPCs are *people on the network*, not menu options.
|
||||
|
||||
**Three rule layers (checked in order):**
|
||||
|
||||
**Rule 1 — Unknown node (not in the game):** Static in-character rejection with onboarding instructions. No LLM call. Each NPC has a fixed response:
|
||||
- Grist: `"Don't know you. DM EMBR to start. Then we'll talk."`
|
||||
- Maren: `"I only patch up adventurers. DM EMBR to become one."`
|
||||
- Torval: `"No account, no credit, friend. DM EMBR to join up."`
|
||||
- Whisper: `"...not yet. EMBR. Begin there."`
|
||||
|
||||
**Rule 2 — Known player, not in the bar:** Static in-character refusal. Player is in the dungeon, dead, or otherwise not in town. No LLM call.
|
||||
- Grist: `"You're not here, {name}. Come back to the bar first."`
|
||||
- Maren: `"I can hear you're still down there. Come back alive."`
|
||||
- Torval: `"I don't do deliveries. Get back to the Ember."`
|
||||
- Whisper: `"...too far. Return."`
|
||||
|
||||
**Rule 3 — Known player, in the bar:** Full LLM conversation. This is the only case that triggers a live LLM call.
|
||||
|
||||
**System prompt per NPC includes:**
|
||||
- Full backstory and personality card
|
||||
- Current game state injection: active bounties, recent deaths, Breach status, epoch day, floor control percentages, raid boss HP — whatever is relevant. The NPC *knows what's happening.*
|
||||
- Hard rules: respond in character, NEVER break character, response MUST be under 150 characters, never reveal exact secret locations or puzzle solutions (hints only), never acknowledge being an AI, never discuss anything outside the game world.
|
||||
|
||||
**What each NPC brings:**
|
||||
- **Grist** — gossip and world state. Knows everything from broadcast logs. Ask about another player and he'll tell you what they've been up to. Dry, factual, slightly unsettling in how much he knows.
|
||||
- **Maren** — the human element. Comments on your injuries, your play pattern, your stubbornness. Has opinions about the dungeon. Will never talk about what she saw on the lowest floor no matter how hard you try.
|
||||
- **Torval** — comic relief and commerce. Banter about items, terrible jokes, comments on your gear. "You're wearing THAT to floor 3? Bold." Embellished sales pitches.
|
||||
- **Whisper** — lore oracle. High-skill conversation. Speaks in fragments. Ask the right questions and get real, useful information about secrets. Her cryptic style is the LLM prompt, not a gimmick — talking to Whisper IS a puzzle.
|
||||
|
||||
**Guardrails:**
|
||||
- Conversation memory is session-only — NPCs don't remember yesterday's chat. Keeps context windows small and prevents exploit accumulation.
|
||||
- If the LLM fails or times out, fall back to a random pre-generated dialogue snippet from the batch pipeline (20 per NPC already generated at epoch start).
|
||||
- No rate limit on NPC conversations. Players can talk as long as they want. The NPCs are storytellers, historians, and characters — extended conversation is a feature, not abuse.
|
||||
- Uses the same pluggable LLM backend as the epoch generation pipeline (Anthropic, OpenAI, Google, or Dummy).
|
||||
|
||||
**Server History Seed — 2 Years of Lore:**
|
||||
|
||||
Before the server goes live, generate 24 epochs (2 years) of simulated history. For each epoch:
|
||||
- Epoch number, endgame mode, Breach type, narrative theme
|
||||
- Whether the server won or lost (mix of both — some epic victories, some heartbreaking failures)
|
||||
- 3-5 notable players per epoch (generated names, classes, levels reached, what they did)
|
||||
- 1-2 memorable moments per epoch ("Kira carried the Crown from floor 4 to floor 1 with 3 HP", "The Warden stood for 28 days — the server failed on the final push", "Epoch 11's Raid Boss had No Escape + Enraged — three players died on the killing blow")
|
||||
- Hall of fame entries, titles earned
|
||||
|
||||
Stored in the persistent tables (accounts, hall_of_fame, hall_of_fame_participants, titles). When the real server starts on epoch 25, the NPCs have 24 epochs of history to draw from. Grist drops names of old champions. Maren compares your injuries to legends. Torval mentions gear from epochs past. Whisper sees patterns across cycles that nobody else notices.
|
||||
|
||||
**NPC context injection includes a lore packet:** A compressed 20-30 sentence summary of server history highlights pulled from the hall of fame tables. Regenerated at each epoch start so it stays current as real player history accumulates and blends with the seed history. The NPCs don't distinguish between seeded and real history — it's all the same to them.
|
||||
|
||||
**Cost math:** At Haiku-tier pricing, ~500 tokens per conversation turn. Even heavy usage (50 turns/day across all players) is ~25,000 tokens/day ≈ $0.006/day. Unlimited conversation is essentially free.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Edit 2: Update Resolved Decisions
|
||||
|
||||
Find the resolved decision line that says:
|
||||
```
|
||||
- NPC live conversations: LLM at runtime exception for talk command in town. Session-only memory, 5/day rate limit per NPC, falls back to pre-generated dialogue on failure.
|
||||
```
|
||||
|
||||
Replace it with:
|
||||
```
|
||||
- NPC live conversations: NPCs are sim nodes on the mesh (GRST, MRN, TRVL, WSPR). Players DM them directly. Three rule layers: unknown node gets static onboarding response, known player not in bar gets static rejection, known player in bar gets full LLM conversation. No rate limit. Session-only memory. Falls back to pre-generated dialogue on failure. 24-epoch history seed provides 2 years of lore for NPCs to draw from.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Edit 3: Add to Open Questions
|
||||
|
||||
Add this to the end of the `## Open Questions` list:
|
||||
```
|
||||
- NPC sim node deployment — which host runs meshtasticd with 5 identities, TCP routing to game LXC
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Commit
|
||||
|
||||
```bash
|
||||
git add -A && git commit -m "Design doc: NPCs as mesh sim nodes, three-layer access rules, onboarding funnel"
|
||||
```
|
||||
61
projects/mmud/mmud-prompts/mmud-prompts/03-darkcragg.md
Normal file
61
projects/mmud/mmud-prompts/mmud-prompts/03-darkcragg.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# Task: Add Darkcragg Depths dungeon name to planned.md
|
||||
|
||||
Edit `/home/zvx/projects/mmud/docs/planned.md` in place.
|
||||
|
||||
---
|
||||
|
||||
## Edit 1: Dungeon section
|
||||
|
||||
Find the `## Dungeon` section. Find the line `### Hub-Spoke Layout with Loops`. Insert a new subsection BEFORE it:
|
||||
|
||||
```markdown
|
||||
### The Darkcragg Depths
|
||||
|
||||
The dungeon is always the Darkcragg Depths. Like the Last Ember, the name is a constant — it persists across every epoch, every server, every wipe. The floors reskin, the layout regenerates, the monsters change, but the Depths are always the Depths. Players descend into the Darkcragg. They talk about the Darkcragg. It's a proper noun, not a generic dungeon.
|
||||
|
||||
The four floors are narratively re-skinned each epoch (Sunken Halls, Fungal Depths, Ember Caverns, Void Reach are defaults — the LLM pipeline may rename them) but the Darkcragg Depths is the name on the door every time.
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Edit 2: Update The Last Ember section
|
||||
|
||||
Find the paragraph in `## The Last Ember — Town Hub` that starts with "The Last Ember is the constant across every epoch". Replace that single line with:
|
||||
|
||||
```markdown
|
||||
The Last Ember and the Darkcragg Depths are the two constants across every epoch, every server, every wipe. The bar and the hole it sits on top of. Everything else changes. These don't.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Edit 3: Update NPC rejection messages
|
||||
|
||||
Find the Rule 2 static responses for known players not in the bar. Update Maren's line:
|
||||
|
||||
Replace:
|
||||
```
|
||||
- Maren: `"I can hear you're still down there. Come back alive."`
|
||||
```
|
||||
With:
|
||||
```
|
||||
- Maren: `"I can hear you're still in the Darkcragg. Come back alive."`
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Edit 4: Resolved Decisions
|
||||
|
||||
Add to the end of the `## Resolved Decisions` list:
|
||||
|
||||
```markdown
|
||||
- Dungeon name: The Darkcragg Depths — persistent across all epochs like the Last Ember. Floor names reskin per epoch but the Darkcragg is always the Darkcragg.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Commit
|
||||
|
||||
```bash
|
||||
git add -A && git commit -m "Design doc: the dungeon is the Darkcragg Depths"
|
||||
```
|
||||
75
projects/mmud/mmud-prompts/mmud-prompts/04-dcrg-node.md
Normal file
75
projects/mmud/mmud-prompts/mmud-prompts/04-dcrg-node.md
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
# Task: Add Darkcragg Depths broadcast node to planned.md
|
||||
|
||||
Edit `/home/zvx/projects/mmud/docs/planned.md` in place.
|
||||
|
||||
---
|
||||
|
||||
## Edit 1: Update NPC Sim Nodes section
|
||||
|
||||
Find the `**Network Architecture — NPCs as Mesh Nodes:**` block inside `## The Last Ember — Town Hub`. Replace the node list (the 5-item bullet list starting with `- **EMBR**` through `- **WSPR**`) with:
|
||||
|
||||
```markdown
|
||||
- **EMBR** — The Last Ember. The game server. All game commands go here. Responds with direct action results only.
|
||||
- **DCRG** — The Darkcragg Depths. One-way broadcast node. All dungeon events come from here — deaths, bounty progress, Breach opening, regen ticks, boss phase transitions, discoveries, level-ups. Does not accept commands. The dungeon is alive on the network.
|
||||
- **GRST** — Grist. DM this node to talk to the barkeep.
|
||||
- **MRN** — Maren. DM this node to talk to the healer.
|
||||
- **TRVL** — Torval. DM this node to talk to the merchant.
|
||||
- **WSPR** — Whisper. DM this node to talk to the sage.
|
||||
|
||||
This splits two distinct streams: EMBR only sends direct responses to your actions. DCRG is the ambient feed of what's happening in the world. The NPCs are people you talk to. Six nodes total, one game DB backing all of them.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Edit 2: Add DCRG rules to the rule layers
|
||||
|
||||
Find `**Three rule layers (checked in order):**`. Insert a new section BEFORE Rule 1:
|
||||
|
||||
```markdown
|
||||
**DCRG rules (broadcast node):**
|
||||
- DCRG never accepts inbound messages. If a player or unknown node DMs DCRG, it responds with a static message: `"The Darkcragg does not answer. It only speaks. DM EMBR to play."`
|
||||
- All tier 1 and tier 2 broadcasts are sent FROM the DCRG node, not EMBR.
|
||||
- Targeted broadcasts (multi-room puzzle feedback) are also sent from DCRG as DMs to qualifying players.
|
||||
- DCRG is the voice of the dungeon. When someone dies, when the Breach opens, when a bounty falls — it comes from the Darkcragg.
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Edit 3: Update Broadcast System section
|
||||
|
||||
Find `## Broadcast System`. Find the first paragraph or description of how broadcasts work. Add this line at the end of the introductory text, before any subsections:
|
||||
|
||||
```markdown
|
||||
All broadcasts are sent from the DCRG (Darkcragg Depths) sim node, not the main EMBR game node. This separates the ambient world feed from direct command responses. EMBR talks to you. The Darkcragg talks about everyone.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Edit 4: Update Resolved Decisions
|
||||
|
||||
Find the resolved decision about NPC live conversations that starts with `- NPC live conversations: NPCs are sim nodes`. Replace it with:
|
||||
|
||||
```markdown
|
||||
- Mesh node architecture: 6 sim nodes — EMBR (game commands + responses), DCRG (one-way dungeon broadcasts), GRST/MRN/TRVL/WSPR (NPC conversations). One game DB backs all of them.
|
||||
- NPC conversations: Players DM NPC nodes directly. Three rule layers: unknown node gets static onboarding, known player not in bar gets static rejection, known player in bar gets full LLM conversation. Session-only memory, 5/day rate limit per NPC, falls back to pre-generated dialogue on failure.
|
||||
- DCRG is broadcast-only — does not accept commands. All tier 1/2 and targeted broadcasts route through DCRG.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Edit 5: Update Open Questions
|
||||
|
||||
Find the open question `- NPC sim node deployment`. Replace it with:
|
||||
|
||||
```markdown
|
||||
- Sim node deployment — which host runs meshtasticd with 6 identities (EMBR, DCRG, GRST, MRN, TRVL, WSPR), TCP routing to game LXC
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Commit
|
||||
|
||||
```bash
|
||||
git add -A && git commit -m "Design doc: DCRG broadcast node — the dungeon speaks on the mesh"
|
||||
```
|
||||
215
projects/mmud/mmud-prompts/mmud-prompts/05-phase5.md
Normal file
215
projects/mmud/mmud-prompts/mmud-prompts/05-phase5.md
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
# Task: MMUD Phase 5 — Endgame Modes
|
||||
|
||||
## Before Writing Any Code
|
||||
|
||||
Re-read these sections of `/home/zvx/projects/mmud/docs/planned.md`:
|
||||
- Endgame: Three Rotating Modes (all of it — mode selection, R&E with Pursuer + support roles, Raid Boss with mechanic tables + phases, Hold the Line with regen + checkpoints + floor bosses)
|
||||
- The Darkcragg Depths (dungeon name context)
|
||||
- Floor Boss Mechanic Tables (all 4 floor tables)
|
||||
- Bounties During Hold the Line
|
||||
|
||||
Also re-read `config.py` for: HTL_REGEN_ROOMS_PER_DAY, FLOOR_BOSS_MECHANICS, WARDEN_HP/REGEN, RAID_BOSS_HP_PER_PLAYER/CAP/REGEN/MECHANIC_TABLE/PHASES, PURSUER_ADVANCE_RATE/SPAWN_DISTANCE/RELAY_RESET_DISTANCE, WARD/LURE constants, ENDGAME_MODES.
|
||||
|
||||
Phase 4 already generates floor bosses, raid boss pre-config, and bounties. This phase wires the runtime game logic for all three modes.
|
||||
|
||||
## Phase 5 Deliverables
|
||||
|
||||
All three endgame modes are playable. The epoch vote selects the mode. Each mode has its own win condition, progression mechanics, and broadcasts.
|
||||
|
||||
### 1. Epoch Vote System
|
||||
|
||||
`src/systems/vote.py` (new file)
|
||||
|
||||
- Day 30 trigger (already in daytick.py — wire it to the vote system)
|
||||
- `vote <mode>` command at barkeep — free action. Modes: `retrieve`, `raid`, `hold` (or numbers 1/2/3).
|
||||
- Votes are public — broadcast on cast: "🗳 {name} voted {mode}."
|
||||
- Votes can be changed up until epoch ends. UPSERT into epoch_votes table.
|
||||
- Tally on epoch end: most votes wins. Tiebreak: longest-unplayed mode. No quorum — 1 vote decides if only 1 player votes. Zero votes → longest-unplayed auto-selected.
|
||||
- `epoch_generate.py` already accepts endgame mode — wire the vote result into the next epoch's generation.
|
||||
|
||||
### 2. Hold the Line — Runtime Logic
|
||||
|
||||
`src/systems/endgame_htl.py` (new file)
|
||||
|
||||
**Room clearing:**
|
||||
- All dungeon rooms start hostile (`htl_cleared = 0`)
|
||||
- Killing all monsters in a room sets `htl_cleared = 1` with timestamp
|
||||
- Regen ticks (already in daytick.py) revert rooms: pick N random cleared non-checkpoint rooms per floor per day, set `htl_cleared = 0`, respawn monsters. Spread ticks across the day (floor 2 at 5/day = 1 room every ~5 hours).
|
||||
- Cleared rooms are safe — no random encounters. Reverted rooms respawn monsters.
|
||||
|
||||
**Checkpoints:**
|
||||
- Checkpoint rooms are defined during worldgen (is_checkpoint = 1 in rooms table). 3 per floor (hub, midpoint, stairway), 1 on floor 4 (Warden).
|
||||
- Establishment condition: all rooms in the checkpoint cluster (checkpoint room + all adjacent rooms) must be cleared within one regen window. Check on each room clear — if the cluster is complete, spawn the floor boss.
|
||||
- Once the floor boss dies, checkpoint locks permanently. `htl_checkpoints.established = 1`. Regen can never revert rooms behind an established checkpoint.
|
||||
- Final checkpoint on each floor (stairway) unlocks the next floor for all players.
|
||||
|
||||
**Floor bosses:**
|
||||
- Already generated with rolled mechanics (from Phase 4 bossgen).
|
||||
- Floor boss spawns in the checkpoint room when cluster is cleared. Uses the same shared HP pool / chip-and-run combat as bounties.
|
||||
- Boss mechanic implementation — each mechanic modifies combat behavior:
|
||||
- `armored` — damage halved until boss below 50% HP
|
||||
- `enraged` — boss deals double damage below 50% HP, takes 25% more
|
||||
- `regenerator` — boss heals 10% HP between sessions (check on engagement, apply since last fight)
|
||||
- `stalwart` — first flee attempt per engagement always fails
|
||||
- `warded` — boss has +50% DEF until a discovery secret on the same floor is found (check secret_progress)
|
||||
- `phasing` — boss is immune to damage on even-numbered epoch days (check epoch.day_number)
|
||||
- `draining` — boss steals 10% of damage dealt as HP from the attacker
|
||||
- `splitting` — at 50% HP, boss splits into two half-HP monsters in adjacent rooms. Both must die.
|
||||
- `rotating_resistance` — immune to the highest stat used by the last player who fought it. Track in DB.
|
||||
- `retaliator` — reflects 20% of damage back to attacker
|
||||
- `summoner` — spawns 1 add at start of each engagement. Add must die before boss can be damaged.
|
||||
- `cursed` — player who dealt most damage last session gets -2 to a random stat next login
|
||||
|
||||
- Floor 4 Warden: shared HP pool 300-500, regen at 3%/8h, rolls 2 mechanics from the full table.
|
||||
- Warden kill = epoch win. Broadcast: "🏆 The Warden has fallen! The Darkcragg Depths are conquered!"
|
||||
|
||||
**Broadcasts from DCRG:**
|
||||
- "🏰 Floor {n} Checkpoint {name} established!"
|
||||
- "⚠ Floor {n} lost {x} rooms. Frontline at {room}."
|
||||
- "🏰 Floor {n} unlocked! The descent continues."
|
||||
- "💀 Floor {n} frontline collapsed to Checkpoint {name}. Rally!"
|
||||
- Floor boss spawned, floor boss killed, Warden progress.
|
||||
|
||||
**Barkeep integration:**
|
||||
- Grist's recap includes HtL status: floors cleared percentage, checkpoint status, frontline position.
|
||||
|
||||
### 3. Raid Boss — Runtime Logic
|
||||
|
||||
`src/systems/endgame_raid.py` (new file)
|
||||
|
||||
**Activation:**
|
||||
- On epoch start (if mode is raid_boss), calculate active player count (anyone who entered the dungeon in first 3 days).
|
||||
- Set raid_boss.hp = 300 × active players, cap 6000. Set raid_boss.hp_max to same value.
|
||||
- Place boss in a room on floor 3-4 (from pre-generated config in Phase 4).
|
||||
|
||||
**Combat:**
|
||||
- Same chip-and-run as bounties — shared HP pool, engage/damage/flee.
|
||||
- Regen: 3%/8h (lazy-evaluated like bounties — calculate on engagement).
|
||||
- Track contributions in raid_boss_contributors.
|
||||
|
||||
**Mechanic implementation (2-3 rolled):**
|
||||
- `windup_strike` — every 3rd combat round, next round deals triple damage unless player uses `defend` or `dodge` action. Add `defend` and `dodge` as combat commands (cost 1 action, negate the windup).
|
||||
- `flat_damage_boost` — boss damage multiplied by 1.5x
|
||||
- `retribution` — at 75%/50%/25% HP thresholds, burst damage (2x normal) to the player who pushed it past the threshold
|
||||
- `aura_damage` — player takes 5% max HP unavoidable damage each combat round regardless of DEF
|
||||
- `extra_regen` — regen rate becomes 5%/8h instead of 3%/8h
|
||||
- `armor_phase` — boss takes half damage until: a discovery secret on the floor is found, OR 5+ unique players have contributed damage
|
||||
- `boss_flees` — at 75%/50%/25% HP, boss relocates to random room on same floor. Broadcast from DCRG: "🐉 The {boss} has fled to somewhere on Floor {n}!" Players must find it.
|
||||
- `regen_burst` — once per day at a random hour, boss heals 15% max HP in one tick. Trackable through observation.
|
||||
- `no_escape` — below 25% HP, all flee attempts fail. Fight to the death.
|
||||
- `summoner` — 1-2 adds spawn per engagement, must be killed before boss takes damage
|
||||
- `lockout` — after engaging, player can't reengage for 24 hours. Store lockout_until in raid_boss_contributors.
|
||||
- `enrage_timer` — after 5 combat rounds in a single engagement, boss damage doubles each subsequent round
|
||||
|
||||
**Phases:**
|
||||
- Phase transitions at 66% and 33% HP (`RAID_BOSS_PHASES`).
|
||||
- At each threshold, rolled mechanics intensify. Implementation: each mechanic has a `phase_modifier(phase_num)` that scales its effect. E.g., summoner spawns 1 add in phase 1, 2 in phase 2, 3 in phase 3. Windup goes from every 3rd round to every 2nd.
|
||||
- Phase transition broadcasts from DCRG: "🐉 The {boss} enters its second phase!"
|
||||
|
||||
**Win condition:** Boss HP reaches 0. All contributors rewarded. Killing blow gets bonus. Broadcast: "🏆 The {boss} has been slain! Victory belongs to the Darkcragg!"
|
||||
|
||||
### 4. Retrieve and Escape — Runtime Logic
|
||||
|
||||
`src/systems/endgame_rne.py` (new file)
|
||||
|
||||
**Setup:**
|
||||
- Guardian monster placed on floor 4 during epoch generation (add to bossgen if not already there — a strong but non-boss monster guarding the objective).
|
||||
- `escape_run` table tracks run state.
|
||||
|
||||
**Claiming the objective:**
|
||||
- Player defeats the guardian on floor 4 → objective claimed. `escape_run.active = 1`, carrier set, pursuer spawns.
|
||||
- Broadcast from DCRG: "👑 {name} claimed the {objective}! The Pursuer stirs."
|
||||
- Monster spawn rates double on all floors (multiply spawn chance by `ESCAPE_SPAWN_RATE_MULTIPLIER`).
|
||||
|
||||
**Pursuer:**
|
||||
- Tracks carrier. Advances 1 room toward carrier every 2 carrier actions (`PURSUER_ADVANCE_RATE`).
|
||||
- Spawns 3 rooms behind carrier (`PURSUER_SPAWN_DISTANCE`).
|
||||
- Track pursuer position in `escape_run.pursuer_room_id`. Track fractional ticks in `pursuer_ticks`.
|
||||
- On every carrier action: increment pursuer_ticks. When pursuer_ticks >= PURSUER_ADVANCE_RATE, advance pursuer 1 room toward carrier (pathfind shortest route), reset ticks.
|
||||
- When pursuer enters carrier's room: forced combat. Pursuer is invulnerable (takes no damage). Hits hard. Carrier can only flee. Flee uses normal SPD check. Success = carrier moves 1 room. Failure = take damage + try again next action.
|
||||
|
||||
**Carrier death and relay:**
|
||||
- Carrier dies → objective drops at death room. Broadcast from DCRG: "💀 The carrier has fallen on Floor {n}. The {objective} lies unguarded."
|
||||
- `escape_run.objective_dropped = 1`, `dropped_room_id` set.
|
||||
- Any player can `pickup` the objective in that room.
|
||||
- On pickup: pursuer resets to 5 rooms behind new carrier (`PURSUER_RELAY_RESET_DISTANCE`). Broadcast: "👑 {name} picks up the {objective}! The Pursuer resets."
|
||||
- Death penalty still applies to the dead carrier (gold loss, respawn in town).
|
||||
|
||||
**Three support roles:**
|
||||
|
||||
**Blockers:**
|
||||
- Non-carrier in a room between pursuer and carrier. When pursuer reaches a blocker's room, forced combat with the blocker instead of advancing.
|
||||
- Blocker can't kill pursuer (invulnerable). Each round blocker survives = 1 round pursuer isn't moving.
|
||||
- Blocker can flee (normal SPD check). Blocker can die.
|
||||
- Broadcast: "🛡 {name} is blocking the Pursuer on Floor {n}!" and "💀 {name} fell holding the line. The Pursuer advances."
|
||||
- Implementation: on pursuer advance, check if any player is in the target room. If yes, pursuer enters combat with them instead of continuing.
|
||||
|
||||
**Warders:**
|
||||
- `ward` command in a cleared dungeon room (1 extra action after clearing = `WARD_ACTION_COST`). Sets `rooms.ward_active = 1`.
|
||||
- Warded room slows pursuer — takes 2 advance ticks to pass through instead of 1 (`WARD_PURSUER_SLOWDOWN`).
|
||||
- Ward breaks after one use (reset to 0 when pursuer passes through).
|
||||
- No broadcast on warding — silent preparation.
|
||||
|
||||
**Lures:**
|
||||
- `lure` command when on same floor as pursuer. Costs 2 actions (`LURE_ACTION_COST`).
|
||||
- Pursuer diverts toward lure player for 3 ticks (`LURE_DIVERT_TICKS`), then snaps back to carrier tracking. Total delay ~6 ticks (`LURE_TOTAL_DELAY_TICKS`) including backtrack.
|
||||
- Broadcast: "🎯 {name} lured the Pursuer into {room}! It diverts."
|
||||
- After divert expires: "👁 The Pursuer has reacquired the carrier."
|
||||
|
||||
**Pursuer distance broadcasts (from DCRG):**
|
||||
- "👁 The Pursuer is {n} rooms behind the carrier." (every 5 carrier actions)
|
||||
- "👁 The Pursuer is 3 rooms behind. It's closing."
|
||||
- "⚠ The Pursuer has reached the carrier!"
|
||||
|
||||
**Win condition:** Any player delivers objective to town (The Last Ember). Broadcast: "🏆 The {objective} has reached the surface! Victory belongs to the Darkcragg!"
|
||||
- All participants get epoch win credit (tracked in escape_participants by role).
|
||||
|
||||
### 5. Mode Activation in Engine
|
||||
|
||||
Update `src/core/engine.py` and `src/core/actions.py`:
|
||||
- On game start, check epoch.endgame_mode. Load the appropriate endgame system.
|
||||
- Mode-specific commands only available when that mode is active:
|
||||
- HtL: checkpoint status command, floor control display
|
||||
- Raid: raid boss status command (`boss` — show HP, phase, mechanics discovered so far)
|
||||
- R&E: `pickup`, `ward`, `lure`, `block` commands. Carrier status. Pursuer distance.
|
||||
- Combat system needs to dispatch to endgame boss combat (floor boss, raid boss, pursuer) when the target is a special entity. Same chip-and-run framework but with mechanic overlays.
|
||||
- Endgame status integrated into barkeep recap and stats display.
|
||||
|
||||
### 6. New Combat Commands
|
||||
|
||||
For raid boss mechanics:
|
||||
- `defend` / `def` — defensive stance. Negates windup strike. Costs 1 dungeon action. Does no damage that round.
|
||||
- `dodge` / `dge` — evasion. Negates windup strike. Costs 1 dungeon action. Does no damage that round.
|
||||
|
||||
For R&E:
|
||||
- `pickup` — pick up dropped objective in current room. Free action.
|
||||
- `ward` — ward current room after clearing it. 1 dungeon action.
|
||||
- `lure` — lure the Pursuer. 2 dungeon actions.
|
||||
- `block` — (passive) just being in the pursuer's path triggers blocking. No explicit command needed — the system detects it. But add a `block` info command that shows: "Stand in the Pursuer's path to block. It will fight you instead of advancing."
|
||||
|
||||
## Rules
|
||||
|
||||
- All responses under 150 chars. Test this.
|
||||
- All broadcasts route through DCRG node, not EMBR.
|
||||
- Endgame mode commands are only available when that mode is active. Other mode commands return: "That doesn't apply this epoch."
|
||||
- Boss combat uses the same chip-and-run framework as bounties — shared HP pool, damage persists, flee to disengage.
|
||||
- Floor boss and raid boss regen is lazy-evaluated (calculate accumulated regen on engagement).
|
||||
- Use constants from `config.py`.
|
||||
- Raw parameterized SQL, no ORM.
|
||||
- Commit after each mode is working (3 major commits minimum).
|
||||
|
||||
## Testing
|
||||
|
||||
Add to `tests/`:
|
||||
- `tests/test_vote.py` — vote casting, changing, public broadcast, tally, tiebreak, zero-vote fallback
|
||||
- `tests/test_htl.py` — room clearing, regen ticks, checkpoint cluster detection, checkpoint establishment, floor boss spawn on cluster clear, floor unlock, Warden kill = win, rooms behind checkpoint immune to regen
|
||||
- `tests/test_boss_mechanics.py` — test each of the 12 mechanic implementations: armored, enraged, regenerator, stalwart, warded, phasing, draining, splitting, rotating_resistance, retaliator, summoner, cursed. Test phase scaling for raid boss.
|
||||
- `tests/test_raid.py` — HP scaling from active players, cap at 6000, regen, phase transitions at 66%/33%, contribution tracking, lockout mechanic, completion + rewards
|
||||
- `tests/test_rne.py` — objective claim, pursuer advancement (2:1 ratio), pursuer in carrier room triggers combat, carrier death drops objective, relay pickup resets pursuer, ward slows pursuer, lure diverts pursuer, blocker intercepts pursuer, win condition on town delivery
|
||||
- `tests/test_rne_broadcasts.py` — all R&E broadcasts fire correctly (claim, distance, blocker, lure, death, relay, victory)
|
||||
|
||||
Use in-memory SQLite for tests. All endgame tests should generate a proper epoch first (use epoch_generate with DummyBackend).
|
||||
|
||||
## Done When
|
||||
|
||||
All three endgame modes are playable end-to-end. A Hold the Line epoch can be won by clearing all floors and killing the Warden. A Raid Boss epoch can be won by depleting the boss HP pool through coordinated chip-and-run combat with mechanic discovery. A Retrieve and Escape epoch can be won through a relay of carriers with blockers, warders, and lures supporting. The epoch vote selects the next mode. All broadcasts route through DCRG. All responses under 150 chars, all tests passing. Commit and report.
|
||||
120
projects/mmud/mmud-prompts/mmud-prompts/06-phase6.md
Normal file
120
projects/mmud/mmud-prompts/mmud-prompts/06-phase6.md
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
# Task: MMUD Phase 6 — The Breach
|
||||
|
||||
## Before Writing Any Code
|
||||
|
||||
Re-read these sections of `/home/zvx/projects/mmud/docs/planned.md`:
|
||||
- The Breach — Mid-Epoch Event (Day 15) (all of it — 4 mini-events, endgame interaction, design rationale)
|
||||
- Breach secrets (the 3 breach-type secrets)
|
||||
|
||||
Also re-read `config.py` for: BREACH_ROOMS_MIN/MAX, BREACH_CONNECTS_FLOORS, BREACH_SECRETS, BREACH_MINI_EVENTS, EMERGENCE_HP, INCURSION_REGEN/HOLD_HOURS.
|
||||
|
||||
Phase 4 already generates the Breach zone (breachgen.py) and Phase 4's daytick.py already handles the day 15 trigger and days 12-13 foreshadowing. Phase 4's breach.py has basic state management. This phase wires the full runtime logic for all 4 mini-events.
|
||||
|
||||
## Phase 6 Deliverables
|
||||
|
||||
The Breach opens on day 15 with a random mini-event. Each of the 4 types plays differently. The Breach interacts with whichever endgame mode is active.
|
||||
|
||||
### 1. Breach Activation (verify/extend existing)
|
||||
|
||||
The day 15 trigger should already be in daytick.py. Verify it:
|
||||
- Day 12-13: barkeep foreshadowing broadcasts from DCRG: "The walls grow thin between the second and third depths. Something stirs."
|
||||
- Day 15: Breach opens. Set `breach.active = 1`. Open the room exits connecting Breach zone to floors 2 and 3. Broadcast from DCRG: "⚡ The ground splits. A new passage has opened between Floors 2 and 3. Strange light pours from within."
|
||||
- Players can now enter Breach rooms via the new exits from floors 2 and 3.
|
||||
- The permanent shortcut between floors 2 and 3 persists for the rest of the epoch.
|
||||
|
||||
### 2. Mini-Event: The Heist (mini Retrieve & Escape)
|
||||
|
||||
`src/systems/breach_heist.py` (new file)
|
||||
|
||||
- Artifact in the deepest Breach room, guarded by the Breach mini-boss.
|
||||
- Kill mini-boss → claim artifact. Carrier must bring it back to town.
|
||||
- Pursuer spawns (slower, Breach-only — only operates within the 5-8 Breach rooms + the floors 2-3 connection).
|
||||
- If carrier dies, artifact drops. Any player can pick up.
|
||||
- Relay mechanics same as R&E but compressed — 5-8 rooms, not 4 floors.
|
||||
- 3 Breach secrets scattered along the escape route. Found under pressure.
|
||||
- Completion: artifact delivered to town. Breach rewards distributed. Broadcast from DCRG: "🏆 The artifact has been extracted from the Breach!"
|
||||
|
||||
Reuse as much R&E logic from Phase 5 as possible — shared carrier/pursuer/relay patterns.
|
||||
|
||||
### 3. Mini-Event: The Emergence (mini Raid Boss)
|
||||
|
||||
`src/systems/breach_emergence.py` (new file)
|
||||
|
||||
- Creature with shared HP pool (500-800 HP, `EMERGENCE_HP_MIN/MAX`) sits in central Breach room.
|
||||
- Surrounding rooms spawn minions on a timer (respawn every 8 hours).
|
||||
- Same chip-and-run combat as bounties/raid boss. Regen at 3%/8h.
|
||||
- 3 Breach secrets are in the minion rooms — discovered while contributing to the kill.
|
||||
- Completion: creature HP reaches 0. Broadcast: "🏆 The Breach creature has been destroyed!"
|
||||
|
||||
Reuse raid boss combat framework from Phase 5.
|
||||
|
||||
### 4. Mini-Event: The Incursion (mini Hold the Line)
|
||||
|
||||
`src/systems/breach_incursion.py` (new file)
|
||||
|
||||
- Breach rooms start fully hostile. Regen at 2 rooms/day (`INCURSION_REGEN_ROOMS_PER_DAY`) within just 5-8 rooms.
|
||||
- Players must clear ALL Breach rooms and hold them all for 48 hours (`INCURSION_HOLD_HOURS`).
|
||||
- If any room reverts during the hold timer, the clock resets.
|
||||
- 3 Breach secrets behind the hardest rooms, found as part of the push.
|
||||
- Track hold start time in `breach.incursion_hold_started_at`. On each regen tick, check if any Breach room reverted — if so, reset the timer.
|
||||
- Completion: 48 hours with all rooms held. Broadcast: "🏆 The Breach has been secured! The incursion is contained."
|
||||
|
||||
Reuse HtL room clearing/regen logic from Phase 5.
|
||||
|
||||
### 5. Mini-Event: The Resonance (puzzle dungeon)
|
||||
|
||||
`src/systems/breach_resonance.py` (new file)
|
||||
|
||||
- No combat focus. Breach rooms contain environmental puzzles.
|
||||
- 3 Breach secrets ARE the puzzle rewards. Finding all 3 unlocks a bonus cache in the deepest room.
|
||||
- Puzzles are generated in Phase 4 (breachgen already places Breach secrets). This phase adds the interaction logic:
|
||||
- `examine` objects in Breach rooms triggers puzzle checks
|
||||
- Puzzle state tracked per-player in secret_progress
|
||||
- Sequence puzzles, item-interaction puzzles, cross-room clue puzzles (use the same multi-room puzzle archetypes from the main dungeon)
|
||||
- Completion: all 3 Breach secrets found by any player(s). Bonus cache unlocked. Broadcast: "🏆 The Resonance has been understood. The Breach yields its secrets."
|
||||
|
||||
Soloable by nature — knowledge not stats.
|
||||
|
||||
### 6. Breach Interaction with Endgame Modes
|
||||
|
||||
Regardless of which mini-event is running, the Breach benefits the active endgame mode:
|
||||
|
||||
- **Retrieve & Escape:** The Breach shortcut (floors 2↔3) becomes an alternate escape route. Carrier can path through it. Shorter but Breach content (mini-boss, minions, etc.) may still be there.
|
||||
- **Raid Boss:** Breach completion (any mini-event) drops a buff item granting +20% damage vs the raid boss for the rest of the epoch. Add to player inventory on Breach completion.
|
||||
- **Hold the Line:** Breach rooms count as bonus territory toward checkpoint progress on both floors 2 and 3. Cleared Breach rooms contribute to the cleared room count for both floor 2 and floor 3 checkpoints.
|
||||
|
||||
### 7. Breach Secret Integration
|
||||
|
||||
Verify that the 3 Breach secrets work with the existing discovery system:
|
||||
- `secrets` command includes Breach secrets in the count after day 15
|
||||
- Secret milestones (5/10/15/20) fire correctly with Breach secrets included
|
||||
- Barkeep hints for Breach secrets only available after day 15
|
||||
- Breach secrets contribute to the completionist reward (all 20 found)
|
||||
|
||||
## Rules
|
||||
|
||||
- All responses under 150 chars.
|
||||
- All Breach broadcasts route through DCRG.
|
||||
- Breach mini-event is always random (selected at epoch gen, never voted).
|
||||
- Reuse combat/territory frameworks from Phase 5 — don't duplicate code.
|
||||
- Breach content is inaccessible before day 15. Exits to Breach rooms don't exist until activation.
|
||||
- Use constants from `config.py`.
|
||||
- Commit after each mini-event works.
|
||||
|
||||
## Testing
|
||||
|
||||
Add to `tests/`:
|
||||
- `tests/test_breach_activation.py` — day 15 trigger, foreshadowing on days 12-13, exits open, Breach accessible, inaccessible before day 15
|
||||
- `tests/test_breach_heist.py` — mini-boss, artifact claim, mini-pursuer, relay, completion, secrets under pressure
|
||||
- `tests/test_breach_emergence.py` — shared HP pool, minion respawn, chip-and-run, completion, secrets in minion rooms
|
||||
- `tests/test_breach_incursion.py` — room clearing, regen within Breach, 48h hold timer, timer reset on revert, completion
|
||||
- `tests/test_breach_resonance.py` — puzzle interaction, secret discovery, bonus cache unlock, no combat required
|
||||
- `tests/test_breach_endgame.py` — R&E shortcut, raid boss damage buff, HtL bonus territory
|
||||
|
||||
Use in-memory SQLite for tests. Generate full epoch with DummyBackend for each test.
|
||||
|
||||
## Done When
|
||||
|
||||
The Breach opens on day 15 with one of four randomly selected mini-events. Each mini-event is playable end-to-end with its own win condition. Breach secrets integrate cleanly with the discovery system. The Breach interacts with whichever endgame mode is active. All broadcasts route through DCRG. All responses under 150 chars, all tests passing. Commit and report.
|
||||
|
||||
This is the final gameplay phase. After this, the full 30-day epoch loop is complete: epoch generates → players explore and progress → Breach opens day 15 → endgame mode pushes through days 20-30 → epoch vote → wipe → new epoch.
|
||||
32
projects/mmud/mmud-prompts/mmud-prompts/README.md
Normal file
32
projects/mmud/mmud-prompts/mmud-prompts/README.md
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# MMUD Prompt Bundle
|
||||
|
||||
## Status
|
||||
- Phases 1-4: COMPLETE (265 tests passing)
|
||||
- Phases 5-6: Prompts ready
|
||||
- Design doc: NEEDS UPDATES (4 prompts below, run before Phase 5)
|
||||
|
||||
## Run Order
|
||||
|
||||
### Step 1: Design Doc Updates (run in CC in this exact order)
|
||||
These update `/home/zvx/projects/mmud/docs/planned.md` in place:
|
||||
|
||||
1. `01-update-planned.md` — Adds The Last Ember (bar + 4 NPC bios), NPC live conversations, command discovery
|
||||
2. `02-npc-nodes.md` — Replaces talk command with sim node architecture (6 nodes), three rule layers, onboarding funnel
|
||||
3. `03-darkcragg.md` — Names the dungeon "The Darkcragg Depths"
|
||||
4. `04-dcrg-node.md` — Adds DCRG as one-way broadcast node, separates broadcast stream from EMBR
|
||||
|
||||
### Step 2: Build Phases
|
||||
5. `05-phase5.md` — Endgame modes: Hold the Line (regen, checkpoints, floor bosses, 12 mechanics), Raid Boss (HP scaling, 12 mechanics, 3 phases), Retrieve & Escape (Pursuer, blockers, warders, lures), epoch vote
|
||||
6. `06-phase6.md` — The Breach: 4 mini-events (Heist, Emergence, Incursion, Resonance), endgame interaction, day 15 trigger. Final gameplay phase.
|
||||
|
||||
### If Needed
|
||||
- `mmud-project.md` — Drop into `/home/zvx/projects/.ref/projects/` if not already there
|
||||
|
||||
## What's Complete After Phase 6
|
||||
The full 30-day epoch loop: generate → explore → Breach day 15 → endgame push days 20-30 → vote → wipe → new epoch. All three endgame modes, all four Breach mini-events, 20 secrets, 40 bounties, floor bosses, raid boss, Pursuer + support roles.
|
||||
|
||||
## What Comes After Phase 6
|
||||
- NPC live conversations (LLM runtime for talk via sim nodes) — needs implementation prompt
|
||||
- Sim node deployment (meshtasticd with 6 identities) — needs infrastructure work
|
||||
- Last Ember spectator web dashboard — separate project, parallel track
|
||||
- Playtesting and number tuning
|
||||
48
projects/mmud/mmud-prompts/mmud-prompts/mmud-project.md
Normal file
48
projects/mmud/mmud-prompts/mmud-prompts/mmud-project.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# MMUD — Mesh Multi-User Dungeon
|
||||
|
||||
Text-based multiplayer dungeon crawler for Meshtastic LoRa mesh networks. BBS door games (LORD, TradeWars) adapted for 150-char mesh radio constraints, async play, 30-day wipe cycles.
|
||||
|
||||
## Status
|
||||
|
||||
**Phase:** Pre-development — design complete, repo scaffolded, implementation not started.
|
||||
|
||||
## Repo
|
||||
|
||||
`/home/zvx/projects/mmud`
|
||||
|
||||
The repo contains a `CLAUDE.md` with full architecture, directory structure, development phases, and implementation guidance. **Read it first before any implementation work.**
|
||||
|
||||
## Key Files
|
||||
|
||||
- `CLAUDE.md` — Architecture, patterns, dev phases, gotchas
|
||||
- `docs/planned.md` — Complete game design document (~950 lines). Source of truth for all mechanics. If code contradicts this, code is wrong.
|
||||
- `config.py` — All game constants with rationale
|
||||
- `src/db/schema.sql` — Full database schema
|
||||
|
||||
## Design Constraints
|
||||
|
||||
- 150 characters per Meshtastic LoRa message (hard ceiling)
|
||||
- Zero runtime LLM calls — all text batch-generated at epoch start
|
||||
- Async-first — all multiplayer through shared DB state
|
||||
- 12 dungeon actions/day, 30-day epochs
|
||||
- Python 3.11+, SQLite, Meshtastic Python API
|
||||
|
||||
## Development Phases
|
||||
|
||||
1. **Core Loop** — Meshtastic message handling, command parser, player creation, room navigation, basic combat, death, action budget
|
||||
2. **Economy & Progression** — XP, leveling, gold, shops, gear (weapon/armor/trinket), bank, healer
|
||||
3. **Social Systems** — Broadcasts (tier 1/2/targeted), barkeep (recap, tokens, hints), bounty board, player messages, mail
|
||||
4. **Epoch Generation** — World gen, LLM narrative pipeline (batch + validation), secret placement, bounty pool generation
|
||||
5. **Endgame Modes** — Hold the Line (regen, checkpoints, floor bosses), Raid Boss (HP scaling, mechanic tables, phases), Retrieve & Escape (Pursuer, blockers, warders, lures), epoch vote
|
||||
6. **The Breach** — Breach zone gen, 4 mini-event types (Heist, Emergence, Incursion, Resonance), day 15 trigger
|
||||
|
||||
## No Runbooks Needed
|
||||
|
||||
This is a pure software project — no LXC provisioning, no Caddy config, no Authentik integration. Runs as a Python daemon connected to a Meshtastic device via USB/serial or TCP. No infrastructure runbooks apply.
|
||||
|
||||
## Notes
|
||||
|
||||
- All regen/HP/damage numbers in the design doc are targets, not validated — will need playtesting
|
||||
- The game runs on a Meshtastic mesh network, not a web server
|
||||
- SQLite single file DB, no ORM, raw parameterized SQL
|
||||
- Every outbound message must fit 150 chars — the formatter is the final gate
|
||||
Loading…
Add table
Add a link
Reference in a new issue