- Set variant defense registration to mode="*" (both attacks and defenses)
- Strengthen telegraph switch test to verify new move's telegraph text
- Remove unused punch parameter from four idle timeout tests
- Use single time.monotonic() call in attack() method
Encounters track last_action_at (updated on attack and defend). If 30
seconds pass with no actions, combat fizzles out with a message to both
players and combat mode is popped. start_encounter initializes the
timestamp so fresh encounters don't immediately timeout.
resolve() returns ResolveResult dataclass with attacker_msg, defender_msg,
damage, countered, and combat_ended fields. process_combat is now async
and sends messages to both participants on resolve. Counter, hit, and
slam messages give each player their own perspective on what happened.