riddle/wyr: fix quality issues from tonight's chat
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 8s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Successful in 48s
Lint / Secret scan (gitleaks) (push) Successful in 12s

riddle:
- Tighten generation prompt with explicit rules: specific noun answer,
  no answer word in the riddle, no 'what could it possibly mean', clues
  must logically point to ONE answer, prefer concrete things
- Fix answer matching: strip articles (a/an/the), allow partial match
  so 'person' hits 'a person' and 'shadow' hits 'my shadow' etc.

wyr:
- Prompt now asks for genuinely difficult dilemmas with real downsides
  on both sides; explicitly bans boring options like dolphins/karaoke

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-22 21:17:44 -04:00
parent 2457451d4c
commit b6e99d165b
+31 -8
View File
@@ -1647,11 +1647,15 @@ def record_wyr_vote(event_id: str, sender: str, key: str) -> None:
async def _generate_wyr() -> dict | None:
system_msg = (
"You are a game host generating Would You Rather questions. "
"You are a game host generating Would You Rather questions for a group of adult friends. "
"Always respond with ONLY a JSON object — no markdown fences, no explanation. "
'Format: {"question": "Would you rather...", "option_a": "short option", "option_b": "short option"}'
'Format: {"question": "Would you rather...", "option_a": "short option", "option_b": "short option"}\n'
"Make the dilemma genuinely difficult — both options should have real downsides so it's actually a hard choice. "
"Be creative and edgy: embarrassing scenarios, weird superpowers, social nightmares, gross but survivable situations, "
"impossible tradeoffs. Avoid boring safe options like 'dance with dolphins' or 'sing karaoke'. "
"Keep each option under 10 words."
)
user_msg = "Generate a fun, creative Would You Rather question. Keep each option under 10 words."
user_msg = "Generate a spicy, genuinely difficult Would You Rather question."
try:
timeout = aiohttp.ClientTimeout(total=60)
async with aiohttp.ClientSession(timeout=timeout) as session:
@@ -1774,9 +1778,16 @@ async def _generate_riddle() -> dict | None:
) if _riddle_recent else ""
system_msg = (
"You are a riddle generator. Always respond with ONLY a JSON object — no markdown fences, no explanation. "
'Format: {"riddle": "the riddle text", "answer": "short answer"}'
'Format: {"riddle": "the riddle text", "answer": "short answer"}\n'
"Rules for a good riddle:\n"
"- The answer must be a specific, unambiguous noun (1-3 words). Avoid abstract answers.\n"
"- The riddle must describe the answer through metaphor or wordplay — NOT by literally describing it.\n"
"- Do NOT include the answer word anywhere in the riddle text.\n"
"- Do NOT end the riddle with 'what am I?' or 'what could it possibly mean?' — the riddle should stand alone.\n"
"- The clues must logically point to ONE specific answer. Test it: would most people agree this answer is correct?\n"
"- Avoid riddles about riddles, shadows, or abstract concepts. Prefer concrete things: candle, mirror, clock, river, echo, stamp, etc."
)
user_msg = f"Generate a clever, original riddle. The answer should be 1-4 words.{avoid_clause}"
user_msg = f"Generate a clever, original riddle with a clear unambiguous answer.{avoid_clause}"
try:
timeout = aiohttp.ClientTimeout(total=60)
async with aiohttp.ClientSession(timeout=timeout) as session:
@@ -1856,14 +1867,26 @@ async def cmd_riddle(client: AsyncClient, room_id: str, sender: str, args: str):
_RIDDLE_ACTIVE[room_id]["task"] = task
def _riddle_matches(answer: str, body: str) -> bool:
"""Fuzzy match: strip articles, allow the core word to appear in the guess or vice versa."""
def _normalize(s: str) -> str:
s = s.strip().lower()
for art in ("a ", "an ", "the "):
if s.startswith(art):
s = s[len(art):]
return s.strip()
ans = _normalize(answer)
guess = _normalize(body)
return ans == guess or ans in guess or guess in ans
async def check_riddle_answer(client: AsyncClient, room_id: str, sender: str, body: str) -> bool:
"""Check if a room message answers the active riddle. Returns True if correct."""
if room_id not in _RIDDLE_ACTIVE:
return False
game = _RIDDLE_ACTIVE[room_id]
answer_lower = game["answer"].lower()
body_lower = body.strip().lower()
if answer_lower in body_lower:
if _riddle_matches(game["answer"], body.strip()):
task = game.get("task")
if task:
task.cancel()