Add dice-roll animation and tighten attack-roll prompt rules

Broadcast a "rolling" WS event when the DM invokes roll_dice, and show
a cycling dice-emoji animation with the roll notation in the chat while
waiting for the result, instead of just the generic typing indicator.

Also split the dice-roll prompt rule into skill/save checks (DC shown
to the player) vs. attack rolls (AC stays secret but must still be
labeled as a roll), and made the "always roll yourself, never ask the
player to roll" instruction unconditional.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Thorsten
2026-09-01 17:28:37 +02:00
parent 624644619c
commit 2b99451fdf
6 changed files with 62 additions and 11 deletions
+7 -1
View File
@@ -1,6 +1,7 @@
import json
import logging
import uuid
from collections.abc import Awaitable, Callable
from sqlalchemy.ext.asyncio import AsyncSession
@@ -42,7 +43,10 @@ async def _execute_tool_call(
async def run_dm_turn(
session: AsyncSession, game_id: uuid.UUID, latest_player_message: str | None = None
session: AsyncSession,
game_id: uuid.UUID,
latest_player_message: str | None = None,
on_roll: Callable[[str], Awaitable[None]] | None = None,
) -> Message:
client = get_llm_client()
system_prompt = get_dm_system_prompt()
@@ -83,6 +87,8 @@ async def run_dm_turn(
for tool_call in message.tool_calls:
tool_input = fix_double_escaped_unicode(json.loads(tool_call.function.arguments))
if tool_call.function.name == "roll_dice" and on_roll is not None:
await on_roll(tool_input.get("notation", ""))
result = await _execute_tool_call(session, game_id, tool_call.function.name, tool_input)
messages.append(
{