
    Ii,\             
         S SK Jr  S SKJrJr  S SKrSSKJrJrJ	r	  SSK
Jr  SSKJrJrJrJrJr  SS	KJrJr  SS
KJrJrJr  SSKJr  SSKJr  SSKJr  S SKJ r   S SK!J"r"  S SK#J$r$J%r%J&r&  SSK'J(r(  / SQr)SSSSSSSSSS.	r*Sr+SSS S!S"S#S$.r,S/S% jr-S0S& jr.S1S' jr/S2S( jr0\ " S) S*\	5      5       r1\ " S+ S,\5      5       r2\\ " S- S.\5      5       5       r3g)3    )annotations)	dataclassfieldN   )GamePlayerGameOptions)register_game   )Action	ActionSet
VisibilityEditboxInput	MenuInput)
GameResultPlayerResult)
MenuOption
BoolOptionoption_field)	BotHelper)PokerTurnTimer)Localization)KeybindState)Bot)UserMenuItemEscapeBehavior   	bot_think)	15304560901201803000zpoker-timer-15zpoker-timer-30zpoker-timer-45zpoker-timer-60zpoker-timer-90zchess-timer-120zchess-timer-180zchess-timer-300zpoker-timer-unlimitedabcdefghzchess-piece-pawnzchess-piece-knightzchess-piece-bishopzchess-piece-rookzchess-piece-queenzchess-piece-kingpawnknightbishoprookqueenkingc                F    U S-  nU S-  S-   n[         U   [        U5      -   $ )z5Convert board index (0-63) to chess notation (a1-h8).   r   )FILE_LETTERSstr)indexfileranks      6c:\Users\dbart\PlayPalace11\server\games\chess\game.pyindex_to_notationr:   /   s,    19DA:>DD	))    c                    [        U 5      S:w  a  gU S   R                  5       nU[        ;  a  g [        U S   5      nUS:  d  US:  a  gUS-
  S-  [        R                  U5      -   $ ! [         a     gf = f)z5Convert chess notation (a1-h8) to board index (0-63).r   Nr   r   r3   )lenlowerr4   int
ValueErrorr6   )notationfile_letterr8   s      r9   notation_to_indexrC   6   s    
8}1+##%K,&8A; ax4!81H>L..{;;;	  s   A) )
A65A6c                j    [         R                  U 5      nU(       a  [        R                  " X5      $ U $ )zGet localized piece name.)PIECE_NAMESgetr   )piecelocalekeys      r9   
piece_namerJ   F   s)    
//%
 C
,,Lr;   c                    [         R                  " USU  S35      nUS;  a  Sn[         R                  " USU SU 35      $ )zGet the grammatically correct localized color word for a piece.

Looks up the piece's gender from chess-piece-{piece}-gender, then
returns color-{color}-m or color-{color}-f accordingly.
chess-piece-z-gender)mfrM   color--)r   rF   )rG   colorrH   genders       r9   piece_color_namerS   N   sL     fUG7&CDFZFfUG1VH$=>>r;   c                      \ rS rSr% Sr\" \" \SSSS\S95      r	S\
S	'   \" \" S
SSSS95      rS\
S'   \" \" S
SSSS95      rS\
S'   Srg)ChessOptionsZ   zOptions for Chess.r)   zchess-set-turn-timerzchess-select-turn-timerzchess-option-changed-turn-timer)choicesdefaultlabelprompt
change_msgchoice_labelsr5   
turn_timerTenabledzchess-toggle-auto-drawzchess-option-changed-auto-draw)rX   	value_keyrY   r[   bool	auto_drawzchess-toggle-show-coordinatesz%chess-option-changed-show-coordinatesshow_coordinates N)__name__
__module____qualname____firstlineno____doc__r   r   TURN_TIMER_CHOICESTURN_TIMER_LABELSr]   __annotations__r   ra   rb   __static_attributes__rc   r;   r9   rU   rU   Z   s    "&(,8+	
	J 	 #*7		
