Early returns in log_chaos, log_sac_bunt, and log_stealing left play
locks permanently stuck because the lock was acquired but never released.
The new locked_play async context manager wraps checks_log_interaction()
and guarantees lock release on exception, early return, or normal exit.
Migrated all 18 locking commands in gameplay.py and removed redundant
double-locking in end_game_command.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>