Word Search polish: constant cell size, 28-word themes, per-size variety, palette
Playtesting fixes: * Constant cell size (~32px) — the board GROWS with the grid instead of shrinking letters into a fixed box. Fixes Small's oversized spacing; on a narrow phone the largest grid gently scales to fit (the standard word-search compromise). * Themes now gather ~28 words (LLM asked for 28; curated fallbacks ~22 each), and each size samples its OWN subset — so every tier is a distinct puzzle. Large is now reliably full (14 words on 14×14), fixing the "13 words / 11 listed" mismatch. * Tiers: small 8×8/6, med 11×11/10, large 14×14/14. * Word list is now a framed "Find these · n/total" palette panel (pill chips that take on each found word's colour) instead of loose text under the grid. * Size chips use qualitative labels (cosy / balanced / a longer sit) so no count can ever contradict the actual puzzle. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+38
-25
@@ -159,28 +159,38 @@ def adjudicate_word_guess(conn: sqlite3.Connection, date: str, variant: str, gue
|
||||
_DIRS = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
|
||||
|
||||
# Size tiers: bigger grid → more words → a longer sit. Built per-request from one
|
||||
# stored theme+word list, so all three sizes share the day's theme.
|
||||
WS_TIERS = {"small": {"grid": 8, "count": 6}, "med": {"grid": 11, "count": 9}, "large": {"grid": 14, "count": 13}}
|
||||
# stored theme+word list, sampling a different subset per size so each is its own
|
||||
# puzzle, while all three share the day's theme.
|
||||
WS_TIERS = {"small": {"grid": 8, "count": 6}, "med": {"grid": 11, "count": 10}, "large": {"grid": 14, "count": 14}}
|
||||
WS_TARGET = 28 # words to gather per theme, so there's variety to sample from
|
||||
|
||||
# Curated fallbacks — calm and neutral everyday scenes, not just upbeat. ~13
|
||||
# words each (4–8 letters, uppercase) so the large tier has enough to place.
|
||||
# Curated fallbacks — calm and neutral everyday scenes, not just upbeat. ~22 words
|
||||
# each (4–8 letters, uppercase) so every size has a fresh subset to draw from.
|
||||
_WS_FALLBACKS = [
|
||||
("Around the house", ["TABLE", "CHAIR", "CLOCK", "SHELF", "COUCH", "LAMP", "PILLOW", "WINDOW",
|
||||
"CARPET", "MIRROR", "CANDLE", "KETTLE", "DRAWER"]),
|
||||
("At the beach", ["WAVES", "SHELL", "SANDY", "TIDE", "SHORE", "TOWEL", "BREEZE", "SUNSET",
|
||||
"PEBBLE", "CORAL", "OCEAN", "SAILS", "PIER"]),
|
||||
("In the kitchen", ["BREAD", "SPOON", "PLATE", "KETTLE", "FLOUR", "APRON", "WHISK", "SUGAR",
|
||||
"BUTTER", "RECIPE", "SIMMER", "PANTRY", "TEAPOT"]),
|
||||
("In the garden", ["BLOOM", "PETAL", "ROOTS", "LEAF", "GARDEN", "FLOWER", "SUNNY", "SEEDS",
|
||||
"MEADOW", "SPROUT", "HEDGE", "TROWEL", "VINES"]),
|
||||
("A walk outdoors", ["TRAIL", "MEADOW", "BROOK", "BIRDS", "BREEZE", "PEBBLE", "FOREST", "MAPLE",
|
||||
"ACORN", "STREAM", "BRANCH", "VALLEY", "PATH"]),
|
||||
("Making music", ["PIANO", "DRUMS", "CHOIR", "MELODY", "GUITAR", "VIOLIN", "SINGER", "BALLAD",
|
||||
"RHYTHM", "ENCORE", "TEMPO", "NOTES", "SONG"]),
|
||||
("Quiet calm", ["PEACE", "QUIET", "STILL", "SERENE", "REST", "SOOTHE", "GENTLE", "BREATHE",
|
||||
"CALM", "HUSH", "DRIFT", "EASE", "DREAM"]),
|
||||
("Small joys", ["SMILE", "LAUGH", "CHEER", "HAPPY", "MERRY", "DANCE", "DELIGHT", "GLOW",
|
||||
"PLAY", "GRIN", "BEAM", "GLEE", "WARM"]),
|
||||
("Around the house", ["TABLE", "CHAIR", "CLOCK", "SHELF", "COUCH", "PILLOW", "WINDOW", "CARPET",
|
||||
"MIRROR", "CANDLE", "KETTLE", "DRAWER", "CLOSET", "CURTAIN", "CUSHION",
|
||||
"BASKET", "BOTTLE", "TOWEL", "BROOM", "LADDER", "STAIRS", "PANTRY", "BLANKET"]),
|
||||
("At the beach", ["WAVES", "SHELL", "SANDY", "TIDE", "SHORE", "TOWEL", "BREEZE", "SUNSET", "PEBBLE",
|
||||
"CORAL", "OCEAN", "SAILS", "SURF", "SEAGULL", "BUCKET", "SPADE", "DUNES", "LAGOON",
|
||||
"DRIFT", "SALTY", "SUNNY", "HORIZON", "COVE", "PIER"]),
|
||||
("In the kitchen", ["BREAD", "SPOON", "PLATE", "KETTLE", "FLOUR", "APRON", "WHISK", "SUGAR", "BUTTER",
|
||||
"RECIPE", "SIMMER", "PANTRY", "TEAPOT", "SAUCER", "LADLE", "KNIFE", "BOWL", "GRATER",
|
||||
"SKILLET", "PEPPER", "GARLIC", "HONEY", "TOAST"]),
|
||||
("In the garden", ["BLOOM", "PETAL", "ROOTS", "LEAF", "GARDEN", "FLOWER", "SUNNY", "SEEDS", "MEADOW",
|
||||
"SPROUT", "HEDGE", "TROWEL", "VINES", "SOIL", "SHRUB", "BUDS", "STALK", "DAISY",
|
||||
"TULIP", "FERNS", "SHOVEL", "BRANCH", "BREEZE"]),
|
||||
("A walk outdoors", ["TRAIL", "MEADOW", "BROOK", "BIRDS", "BREEZE", "PEBBLE", "FOREST", "MAPLE", "ACORN",
|
||||
"STREAM", "BRANCH", "VALLEY", "PATH", "HILLS", "RIVER", "FIELD", "CLOUDS", "LEAVES",
|
||||
"MOSSY", "TWIGS", "FENCE", "BENCH", "RAMBLE"]),
|
||||
("Making music", ["PIANO", "DRUMS", "CHOIR", "MELODY", "GUITAR", "VIOLIN", "SINGER", "BALLAD", "RHYTHM",
|
||||
"ENCORE", "TEMPO", "NOTES", "SONG", "FLUTE", "CELLO", "BRASS", "CHORD", "STRUM",
|
||||
"HARMONY", "LYRICS", "BANJO", "ANTHEM", "TUNES"]),
|
||||
("Quiet calm", ["PEACE", "QUIET", "STILL", "SERENE", "REST", "SOOTHE", "GENTLE", "BREATHE", "CALM",
|
||||
"HUSH", "DRIFT", "EASE", "DREAM", "RELAX", "MELLOW", "STEADY", "SETTLE", "LINGER",
|
||||
"PAUSE", "SLOW", "SOFT", "WARM"]),
|
||||
("Small joys", ["SMILE", "LAUGH", "CHEER", "HAPPY", "MERRY", "DANCE", "DELIGHT", "GLOW", "PLAY", "GRIN",
|
||||
"BEAM", "GLEE", "WARM", "GIGGLE", "SHARE", "TREAT", "SUNNY", "SWEET", "LUCKY", "CHARM",
|
||||
"SPARK", "BLISS"]),
|
||||
]
|
||||
|
||||
|
||||
@@ -193,9 +203,9 @@ def _ws_propose(client) -> tuple[str, list[str]] | None:
|
||||
{"role": "system", "content": "You set up a calm word search. The theme can be uplifting OR just a "
|
||||
"pleasant everyday scene (e.g. 'Around the house', 'At the beach', "
|
||||
"'In the kitchen'). Reply exactly as two lines:\n"
|
||||
"THEME: <2-4 word theme>\nWORDS: W1, W2, ... W13\n"
|
||||
"Give 13 single real words, 4-8 letters, UPPERCASE, related to the theme, "
|
||||
"nothing negative or unpleasant, no phrases."},
|
||||
"THEME: <2-4 word theme>\nWORDS: W1, W2, ... W28\n"
|
||||
f"Give {WS_TARGET} single real words, 4-8 letters, UPPERCASE, related to the "
|
||||
"theme, a good mix of lengths, nothing negative or unpleasant, no phrases."},
|
||||
{"role": "user", "content": "Give me one calm theme."},
|
||||
]
|
||||
text = client.chat_text(msg) or ""
|
||||
@@ -272,8 +282,11 @@ def wordsearch_response(conn: sqlite3.Connection, date: str, size: str = "med")
|
||||
size = "med"
|
||||
p = generate_wordsearch_puzzle(conn, date) # on-demand (curated fallback) if missing
|
||||
tier = WS_TIERS[size]
|
||||
usable = [w for w in p["words"] if len(w) <= tier["grid"]][:tier["count"]]
|
||||
grid, placed = _build_grid(usable, tier["grid"], _seed(date, "wordsearch", size))
|
||||
usable = [w for w in p["words"] if len(w) <= tier["grid"]]
|
||||
# Sample a fresh subset per size so each tier is its own puzzle (seeded → stable).
|
||||
rng = random.Random(_seed(date, "wordsearch", size, "pick"))
|
||||
chosen = rng.sample(usable, min(tier["count"], len(usable))) if usable else []
|
||||
grid, placed = _build_grid(chosen, tier["grid"], _seed(date, "wordsearch", size))
|
||||
return {"game": "wordsearch", "date": date, "size": size, "theme": p["theme"],
|
||||
"words": placed, "grid": grid}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user