It  *1>		
d r;   rU   c                  2    \ rS rSr% SrS\S'   SrS\S'   Srg	)
ChessPlayerz    r5   rQ   r   r?   winsrc   N)rd   re   rf   rg   rQ   rk   rq   rl   rc   r;   r9   rn   rn   z   s    E3OD#Mr;   rn   c                  D  ^  \ rS rSr% Sr\" \S9rS\S'   \" \	S9r
S\S'   \" S S9rS	\S
'   SrS\S'   \" \S9rS\S'   SrS\S'   SrS\S'   SrS\S'   SrS\S'   SrS\S'   SrS\S'   SrS\S'   SrS\S'   \" \S9rS\S'   \" \S9rS \S!'   S"rS\S#'   SrS\S$'   SrS\S%'   SrS\S&'   SrS\S''   \" \S9rS(\S)'   Sr S\S*'   \" \S9r!S+\S,'   S-r"S.\S/'   U 4S0 jr#\$SS1 j5       r%\$SS2 j5       r&\$SS3 j5       r'\$SS4 j5       r(\$SS5 j5       r)SSS6 jjr*SU 4S7 jjr+SS8 jr,SS9 jr-SU 4S: jjr.SU 4S; jjr/S-S<.SS= jjr0SS> jr1SU 4S? jjr2SS@ jr3SSA jr4SSB jr5SSC jr6SSD jr7SSE jr8SU 4SF jjr9SSG jr:SSH jr;                    SSI jr<SSJ jr=SSK jr>SSL jr?SSM jr@SSN jrASSO jrBSSP jrCSSQ jrDSSR jrESSS jrFSST jrGSSU jrHSSV jrISSW jrJSSX jrK            SSY jrLSSZ jrMSS[ jrNSS\ jrOSS] jrPSS^ jrQSS_ jrRSS` jrSSSa jrTSSb jrUSSc jrVSSd jrWSSe jrXSSf jrYSSg jrZSSh jr[SSi jr\SSj jr]SSk jr^SSl jr_SSm jr`SSn jraSSo jrbSSp jrcSSq jrdSSr jreSSs jrfSSt jrgSSu jrhSSv jriSSw jrjS-Sx.SSy jjrkS-Sx.SSz jjrlSS{ jrmSS| jrnSS} jroSS~ jrpSS jrqSS jrrSS jrsSS jrtSS jruSS jrvSS jrwSS jrxSS jrySS jrzSS jr{SS jr|SS jr}SS jr~SS jrSS jrSS jrSS jrSS jr S         SS jjrSrU =r$ )	ChessGame   zChess game implementation.)default_factoryzlist[ChessPlayer]playersrU   optionsc                     S /S-  $ )N@   rc   rc   r;   r9   <lambda>ChessGame.<lambda>   s
    dVb[r;   zlist[dict | None]boardwhiter5   current_colorzdict[str, int | None]selected_squareFr`   	game_overrp   winner_colordraw_reasonTcastle_white_kingsidecastle_white_queensidecastle_black_kingsidecastle_black_queensider?   en_passant_target
list[dict]move_history	list[str]position_historyr   halfmove_clockpromotion_pendingpromotion_squaredraw_offer_fromundo_request_fromr   timertimer_warning_playedzdict[str, bool]board_flippedN
str | None_turn_sound_player_idc                "   > [         TU ]  5         g N)super__post_init__self	__class__s    r9   r   ChessGame.__post_init__   s    r;   c                    g)NChessrc   clss    r9   get_nameChessGame.get_name       r;   c                    g)Nchessrc   r   s    r9   get_typeChessGame.get_type   r   r;   c                    g)Nzcategory-board-gamesrc   r   s    r9   get_categoryChessGame.get_category   s    %r;   c                    gNr   rc   r   s    r9   get_min_playersChessGame.get_min_players       r;   c                    gr   rc   r   s    r9   get_max_playersChessGame.get_max_players   r   r;   c                    [        XUS9$ )N)idnameis_bot)rn   )r   	player_idr   r   s       r9   create_playerChessGame.create_player   s    i6BBr;   c                r   > [         TU ]  X5      nUR                  (       a  SOSnU R                  U5        U$ )Nzgame_chess/botsit.oggzgame_chess/personsit.ogg)r   
add_playerr   
play_sound)r   r   userplayersoundr   s        r9   r   ChessGame.add_player   s2    #D/+1=='>Xr;   c                2   U R                   S:X  a  UR                  (       d  SUl        U R                  R                  UR                  S 5        [        UR                  UR                  S9nU R                  UR                  U5        U R                  SUR                  S9  U R                  S5        [        S U R                   5       5      nU(       d  U R                  5         g U R                  5         g U R                   Vs/ s H   oDR                  UR                  :w  d  M  UPM"     snU l        U R                  R                  UR                  S 5        U R                  R                  UR                  S 5        U R                  SUR                  S9  UR                  (       a  S	OSnU R                  U5        [        S
 U R                   5       5      nU(       d  U R                  5         g U R                   S:X  a  UR                  U R                  :X  ab  U R                  (       aQ  U R                   HA  nUR                  (       a  M  UR                  U l        U R                  SUR                  S9    O   U R                  5         g g s  snf )NplayingT)uuidzplayer-replaced-by-botr   zgame_chess/personleave.oggc              3  B   #    U  H  oR                   (       + v   M     g 7fr   r   .0ps     r9   	<genexpr>0ChessGame._perform_leave_game.<locals>.<genexpr>   s     @<a\\<   z
table-leftzgame_chess/botleave.oggc              3  B   #    U  H  oR                   (       + v   M     g 7fr   r   r   s     r9   r   r      s     <|!XX|r   waitingznew-host)statusr   _userspopr   r   r   attach_userbroadcast_lr   anyrv   destroyrebuild_all_menusplayer_action_setshost)r   r   bot_user
has_humansr   leave_sounds         r9   _perform_leave_gameChessGame._perform_leave_game   s   ;;)#FMM FMKKOOFIIt,6;;VYY7HVYY15fkkJOO89@4<<@@J""$#'<<E<a446993D<E##FIIt4		4(fkk:39==/Fb$<t||<<
LLN;;)#{{dii'DLLA888$%FF	((AFF(C	 &
 ""$ $ Fs   J(Jc                ,   [        SS9nU R                  U5      n[        SSS5       H?  n[        S5       H-  nUS-  U-   nUR                  [	        SU 3SSS	S
SSSS95        M/     MA     S H;  nUR                  [	        SU 3[
        R                  " USU 35      SSSSS95        M=     UR                  [	        S[
        R                  " US5      SSSSS95        UR                  [	        S[
        R                  " US5      SSSSS95        UR                  [	        S [
        R                  " US!5      S"SSSS95        UR                  [	        S#[
        R                  " US$5      S%S&S'SS95        UR                  [	        S([
        R                  " US)5      S*S+S,SS95        UR                  [	        S-[
        R                  " US.5      S/S+S,SS95        UR                  [	        S0[
        R                  " US15      S2S3S4S[        S5S6SS79S895        U$ )9Nturn)r      r   r3   square_rp   _action_square_click_is_square_enabled_is_square_hidden_get_square_labelF)r   rY   handler
is_enabled	is_hidden	get_labelshow_in_actions_menushow_disabled_labelr0   r/   r.   r-   promote_rL   _action_promote_is_promote_enabled_is_promote_hidden)r   rY   r   r   r   r   
offer_drawzchess-offer-draw_action_offer_draw_is_offer_draw_enabled_is_offer_draw_hiddenTaccept_drawchess-you-accept-draw_action_accept_draw_is_draw_response_enabled_is_draw_response_hiddendecline_drawchess-you-decline-draw_action_decline_drawrequest_undozchess-undo-request_action_request_undo_is_request_undo_enabled_is_request_undo_hiddenaccept_undochess-you-accept-undo_action_accept_undo_is_undo_response_enabled_is_undo_response_hiddendecline_undochess-you-decline-undo_action_decline_undoresignzchess-resign_action_resign_is_resign_enabled_is_resign_hiddenchess-resign-confirm_resign_confirm_options)rZ   rw   include_cancel)r   rY   r   r   r   r   input_request)r   _player_localerangeaddr   r   rF   r   )r   r   
action_setrH   r8   r7   irG   s           r9   create_turn_action_set ChessGame.create_turn_action_set  s]   F+
$$V, !R$Da1HtO$QC=  6#7"5"5-2,1	 ! %" ;ENN!%)&**6\%3IJ-42).	 ; 	"&&v/AB,31%)		
 	 "&&v/FG-64%*		
 	!"&&v/GH.64%*		
 	!"&&v/CD.53%)		
 	 "&&v/FG-64%*		
 	!"&&v/GH.64%*		
 	"&&v~>(/-%)'15#(	
  r;   c                  > [         TU ]  U5      nU R                  U5      n[        S[        R
                  " US5      SSSS9[        S[        R
                  " US5      S	SSS9[        S
[        R
                  " US5      SSSS9[        S[        R
                  " US5      SSS[        SS9S9[        S[        R
                  " US5      SSSS S9[        S[        R
                  " US5      SSSS9/n[        U5       Hy  nUR                  U5        UR                  UR                  ;   a%  UR                  R                  UR                  5        UR                  R                  SUR                  5        M{     U$ )N
view_boardzchess-view-board_action_view_board_is_check_enabled_is_always_hidden)r   rY   r   r   r   
flip_boardzchess-flip-board_action_flip_boardcheck_statuszchess-check-status_action_check_status	type_movezchess-type-move_action_type_move_is_type_move_enabledzchess-enter-move)rZ   )r   rY   r   r   r   r  
import_fenzchess-import-fen_action_import_fencheck_turn_timerzchess-check-turn-timer_action_check_turn_timerr   )r   create_standard_action_setr  r   r   rF   r   reversedr  r   _orderremoveinsert)r   r   r  rH   local_actionsactionr   s         r9   r*  $ChessGame.create_standard_action_setx  s   W7?
$$V,"&&v/AB,.- "&&v/AB,.- !"&&v/CD..- "&&v/@A+2-*2DE "&&v/AB,.-" %"&&v/GH2.-M-
\ }-FNN6"yyJ---!!((3$$Q		2	 .
 r;   c                  > [         TU ]  5         U R                  SSS/[        R                  SS9  U R                  SSS/[        R                  SS9  U R                  S	S
S/[        R                  S9  U R                  SSS/[        R                  S9  U R                  SSS/[        R                  SS9  U R                  SSS/[        R                  SS9  U R                  SSS/[        R                  S9  U R                  SSS/[        R                  S9  U R                  SSS/[        R                  S9  U R                  SS S!/[        R                  S9  U R                  S"S#S$/[        R                  S9  U R                  SS%S&/[        R                  S9  U R                  S"S'S(/[        R                  S9  U R                  S)S*S+/[        R                  S9  U R                  S,S-S./[        R                  S9  U R                  S/S0S1/[        R                  S9  U R                  S2S3S4/[        R                  S9  g )5Nbz
View boardr  T)stateinclude_spectatorsszCheck statusr!  rM   zType a mover#  )r4  r  z
Import FENr&  zshift+tz
Turn timerr(  zshift+fz
Flip boardr  zshift+dz
Offer drawr   zshift+uzRequest undor   zshift+rResignr  yzAccept drawr   nzDecline drawr   zAccept undor  zDecline undor  qzPromote queenpromote_queenrzPromote rookpromote_rookzshift+bzPromote bishoppromote_bishopkzPromote knightpromote_knight)r   setup_keybindsdefine_keybindr   ACTIVEr   s    r9   rA  ChessGame.setup_keybinds  sb    ~\5H5H]a 	 	
 	%%# 	 	
 	C\EXEXYC~\EXEXY %%# 	 	
 	N%%# 	 	
 	I|l^<K^K^_I~7G|ObObcIx(<CVCVWC|GZGZ[C.1AI\I\]C|GZGZ[C.1AI\I\]C?2C<K^K^_C.1AI\I\]'*:);<CVCV 	 	
 	C!14D3E\M`M`ar;   )positionc          
        U R                   (       d  U R                  S:X  a  gUR                  U R                  ;   a  gU R	                  U5      nU(       d  g/ n/ nU R                  U5       H  nUR                  nUR                  (       dC  UR                  R                  (       a(  [        R                  " UR                  S5      nU SU 3n[        XvR                  R                  UR                  S9n	UR                  R                  R                  S5      (       a  UR!                  U	5        M  UR!                  U	5        M     [#        U5      S:H  n
U
(       a;  U R$                  R                  UR                  S5      (       a  UR'                  5         UR)                  S	XE-   S[*        R,                  UU
U
(       a  S
OSS9  g)zCOverride to enable grid mode only when the board squares are shown.finishedNzvisibility-unavailablez; )textr   r   r   ry   F	turn_menur3   r   )multiletterescape_behaviorrE  grid_enabled
grid_width)
_destroyedr   r   _status_box_openget_userget_all_visible_actionsrY   r^   r0  r   r   rF   rH   r   r   
startswithappendr=   r   reverse	show_menur   KEYBIND)r   r   rE  r   square_itemsother_itemsresolvedrY   unavailableitemuse_grids              r9   rebuild_player_menuChessGame.rebuild_player_menu  sd   ??dkkZ799---}}V$')&(44V<HNNE##(K(K*..t{{<TU 'K=1??+=+=X^^TD!!,,Y77##D)""4( = |$***..vyy%@@  "&*22!$q! 	 	
r;   c                ^   SU l         SU l        SU l        U R                  S5        U R                   Vs/ s H  oR
                  (       a  M  UPM     nnU R                  USS9  SU R                  l        U R                  R                  U Vs/ s H  oR                  PM     sn5        [        R                  " 5       S:  a  SUS	   l        S
US   l        OS
US	   l        SUS   l        U R                  S5      nU R                  S
5      nU(       a  SU R                  UR                  '   U R!                  5         U R#                  SU(       a  UR                  OSU(       a  UR                  OSS9  U R%                  S5        U(       a  X0l        U R)                  5         g s  snf s  snf )Nr   Tr   zgame_chess/mus.ogg)reset_index
individualg      ?r}   r   blackzchess-game-started?)r}   rb  zgame_chess/intro.ogg)r   game_activeround
play_musicrv   is_spectatorset_turn_players_team_manager	team_modesetup_teamsr   randomrQ   _get_player_by_colorr   r   _init_boardr   r   current_player_start_turn)r   r   active_playerswhite_playerblack_players        r9   on_startChessGame.on_start  su   
,-%)\\H\!\Hn$?'3$&&'G1'GH ==?S &-N1#&-N1#&-N1#&-N1#009009 26D|/ 	 '3,##'3,## 	 	

 	./ ".G I (Hs   F%F%F*c                   > [         TU ]  5         U R                  (       d  g U R                  R	                  5       (       a  U R                  5         U R                  5         [        R                  " U 5        g r   )r   on_tickrd  r   tick_handle_turn_timeout_maybe_play_timer_warningr   r   s    r9   rw  ChessGame.on_tick8  sP    ::??%%'&&($r;   c                   U R                   n[        U[        5      (       d  g UR                  U l        SU l        0 U l        SU l        SU l        U R                  5         U R                  5         U R                  USS5        UR                  (       a+  [        R                  " U[        R                   " SS5      S9  g g )NFrp   zgame-your-turnzgame-turn-start   <   ticks)ro  
isinstancern   rQ   r~   r   r   r   r   _start_turn_timerr   broadcast_personal_lr   r   jolt_botrl  randintr   r   s     r9   rp  ChessGame._start_turnA  s    $$&+..#\\$)!  "  "!#  !!&*:<MN==vV^^B-CD r;   c                B    U R                  SS9  U R                  5         g )NF)announce)advance_turnrp  r   s    r9   _advance_turnChessGame._advance_turnW  s    5)r;   c                     [        U R                  R                  5      nUS::  a  U R                  R                  5         g U R                  R                  U5        SU l        g ! [         a    Sn NRf = f)Nr   F)r?   rw   r]   r@   r   clearstartr   r   secondss     r9   r  ChessGame._start_turn_timer[  sg    	$,,112G a<JJ

!$)!  	G	s   A% %A43A4c                    [        U R                  R                  5      nUS:  a  g U R                  (       a  g U R
                  R                  5       S:X  a  SU l        U R                  S5        g g ! [         a    Sn N_f = f)Nr         Tzgame_chess/fivesec.ogg)r?   rw   r]   r@   r   r   seconds_remainingr   r  s     r9   rz  #ChessGame._maybe_play_timer_warningf  sx    	$,,112G R<$$::'')Q.(,D%OO45 /  	G	s   A2 2B Bc                    U R                   n[        U[        5      (       d  g U R                  S5        [	        X5      nU(       a  U R                  X5        g g )Nzgame_chess/expired.ogg)ro  r  rn   r   r    execute_actionr   r   	action_ids      r9   ry  ChessGame._handle_turn_timeouts  sJ    $$&+..01d+	2 r;   c                    [        X5      $ r   r   r  s     r9   r    ChessGame.bot_think}  s    &&r;   c                Z  > U(       aR  UR                  S5      (       a<  UR                  S5      S:X  a'  [        U[        5      (       a  U R	                  X5        gUS:X  a=  Uc:  UR
                  (       d)  U R                  U5      nU(       a  UR                  S5        [        TU ]%  XX4S9  g)z@Override to handle bot combined move format: square_{from}_{to}.r   _r   Nr  r  )input_valuecontext)
rR  countr  rn   r   r   rP  speak_lr   r  )r   r   r  r  r  r   r   s         r9   r  ChessGame.execute_action  s    --i88Y__S=QUV=V&+..))&< [%8==(D34vk[r;   c                J   S/S-  U l         / SQn[        U5       H  u  p#USSS.U R                   U'   M     [        SS5       H  nS	SSS.U R                   U'   M     [        S
S5       H  nS	SSS.U R                   U'   M     [        U5       H  u  p#USSS.U R                   SU-   '   M     SU l        0 U l        SU l        SU l        SU l        SU l        SU l	        SU l
        SU l        SU l        / U l        / U l        SU l        SU l        SU l        SU l        SU l        g)z/Initialize board to standard starting position.Nry   )r/   r-   r.   r0   r1   r.   r-   r/   r}   FrG   rQ   	has_movedr3      r,   0   8   rb  rp   Tr   r   )r|   	enumerater  r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r   	back_rankr  rG   s       r9   rn  ChessGame._init_board  s>   Vb[
 ^	!),HA&+gERDJJqM - q"A&,wUSDJJqM  r2A&,wUSDJJqM  "),HA+07QV!WDJJrAv - %!%)"&*#%)"&*#!# "!& "!!#r;   c                   US-  nUS-  nUS-  nUS-  n[        Xd-
  5      n[        Xu-
  5      n	US   n
U
S:X  a  U R                  XX4XVXxU	5	      $ U
S:X  a)  US:H  =(       a    U	S:H  =(       d    US:H  =(       a    U	S:H  $ U
S:X  a(  X:H  =(       a    US:  =(       a    U R                  X5      $ U
S	:X  a7  US:H  =(       d    U	S:H  =(       a    X-   S:  =(       a    U R                  X5      $ U
S
:X  aB  X:X  a  US:  a  U R                  X5      $ US:X  d  U	S:X  a  X-   S:  a  U R                  X5      $ gU
S:X  a  US:*  =(       a    U	S:*  =(       a    X-   S:  $ g)z7Check if move is valid for piece type (ignoring check).r3   rG   r,   r-   r   r   r.   r   r/   r0   Fr1   )abs_is_valid_pawn_move_is_path_clear)r   from_sqto_sqrG   	from_file	from_rankto_fileto_rank	file_diff	rank_diffr   s              r9   _is_valid_piece_moveChessGame._is_valid_piece_move  s   aK	qL	!)1*+,	+,	'N;++)gZc  (]N5yA~]9>;\i[\n](])ci!mc@S@ST[@cc&[a19> 8*Q.8''7
 '\%)a-**7::Q)q.y7Lq7P**7::&[>Ti1nT):ORS:STr;   c
                D   US   S:X  a  SOSn
US   S:X  a  SOSnXd:X  aR  XuU
-   :X  a  U R                   U   c  gX[:X  a4  XuSU
-  -   :X  a)  USU
-  -   nU R                   U   c  U R                   U   c  gUS:X  a)  XuU
-   :X  a!  U R                   U   b  gX R                  :X  a  gg	)
NrQ   r}   r   r      Tr   r3   F)r|   r   )r   r  r  rG   r  r  r  r  r  r  	direction
start_rankmiddles                r9   r  ChessGame._is_valid_pawn_move  s     w72A	.G3Q
 i//DJJu4E4M&7!i-6O+O 1y=0::f%-$**U2C2K >gY)>>zz% ,...r;   c                    US-  nUS-  nUS-  nUS-  nXS:w  a	  XS:  a  SOSOSnXd:w  a	  Xd:  a  SOSOSnX7-   n	XH-   n
X:w  d  X:w  a/  U
S-  U	-   nU R                   U   b  gX-  n	X-  n
X:w  a  M(  X:w  a  M/  g)z<Check if path between squares is clear (for sliding pieces).r3   r   r   r   FTr|   )r   r  r  r  r  r  r  	file_step	rank_stepcurrent_filecurrent_rankr6   s               r9   r  ChessGame._is_path_clear  s    aK	qL	!)1*:A:N'-Q2TU	:A:N'-Q2TU	 , ,%)@ 1$|3Ezz% ,%L%L %)@ r;   c                    [        S5       H3  nU R                  U   nU(       d  M  US   S:X  d  M&  US   U:X  d  M1  Us  $    g)zFind king position for a color.ry   rG   r1   rQ   N)r  r|   )r   rQ   r  sqs       r9   
_find_kingChessGame._find_king  sB    rAABrbkV+7u0D  r;   c                   X:X  a  gUS-  nUS-  nUS-  nUS-  n[        Xd-
  5      n[        Xu-
  5      n	US   n
U
S:X  a   US   S:X  a  SOSnUS:H  =(       a    XuU-   :H  $ U
S	:X  a)  US
:H  =(       a    U	S:H  =(       d    US:H  =(       a    U	S
:H  $ U
S:X  a(  X:H  =(       a    US:  =(       a    U R                  X5      $ U
S:X  a7  US:H  =(       d    U	S:H  =(       a    X-   S:  =(       a    U R                  X5      $ U
S:X  aB  X:X  a  US:  a  U R                  X5      $ US:X  d  U	S:X  a  X-   S:  a  U R                  X5      $ gU
S:X  a  US:*  =(       a    U	S:*  $ g)z6Check if a piece can attack a square (ignoring check).Fr3   rG   r,   rQ   r}   r   r   r-   r   r.   r   r/   r0   r1   )r  r  )r   r  r  rG   r  r  r  r  r  r  r   r  s               r9   _can_piece_attackChessGame._can_piece_attack!  s   aK	qL	!)1*+,	+,	'N;"7^w6BI>FgY1F&FF(]N5yA~]9>;\i[\n](])ci!mc@S@ST[@cc&[a19> 8*Q.8''7
 '\%)a-**7::Q)q.y7Lq7P**7::&[>4i1n4r;   c                    [        S5       H?  nU R                  U   nU(       d  M  US   U:X  d  M&  U R                  X1U5      (       d  M?    g   g)z1Check if a square is attacked by the given color.ry   rQ   TF)r  r|   r  )r   squareby_colorr  r  s        r9   _is_square_attackedChessGame._is_square_attackedF  sH    rAABrbkX-))!R88	 
 r;   c                b    U R                  U5      nUc  gUS:X  a  SOSnU R                  X#5      $ )z$Check if a color's king is in check.Fr}   rb  )r  r  )r   rQ   king_sqopponents       r9   is_in_checkChessGame.is_in_checkO  s7    //%(?#w.7G''::r;   c                   U R                   U   nU(       d  gUS   U:w  a  gU R                   U   nU(       a
  US   U:X  a  gUS   S:X  a1  U R                  XU5      u  pgU(       a  U R                  X75      u  pX4$ U R                  XU5      (       d  gU R	                  5       n
U R                  X5        U R                  U5      nU R                  U
5        U(       a  gg	)
z6Check if a move is legal (including check validation).)FzNo piece at source squarerQ   )FzNot your piece)FzCannot capture your own piecerG   r1   )FzInvalid move for this piece)FzMove leaves king in checkTrp   )r|   _is_castling_move_is_castling_legalr  save_positionexecute_move_silentr  restore_position)r   r  r  rQ   rG   target	is_castlecastle_typelegalreasonsavedking_in_checks               r9   _is_legal_moveChessGame._is_legal_moveW  s    

7#5>U"*E"fWo.9 >V#%)%;%;GE%R"I $ 7 7 K}$ ((??7 ""$  0((/e$5r;   c                   / n[        S5       Hn  nU R                  U   nU(       a	  US   U:w  a  M$  U R                  X45      nU H3  nU R                  X6U5      u  pxU(       d  M   UR	                  X6S.5        M5     Mp     U$ )z%Generate all legal moves for a color.ry   rQ   )fromto)r  r|   _get_candidate_squaresr  rS  )	r   rQ   movesr  rG   
candidatesr  r  r  s	            r9   get_legal_movesChessGame.get_legal_movesx  s}    RyGJJw'EE'Ne344WDJ#..wuE5LL'!?@ $ ! r;   c                   US   nUS-  nUS-  n/ nUS:X  a  US   S:X  a  SOSnUS   S:X  a  SOSnUSU-  -   n	S	U	s=::  a  S
:  a  O  OUR                  U	5        XX:X  a)  USU-  -   n
S	U
s=::  a  S
:  a  O  OUR                  U
5        S Hb  nXK-   nS	Us=::  a  S:  d  M  O  M  S	X-   s=::  a  S
:  a  O  OX-   OSnXW-   nS	Us=::  a  S:  d  ME  O  MI  US-  U-   nUR                  U5        Md     GOUS:X  aQ  S HI  u  pX_-   XK-   pS	Us=::  a  S:  d  M  O  M  S	Us=::  a  S:  d  M.  O  M2  UR                  US-  U-   5        MK     GOnUS:X  a  S H  u  pX_-   XK-   nnS	Us=::  a  S:  d  M  O  M   S	Us=::  a  S:  d  M/  O  M3  UR                  US-  U-   5        U R                  US-  U-      b  Mb  UU-  nUU-  nS	Us=::  a  S:  d  M{  O  M  S	Us=::  a	  S:  a  M[  M    M     GOUS:X  a  S H  u  pX_-   XK-   nnS	Us=::  a  S:  d  M  O  M   S	Us=::  a  S:  d  M/  O  M3  UR                  US-  U-   5        U R                  US-  U-      b  Mb  UU-  nUU-  nS	Us=::  a  S:  d  M{  O  M  S	Us=::  a	  S:  a  M[  M    M     GO0US:X  a  S H  u  pX_-   XK-   nnS	Us=::  a  S:  d  M  O  M   S	Us=::  a  S:  d  M/  O  M3  UR                  US-  U-   5        U R                  US-  U-      b  Mb  UU-  nUU-  nS	Us=::  a  S:  d  M{  O  M  S	Us=::  a	  S:  a  M[  M    M     OUS:X  a  S H^  nS HU  nUS	:X  a  US	:X  a  M  X_-   XK-   pS	Us=::  a  S:  d  M'  O  M+  S	Us=::  a  S:  d  M:  O  M>  UR                  US-  U-   5        MW     M`     UR                  US-   5        UR                  US-
  5        U Vs/ s H  nS	Us=::  a  S
:  d  M  O  M  UPM     sn$ s  snf )z@Get candidate destination squares for a piece (fast pre-filter).rG   r3   r,   rQ   r}   r   r   r  r   ry   r  r   r   r-   ))r   )r  r   )r   r  )r   r   )r   r  )r   r   )r   r   )r   r   r.   )r   r   r  r   r   r   r   r/   )r   r   r   r   r   r   r   r   r0   )r  r  r  r  r  r  r  r  r1   )r   r   r   r   )rS  r|   )r   r  rG   r   r  r  r  r  r  fwddbldftfcaptrdrr<  rN   r  s                      r9   r   ChessGame._get_candidate_squares  s   'NaK	qL	
;"7^w6BI#Gn7QJA	M)CC}"}!!#&&Y.=b=%%c*^?U??&'38&8b&8#(bC".BB{{{ 1frk"))#.  (]b"B;Q;;1;Q;;%%b1frk2 c
 (]> ~y~11jqjjQ!ZaZZ%%a!eai0zz!a%!),8GAGA 1jqjjQ!ZaZZ ? &[< ~y~11jqjjQ!ZaZZ%%a!eai0zz!a%!),8GAGA 1jqjjQ!ZaZZ = '\` ~y~11jqjjQ!ZaZZ%%a!eai0zz!a%!),8GAGA 1jqjjQ!ZaZZ a &[ $BQw27 &^Y^B{{{qB{{{"))"q&2+6 % ! gk*gk*'8Zr1<R<<Z888s   <OOOc                v    U R                   U   nU(       a	  US   S:w  a  gUS-  US-  -
  nUS:X  a  gUS:X  a  gg)	z&Check if a move is a castling attempt.rG   r1   )Frp   r3   r   )Tkingsider  )T	queensider  )r   r  r  rQ   rG   r  s         r9   r  ChessGame._is_castling_move  sJ    

