Word Search bug-fixes + Codex polish
Two reported bugs, same root cause: the fixed-cell grid overflowed its wrapper on Large, so (a) the last column spilled past the border and (b) the pointer→cell math drifted across the row, recording finds "off by a letter". * Grid now uses 1fr columns with max-width = n·32px: the board grows with the grid and can never overflow (shrinks to fit a narrow phone instead). * cellAt() accounts for the grid padding/border, so selection is exact edge-to-edge. * restore() now validates each saved find against the CURRENT grid and drops any whose cells no longer spell the word — clears stale highlights if the day's puzzle changed. Codex follow-ups: * _ws_propose now requires >= large.count + 4 valid words before accepting an LLM proposal (else falls back to a curated theme), so a thin LLM result can't underfill Large. Added a thin-LLM fallback test. * Cleaned Svelte warnings: removed the now-unused .gamecard.soon CSS, added an ARIA role/label to the grid, declared gridEl with $state. Build is warning-clean. * Added a stale-load guard in WordSearchGame.load() so rapid size switches can't let an older request overwrite the newer selection. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+5
-2
@@ -162,7 +162,10 @@ _DIRS = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
|
||||
# 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
|
||||
WS_TARGET = 28 # words to ask the LLM for, so there's variety to sample from
|
||||
# Only accept an LLM proposal with enough words to fill Large with room to spare;
|
||||
# otherwise fall back to a curated theme (which always has plenty).
|
||||
WS_MIN_ACCEPT = WS_TIERS["large"]["count"] + 4
|
||||
|
||||
# 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.
|
||||
@@ -217,7 +220,7 @@ def _ws_propose(client) -> tuple[str, list[str]] | None:
|
||||
elif s.upper().startswith("WORDS:"):
|
||||
words = [w.strip().upper() for w in re.split(r"[,\s]+", s.split(":", 1)[1]) if w.strip()]
|
||||
words = [w for w in dict.fromkeys(words) if w.isalpha() and 4 <= len(w) <= 8]
|
||||
if theme and len(words) >= 6:
|
||||
if theme and len(words) >= WS_MIN_ACCEPT: # enough to fill Large + spare
|
||||
return theme, words
|
||||
except Exception: # noqa: BLE001 — fall back to a curated theme
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user