WORLD = { "id": "maple_street", "name": "Maple Street", "theme": "cozy modern suburb", "diorama": "assets/worlds/maple_street.png", "palette": { "bg": "#0b0f1a", "grass": "#1a4a2a", "road": "#1e2235", "house": "#c45b5b", "park": "#0a3a2a", "tree": "#0a2a1a", "sky": "#0a0f1a", "tint_day": "#fff3d6", "tint_night": "#1a2342", }, "hotspots": { "marta_home": [17, 63], "cafe": [72, 58], "park": [58, 50], "square": [48, 73], "jay_home": [89, 87], "school": [37, 56], "nia_clinic": [13, 81], "priya_office": [82, 78], }, "scenery": { "buildings": [ {"left": 5, "top": 40, "w": 15, "h": 15, "front": "#3a2b4d", "roof": "#ff5fa2", "side": "#241a33", "label": "๐Ÿ•ฐ๏ธ"}, {"left": 27, "top": 33, "w": 20, "h": 14, "front": "#23314f", "roof": "#38e8ff", "side": "#16213a", "label": "๐Ÿซ"}, {"left": 63, "top": 36, "w": 17, "h": 14, "front": "#4a3b2b", "roof": "#ffd76a", "side": "#33291d", "label": "โ˜•"}, {"left": 3, "top": 61, "w": 14, "h": 14, "front": "#1f3d3a", "roof": "#7CFFB2", "side": "#142826", "label": "๐Ÿš‘"}, {"left": 71, "top": 53, "w": 16, "h": 17, "front": "#2c2b4d", "roof": "#9b6bff", "side": "#1d1c33", "label": "๐Ÿข"}, {"left": 82, "top": 69, "w": 14, "h": 12, "front": "#3a2030", "roof": "#ff8a5f", "side": "#281622", "label": "๐Ÿช"}, ], "roads": [ {"left": -5, "top": 66, "w": 120, "h": 9, "rot": -8}, {"left": 40, "top": 30, "w": 9, "h": 70, "rot": 6}, ], "trees": [ {"left": 21, "top": 52, "s": 1.0}, {"left": 52, "top": 46, "s": 0.8}, {"left": 62, "top": 66, "s": 1.1}, {"left": 33, "top": 80, "s": 0.9}, {"left": 94, "top": 52, "s": 0.8}, ], "props": [ {"left": 49, "top": 64, "emoji": "โ›ฒ"}, {"left": 30, "top": 67, "emoji": "๐Ÿชง"}, ], }, "cast": [ { "name": "Marta Voss", "age": 68, "job": "retired watchmaker", "traits": ["blunt", "observant", "nostalgic"], "backstory": "She ran the neighborhood clock shop for four decades and still notices every tiny change on the street.", "relationships": { "Jay Park": "rival", "Nia Okafor": "friend", "Luca Bell": "family", "Priya Raman": "friend", }, "voice_description": "(a grumpy elderly woman, deep measured low-pitched voice)", "model": "nvidia/Nemotron-Mini-4B-Instruct", "emoji": "๐Ÿง“", "home": "marta_home", "catchphrase_hint": "always compares things to the past", }, { "name": "Jay Park", "age": 24, "job": "food delivery cyclist", "traits": ["restless", "funny", "impulsive"], "backstory": "He knows every shortcut in the district and treats ordinary afternoons like they might become legends.", "relationships": { "Marta Voss": "rival", "Nia Okafor": "crush", "Luca Bell": "friend", "Priya Raman": "friend", }, "voice_description": "(an energetic young man, quick bright mid-pitched voice)", "model": "nvidia/Nemotron-Mini-4B-Instruct", "emoji": "๐Ÿšด", "home": "jay_home", "catchphrase_hint": "turns everything into an adventure", }, { "name": "Nia Okafor", "age": 35, "job": "paramedic", "traits": ["calm", "protective", "dry-witted"], "backstory": "After years on emergency shifts, she reads chaos quickly and trusts people more than they expect.", "relationships": { "Marta Voss": "friend", "Jay Park": "crush", "Luca Bell": "friend", "Priya Raman": "family", }, "voice_description": "(a steady adult woman, warm confident medium-low voice)", "model": "nvidia/Nemotron-Mini-4B-Instruct", "emoji": "๐Ÿš‘", "home": "nia_clinic", "catchphrase_hint": "downplays danger but always steps up", }, { "name": "Luca Bell", "age": 15, "job": "student and arcade regular", "traits": ["curious", "dramatic", "inventive"], "backstory": "He documents neighborhood rumors in a battered notebook and is convinced something world-changing will happen here first.", "relationships": { "Marta Voss": "family", "Jay Park": "friend", "Nia Okafor": "friend", "Priya Raman": "rival", }, "voice_description": "(a teenage boy, eager expressive slightly high-pitched voice)", "model": "nvidia/Nemotron-Mini-4B-Instruct", "emoji": "๐Ÿง’", "home": "school", "catchphrase_hint": "treats everything like breaking news", }, { "name": "Priya Raman", "age": 42, "job": "city planner", "traits": ["organized", "skeptical", "secretly romantic"], "backstory": "She came to fix the block's chronic little problems and keeps getting pulled into everyone else's dramas.", "relationships": { "Marta Voss": "friend", "Jay Park": "friend", "Nia Okafor": "family", "Luca Bell": "rival", }, "voice_description": "(a precise middle-aged woman, crisp thoughtful medium voice)", "model": "nvidia/Nemotron-Mini-4B-Instruct", "emoji": "๐Ÿ‘ฉโ€๐Ÿ’ผ", "home": "priya_office", "catchphrase_hint": "tries to stay logical but feelings leak through", }, ], "board": { # A real residential street: a suburban grid of homes with a small high street, # a school, a clinic and a park. Deliberately NOT the same shape as the other worlds. "cols": 22, "rows": 18, "ambient": 6, "roads": {"cols": [5, 11, 17], "rows": [6, 13]}, "plaza": [[12, 9], [13, 9], [12, 10], [13, 10]], "plaza_center": [12.5, 9.5], "buildings": [ # homes โ€” pitched-roof houses in warm, lived-in colours (most of a neighborhood is houses) {"gx": 1, "gy": 1, "w": 2, "d": 2, "h": 24, "kind": "house", "wall": "#caa074", "roof": "#8a3b2e", "label": "MARTA"}, {"gx": 8, "gy": 1, "w": 2, "d": 2, "h": 24, "kind": "house", "wall": "#b6c081", "roof": "#4a6b32", "label": "THE PARKS"}, {"gx": 19, "gy": 1, "w": 2, "d": 2, "h": 26, "kind": "house", "wall": "#b79ec0", "roof": "#5a3b6b", "label": "RAMAN"}, {"gx": 1, "gy": 15, "w": 2, "d": 2, "h": 24, "kind": "house", "wall": "#c79a78", "roof": "#7a4a2e", "label": "No. 12"}, {"gx": 15, "gy": 15, "w": 2, "d": 2, "h": 24, "kind": "house", "wall": "#9ab0c0", "roof": "#3b5a6b", "label": "No. 9"}, {"gx": 19, "gy": 9, "w": 2, "d": 2, "h": 24, "kind": "house", "wall": "#c0a86a", "roof": "#6b5a2e", "label": "No. 7"}, # the little high street โ€” a cafรฉ and a corner store with real storefronts {"gx": 14, "gy": 1, "w": 2, "d": 2, "h": 30, "kind": "shop", "wall": "#8a6f3f", "roof": "#ff8a5f", "label": "CAFร‰"}, {"gx": 1, "gy": 8, "w": 2, "d": 2, "h": 28, "kind": "shop", "wall": "#6f5a8a", "roof": "#38e8ff", "label": "CORNER STORE"}, # civic โ€” a small school and a clinic {"gx": 8, "gy": 15, "w": 3, "d": 2, "h": 34, "kind": "block", "wall": "#6a6f8a", "roof": "#ffd76a", "label": "SCHOOL"}, {"gx": 19, "gy": 15, "w": 2, "d": 2, "h": 30, "kind": "block", "wall": "#4f8576", "roof": "#7CFFB2", "label": "CLINIC"}, ], "trees": [ [9, 11], [10, 12], [7, 4], [16, 4], [4, 10], [20, 12], [7, 16], [12, 16], [18, 6], [6, 7], ], "props": [ {"type": "fountain", "gx": 12, "gy": 12}, {"type": "pond", "gx": 15, "gy": 11, "w": 2, "d": 2}, {"type": "bench", "gx": 10, "gy": 11}, {"type": "bench", "gx": 14, "gy": 12}, # cafรฉ seating on the high street {"type": "table", "gx": 13, "gy": 3}, {"type": "table", "gx": 16, "gy": 3}, # corner-store produce stall {"type": "stall", "gx": 3, "gy": 9, "color": "#caa23f"}, # greenery + lamps to make it feel lived-in {"type": "planter", "gx": 7, "gy": 12}, {"type": "planter", "gx": 12, "gy": 7}, {"type": "lamp", "gx": 11, "gy": 8}, {"type": "lamp", "gx": 14, "gy": 8}, {"type": "lamp", "gx": 5, "gy": 12}, ], "hotspots_tile": { "marta_home": [3, 2], "jay_home": [8, 3], "priya_office": [18, 2], "school": [10, 14], "nia_clinic": [18, 15], "cafe": [14, 4], "shop": [3, 8], "park": [10, 11], "fountain": [11, 12], "square": [13, 10], }, # where each character goes (and what they do) when an event hits โ€” spread out, # in-character, so the street reads like a real place reacting, not a mob. "activities": { "Marta Voss": {"tile": [10, 11], "label": "๐Ÿช‘ watches from the park bench"}, "Jay Park": {"tile": [14, 4], "label": "๐Ÿšด races to the cafรฉ", "vehicle": "bike"}, "Nia Okafor": {"tile": [18, 15], "label": "๐Ÿš‘ heads to the clinic"}, "Luca Bell": {"tile": [11, 12], "label": "๐Ÿ”Ž investigates the fountain"}, "Priya Raman": {"tile": [18, 2], "label": "๐Ÿ  hurries home to plan"}, }, }, "scenarios": [ { "id": "school_closing", "title": "The school will be closed by the city", "event": "The city announces Maple Street Elementary will be shut down at the end of the semester due to budget cuts.", "focus": "How do different generations react to losing a community institution?", }, { "id": "new_neighbor", "title": "A new family moves in next door", "event": "A young family with two kids moves into the empty house on Maple Street. They seem nice but awfully quiet.", "focus": "How does the neighborhood welcome (or distrust) newcomers?", }, { "id": "park_renovation", "title": "The park gets a makeover", "event": "The city approves a full renovation of the tiny park on Maple Street. Construction starts Monday.", "focus": "Who benefits from change and who loses something familiar?", }, { "id": "power_outage", "title": "A summer power outage hits the block", "event": "A heatwave knocks out power to the entire block for an estimated six hours. No AC, no lights, no screens.", "focus": "How do people cope when their routines are stripped away?", }, ], "events": [ "A mysterious glowing object lands in the park", "The power goes out across the entire neighborhood", "A stray cat starts following people around town", "Someone paints a giant mural on the side of the corner store", "A food truck rolls in and parks in the middle of the square", "The old clock tower starts chiming at random hours", "A thunderstorm knocks down the biggest tree on Maple Street", "Someone leaves a box of kittens on the church doorstep", "The neighborhood gets its own Wikipedia page overnight", "A film crew shows up to shoot a commercial on the block", ], # ---- Crisis Mode content ------------------------------------------------- # Each crisis declares the concrete responses that count as "handling it". # The resolver (crisis.py) checks the residents' goto + action against these. "crises": [ { "id": "cafe_fire", "title": "Kitchen fire at the cafรฉ", "narrative": "Smoke is pouring out of the cafรฉ on the high street โ€” a grease fire has caught in the kitchen and it's spreading fast.", "severity": 3, "kind": "fire", "affected_hotspot": "cafe", "time_limit": 4, "escalation": "The flames are climbing toward the upstairs flats.", "focus": "When the same emergency hits, who runs toward it, who organizes, and who freezes?", "success_text": "The fire's out, everyone's accounted for, and the cafรฉ will reopen.", "failure_text": "The cafรฉ is gutted and the block is shaken.", "requirements": [ { "id": "containment", "label": "๐Ÿ”ฅ Contain the fire", "hotspots": ["cafe"], "action_keywords": [ "fire", "flame", "douse", "extinguish", "put out", "water", "smoke", "hose", "blanket", ], "weight": 1.5, }, { "id": "medical", "label": "๐Ÿš‘ Get medical on scene", "hotspots": ["cafe", "nia_clinic"], "action_keywords": [ "help", "treat", "check", "injur", "hurt", "burn", "aid", "care", "first aid", "ambulance", ], "role": "medic", "weight": 1.0, }, { "id": "evacuation", "label": "๐Ÿƒ Evacuate the building", "hotspots": ["cafe", "square"], "action_keywords": [ "evacuat", "get everyone out", "clear", "warn", "usher", "people out", "safe", "away", ], "weight": 1.0, }, { "id": "coordination", "label": "๐Ÿ“‹ Coordinate the response", "hotspots": ["priya_office", "square"], "action_keywords": [ "coordinat", "organi", "plan", "call", "rally", "manage", "direct", "report", "emergency", ], "role": "worker", "weight": 1.0, "optional": True, }, ], }, { "id": "heatwave_blackout", "title": "Heatwave blackout", "narrative": "A record heatwave has knocked out power to the whole block โ€” no AC, no fans, and the elderly are sweltering in their flats.", "severity": 3, "kind": "blackout", "affected_hotspot": "priya_office", "time_limit": 4, "escalation": "It's getting dangerously hot indoors.", "focus": "In a slow-burning emergency with no obvious villain, who takes initiative and who waits?", "success_text": "Power's restored, the vulnerable were looked after, and the block cooled down.", "failure_text": "People suffered through the heat with no one taking charge.", "requirements": [ { "id": "restore", "label": "โšก Get the power back", "hotspots": ["priya_office"], "action_keywords": ["power", "grid", "restore", "electric", "generator", "call", "utility", "fix"], "role": "worker", "weight": 1.5, }, { "id": "welfare", "label": "๐Ÿš‘ Check on the vulnerable", "hotspots": ["marta_home", "nia_clinic", "square"], "action_keywords": ["check", "elderly", "vulnerable", "welfare", "water", "cool", "help", "care"], "role": "medic", "weight": 1.0, }, { "id": "coordination", "label": "๐Ÿ“‹ Organize a cooling shelter", "hotspots": ["square", "priya_office"], "action_keywords": ["organi", "plan", "coordinat", "shelter", "gather", "rally"], "weight": 1.0, }, { "id": "relief", "label": "๐Ÿ’ง Hand out water & shade", "hotspots": ["cafe", "square"], "action_keywords": ["water", "cool", "shade", "drinks", "ice", "relief"], "weight": 1.0, "optional": True, }, ], }, { "id": "storm_tree", "title": "Storm downs the big maple", "narrative": "A violent summer storm has torn down the giant maple in the park โ€” and someone is trapped under the branches.", "severity": 4, "kind": "storm", "affected_hotspot": "park", "time_limit": 4, "escalation": "The trapped neighbor is hurt and the rain is still coming down.", "focus": "Under real physical danger, who acts on instinct and who needs a plan first?", "success_text": "They freed the trapped neighbor and got everyone to safety.", "failure_text": "Help came too slow and the night turned grim.", "requirements": [ { "id": "rescue", "label": "๐ŸŒณ Free the trapped neighbor", "hotspots": ["park"], "action_keywords": ["lift", "free", "rescue", "trapped", "move", "clear", "branch", "pull", "dig"], "weight": 1.5, }, { "id": "medical", "label": "๐Ÿš‘ Treat the injured", "hotspots": ["park", "nia_clinic"], "action_keywords": ["treat", "help", "injur", "aid", "first aid", "hurt", "care", "bandage"], "role": "medic", "weight": 1.0, }, { "id": "safety", "label": "๐Ÿšง Secure the area", "hotspots": ["park", "square"], "action_keywords": ["clear", "warn", "safe", "away", "cordon", "keep back", "secure"], "weight": 1.0, }, { "id": "coordination", "label": "๐Ÿ“‹ Call for help", "hotspots": ["priya_office", "square"], "action_keywords": ["coordinat", "plan", "call", "report", "organi", "emergency"], "role": "worker", "weight": 1.0, "optional": True, }, ], }, { "id": "missing_child", "title": "A child goes missing", "narrative": "In all the chaos, a little one has wandered off โ€” nobody has seen them for an hour and it's getting dark.", "severity": 4, "kind": "search", "affected_hotspot": "square", "time_limit": 4, "escalation": "Night is falling and the search is getting harder.", "focus": "When the task needs everyone spread out, who organizes the search and who just runs?", "success_text": "They found the child safe โ€” a whole block searching together.", "failure_text": "The search stayed scattered and frightened.", "requirements": [ { "id": "search_park", "label": "๐Ÿ”ฆ Search the park", "hotspots": ["park"], "action_keywords": ["search", "look", "find", "check", "comb", "scour"], "weight": 1.0, }, { "id": "search_school", "label": "๐Ÿ”ฆ Search the school", "hotspots": ["school"], "action_keywords": ["search", "look", "find", "check", "comb", "scour"], "weight": 1.0, }, { "id": "coordination", "label": "๐Ÿ“‹ Organize the search", "hotspots": ["square", "priya_office"], "action_keywords": ["organi", "coordinat", "plan", "split up", "call", "rally", "direct"], "weight": 1.0, }, { "id": "reassure", "label": "๐Ÿซ‚ Reassure the family", "hotspots": ["square", "marta_home"], "action_keywords": ["calm", "reassure", "comfort", "stay", "with the family"], "weight": 1.0, "optional": True, }, ], }, { "id": "everything_at_once", "title": "The town comes apart", "narrative": "It's all happening at once โ€” a fire on the high street, the power failing, and panic spreading through the square. This is no accident.", "severity": 5, "kind": "fire", "affected_hotspot": "square", "time_limit": 5, "escalation": "Everything that can go wrong is going wrong together.", "focus": "When everything fails at once, does the town fall apart or pull together?", "success_text": "Against the odds, the block held โ€” every person did their part.", "failure_text": "It was too much, all at once.", "requirements": [ { "id": "containment", "label": "๐Ÿ”ฅ Contain the fire", "hotspots": ["cafe"], "action_keywords": ["fire", "flame", "douse", "extinguish", "put out", "water", "smoke"], "weight": 1.5, }, { "id": "restore", "label": "โšก Restore the power", "hotspots": ["priya_office"], "action_keywords": ["power", "grid", "restore", "electric", "generator", "call", "fix"], "role": "worker", "weight": 1.0, }, { "id": "medical", "label": "๐Ÿš‘ Tend the hurt", "hotspots": ["cafe", "square", "nia_clinic"], "action_keywords": ["treat", "help", "injur", "aid", "first aid", "hurt", "care"], "role": "medic", "weight": 1.0, }, { "id": "evacuation", "label": "๐Ÿƒ Calm the square", "hotspots": ["square"], "action_keywords": ["evacuat", "calm", "clear", "warn", "safe", "away", "usher", "people out"], "weight": 1.0, }, ], }, ], "campaign": { "id": "long_summer", "title": "Season 1 ยท The Long Summer", "chapters": [ { "id": "ch1", "crisis_id": "cafe_fire", "intro": "A hot, ordinary afternoon on Maple Street. Then smoke starts rising from the cafรฉโ€ฆ", "outro_win": "The fire's out. People hug on the pavement. 'Could've been so much worse,' someone says.", "outro_loss": "The cafรฉ smolders. Nobody quite knows how it got so bad so fast.", "clue": "Nia notices the fire started right after the gas line was 'serviced' this morning. Odd.", }, { "id": "ch2", "crisis_id": "heatwave_blackout", "intro": "A week later, the hottest day on record โ€” and then every light on the block goes dark at once.", "outro_win": "The fans whir back to life. Marta mutters that nothing on this street is a coincidence anymore.", "outro_loss": "A long, sweltering night. People start asking why this keeps happening here.", "clue": "Priya checks the grid logs: the outage was triggered manually, from outside the neighborhood.", }, { "id": "ch3", "crisis_id": "storm_tree", "intro": "The forecast promised clear skies. The storm that hits the park was nowhere on the radar.", "outro_win": "Soaked and shaking, they carry their neighbor to safety. 'Who's doing this to us?'", "outro_loss": "A hard night under the fallen maple. The block feels watched.", "clue": "Luca's notebook: every disaster has hit a different corner of Maple Street, in order, like a map.", }, { "id": "ch4", "crisis_id": "missing_child", "intro": "Fear has settled over the block. And now, in the middle of it, a child is gone.", "outro_win": "The child is found, safe. The relief is enormous โ€” but so is the dread.", "outro_loss": "The search drags on into the dark. The town has never felt so alone.", "clue": "The child says a 'nice voice on the speaker' told them where to go. Someone is steering all of this.", }, { "id": "ch5", "crisis_id": "everything_at_once", "intro": "Then it all comes at once โ€” fire, blackout, panic. The town finally understands: none of it was an accident.", "outro_win": "Battered but unbroken, the five of them stand in the square. They made it through. Together.", "outro_loss": "The Long Summer breaks the block. But they'll remember who they were to each other.", "clue": "The pieces fit. There was always a hand behind the chaos.", }, ], "finale_reveal": ( "Every fire, every blackout, every storm โ€” traced back to one source. " "The one who threw each event at the town. The one at the controls. You." ), }, }