godseed / mind /mock_scripts.py
AndresCarreon's picture
Town Mode: close town view by default, build_district + place_road, bank/market/house, grow-one-town steering, behold-the-world reveal, tamed needle
b0d758d verified
Raw
History Blame Contribute Delete
25.7 kB
"""Deterministic scripted plans for the MockBackend.
Each wish maps to a category by keyword; each category builds a Reading plus
a short turn list (calls + a done turn), with coordinates, hues, and a few
phrasings varied by a seed derived from the wish text (crc32 — stable across
processes, unlike hash()). Same wish in, same plan out: demos replay exactly.
Across the category library every one of the 11 tools appears, so a varied
demo session exercises the full DSL. All numbers are kept inside the engine's
clamp ranges; all thoughts <=160 chars; all epitaphs <=120; inscriptions <=90.
This module produces *content* only. The MockBackend (mind/backends.py) is
responsible for streaming it token-by-token with delays.
"""
from __future__ import annotations
import random
import re
import zlib
from .prompts import infer_mood
THOUGHT_MAX = 160
EPITAPH_MAX = 120
INSCRIBE_MAX = 90
# --------------------------------------------------------------------------
# Small helpers
# --------------------------------------------------------------------------
def _seed_for(wish: str) -> int:
return zlib.crc32(" ".join(wish.lower().split()).encode("utf-8")) & 0x7FFFFFFF
def _r1(rng: random.Random, lo: float, hi: float) -> float:
return round(rng.uniform(lo, hi), 1)
def _r2(rng: random.Random, lo: float, hi: float) -> float:
return round(rng.uniform(lo, hi), 2)
def _clamp_lat(lat: float) -> float:
return max(-85.0, min(85.0, round(lat, 1)))
def _wrap_lon(lon: float) -> float:
wrapped = ((lon + 180.0) % 360.0) - 180.0
return round(wrapped, 1)
def _call(thought: str, tool: str, **args) -> dict:
return {"thought": thought[:THOUGHT_MAX], "call": {"tool": tool, "args": args}}
def _done(thought: str, epitaph: str) -> dict:
return {
"thought": thought[:THOUGHT_MAX],
"done": True,
"epitaph": epitaph[:EPITAPH_MAX],
}
def _snippet(wish: str, limit: int) -> str:
text = " ".join(wish.split()).replace('"', "'").strip()
if len(text) <= limit:
return text
return text[: limit - 1].rstrip() + "…"
def _inscription(wish: str) -> str:
return _snippet(wish, INSCRIBE_MAX)
_PLACES = (
"the north", "the far south", "the morning side", "the evening side",
"the quiet latitudes", "the world's shoulder",
)
def _place(rng: random.Random) -> str:
return rng.choice(_PLACES)
def _anchor(rng: random.Random) -> tuple[float, float]:
return _r1(rng, -55, 55), _r1(rng, -165, 165)
def _mood_sky(rng: random.Random, mood: str) -> str:
table = {
"melancholy": ("dusk", "night", "void"),
"joyful": ("dawn", "gold"),
"eerie": ("night", "aurora"),
"absurd": ("aurora", "ember", "gold"),
"still": ("dusk", "night", "dawn"),
}
return rng.choice(table.get(mood, table["still"]))
# --------------------------------------------------------------------------
# Category scripts
# --------------------------------------------------------------------------
def _water(wish: str, rng: random.Random, mood: str) -> dict:
lat, lon = _anchor(rng)
place = _place(rng)
palette = _mood_sky(rng, mood if mood != "joyful" else "still")
hue = _r1(rng, 170, 230)
reading = (
f"Water, then. The oldest ask, and the kindest. I will press a basin "
f"into {place} and teach a bright stream to find it. The sky should "
f"lean {palette} over it, so the surface has something to study."
)
path = [
[_clamp_lat(lat + 14), _wrap_lon(lon - 18)],
[_clamp_lat(lat + 6), _wrap_lon(lon - 8)],
[lat, lon],
]
return {
"reading": reading,
"turns": [
_call(
"First the hollow. Water needs somewhere to be.",
"lower_terrain",
lat=lat, lon=lon, radius_deg=_r1(rng, 12, 20),
depth=_r2(rng, 0.05, 0.08), roughness=0.4,
),
_call(
"Now the stream, from the high ground down.",
"place_water",
kind="stream", path=path, hue=hue,
),
_call(
"A pool where it gathers, lit from beneath.",
"place_water",
kind="pool", path=[[lat, lon]],
radius_deg=_r1(rng, 4, 7), hue=hue,
),
_call(
"A sky for the water to look back at.",
"set_sky",
palette=palette, star_density=_r2(rng, 0.4, 0.8),
moons=rng.randint(1, 2),
),
_done(
"The water moves. That is most of what water is for.",
"A stream now runs to a patient pool, and the sky watches itself there.",
),
],
}
def _mountain(wish: str, rng: random.Random, mood: str) -> dict:
lat, lon = _anchor(rng)
reading = (
f"A mountain. Good. The ground here has been humble too long. I will "
f"raise it slow, with rough shoulders, and hang mist on it so it "
f"keeps its own counsel."
)
return {
"reading": reading,
"turns": [
_call(
"Lift the bedrock first; the rest is ornament.",
"raise_terrain",
lat=lat, lon=lon, radius_deg=_r1(rng, 18, 30),
height=_r2(rng, 0.08, 0.11), roughness=_r2(rng, 0.7, 0.9),
),
_call(
"A second shoulder, lower, so the peak has company.",
"raise_terrain",
lat=_clamp_lat(lat - 9), lon=_wrap_lon(lon + 11),
radius_deg=_r1(rng, 10, 16),
height=_r2(rng, 0.04, 0.06), roughness=0.6,
),
_call(
"Mist for the high places.",
"set_weather",
kind="mist", intensity=_r2(rng, 0.4, 0.7),
),
_call(
"Set the words at the foot, in stone.",
"inscribe_wish",
text=_inscription(wish), style="stone",
),
_done(
"Let it stand. Mountains are mostly patience.",
"A mountain stands where flatness was, wearing its mist like a vow.",
),
],
}
def _forest(wish: str, rng: random.Random, mood: str) -> dict:
lat, lon = _anchor(rng)
place = _place(rng)
flora_hue = _r1(rng, 110, 150) if mood != "joyful" else _r1(rng, 60, 120)
reading = (
f"A forest asks for patience, and gets mine. Trees in {place}, "
f"glowgrass beneath them so the dark has small lights, and a soft "
f"rain to keep the roots believing."
)
return {
"reading": reading,
"turns": [
_call(
"Trees first. Tall, unhurried.",
"spawn_flora",
lat=lat, lon=lon, radius_deg=_r1(rng, 14, 22),
kind="trees", density=_r2(rng, 0.6, 0.8), hue=flora_hue,
),
_call(
"Glowgrass under them, for the small hours.",
"spawn_flora",
lat=_clamp_lat(lat + 3), lon=_wrap_lon(lon + 4),
radius_deg=_r1(rng, 8, 14),
kind="glowgrass", density=_r2(rng, 0.5, 0.9),
hue=_r1(rng, 140, 180),
),
_call(
"Rain, gentle, so nothing here is ever finished.",
"set_weather",
kind="rain", intensity=_r2(rng, 0.2, 0.4),
),
_call(
"Fireflies, to carry the glowgrass up into the air.",
"spawn_life",
lat=lat, lon=lon, radius_deg=_r1(rng, 8, 14),
kind="fireflies", count=rng.randint(6, 12),
hue=_r1(rng, 150, 200),
),
_done(
"Forests finish themselves. I only start them.",
f"A forest grows in {place}, lit from below and adrift with fireflies.",
),
],
}
def _mushroom(wish: str, rng: random.Random, mood: str) -> dict:
lat, lon = _anchor(rng)
hue = _r1(rng, 270, 320)
reading = (
"Mushrooms, then — the small folk of the dark. I will seed them in a "
"ring, set a shrine where their song gathers, and dim the sky to "
"violet hours so they can be heard."
)
return {
"reading": reading,
"turns": [
_call(
"A ring of them, like a held note.",
"spawn_flora",
lat=lat, lon=lon, radius_deg=_r1(rng, 8, 14),
kind="mushrooms", density=_r2(rng, 0.7, 0.95), hue=hue,
),
_call(
"A shrine at the center, to collect the song.",
"place_structure",
lat=lat, lon=lon, kind="shrine",
scale=_r2(rng, 0.8, 1.2), hue=hue,
),
_call(
"Mist, thin, so the glow carries.",
"set_weather",
kind="mist", intensity=_r2(rng, 0.3, 0.5),
),
_call(
"Night above; violet hours below.",
"set_sky",
palette="night", star_density=_r2(rng, 0.7, 0.9),
moons=rng.randint(1, 2),
),
_done(
"Let them sing to no one. That is still singing.",
"In a ring of singing mushrooms, a shrine holds the long low note.",
),
],
}
def _lighthouse(wish: str, rng: random.Random, mood: str) -> dict:
lat, lon = _anchor(rng)
place = _place(rng)
reading = (
f"Someone is thinking of the lost. I will raise a headland in "
f"{place}, set a tower with a turning lamp upon it, and give the "
f"dark water a reason to be less sure of itself."
)
return {
"reading": reading,
"turns": [
_call(
"Ground first; a tower needs a shoulder to stand on.",
"raise_terrain",
lat=lat, lon=lon, radius_deg=_r1(rng, 8, 12),
height=_r2(rng, 0.05, 0.07), roughness=0.5,
),
_call(
"The tower. The lamp. The long patience.",
"place_structure",
lat=_clamp_lat(lat + 1), lon=_wrap_lon(lon - 1),
kind="lighthouse", scale=_r2(rng, 1.4, 1.9),
hue=_r1(rng, 40, 55),
),
_call(
"Dusk, so the beam means something.",
"set_sky",
palette="dusk", star_density=_r2(rng, 0.3, 0.5), moons=1,
),
_done(
"Lit things stay lit. That is the whole law of lighthouses.",
f"A light turns in {place}, for the ones still on their way.",
),
],
}
def _village(wish: str, rng: random.Random, mood: str) -> dict:
lat, lon = _anchor(rng)
warm_hue = _r1(rng, 28, 46)
reading = (
"A hearth-wish. These are my favorite, though a god should not say "
"so. A village in a gentle fold of land, a small cafe with its light "
"on the road, lantern-carts at dusk, and the words kept over the roofs."
)
return {
"reading": reading,
"turns": [
_call(
"A gentle rise, enough to shed the rain.",
"raise_terrain",
lat=lat, lon=lon, radius_deg=_r1(rng, 10, 14),
height=_r2(rng, 0.02, 0.03), roughness=0.3,
),
_call(
"The houses, lit from inside.",
"place_structure",
lat=lat, lon=lon, kind="village",
scale=_r2(rng, 1.0, 1.4), hue=_r1(rng, 30, 50),
),
_call(
"A cafe at the corner, its warmth spilled on the road.",
"place_structure",
lat=_clamp_lat(lat + 1), lon=_wrap_lon(lon - 2),
kind="cafe", scale=_r2(rng, 0.8, 1.1), hue=warm_hue,
),
_call(
"Lantern-carts, gliding home at dusk.",
"spawn_life",
lat=lat, lon=lon, radius_deg=_r1(rng, 6, 10),
kind="carts", count=rng.randint(3, 6), hue=warm_hue,
),
_call(
"Set the wish over the rooftops, where smoke would go.",
"inscribe_wish",
text=_inscription(wish), style="orbit",
),
_done(
"Small lights, kept on. There is no greater architecture.",
"A village stands with its windows lit, and carts come and go beneath them.",
),
],
}
def _city(wish: str, rng: random.Random, mood: str) -> dict:
# Everything clusters TIGHT around one anchor — a town you build up close,
# not specks scattered across a sphere (town mode, v1.2).
lat, lon = _anchor(rng)
glow_hue = _r1(rng, 200, 280)
warm_hue = _r1(rng, 30, 50)
reading = (
"A city, then — the big wish, the brave one. I will lay a district "
"where the town already stands, raise a tower over it, a warehouse and "
"a cafe beside, and run a road and its carts between them."
)
return {
"reading": reading,
"turns": [
_call(
"First a whole district — houses and footpaths in one breath.",
"build_district",
lat=lat, lon=lon, radius_deg=_r1(rng, 6, 12),
density=_r2(rng, 0.6, 0.9), hue=warm_hue,
),
_call(
"The tower over it, slender, its rooftop light slow-pulsing.",
"place_structure",
lat=_clamp_lat(lat + 1), lon=_wrap_lon(lon + 1),
kind="tower", scale=_r2(rng, 1.4, 1.9), hue=glow_hue,
),
_call(
"A warehouse at its foot, one great door glowing.",
"place_structure",
lat=_clamp_lat(lat - 2), lon=_wrap_lon(lon + 2),
kind="warehouse", scale=_r2(rng, 1.0, 1.4), hue=_r1(rng, 36, 52),
),
_call(
"A cafe to keep one window warm against all of it.",
"place_structure",
lat=_clamp_lat(lat + 2), lon=_wrap_lon(lon - 1),
kind="cafe", scale=_r2(rng, 0.7, 1.0), hue=warm_hue,
),
_call(
"A road to bind them, paved and faintly lit.",
"place_road",
path=[
[_clamp_lat(lat - 2), _wrap_lon(lon + 2)],
[lat, lon],
[_clamp_lat(lat + 2), _wrap_lon(lon - 1)],
],
),
_call(
"Carts to thread the streets between them, slow and constant.",
"spawn_life",
lat=lat, lon=lon, radius_deg=_r1(rng, 6, 10),
kind="carts", count=rng.randint(6, 10), hue=warm_hue,
),
_done(
"A city is only small lights agreeing to stay near each other.",
"A district, a tower, a warehouse and cafe, a road and its carts — all in one place.",
),
],
}
def _town(wish: str, rng: random.Random, mood: str) -> dict:
# The town-growth script: a district plus civic buildings (bank, market,
# house), a road, and carts — all clustered into one block, so the mock
# demo + headless shots show a real town densifying, not lone specks.
lat, lon = _anchor(rng)
warm_hue = _r1(rng, 28, 48)
stone_hue = _r1(rng, 200, 250)
reading = (
"A town wants growing, not founding anew. I will lay a fresh district "
"where the others stand, set a bank and a market at its heart, a house "
"on the corner, and a road to tie the block together."
)
return {
"reading": reading,
"turns": [
_call(
"A district first — a dozen small roofs and the paths between.",
"build_district",
lat=lat, lon=lon, radius_deg=_r1(rng, 6, 12),
density=_r2(rng, 0.6, 0.9), hue=warm_hue,
),
_call(
"A bank at the heart, stone-faced and certain.",
"place_structure",
lat=_clamp_lat(lat + 1), lon=_wrap_lon(lon + 1),
kind="bank", scale=_r2(rng, 0.9, 1.3), hue=stone_hue,
),
_call(
"A market beside it, its awnings warm at dusk.",
"place_structure",
lat=_clamp_lat(lat - 1), lon=_wrap_lon(lon + 2),
kind="market", scale=_r2(rng, 0.8, 1.1), hue=warm_hue,
),
_call(
"One house on the corner, a lamp in its window.",
"place_structure",
lat=_clamp_lat(lat + 2), lon=_wrap_lon(lon - 1),
kind="house", scale=_r2(rng, 0.7, 1.0), hue=warm_hue,
),
_call(
"A road to tie the block to the rest of the town.",
"place_road",
path=[
[_clamp_lat(lat + 2), _wrap_lon(lon - 1)],
[lat, lon],
[_clamp_lat(lat - 1), _wrap_lon(lon + 2)],
],
),
_call(
"Lantern-carts to walk the new street home.",
"spawn_life",
lat=lat, lon=lon, radius_deg=_r1(rng, 5, 9),
kind="carts", count=rng.randint(3, 6), hue=warm_hue,
),
_done(
"A town grows the way moss does — outward, and toward the light.",
"A new block stands by the others: a district, a bank, a market, a house, a lit road.",
),
],
}
def _storm(wish: str, rng: random.Random, mood: str) -> dict:
lat, lon = _anchor(rng)
reading = (
"A storm. Yes. Even a small world needs its temper. I will bruise "
"the sky to ember, send the rain sideways, and let the thunder say "
"the part I will not."
)
return {
"reading": reading,
"turns": [
_call(
"First the sky goes dark — ember, bruised at the edges.",
"set_sky",
palette="ember", star_density=_r2(rng, 0.1, 0.2),
moons=rng.randint(0, 1),
),
_call(
"Now the storm itself, full-throated.",
"set_weather",
kind="storm", intensity=_r2(rng, 0.8, 1.0),
),
_call(
"Reeds in the lowlands; something must bend and live.",
"spawn_flora",
lat=lat, lon=lon, radius_deg=_r1(rng, 10, 16),
kind="reeds", density=_r2(rng, 0.4, 0.6),
hue=_r1(rng, 90, 130),
),
_done(
"Let it rage. Weather is honesty at scale.",
"A storm now walks the world, and the world is briefly honest.",
),
],
}
def _snow(wish: str, rng: random.Random, mood: str) -> dict:
lat, lon = _anchor(rng)
reading = (
"Winter, asked for kindly. I will thin the sky, let snow stand in "
"the air, and raise one pale hill for the cold to keep."
)
return {
"reading": reading,
"turns": [
_call(
"The sky first: thin, far, wintry.",
"set_sky",
palette=rng.choice(("night", "void")),
star_density=_r2(rng, 0.5, 0.7), moons=rng.randint(1, 2),
),
_call(
"Snow, unhurried.",
"set_weather",
kind="snow", intensity=_r2(rng, 0.5, 0.8),
),
_call(
"One hill for the drifts to lean against.",
"raise_terrain",
lat=lat, lon=lon, radius_deg=_r1(rng, 12, 18),
height=_r2(rng, 0.04, 0.06), roughness=0.5,
),
_done(
"Hush, then. Winter keeps its own ledger.",
"Snow falls without hurry on a world that has agreed to hush.",
),
],
}
def _sky(wish: str, rng: random.Random, mood: str) -> dict:
lat, lon = _anchor(rng)
moons = rng.randint(2, 3)
palette = rng.choice(("aurora", "night"))
reading = (
"The mortal looks up; so will I. More stars, another moon or two, "
"and the wish itself set in orbit where the night can read it."
)
return {
"reading": reading,
"turns": [
_call(
"More stars. There is no such thing as enough.",
"set_sky",
palette=palette, star_density=_r2(rng, 0.8, 1.0), moons=moons,
),
_call(
"The wish goes into orbit, where the night can read it.",
"inscribe_wish",
text=_inscription(wish), style="orbit",
),
_call(
"Glowgrass below, so the ground answers the sky.",
"spawn_flora",
lat=lat, lon=lon, radius_deg=_r1(rng, 8, 14),
kind="glowgrass", density=_r2(rng, 0.4, 0.7),
hue=_r1(rng, 150, 200),
),
_call(
"And a flock to circle beneath the new moons.",
"spawn_life",
lat=lat, lon=lon, radius_deg=_r1(rng, 10, 16),
kind="birds", count=rng.randint(5, 9), hue=_r1(rng, 200, 260),
),
_done(
"Look up, little world. I rewrote you an answer.",
f"The night is rewritten: more stars, {moons} moons, a flock, one wish in orbit.",
),
],
}
def _default(wish: str, rng: random.Random, mood: str) -> dict:
lat, lon = _anchor(rng)
short = _snippet(wish, 40)
structure = rng.choice(("arch", "monolith"))
style = rng.choice(("stone", "orbit"))
article = "an" if structure == "arch" else "a"
reading = (
f'I will be honest: I do not know what "{short}" is. The world has '
f"room for things I cannot name. I will make a small strange place "
f"and let the wish live there as itself."
)
structure_thought = {
"arch": "An arch to nowhere, which is somewhere now.",
"monolith": "A monolith, blank-faced, exactly as confused as I am.",
}[structure]
return {
"reading": reading,
"turns": [
_call(
"Vines, I think. Nonsense climbs well.",
"spawn_flora",
lat=lat, lon=lon, radius_deg=_r1(rng, 6, 12),
kind="vines", density=_r2(rng, 0.5, 0.8),
hue=_r1(rng, 0, 360),
),
_call(
structure_thought,
"place_structure",
lat=_clamp_lat(lat + 2), lon=_wrap_lon(lon - 3),
kind=structure, scale=_r2(rng, 0.7, 1.3),
hue=_r1(rng, 0, 360),
),
_call(
f"The wish itself, set in {style}, exactly as spoken.",
"inscribe_wish",
text=_inscription(wish), style=style,
),
_done(
f"It is made. Let {article} {structure} explain it to the rain.",
f'The world now holds "{_snippet(wish, 60)}", which is more than it held before.',
),
],
}
# --------------------------------------------------------------------------
# Category routing (first match wins; most specific first)
# --------------------------------------------------------------------------
_CATEGORIES: tuple[tuple[re.Pattern[str], object], ...] = (
(re.compile(r"\b(mushrooms?|fungus|fungi|spores?)\b", re.I), _mushroom),
(re.compile(r"\b(lighthouses?|beacons?|lamps?|ships?|sailors?|harbou?rs?|light)\b", re.I), _lighthouse),
(re.compile(r"\b(towns?|districts?|neighbou?rhoods?|quarters?|suburbs?|blocks?|streets?|roads?|banks?|markets?|marketplaces?)\b", re.I), _town),
(re.compile(r"\b(cit(?:y|ies)|towers?|skyscrapers?|warehouses?|caf[eé]s?|cafeterias?|cars?|carts?|traffic|downtown|metropolis|buildings?)\b", re.I), _city),
(re.compile(r"\b(villages?|homes?|houses?|hearths?|kettles?|people|friends?|family)\b", re.I), _village),
(re.compile(r"\b(seas?|oceans?|lakes?|rivers?|streams?|water|tides?|waves?|shores?|pools?)\b", re.I), _water),
(re.compile(r"\b(mountains?|peaks?|hills?|cliffs?|summits?|crags?|valleys?)\b", re.I), _mountain),
(re.compile(r"\b(forests?|trees?|groves?|woods?|firefl\w*|gardens?|meadows?|flowers?|blooms?)\b", re.I), _forest),
(re.compile(r"\b(storms?|thunder|lightning|rain|winds?|tempests?)\b", re.I), _storm),
(re.compile(r"\b(snow|winter|ice|frost|cold)\b", re.I), _snow),
(re.compile(r"\b(stars?|sky|skies|night|moons?|auroras?|dawn|dusk|sun|comets?)\b", re.I), _sky),
)
def build_script(wish: str) -> dict:
"""Build the deterministic script for a wish.
Returns {"reading": str, "turns": [turn, ...]} where the final turn is a
done turn. Same wish (modulo case/whitespace) always yields the same
script.
"""
wish = (wish or "").strip() or "nothing in particular"
rng = random.Random(_seed_for(wish))
mood, _guidance = infer_mood(wish)
for pattern, builder in _CATEGORIES:
if pattern.search(wish):
return builder(wish, rng, mood) # type: ignore[operator]
return _default(wish, rng, mood)