7#g&0QY7Q;/	>#?$r;   c                    US:X  a  SOSnUS-  S-   nU R                   U   nU(       a  US   S:w  d	  US   U:w  a  g	UR                  S
S5      (       a  gUS:X  Ga  US:X  a  U R                  (       d  gUS:X  a  U R                  (       d  gUS-  S-   nUS-  S-   nUS-  S-   nU R                   U   (       d  U R                   U   (       a  gU R                   U   n	U	(       a  U	S   S:w  d	  U	S   U:w  a  gU	R                  S
S5      (       a  gU R	                  U5      (       a  gUS:X  a  SOSn
U R                  Xj5      (       a  gU R                  Xz5      (       a  ggUS:X  Ga  US:X  a  U R                  (       d  gUS:X  a  U R                  (       d  gUS-  S-   nUS-  S-   nUS-  S-   nUS-  nU R                   U   (       d(  U R                   U   (       d  U R                   U   (       a  gU R                   U   n	U	(       a  U	S   S:w  d	  U	S   U:w  a  gU	R                  S
S5      (       a  gU R	                  U5      (       a  gUS:X  a  SOSn
U R                  X5      (       a  gU R                  X5      (       a  ggg)zCheck if castling is legal.r}   r   r   r3      rG   r1   rQ   )FzKing not on starting squarer  F)FzKing has movedr  )FzNo castling rightsrb  r  r  )FzSquares not emptyr/   )FzRook not present)FzRook has moved)FzCannot castle out of check)FzCannot castle through check)FzCannot castle into checkr  r  r   r   r   )FzInvalid castle type)r|   rF   r   r   r  r  r   r   )r   rQ   r  r8   r  r1   f_sqg_sqrook_sqr/   r  b_sqc_sqd_sqs                 r9   r  ChessGame._is_castling_legal  sh   W$q!(Q,zz'"tG}.$w-52H788K''**$(B(B2(B(B2!8a<D!8a<DQhlGzz$4::d#31::g&D4=F2d7mu6L0xxU++.&&: #(7"2wH''77;''778K'(C(C2(C(C2!8a<D!8a<D!8a<DQhGzz$4::d#3tzz$7G1::g&D4=F2d7mu6L0xxU++.&&:"'7"2wH''77;''778+r;   c                R   US:X  a  SOSnUS-  S-   nUS:X  a  US-  S-   nUS-  S-   nUS-  S-   nOUS-  S	-   nUS-  nUS-  S
-   nU R                   U   U R                   U'   SU R                   U'   U R                   U   U R                   U'   SU R                   U'   U R                   U   (       a  SU R                   U   S'   U R                   U   (       a  SU R                   U   S'   US:X  a  SU l        SU l        OSU l        SU l        U =R
                  S-  sl        SU l        g)zExecute a castling move.r}   r   r   r3   r  r  r  r  r   r   NTr  Fr   r   )r|   r   r   r   r   r   r   )r   rQ   r  r8   r  new_kingold_rooknew_rooks           r9   _execute_castlingChessGame._execute_castling1  s:   W$q!(Q,*$ax!|Hax!|Hax!|Hax!|HaxHax!|H#zz'2

8"

7#zz(3

8#

8::h04DJJx -::h04DJJx - G).D&*/D').D&*/D'q !#r;   c                   U R                   U   nU(       d  gUS   S:X  a3  X R                  :X  a$  US   S:X  a  SOSnUSU-  -   nSU R                   U'   U R                  XUS   5      u  pgU(       a  U R                  US   U5        gX0R                   U'   SU R                   U'   SU l        US   S:X  a5  US-  nUS-  n	[	        X-
  5      S	:X  a  US   S:X  a  SOSnUSU-  -   U l        U R                  X5        S
US'   US-  n	US   S:X  a7  US   S:X  a  U	S:X  d  US   S:X  a  U	S:X  a  SUS   S
S.U R                   U'   gggg)z9Execute a move without sounds/broadcasts (for AI search).NrG   r,   rQ   r}   r   r   r3   r   Tr  r   rb  r   r0   r  )r|   r   r  r  r  _update_castling_rights)
r   r  r  rG   r  captured_sqr  r  r  r  s
             r9   r  ChessGame.execute_move_silentX  s   

7# >V#1G1G(G#Gn7QI!i-/K&*DJJ{# "&!7!7g!W	""5>;? "

5"

7 "$>V#1IqjG7&'1,!&w7!:A	)01y=)@& 	$$W4!k 1*>V#g')glg')gl.5g]a$b

5! /;) $r;   c                x   U R                   U   nU(       d  gU R                   U   n[        U5      n[        U5      nU R                  X#US   5      u  pU(       ax  U R                  US   U	5        U R	                  S5        U	S:X  a  U R                  USS5        OU R                  USS5        U R                  X#XEU	5        U R                  U5        gUS	   S
:H  =(       a    X0R                  :H  n
U
(       ag  US   S:X  a  SOSnUSU-  -   nSU R                   U'   U R	                  S[        R                  " SS5       S35        U R
                  " USS4SU0SU0D6  X@R                   U'   SU R                   U'   U
(       d  U(       aN  U R	                  S[        R                  " SS5       S35        U R                  " USS4US	   US	   S.US.SU0D6  O3U R                  US	   5        U R                  " USS4S	US	   0US.SU0D6  SUS'   U R                  X$5        SU l        US	   S
:X  a5  US-  nUS-  n[        X-
  5      S:X  a  US   S:X  a  SOSnUSU-  -   U l        US	   S
:X  d  U(       a  SU l        OU =R                  S-  sl        U R                  X#XES5        US-  nUS	   S
:X  aw  US   S:X  a  US :X  d  US   S!:X  a_  US:X  aY  SU l        X0l        U R%                  5         UR&                  (       a*  [(        R*                  " U[        R                  " S"S#5      S$9  gU R                  U5        g)%z1Execute a move with full sound/broadcast support.NrQ   game_chess/moveking.oggr  zchess-you-castle-kingsidezchess-player-castles-kingsidezchess-you-castle-queensidezchess-player-castles-queensiderG   r,   r}   r   r   r3   zgame_chess/capturer   .oggzchess-you-en-passantzchess-player-en-passantr  r  zchess-you-capturezchess-player-captures)rG   captured)piecesr  zchess-you-movezchess-player-movesTr  r   rp   r   rb  
   r  r  )r|   r:   r  r  r   r  _record_move_post_move_checksr   rl  r  _broadcast_move_play_piece_soundr  r  r   r   r   r   r   r   r  )r   r   r  r  rG   r  from_notationto_notationr  r  
en_passantr  r  r  r  s                  r9   _execute_move_fullChessGame._execute_move_full  s   

7#E")'2'. "&!7!7g!W	""5>;?OO56j())79X ))8:Z ge[I""6* 7^v-Q%;Q;Q2Q
#Gn7QI!i-/K&*DJJ{#OO011E0FdKL%%&) 	
 =) "

5"

7 "4V^^Aq5I4J$ OP$$'+ &+7^Q" }- &&uW~6$$$( $U7^4" }- "k 	$$W4 "$>V#1IqjG7&'1,!&w7!:A	)01y=)@& >V#v"#D1$ 	'%< 1*>V#g')glg')gl)-&(-%&&(==&&vV^^B5KLv&r;   c                    S[         R                  " SS5       S3SSSSS	S
.nUR                  US5      nU R                  U5        g)z%Play movement sound for a piece type.zgame_chess/movepawnr   r   r  zgame_chess/moveknight.oggzgame_chess/movebishop.oggzgame_chess/moverook.oggzgame_chess/movequeen.oggr  r+   zgame_chess/movepawn1.oggN)rl  r  rF   r   )r   
piece_typesoundsr   s       r9   r&  ChessGame._play_piece_sound  sQ     *&..A*>)?tD11-/-
 

:'ABr;   c                    US   S:X  a'  US   S:X  a  SU l         SU l        gSU l        SU l        gUS   S:X  a9  US:X  a  SU l        gUS:X  a  SU l         gUS	:X  a  SU l        gUS
:X  a  SU l        ggg)z$Update castling rights after a move.rG   r1   rQ   r}   Fr/   r   r   r  ?   N)r   r   r   r   )r   r  rG   s      r9   r  !ChessGame._update_castling_rights  s    >V#W~(-2*.3+-2*.3+7^v%!|.3+A-2*B.3+B-2*  &r;   c           	         U R                   R                  UUUS   US   U(       a  US   OSUS.5        U R                  R                  U R                  5       5        g)zRecord a move in history.rG   rQ   rp   )r  r  rG   rQ   r   specialN)r   rS  r   _get_position_hash)r   r  r  rG   r  r4  s         r9   r#  ChessGame._record_move  s^     	  ww/5F7O2"		
 	$$T%<%<%>?r;   c                   UR                   S:X  a  SOSnU R                  U5      nU R                  U5      nU R                  U5      (       aW  SU l        UR                   U l        U R                  S5        U R                  USSUR                  S9  U R                  U5        gU R                  U5      (       aA  SU l        S	U l        U R                  S
5        U R                  S5        U R                  5         gU R                  R                  (       a  U R!                  5       nU(       a  gU(       a!  U R#                  SSS9  U R                  S5        U R%                  5         g)z3Check for checkmate, stalemate, draws after a move.r}   rb  Tzgame_chess/checkmate.oggzchess-you-win-checkmatechess-checkmatewinnerN	stalemategame_chess/draw.oggchess-stalematezgame_chess/check.oggr  )delay_tickszchess-check)rQ   rm  r  is_checkmater   r   r   r  r   	_end_gameis_stalemater   r   _end_game_drawrw   ra   _check_draw_conditionsschedule_soundr  )r   r   opponent_colorr  in_checkdraws         r9   r$  ChessGame._post_move_checks  s=   $*LLG$;,,^< ##N3 ^,,!DN &DOO67%%13DV[[ &  NN6" ^,,!DN*DOO12./! <<!!..0D 6AF]+r;   c                j    U R                  U5      (       d  g[        U R                  U5      5      S:H  $ NFr   r  r=   r  r   rQ   s     r9   r?  ChessGame.is_checkmateK  s1    &&4''./144r;   c                j    U R                  U5      (       a  g[        U R                  U5      5      S:H  $ rJ  rK  rL  s     r9   rA  ChessGame.is_stalemateP  s1    E""4''./144r;   c                `  ^ U R                   S:  aA  SU l        SU l        U R                  S5        U R	                  S5        U R                  5         gU R                  (       au  U R                  S   m[        U4S jU R                   5       5      nUS:  aA  SU l        S	U l        U R                  S5        U R	                  S
5        U R                  5         gU R                  5       (       aA  SU l        SU l        U R                  S5        U R	                  S5        U R                  5         gg)z6Check automatic draw conditions. Returns True if draw.d   Tfifty_move_ruler<  chess-draw-fiftyr   c              3  6   >#    U  H  oT:X  d  M
  S v   M     g7f)r   Nrc   )r   r   currents     r9   r   3ChessGame._check_draw_conditions.<locals>.<genexpr>c  s     I#8aL#8s   		r   threefold_repetitionchess-draw-repetitioninsufficient_materialchess-draw-materialF)	r   r   r   r   r   rB  r   sum_is_insufficient_material)r   r  rU  s     @r9   rC   ChessGame._check_draw_conditionsU  s    #%!DN0DOO12/0!   ++B/GI4#8#8IIEz!%#9  56  !89##% ))++!DN6DOO1223!r;   c                8   / n[        S5       H7  nU R                  U   (       d  M  UR                  U R                  U   5        M9     [        U5      S:X  a  g[        U5      S:X  a  U H  nUS   S;   d  M    g   [        U5      S:X  a  / n[        S5       HB  nU R                  U   (       d  M  U R                  U   S   S:X  d  M1  UR                  U5        MD     [        U5      S:X  a.  US	   S
-  US	   S
-  -   S-  nUS   S
-  US   S
-  -   S-  nXV:X  a  gg)z$Check if neither side can checkmate.ry   r   Tr   rG   )r.   r-   r  r.   r   r3   r   F)r  r|   rS  r=   )r   r!  r  r   bishopscolor1color2s          r9   r\  #ChessGame._is_insufficient_materialw  s   rAzz!}}djjm, 
 v;! v;!W:!55 
 v;!G2Y::a==TZZ]7%;x%GNN1%  7|q !!*/GAJN:a?!!*/GAJN:a?#r;   c                   / nU R                    H3  nUc  UR                  S5        M  UR                  [        U5      5        M5     UU R                  U R                  U R
                  U R                  U R                  U R                  S.$ )z&Save current board state for rollback.N)r|   r)  	castle_wk	castle_wq	castle_bk	castle_bqhalfmove)	r|   rS  dictr   r   r   r   r   r   )r   
board_copyr  s      r9   r  ChessGame.save_position  s    
**Bz!!$'!!$r(+	   0033443344++
 	
r;   c                    US   U l         US   U l        US   U l        US   U l        US   U l        US   U l        US   U l        g)	zRestore a saved board state.r|   r)  rd  re  rf  rg  rh  N)r|   r   r   r   r   r   r   )r   r  s     r9   r  ChessGame.restore_position  s[    7^
!&|!4%*;%7"&+K&8#%*;%7"&+K&8##J/r;   c                8   / n[        S5       H?  nU R                  U   nU(       d  M  UR                  U SUS   S    US   S    35        MA     SnU R                  (       a  US-  nU R                  (       a  US-  nU R
                  (       a  US	-  nU R                  (       a  US
-  nUR                  SU 35        U R                  S:  a  UR                  SU R                   35        UR                  SU R                   35        SR                  U5      $ )zCGet a string hash of the current position for repetition detection.ry   :rQ   r   rG   rp   KQr?  r:  zc:zep:zt:|)
r  r|   rS  r   r   r   r   r   r~   join)r   partsr  r  castlings        r9   r5  ChessGame._get_position_hash  s   rAABrs!BwKN#3BwKN3CDE 
 %%OH&&OH%%OH&&OHr(_%!!Q&LL3t55678r$,,-./xxr;   c                   UR                  5       R                  5       n[        U5      S:  a  gUS   nS/S-  nSnSnU H  nUS:X  a  US-  nSnUS:  a    gM  UR                  5       (       a  U[	        U5      -  nM?  US:  d  US:  a    g	US
-  U-   nUR                  5       (       a  SOSn	SSSSSSS.n
U
R                  UR                  5       5      nU(       d	  SSU 34s  $ XSS.XH'   US-  nM     X@l        [        U5      S:  a  US   S:X  a  SOSU l	        [        U5      S:  a-  US   nSU;   U l
        SU;   U l        SU;   U l        SU;   U l        [        U5      S:  a$  US   S:w  a  [        US   5      nUb  UOS U l        OS U l        [        U5      S!:  a   [	        US!   5      U l        0 U l        SU l        S U l        U R+                  5       /U l        g"! ["         a
    SU l         N?f = f)#zLoad board from FEN string.r   )FzInvalid FENr   Nry   r   /)FzToo many ranks)FzInvalid positionr3   r}   rb  r,   r-   r.   r/   r0   r1   )r   r9  r3  r<  r:  r?  FzUnknown piece: Tr  wr   rp  rq  r?  r:  r   rP   r   r  r  )stripsplitr=   isdigitr?   isupperrF   r>   r|   r~   r   r   r   r   rC   r   r   r@   r   r   r   r5  r   )r   
fen_stringrt  	board_fen	new_boardr8   r7   charr6   rQ   	piece_maprG   ru  eps                 r9   	_load_fenChessGame._load_fen  s"     "((*u:>'!H	(,v{	Ds{	!82 D	!!8tax4q4#'<<>>w!! 	 "djjl3 OD6":::-2QU#V	 	3 6 
u:>,1!HODu:>QxH),D&*-/D'),D&*-/D'u:>eAh#o"58,B+->RrD"%'D"u:>(&)%(m#  "!& "!%!8!8!: ;  (&'#(s   #G" "G65G6c                   / n[        SSS5       H  nSnSn[        S5       Hy  nUS-  U-   nU R                  U   nU(       aS  US:  a  U[        U5      -  nSnSSSS	S
SS.nUR                  US   S5      n	US   S:X  a  U	R	                  5       n	X9-  nMt  US-  nM{     US:  a  U[        U5      -  nUR                  U5        M     SR                  U5      n
U R                  S:X  a  SOSnSnU R                  (       a  US-  nU R                  (       a  US-  nU R                  (       a  US-  nU R                  (       a  US
-  nU(       d  SnU R                  S:  a  [        U R                  5      OSn[        U R                  5      n[        [        U R                   5      S-  S-   5      nU
 SU SU SU SU SU 3$ )zExport board to FEN string.r   r   rp   r   r3   r   r9  r3  r<  r:  r?  r+   rG   rc  rQ   r}   r   rx  ry  rp  rq  rP   r    )r  r|   r5   rF   upperrS  rs  r~   r   r   r   r   r   r:   r   r=   r   )r   rowsr8   rowemptyr7   r6   r  piece_charsr  	board_stractiveru  r  rh  fullmoves                   r9   _get_fenChessGame._get_fen  s   !R$DCEaq4ZZ&qys5z) ! #"%"% #!$ ##K '??2g;<D'{g-#zz|KCQJE) !* qys5z!KK5 %8 HHTN	**g53%%OH&&OH%%OH&&OHH:>:P:PTU:Ut556[^t**+s4,,-2Q67AfXQxj"Qxj(LLr;   c                R   U R                   (       d  gU R                   SS nU R                   S   nU R                  5         U H6  nU R                  US   US   5        U R                   R                  U5        M8     U R                  (       a  U R                  R                  5         g)z/Undo the last move. Returns True if successful.FNr   r  r  T)r   rn  r  rS  r   r   )r   r  lastmoves       r9   _undo_last_moveChessGame._undo_last_moveW  s      
 !!#2&  $ 	 D$$T&\4:>$$T* 
   !!%%'r;   c                   [        U[        5      (       d  gU R                  (       d  U R                  (       a  gUR                  U R
                  :w  a  gUR                  S5      n[        U5      S:X  aU   [        US   5      n[        US   5      nU R                  XEUR                  5      u  pgU(       a  U R                  XU5        g [        US   5      nUR                  n	U R                  R                  U	5      n
U R!                  U5      nU
c  U R"                  U   nU(       a  US   UR                  :X  a  XR                  U	'   U R%                  S5        U R'                  U5      nU(       aC  [)        U5      n[+        US   U5      n[-        US   US   U5      nUR/                  S	U S
U 3US9  U R1                  U5        gU R'                  U5      nU(       a  UR/                  S5        ggSU R                  U	'   X:X  aL  U R%                  S5        U R'                  U5      nU(       a  UR/                  S5        U R1                  U5        gU R                  XUR                  5      u  nnU(       a  U R                  XU5        gU R%                  S5        U R'                  U5      nU(       a  UR/                  S5        U R1                  U5        g! [         a     gf = f! [        [        4 a     gf = f)zHandle square click (two-click move system).

Bots use combined format: square_{from}_{to} for direct moves.
Humans use two clicks: square_{index} twice.
Nr  r   r   r   rQ   zgame_chess/pickup.oggrG   zchess-you-selectr  )rG   r  zchess-no-piecezgame_chess/setdown.oggzchess-move-cancelledchess-illegal-move)r  rn   r   r   rQ   r~   r{  r=   r?   r@   r  r*  
IndexErrorr   r   rF   r  r|   r   rP  r:   rJ   rS   r  update_player_menu)r   r   r  rt  r  r  r  r  sq_indexr   selectedrH   rG   r   rA   p_name
color_name	error_msgs                     r9   r   ChessGame._action_square_clickt  s    &+..>>T33<<4---$u:?eAh-E!H **76<<HHE''?	58}H II	''++I6$$V,JJx(Ew6<<72:$$Y/ 78}}V,0:H'g?F!1%.%.RX!YJLL*ZL&2JS[ !  ''/}}V,LL!12  /3D  +# 89}}V,LL!78''/#228v||TE9''(C 89}}V,LL!56''/o   J' 		s$   6K K) 
K&%K&)K<;K<c                   [        U[        5      (       d  gU R                  (       d  gUR                  U R                  :w  a  gUR                  SS5      nUS;  a  gU R                  nUS:  d  U R                  U   (       d  gX1R                  SS.U R                  U'   SU l        S	U l        [        U5      nU R                  S
5        U R                  USSSU0US9  U R                  U5        g)zHandle pawn promotion choice.Nr   rp   r   r   Tr  Fr   zgame_chess/promote.oggzchess-you-promotezchess-player-promotesrG   )r!  r  )r  rn   r   rQ   r~   replacer   r|   r:   r   r%  r$  )r   r   r  r-  r  rA   s         r9   r   ChessGame._action_promote  s    &+..%%<<4---&&z26
BB""6B#-SWX

2!& "$R(01#Z( 	 	
 	v&r;   c                B   [        U[        5      (       d  gU R                  U5      nU(       a  UR                  5       OSnU(       d  gU R	                  XQR
                  5      u  pgnUb  Uc  U(       a  UR                  S5        gU R                  XgUR
                  5      u  pU	(       d  U(       a  UR                  S5        gU R                  XU5        U(       aC  U R                  (       a1  UR
                  U R                  :X  a  U R                  USU 35        gggg)z4Execute a move typed by the player in text notation.Nrp   zchess-move-parse-errorr  r   )r  rn   rP  rz  _parse_move_textrQ   r  r  r*  r   r~   r   )r   r   r  r  r   rH  r  r  	promotionr  r  s              r9   r$  ChessGame._action_type_move  s    &+..}}V$&1{  "r$($9$9$$M!	?em56&&wv||D127//FLLDDVDV4V  8I;)?@ 5W/9r;   c                J   UR                  5       R                  5       R                  S5      nUS:X  a  SOSnUS;   a  US-  S-   nXTS-  S-   S	4$ US
;   a  US-  S-   nXTS-  S-   S	4$ U(       a  US   S;   a  USS nO&[        U5      S:  a  US   S:X  a  US   S;   a  USS nS	nSU;   a>  UR	                  SS5      u  p7SSSSS.nUR                  UR                  5       SS S	5      nUR                  SS	5      R                  SS	5      n[        U5      S:w  a  gUSS n	USS n
[        U	5      n[        U
5      nUb  Uc  gSnUS-  U:X  aS  US-  U:X  aJ  U R                  U   nU(       a4  US   S:X  a+  US   U:X  a"  US-  nUS:X  a	  US-  S-   nOUS:X  a  US-  S-   nXU4$ )aV  Parse typed move text into (from_sq, to_sq, promotion_piece).

Accepted formats:
  - o-o / O-O / 0-0            kingside castle
  - o-o-o / O-O-O / 0-0-0      queenside castle
  - e2-e4  or  e2e4            coordinate move (hyphen optional)
  - pe2-e4 / Pe2-E4            piece-prefixed coordinate move (prefix ignored)
  - e2xe4                      capture notation (x treated like -)
  - e7-e8=q                    promotion, piece appended after =
  - e1-g1 / e1-h1             remapped to kingside castle for white (king must be on e1)
  - e1-c1 / e1-a1             remapped to queenside castle for white (king must be on e1)
  - e8-g8 / e8-h8             remapped to kingside castle for black (king must be on e8)
  - e8-c8 / e8-a8             remapped to queenside castle for black (king must be on e8)

Returns (None, None, "") on parse failure.
z+#!r}   r   r   )zo-o-oz0-0-0r3   r  r   rp   )zo-oz0-0r  pnrqkr   Nr3  r*   =r0   r/   r.   r-   )r:  r<  r3  r9  rP   x)NNrp   rG   r1   rQ   )	rz  r>   rstripr=   r{  rF   r  rC   r|   )r   rH  rQ   r6  r8   r  r  	promo_strr  from_strto_strr  r  	king_filepiece_on_sqr  s                   r9   r  ChessGame._parse_move_text  s   " JJL ''.W$q! ""QhlG1HqL",,QhlG1HqL",, 1!"AVq[QqTS[QqTZ-?!"A 	!8773?LA%FQI!ioo&7&;R@I IIc2&&sB/q6Q;!Qq61Q#H-!&)?em! 	Q;)#1(<**W-K{73v=+gBVZ_B_!)a< 1HqLE\ 1HqLEy((r;   c                    U R                   S:w  a  g[        U[        5      (       d  gUR                  U R                  :w  a  gU R
                  (       d  U R                  (       a  gg Nr   action-not-playingaction-not-availableaction-not-your-turnr   r  rn   rQ   r~   r   r   r  s     r9   r%  ChessGame._is_type_move_enabledF  sK    ;;)#'&+..)<<4---)>>T33)r;   c                2   [        U[        5      (       d  g U R                  (       a  g U R                  (       a*  U R	                  U5      nU(       a  UR                  S5        g UR                  U l        U R                  USS5        U R                  5         g )Nzchess-already-offeredzchess-you-offer-drawzchess-player-offers-draw)	r  rn   r   r   rP  r  r   r  r   r   r   r  r   s       r9   r   ChessGame._action_offer_drawQ  sr    &+..>>==(D45%yy!!&*@B\] r;   c                   [        U[        5      (       d  g U R                  (       a  U R                  UR                  :X  a*  U R	                  U5      nU(       a  UR                  S5        g SU l        SU l        U R                  S5        U R                  USS5        U R                  S5        U R                  5         g )Nzchess-no-draw-offerT	agreementr<  r   zchess-player-accepts-drawchess-draw-agreement)r  rn   r   r   rP  r  r   r   r   r  r   rB  r  s       r9   r   ChessGame._action_accept_draw`  s    &+..##t';';vyy'H==(D23&-.!!&*AC^_/0r;   c                    [        U[        5      (       d  g U R                  (       a  U R                  UR                  :X  a  g SU l        U R	                  USS5        U R                  5         g )Nrp   r   zchess-player-declines-draw)r  rn   r   r   r  r   r  s      r9   r   ChessGame._action_decline_drawp  sW    &+..##t';';vyy'H!!!&*BD`a r;   c                   [        U[        5      (       d  g U R                  (       a  g U R                  (       d*  U R	                  U5      nU(       a  UR                  S5        g U R                  (       a*  U R	                  U5      nU(       a  UR                  S5        g UR                  U l        U R                  USS5        U R                  5         g )Nzchess-no-moves-to-undozchess-already-requested-undozchess-you-request-undozchess-player-requests-undo)
r  rn   r   r   rP  r  r   r   r  r   r  s       r9   r   ChessGame._action_request_undoz  s    &+..>>  ==(D56!!==(D;<!'!!&*BD`a r;   c                2   [        U[        5      (       d  g U R                  (       a  U R                  UR                  :X  a*  U R	                  U5      nU(       a  UR                  S5        g U R                  U R                  5      nSU l        U R                  5       (       ae  U R                  U R                  5      nU(       a  XPl
        U R                  USS5        U R                  SU R                  S9  U R                  5         U R                  5         g )Nzchess-no-undo-requestrp   r  zchess-player-accepts-undozchess-undo-appliedr   )r  rn   r   r   rP  r  get_player_by_idr  rm  r~   ro  r  r   rp  r   )r   r   r  r   	requestercurrent_color_players         r9   r  ChessGame._action_accept_undo  s    &+..%%)?)?699)L==(D45))$*@*@A	!#!!#'#<#<T=O=O#P #&:#%%f.EGbc1$:L:LM r;   c                    [        U[        5      (       d  g U R                  (       a  U R                  UR                  :X  a  g SU l        U R	                  USS5        U R                  5         g )Nrp   r	  zchess-player-declines-undo)r  rn   r   r   r  r   r  s      r9   r
  ChessGame._action_decline_undo  sW    &+..%%)?)?699)L!#!!&*BD`a r;   c                    U R                  U5      n[        R                  " US5      [        R                  " US5      /$ )Nchess-resign-yeszchess-resign-no)r  r   rF   )r   r   rH   s      r9   r  !ChessGame._resign_confirm_options  s>    $$V,V%78V%67
 	
r;   c                   [        U[        5      (       d  g U R                  (       a  g U R                  U5      nU[        R
                  " US5      :w  a  g UR                  S:X  a  SOSnU R                  U5      nU(       a  UR                  OSnSU l        XPl	        U R                  S5        U R                  USSUS	9  U(       a  U R                  U5        g U R                  5         g )
Nr  r}   rb  rc  Tzgame_chess/resign.oggzchess-you-resignzchess-player-resigns)r  )r  rn   r   r  r   rF   rQ   rm  r   r   r   r  r@  rB  )r   r   r  r  rH   rE  r  opponent_names           r9   r  ChessGame._action_resign  s    &+..>>$$V,,**63EFF$*LLG$;,,^<)1s*/0!!&(> 	" 	
 NN8$!r;   c           	     6   U R                  U5      nU(       d  g UR                  n/ n[        SSS5       H  n/ n[        S5       H  nUS-  U-   n	U R                  U	   n
U
(       a;  UR	                  U
S   S    [        U
S   U5      S   R                  5        35        M\  UR	                  [        R                  " US5      5        M     [        R                  " USUS	-   S
R                  U5      S9nUR	                  U5        M     U R                  X5        g )Nr   r   r3   rQ   r   rG   zchess-emptyzchess-board-rankr   z, )r8   r!  )rP  rH   r  r|   rS  rJ   r  r   rF   rs  
status_box)r   r   r  r   rH   linesr8   rank_piecesr7   r6   r  lines               r9   r  ChessGame._action_view_board  s   }}V$!R$DKaq4ZZ&&&g;q>*:bk6+J1+M+S+S+U*VW  &&|'7'7'NO !  ##*$))KBXD LL % 	&r;   c                   U R                   R                  UR                  S5      nU(       + U R                   UR                  '   U R                  U5      nU(       a  UR                  nU(       d  SOSn[
        R                  " USU 35      n[        U[        5      =(       a    UR                  U:H  nU(       a  SOSn	[
        R                  " XY5      n
UR                  SXS9  U R                  U5        g )	NFrb  r}   rO   zchess-viewer-ownzchess-viewer-opponentzchess-board-flipped)viewerrQ   )r   rF   r   rP  rH   r   r  rn   rQ   r  r]  )r   r   r  flippedr   rH   viewing_colorr  is_own
viewer_keyr  s              r9   r   ChessGame._action_flip_board  s    $$((E:,3699%}}V$[[F+2GM%))&F=/2JKJ4V9VF/5+;RJ!%%f9FLL.vLP  (r;   c           
        U R                  U5      nU(       d  g UR                  nU R                  S5      nU R                  S5      n[        R                  " USU(       a  UR
                  OSS9[        R                  " USU(       a  UR
                  OSS9[        R                  " USU R                  S9[        R                  " US	[        U R                  5      S
9/nU R                  X5        g )Nr}   rb  zchess-status-whiterc  r   zchess-status-blackzchess-status-turn)rQ   chess-status-move-countr  )
rP  rH   rm  r   rF   r   r~   r=   r   r  )r   r   r  r   rH   r}   rb  r  s           r9   r"  ChessGame._action_check_status  s    }}V$))'2))'2V%9PU%**[^_V%9PU%**[^_V%8@R@RSV%>c$J[J[F\]	
 	&r;   c                    U R                  U5      nU(       d  g U R                  5       nUR                  S[        R                  " UR
                  S5      U5        SU R                  UR                  '   g )N	fen_inputzchess-enter-fenr&  )rP  r  show_editboxr   rF   rH   _pending_actionsr   )r   r   r  r   current_fens        r9   r'  ChessGame._action_import_fen  s^    }}V$mmo))$++7HI;	
 ,8fii(r;   c                   US:X  a  U R                   R                  UR                  S5        U R                  U5      nU(       a  UR	                  5       (       a  U R                  UR	                  5       5      u  pVU(       aQ  U(       a  UR                  S5        U R                  U R                  5      nU(       a  Xpl	        U R                  5         gU(       a  UR                  S5        ggggg)zHandle editbox submission.r  Nzchess-fen-loadedzchess-fen-error)r  r   r   rP  rz  r  r  rm  r~   ro  r   )r   r   
editbox_idvaluer   successerrorcps           r9   on_editbox_submitChessGame.on_editbox_submit  s    $!!%%fii6==(D!%!>%782243E3EFB.0+**,%67  'u %r;   c                    U R                  U5      nU(       d  g U R                  R                  5       nUS::  a  UR                  S5        g UR                  SUS9  g )Nr   zpoker-timer-disabledzpoker-timer-remaining)r  )rP  r   r  r  )r   r   r  r   	remainings        r9   r)  "ChessGame._action_check_turn_timer   sM    }}V$JJ002	>LL/0LL0)LDr;   )r  c                   U R                   S:w  a  g[        U[        5      (       d  gUR                  U R                  :w  a  gU R
                  (       a  gU R                  (       a  gg r  r  r  s      r9   r   ChessGame._is_square_enabled.  sO    ;;)#'&+..)<<4---)>>)!!)r;   c                   U R                   S:w  a  [        R                  $ [        U[        5      (       d  [        R                  $ UR
                  (       a  [        R                  $ [        R                  $ Nr   )r   r   HIDDENr  rn   rg  VISIBLEr  s      r9   r   ChessGame._is_square_hidden;  sT    ;;)#$$$&+..$$$$$$!!!r;   c                    [        UR                  S5      S   5      n[	        U5      nU R
                  U   nU R                  U5      n[        U[        5      (       a_  U R                  R                  UR                  5      nXs:X  a5  U(       a.  [        US   U5      n[        US   US   U5      n	SU SU	 SU S	3$ U(       a,  [        US   U5      n[        US   US   U5      n	U SU	 SU 3$ U$ ! [        [        4 a     gf = f)
zGet label for a board square.r  r   rp   rG   rQ   [z: r  ])r?   r{  r@   r  r:   r|   r  r  rn   r   rF   r   rJ   rS   )
r   r   r  r  rA   r  rH   r  r  r  s
             r9   r   ChessGame._get_square_labelD  s   	9??3/23H %X.ZZ!$$V, fk**++//		:H#'7V<F!1"W+r'{F!SJxj:,axqAA7V4F)"W+r'{FKJZr*Qvh77) J' 		s   C3 3DDc                    U R                   (       d  g[        U[        5      (       d  gUR                  U R                  :w  a  gg )Nr  r  )r   r  rn   rQ   r~   r  s     r9   r   ChessGame._is_promote_enabled^  s6    %%)&+..)<<4---)r;   c                   U R                   (       d  [        R                  $ [        U[        5      (       d  [        R                  $ UR
                  U R                  :w  a  [        R                  $ [        R                  $ r   )r   r   r  r  rn   rQ   r~   r  r  s     r9   r   ChessGame._is_promote_hiddeng  sZ    %%$$$&+..$$$<<4---$$$!!!r;   c                    U R                   S:w  d  U R                  (       a  g[        U[        5      (       d  gU R                  (       a  gg Nr   r  )r   r   r  rn   r   r  s     r9   r    ChessGame._is_offer_draw_enabledp  s6    ;;)#t~~)&+..))r;   c                T   U R                   S:w  d  U R                  (       a  [        R                  $ [	        U[
        5      (       a  UR                  (       a  [        R                  $ U R                  (       d  U R                  (       a  [        R                  $ [        R                  $ r  )	r   r   r   r  r  rn   rg  r   r   r  s     r9   r   ChessGame._is_offer_draw_hiddeny  sj    ;;)#t~~$$$&+..&2E2E$$$!!T%9%9$$$   r;   c                    U R                   (       d  g[        U[        5      (       d  gU R                   UR                  :X  a  gg Nr  )r   r  rn   r   r  s     r9   r   #ChessGame._is_draw_response_enabled  s6    ##)&+..)699,)r;   c                   U R                   (       d  [        R                  $ [        U[        5      (       d  [        R                  $ U R                   UR
                  :X  a  [        R                  $ [        R                  $ r   )r   r   r  r  rn   r   r  r  s     r9   r   "ChessGame._is_draw_response_hidden  sZ    ##$$$&+..$$$699,$$$!!!r;   c                    U R                   S:w  d  U R                  (       a  g[        U[        5      (       d  gU R                  (       d  gU R
                  (       a  gg r  )r   r   r  rn   r   r   r  s     r9   r  "ChessGame._is_request_undo_enabled  sB    ;;)#t~~)&+..)  )!!)r;   c                T   U R                   S:w  d  U R                  (       a  [        R                  $ [	        U[
        5      (       a  UR                  (       a  [        R                  $ U R                  (       d  U R                  (       a  [        R                  $ [        R                  $ r  )	r   r   r   r  r  rn   rg  r   r   r  s     r9   r  !ChessGame._is_request_undo_hidden  sj    ;;)#t~~$$$&+..&2E2E$$$!!T%;%;$$$   r;   c                    U R                   (       d  g[        U[        5      (       d  gU R                   UR                  :X  a  gg r	  )r   r  rn   r   r  s     r9   r  #ChessGame._is_undo_response_enabled  s6    %%)&+..)!!VYY.)r;   c                   U R                   (       d  [        R                  $ [        U[        5      (       d  [        R                  $ U R                   UR
                  :X  a  [        R                  $ [        R                  $ r   )r   r   r  r  rn   r   r  r  s     r9   r  "ChessGame._is_undo_response_hidden  sZ    %%$$$&+..$$$!!VYY.$$$!!!r;   c                t    U R                   S:w  d  U R                  (       a  g[        U[        5      (       d  gg r  )r   r   r  rn   r  s     r9   r  ChessGame._is_resign_enabled  s*    ;;)#t~~)&+..)r;   c                    U R                   S:w  d  U R                  (       a  [        R                  $ [	        U[
        5      (       a  UR                  (       a  [        R                  $ [        R                  $ r  )r   r   r   r  r  rn   rg  r  s     r9   r  ChessGame._is_resign_hidden  sM    ;;)#t~~$$$&+..&2E2E$$$   r;   c                &    U R                   S:X  a  gg )Nr   r  )r   r  s     r9   r  ChessGame._is_check_enabled  s    ;;)#'r;   c                "    [         R                  $ r   )r   r  r  s     r9   r  ChessGame._is_always_hidden  s       r;   c                    gNzaction-no-scoresrc   r  s     r9   _is_check_scores_enabled"ChessGame._is_check_scores_enabled      !r;   c                    gr  rc   r  s     r9   !_is_check_scores_detailed_enabled+ChessGame._is_check_scores_detailed_enabled  r!  r;   c                z    UR                   U l        U R                  R                  5         U R	                  5         g)zEnd the game with a winner.N)r   
_winner_idr   r  finish_game)r   r:  s     r9   r@  ChessGame._end_game  s)     ))

r;   c                f    SU l         U R                  R                  5         U R                  5         g)zEnd the game as a draw.rp   N)r&  r   r  r'  r  s    r9   rB  ChessGame._end_game_draw  s%    

r;   c                   SSK J n  [        U R                  5       UR                  5       R	                  5       U R
                  U R                   Vs/ s Ha  n[        U[        5      (       d  M  UR                  (       a  M-  [        UR                  UR                  UR                  UR                  S9PMc     sn[        U R                   5      U R"                  [%        U SS5      U R&                  S.S9$ s  snf )Nr   )datetime)r   player_namer   is_virtual_botr&  rp   )total_movesr   	winner_idr   )	game_type	timestampduration_ticksplayer_resultscustom_data)r,  r   r   now	isoformatsound_scheduler_tickrv   r  rn   rg  r   r   r   r   r.  r=   r   r   getattrr   )r   r,  r   s      r9   build_game_resultChessGame.build_game_result  s    %mmolln..044 	 &Aa- 78nndd !88#$#3#3	 &	  #4#4#45 $ 1 1$T<<#//	
 	
	s   C6.C68C6c                   / nUR                   R                  SS5      nUR                   R                  SS5      nUR                   R                  SS5      nSSSS	S
S.nU(       a  SnUR                   HS  n	U R                  U	R                  5      n
[        U
[        5      (       d  M5  U
R                  U:X  d  MG  U	R                  n  O   UR                  [        R                  " USUS95        O>U(       a7  UR                  US5      nUR                  [        R                  " X+5      5        UR                  [        R                  " USUS95        U$ )Nr   rp   r   r/  r   r=  rS  rX  rZ  r  )r;  rR  rW  rY  r  r8  r9  r  r  )r5  rF   r4  r  r   r  rn   rQ   r-  rS  r   )r   resultrH   r  r   r   r/  	draw_keyswinner_namer   r   rI   s               r9   format_end_screenChessGame.format_end_screen  s#   ))--nbA((,,]B?((,,]A> +1$;%:/
	 K**..q{{;fk22v|||7S"#--K	 +
 LL))&2CKXY--->?CLL))&67\%%f.G{[\r;   c                    U R                    H.  n[        U[        5      (       d  M  UR                  U:X  d  M,  Us  $    g r   )rv   r  rn   rQ   )r   rQ   r   s      r9   rm  ChessGame._get_player_by_color 	  s2    A![))agg.>  r;   c                N    U R                  U5      nU(       a  UR                  $ S$ )Nen)rP  rH   )r   r   r   s      r9   r  ChessGame._player_locale&	  s!    }}V$"t{{,,r;   c           
        U=(       d    0 nU R                    H  nU R                  U5      nU(       d  M  UR                  nUR                  5        V	V
s0 s H  u  pU	[	        X5      _M     nn	n
UR                  U5        XaL a  UR                  " U40 UD6  M  UR                  " U4SUR                  0UD6  M     gs  sn
n	f )a  Like broadcast_personal_l but resolves piece names per-user locale.

Args:
    player: The acting player.
    personal_msg: Message ID for the acting player.
    others_msg: Message ID for everyone else.
    pieces: Mapping of kwarg name to raw piece type (e.g. {"piece": "pawn"}).
            Each value is resolved via piece_name() per recipient locale.
    **kwargs: Other arguments passed through unchanged.
r   N)rv   rP  rH   itemsrJ   updater  r   )r   r   personal_msg
others_msgr!  kwargsr   urH   r?  vrY  s               r9   r%  ChessGame._broadcast_move*	  s    $ 2Aa AXXF=C\\^L^TQ:a00^HLOOF#{		,3(3		*EV[[EHE 
 Ms   B=)r&  r|   r   r   r   r   r~   ro  r   r   r   rd  r   r   r   r   rv   r   r   r   re  r   r   r   r   r   )returnr5   )rP  r?   )F)r   r5   r   r5   r   r`   rP  rn   )r   r5   r   r   rP  rn   )r   r   rP  None)r   rn   rP  r   )r   r   rP  r   )rP  rQ  )r   z'Player'rE  
int | NonerP  rQ  )r   rn   rP  r   )NN)r  r?   r  r?   rG   ri  rP  r`   )r  r?   r  r?   rG   ri  r  r?   r  r?   r  r?   r  r?   r  r?   r  r?   rP  r`   )r  r?   r  r?   rP  r`   )rQ   r5   rP  rR  )r  r?   r  r5   rP  r`   )rQ   r5   rP  r`   )r  r?   r  r?   rQ   r5   rP  tuple[bool, str])rQ   r5   rP  r   )r  r?   rG   ri  rP  z	list[int])rQ   r5   r  r5   rP  rS  )rQ   r5   r  r5   rP  rQ  )r  r?   r  r?   rP  rQ  )r   rn   r  r?   r  r?   rP  rQ  )r-  r5   rP  rQ  )r  r?   rG   ri  rP  rQ  )r  r?   r  r?   rG   ri  r  zdict | Noner4  r5   rP  rQ  )r   rn   rP  rQ  )rP  r`   )rP  ri  )r  ri  rP  rQ  )r~  r5   rP  rS  )r   r   r  r5   rP  rQ  )r   r   r  r5   r  r5   rP  rQ  )rH  r5   rQ   r5   rP  z"tuple[int | None, int | None, str])r   r   rP  r   )r   r   rP  r   )r   r   r  r5   r  r5   rP  rQ  )r   r   r  r   rP  r   )r   r   r  r   rP  r   )r   r   r  r5   rP  r5   )r   r   rP  r   )r:  rn   rP  rQ  )rP  r   )r=  r   rH   r5   rP  r   )rQ   r5   rP  zChessPlayer | None)r   r   rP  r5   r   )
r   r   rJ  r5   rK  r5   r!  zdict[str, str] | NonerP  rQ  )rd   re   rf   rg   rh   r   listrv   rk   rU   rw   r|   r~   ri  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   classmethodr   r   r   r   r   r   r   r   r  r*  rA  r]  rt  rw  rp  r  r  rz  ry  r    r  rn  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r*  r&  r  r#  r$  r?  rA  rC  r\  r  r  r5  r  r  r  r   r   r$  r  r%  r   r   r   r   r  r
  r  r  r  r   r"  r'  r  r)  r   r   r   r   r   r   r   r   r   r  r  r  r  r  r  r  r  r  r#  r@  rB  r:  r@  rm  r  r%  rl   __classcell__)r   s   @r9   rs   rs      s    %!&t!<G<!,?G\?  %5HIEI !M3 -2.O*  ItL#K #'4&#'D'"&4&#'D'  s  %T:L*:"'"=i=NC $t#c OSs ".AE>A!&$& &+4%@M?@ )-:,      & &    C$%Ttl6p+bb OS %
V*X E,	*63'\$&$X"H  	
       
B,#J;BN9h
I,V!$N*cXi'V3&@@#&@/3@=H@SV@	@ &X5
5
 DH
$0<DL2Mp:J0X'BA,M)^	! !!(!,!
"2'.)'88&E MQ  LP "4"!"	!"!
!""
2B- )-FF F 	F
 &F 
F Fr;   rs   )r6   r?   rP  r5   )rA   r5   rP  rR  )rG   r5   rH   r5   rP  r5   )rG   r5   rQ   r5   rH   r5   rP  r5   )4
__future__r   dataclassesr   r   rl  baser   r   r	   registryr
   game_utils.actionsr   r   r   r   r   game_utils.game_resultr   r   game_utils.optionsr   r   r   game_utils.bot_helperr   game_utils.poker_timerr   messages.localizationr   server.core.ui.keybindsr   server.core.users.botr   server.core.users.baser   r   r   botr    ri   rj   r4   rE   r:   rC   rJ   rS   rU   rn   rs   rc   r;   r9   <module>re     s    " (  , , $ X X > F F . 4 1 0 % A A M 




	 
   "" *< 	? ;  > &  
 
E#F E#F  E#Fr;   