diff --git a/matrixbot/commands.py b/matrixbot/commands.py index 04817ab..7e5d7bc 100644 --- a/matrixbot/commands.py +++ b/matrixbot/commands.py @@ -1384,12 +1384,39 @@ def _hangman_board_html(game: dict, status_line: str = "") -> tuple[str, str]: return plain, html +_HANGMAN_RECENT_MAX = 30 +_HANGMAN_CACHE_FILE = Path("hangman_cache.json") + + +def _load_hangman_cache() -> list[str]: + try: + data = json.loads(_HANGMAN_CACHE_FILE.read_text()) + return data.get("words", []) + except Exception: + return [] + + +def _save_hangman_cache(words: list[str]) -> None: + try: + _HANGMAN_CACHE_FILE.write_text(json.dumps({"words": words}, indent=2)) + except Exception as e: + logger.warning("Failed to save hangman cache: %s", e) + + +_hangman_recent: list[str] = _load_hangman_cache() + + async def _generate_hangman_word() -> dict | None: + avoid_clause = ( + " Do NOT use any of these recently used words: " + + ", ".join(f'"{w}"' for w in _hangman_recent[-20:]) + + "." + ) if _hangman_recent else "" system_msg = ( "You are a hangman game generator. Always respond with ONLY a JSON object — no markdown, no explanation. " 'Format: {"word": "example", "hint": "short category or hint"}' ) - user_msg = "Pick a common English word between 5 and 8 letters (lowercase letters only, no hyphens or spaces) and give a short hint." + user_msg = f"Pick a common English word between 5 and 8 letters (lowercase letters only, no hyphens or spaces) and give a short hint.{avoid_clause}" for attempt in range(2): try: timeout = aiohttp.ClientTimeout(total=60) @@ -1419,6 +1446,10 @@ async def _generate_hangman_word() -> dict | None: word = parsed.get("word", "").lower().strip() hint = parsed.get("hint", "").strip() if word.isalpha() and 5 <= len(word) <= 8 and hint: + _hangman_recent.append(word) + if len(_hangman_recent) > _HANGMAN_RECENT_MAX: + _hangman_recent.pop(0) + _save_hangman_cache(_hangman_recent) return {"word": word, "hint": hint} logger.warning("hangman: validation failed (attempt %d): word=%r hint=%r", attempt + 1, word, hint) except Exception as e: