Spaces:
Sleeping
Sleeping
| """Per-location special mechanics from DETAILS.md §3.""" | |
| from __future__ import annotations | |
| import json | |
| import random | |
| from world.book_of_ages import create_entry, get_entries | |
| from world.database import db_session | |
| from world.entities import add_tag, get_entity, update_memory | |
| from world.locations import get_location_by_slug | |
| def effective_days_in_realm(entity: dict) -> float: | |
| """Clock Forest souls age 1.5× faster for lifecycle logic.""" | |
| loc = entity.get("location_slug") | |
| if loc is None and entity.get("location_id"): | |
| from world.locations import get_location_by_id | |
| row = get_location_by_id(entity["location_id"]) | |
| loc = row["slug"] if row else None | |
| days = entity.get("days_in_realm", 0) | |
| if loc == "clock-forest": | |
| return days * 1.5 | |
| return float(days) | |
| def process_library_memory_fragments(world_day: int) -> int: | |
| """Every 3 days, Library inhabitants gain a half-remembered fragment.""" | |
| if world_day % 3 != 0: | |
| return 0 | |
| library = get_location_by_slug("library") | |
| if not library: | |
| return 0 | |
| past = get_entries(limit=30, entry_type=None) | |
| if not past: | |
| return 0 | |
| fragment_source = random.choice(past) | |
| snippet = (fragment_source.get("content") or "")[:120].strip() | |
| if not snippet: | |
| return 0 | |
| updated = 0 | |
| with db_session() as conn: | |
| rows = conn.execute( | |
| "SELECT * FROM entities WHERE location_id = ? AND status != 'dormant'", | |
| (library["id"],), | |
| ).fetchall() | |
| for row in rows: | |
| entity = dict(row) | |
| current = entity.get("memory_summary") or "" | |
| addition = f"They half-remember something from the shelves: {snippet}" | |
| merged = f"{current} {addition}".strip() | |
| if len(merged) > 600: | |
| merged = merged[-600:] | |
| update_memory(entity["id"], merged) | |
| updated += 1 | |
| if updated: | |
| create_entry( | |
| world_day=world_day, | |
| entry_type="milestone", | |
| content=( | |
| f"The Library breathed out {updated} half-forgotten fragments " | |
| "into the minds of those who dwell among unfinished books." | |
| ), | |
| location_id=library["id"], | |
| is_milestone=False, | |
| ) | |
| return updated | |
| def process_mirror_contradictions(world_day: int) -> int: | |
| """Mirror Bogs: after 5+ interactions, a soul may develop a contradicting trait.""" | |
| bogs = get_location_by_slug("mirror-bogs") | |
| if not bogs: | |
| return 0 | |
| count = 0 | |
| with db_session() as conn: | |
| entities = conn.execute( | |
| "SELECT * FROM entities WHERE location_id = ?", | |
| (bogs["id"],), | |
| ).fetchall() | |
| opposites = [ | |
| ("patient", "restless"), | |
| ("gentle", "sharp-tongued"), | |
| ("honest", "evasive"), | |
| ("hopeful", "cynical"), | |
| ("quiet", "loud"), | |
| ("generous", "possessive"), | |
| ] | |
| for row in entities: | |
| entity = dict(row) | |
| traits = json.loads(entity["personality_traits"]) if isinstance(entity["personality_traits"], str) else entity["personality_traits"] | |
| tags = json.loads(entity["tags"]) if isinstance(entity["tags"], str) else entity["tags"] | |
| if "contradiction" in tags: | |
| continue | |
| n = conn_count_interactions_at(entity["id"], bogs["id"]) | |
| if n < 5: | |
| continue | |
| pick_trait = random.choice(traits) | |
| opposite = next((b for a, b in opposites if a in pick_trait.lower()), None) | |
| if not opposite: | |
| opposite = f"secretly unlike their {pick_trait} nature" | |
| new_traits = traits[:] | |
| idx = traits.index(pick_trait) | |
| new_traits[idx] = f"{pick_trait}, yet {opposite}" | |
| with db_session() as conn: | |
| conn.execute( | |
| "UPDATE entities SET personality_traits = ? WHERE id = ?", | |
| (json.dumps(new_traits), entity["id"]), | |
| ) | |
| add_tag(entity["id"], "contradiction") | |
| create_entry( | |
| world_day=world_day, | |
| entry_type="milestone", | |
| content=( | |
| f"{entity['name']} looked into the bog and came away disagreeing " | |
| f"with who they had been." | |
| ), | |
| entity_ids=[entity["id"]], | |
| location_id=bogs["id"], | |
| is_milestone=True, | |
| title="A Contradiction Surfaces", | |
| ) | |
| count += 1 | |
| return count | |
| def conn_count_interactions_at(entity_id: str, location_id: int) -> int: | |
| with db_session() as conn: | |
| row = conn.execute( | |
| """ | |
| SELECT COUNT(*) AS c FROM interactions | |
| WHERE location_id = ? | |
| AND (entity_a_id = ? OR entity_b_id = ?) | |
| """, | |
| (location_id, entity_id, entity_id), | |
| ).fetchone() | |
| return row["c"] if row else 0 | |
| def apply_moon_market_memory_trade( | |
| entity_a: dict, | |
| entity_b: dict, | |
| location_slug: str, | |
| memory_a: str, | |
| memory_b: str, | |
| ) -> tuple[str, str]: | |
| """Moon Market: traded memory fragments bleed between two souls.""" | |
| if location_slug != "moon-market": | |
| return memory_a, memory_b | |
| frag_a = (entity_a.get("memory_summary") or "").split(". ")[-1][:80] | |
| frag_b = (entity_b.get("memory_summary") or "").split(". ")[-1][:80] | |
| if frag_b and frag_b not in memory_a: | |
| memory_a = f"{memory_a} Carries a traded fragment: {frag_b}.".strip() | |
| if frag_a and frag_a not in memory_b: | |
| memory_b = f"{memory_b} Carries a traded fragment: {frag_a}.".strip() | |
| return memory_a[:600], memory_b[:600] | |