
    Ii1                        S r SSKJrJr  SSK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  SS
KJr  SSKJr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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+J,r,J-r-  SSK.J/r/J0r0J1r1  SSK2J3r3  \ " S S\5      5       r4\ " S S\	5      5       r5\\ " S S\5      5       5       r6g)z
Scopa Card Game Implementation for PlayPalace v11.

Classic Italian card game: capture cards from the table by matching ranks or sums.
    )	dataclassfield)datetimeN   )GamePlayerGameOptions)register_game   )Action	ActionSet
Visibility)	BotHelper)CardDeckDeckFactory	card_name
read_cards
sort_cards)
GameResultPlayerResult)	IntOption
MenuOption
BoolOptionTeamModeOptionoption_field)TeamManager)RoundTransitionTimer)Localization)KeybindState   )find_capturesselect_best_captureget_capture_hint)score_roundcheck_winnerdeclare_winner)	bot_thinkc                   R    \ rS rSr% Sr\" \S9r\\   \	S'   \" \S9r
\\   \	S'   Srg)ScopaPlayer*   zPlayer state for Scopa game.default_factoryhandcaptured N)__name__
__module____qualname____firstlineno____doc__r   listr.   r   __annotations__r/   __static_attributes__r0       6c:\Users\dbart\PlayPalace11\server\games\scopa\game.pyr*   r*   *   s+    &T2D$t*2 6Hd4j6r9   r*   c                      \ rS rSr% Sr\" \" SSSSSSS	S
S95      r\\	S'   \" \" SSSSSSSSS95      r
\\	S'   \" \" SSSS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(/ S)QS*S+S,S).S-S.S/S0S195      r\\	S2'   \" \" SSS3S4S5S!95      r\\	S6'   \" \" S7S8S9 S:S;S<S=95      r\\	S>'   \" \" S?SS@SASBS!95      r\\	SC'   \" \" SSSDSESFS!95      r\\	SG'   SHrgI)JScopaOptions2   z7Options for Scopa game using declarative option system.   r!   y   scorezgame-set-target-scorezscopa-enter-target-scorezgame-option-changed-targetzscopa-desc-target-score)defaultmin_valmax_val	value_keylabelprompt
change_msgdescriptiontarget_scorer   
   cardszscopa-set-cards-per-dealzscopa-enter-cards-per-dealzscopa-option-changed-cardszscopa-desc-cards-per-dealcards_per_deal   deckszscopa-set-deckszscopa-enter-deckszscopa-option-changed-deckszscopa-desc-decksnumber_of_decksFenabledzscopa-toggle-escobazscopa-option-changed-escobazscopa-desc-escoba)rA   rD   rE   rG   rH   escobazscopa-toggle-hintszscopa-option-changed-hintszscopa-desc-hintsshow_capture_hintsnormalmechanic)rS   	no_scopasonly_scopaszscopa-mechanic-normalzscopa-mechanic-no_scopaszscopa-mechanic-only_scopaszscopa-set-mechaniczscopa-select-mechaniczscopa-option-changed-mechaniczscopa-desc-mechanic)rA   rD   choiceschoice_labelsrE   rF   rG   rH   scopa_mechaniczscopa-toggle-instant-winzscopa-option-changed-instantzscopa-desc-instant-wininstant_win_scopas
individualmodec                 0    [         R                  " SS5      $ )Nr   rM   )r   get_all_team_modes)gps     r:   <lambda>ScopaOptions.<lambda>   s    !?!?1!Er9   zgame-set-team-modezgame-select-team-modezgame-option-changed-team)rA   rD   rW   rE   rF   rG   	team_modeTzscopa-toggle-team-scoringz!scopa-option-changed-team-scoringzscopa-desc-team-scoringteam_card_scoringzscopa-toggle-inversezscopa-option-changed-inversezscopa-desc-inverseinverse_scopar0   N)r1   r2   r3   r4   r5   r   r   rI   intr7   rL   rO   r   rQ   boolrR   r   rY   strrZ   r   rc   rd   re   r8   r0   r9   r:   r<   r<   2   s   A$)-31		
L#  ',/33		
NC  (#&3*		
OS   '4+	
FD   ,&3*	
   ' :17;
 '*6-	
NC    ,,50	
   " E&*1	
	Is 	 +-:1	
t  '(5,	
M4 r9   r<   c                     ^  \ rS rSr% Sr\" \S9r\\   \	S'   \" \
S9r\
\	S'   \" \S9r\\	S'   \" \S9r\\   \	S'   Sr\S-  \	S	'   S
r\\	S'   S
r\\	S'   S
r\\	S'   S
r\\	S'   U 4S jrSFU 4S jjrSFS jr\S\4S j5       r\S\4S j5       r\S\4S j5       r\S\4S j5       r\S\4S j5       rSGS\S\S\ S\4S jjr!S\S\"4S jr#SFU 4S jjr$S\%S\S-  4S jr&S\%S\'4S  jr(S\%S\S-  4S! jr)S\%S\'4S" jr*S\%S\S-  4S# jr+S\%S\'4S$ jr,S\%S%\S\4S& jr-S\SS4S' jr.SFS( jr/S\\\0\\14   -     4U 4S) jjr2SFS* jr3   SHS+\S,\\   S-  S-\S-  S.\S-  SS4
S/ jjr4SFS0 jr5SFS1 jr6SFS2 jr7SFS3 jr8S\S-\SS4S4 jr9S\S5\S6\\   SS4S7 jr:SFS8 jr;SFS9 jr<S\=4S: jr>S;\=S<\S\\   4S= jr?SFU 4S> jjr@S\%S\S-  4S? jrAS\%S%\SS4S@ jrBS\%S%\SS4SA jrCS\%S%\SS4SB jrDS\%S%\SS4SC jrES\%S%\SS4SD jrFSErGU =rH$ )I	ScopaGame   aJ  
Scopa card game.

Players take turns playing cards from their hand. If the played card matches
a table card by rank, or if table cards sum to the played card's value,
those cards are captured. Clearing all table cards scores a "scopa" point.
Points are also awarded for most cards, most diamonds, the 7 of diamonds,
and most 7s.
r,   playersoptionsdecktable_cardsNlast_capture_player_idr   dealer_indexcurrent_round_current_deal_total_dealsc                 B   > [         TU ]  5         [        U 5      U l        g)zInitialize runtime state.N)super__post_init__r   _round_timerself	__class__s    r:   rw   ScopaGame.__post_init__   s    06r9   returnc                 B   > [         TU ]  5         [        U 5      U l        g)z3Rebuild non-serialized state after deserialization.N)rv   rebuild_runtime_stater   rx   ry   s    r:   r   ScopaGame.rebuild_runtime_state   s    %'06r9   c                 $    U R                  5         g)z6Called when round timer expires. Start the next round.N)_start_round)rz   s    r:   on_round_timer_readyScopaGame.on_round_timer_ready   s    r9   c                     g)NScopar0   clss    r:   get_nameScopaGame.get_name       r9   c                     g)Nscopar0   r   s    r:   get_typeScopaGame.get_type   r   r9   c                     g)Nzcategory-card-gamesr0   r   s    r:   get_categoryScopaGame.get_category   s    $r9   c                     g)Nr   r0   r   s    r:   get_min_playersScopaGame.get_min_players   s    r9   c                     g)N   r0   r   s    r:   get_max_playersScopaGame.get_max_players   s    r9   	player_idnameis_botc                     [        XUS9$ )z.Create a new player with Scopa-specific state.)idr   r   )r*   )rz   r   r   r   s       r:   create_playerScopaGame.create_player   s    i6BBr9   playerc                    U R                  U5      nU(       a  UR                  OSn[        SS9nUR                  [	        S[
        R                  " US5      SSSS	95        UR                  [	        S
[
        R                  " US5      SSSS	95        [        SS5       H/  nUS:  a  SU 3OSnUR                  [	        USU 3SSSS	95        M1     UR                  [	        SSSSSS	95        U$ )z(Create the turn action set for a player.enturn)r   
view_tablezscopa-view-table_action_view_table_is_view_enabled_is_view_hidden)r   rE   handler
is_enabled	is_hiddenview_capturedzscopa-view-captured_action_view_capturedr!   r>   rJ   view_table_card_view_table_card_0View table card _action_view_table_cardpause_timerzPause timer_action_pause_timer_is_pause_timer_enabled_is_pause_timer_hidden)get_userlocaler   addr   r   getrange)rz   r   userr   
action_seti	action_ids          r:   create_turn_action_set ScopaGame.create_turn_action_set   s   }}V$ $$F+
 	"&&v/AB,-+	
 	""&&v/DE/-+	
 q"A23b&*1#.>QINN ,QC051/  	 #-42	
 r9   c           	        > [         TU ]  5         U R                  SSS/[        R                  SS9  U R                  SSS/[        R                  S	9  [        S
S5       HJ  nSU 3nUS:  a  SU 3OSnUS:  a  [        U5      OSnU R                  UUU/[        R                  SS9  ML     U R                  SSS/[        R                  S	9  g)z!Define all keybinds for the game.czView table cardsr   T)stateinclude_spectatorsdzView captured cardsr   )r   r!   r>   r   rJ   r   r   0r`   zPause/skip round timerr   N)rv   setup_keybindsdefine_keybindr    ACTIVEr   rh   )rz   r   rE   r   keyr{   s        r:   r   ScopaGame.setup_keybinds"  s     	  	N%%# 	 	
 	&(9ATAT 	 	

 q"A&qc*E23b&*1#.>QIF#a&C"))#'   	  	)M?,BUBU 	 	
r9   c                 &    U R                   S:w  a  gg)z%View actions are enabled during play.playingaction-not-playingN)statusrz   r   s     r:   r   ScopaGame._is_view_enabledI  s    ;;)#'r9   c                 "    [         R                  $ )z.View actions are always hidden (keybind only).r   HIDDENr   s     r:   r   ScopaGame._is_view_hiddenO         r9   c                 r    UR                   U R                  :w  a  gU R                  R                  (       d  gg)z5Pause timer is enabled for host when timer is active.zaction-not-hostzscopa-timer-not-activeN)r   hostrx   	is_activer   s     r:   r   !ScopaGame._is_pause_timer_enabledS  s*    ;;$))#$  **+r9   c                 "    [         R                  $ )z,Pause timer is always hidden (keybind only).r   r   s     r:   r    ScopaGame._is_pause_timer_hidden[  r   r9   c                 J    U R                   S:w  a  gUR                  (       a  gg)z8Card actions are enabled for current player during play.r   r   zaction-spectatorN)r   is_spectatorr   s     r:   _is_card_action_enabled!ScopaGame._is_card_action_enabled_  s     ;;)#'%r9   c                     U R                   S:w  a  [        R                  $ UR                  (       a  [        R                  $ [        R                  $ )z8Card actions are visible during play for non-spectators.r   )r   r   r   r   VISIBLEr   s     r:   _is_card_action_hidden ScopaGame._is_card_action_hiddenh  s;    ;;)#$$$$$$!!!r9   r   c                   ^ [        U[        5      (       d  g [        UR                  S5      S   5      m[        U4S jUR                   5       S5      nU(       d  gU R                  U5      nU(       a  UR                  OSn[        X55      nU R                  R                  (       a/  [        U R                  X0R                  R                  U5      nXg-  nU$ ! [        [
        4 a     gf = f)z$Get dynamic label for a card action. _c              3   J   >#    U  H  oR                   T:X  d  M  Uv   M     g 7fNr   .0r   card_ids     r:   	<genexpr>,ScopaGame._get_card_label.<locals>.<genexpr>z       ?1ttwQQ   #	#Nr   )
isinstancer*   rf   split
ValueError
IndexErrornextr.   r   r   r   rm   rR   r$   ro   rQ   )	rz   r   r   cardr   r   r   hintr   s	           @r:   _get_card_labelScopaGame._get_card_labelp  s    &+..	)//#.r23G ??F}}V$ $$&<<**#D$4$4dLL<O<OQWXDLD J' 		s   C C.-C.c                 <   U R                  US5      nU(       d  gU R                  S:H  nUR                  nUR                  S5        U(       aO  U(       dG  [	        UR
                  SS9 H.  nUR                  [        SUR                   3SSS	S
SSS95        M0     ggg)z@Update card actions for a player (called when rebuilding menus).r   Nr   
play_card_F)by_suitr   _action_play_cardr   r   r   )r   rE   r   r   r   	get_labelshow_in_actions_menu)	get_action_setr   r   remove_by_prefixr   r.   r   r   r   )rz   r   turn_set
is_playingr   r   s         r:   _update_card_actionsScopaGame._update_card_actions  s    &&vv6[[I-
** 	!!,/ l"6;;>'y1  3#<":"3-2
 ? +:r9   c                 L    U R                    H  nU R                  U5        M     g)z$Update card actions for all players.N)rl   r  r   s     r:   _update_all_card_actions"ScopaGame._update_all_card_actions  s    llF%%f- #r9   c           	        > [         TU ]  5       nU R                  U R                  R                  5      nU(       a  UR                  U5        U R                  5       n[        U5      nSnXPR                  R                  -  nU R                  R                  U-  nXv:  aA  UR                  SU R                  R                  UU R                  R                  UUS.45        U$ )z,Validate game configuration before starting.(   zscopa-error-not-enough-cards)rN   rl   rL   total_cardscards_needed)
rv   prestart_validate_validate_team_moderm   rc   appendget_active_playerslenrO   rL   )	rz   errorsteam_mode_erroractive_playersnum_playerscards_per_deckr  r  r{   s	           r:   r  ScopaGame.prestart_validate  s    *, 224<<3I3IJMM/* 002.)$||'C'CC||22[@%MM2!%!=!=#.*.,,*E*E'2(4	 r9   c                 <   SU l         SU l        SU l        U R                  5       nU Vs/ s H  o"R                  PM     nnU R
                  R                  nSU;   d  [        S U 5       5      (       a  [        R                  " U5      nX@R                  l        U R                  R                  U5        U R                  U5        U H  n/ Ul        / Ul        M     U R                  R!                  5         U R#                  S5        U R%                  5         gs  snf )zCalled when the game starts.r   Tr    c              3   P   #    U  H  oS :w  d  M
  UR                  5       v   M     g7f)vN)isupperr   r   s     r:   r   %ScopaGame.on_start.<locals>.<genexpr>  s     "N	1#X;199;;	s   	&&zgame_pig/mus.oggN)r   game_activerr   r  r   rm   rc   anyr   parse_display_to_team_mode_team_managersetup_teamsset_turn_playersr/   r.   team_managerreset_all_scores
play_musicr   )rz   r  r`   player_namesrc   r   s         r:   on_startScopaGame.on_start  s     002(6717LL**	)s"N	"NNN#>>yII'0$&&|4 	n- %F FOFK % 	**, 	*+ 	/ 8s   D
message_idrK   r   excludec                    U R                    Hy  nXdL a  M	  U R                  U5      nU(       d  M#  [        U5      nUb  [        X'R                  5      US'   Ub  [        X7R                  5      US'   UR                  " U4SS0UD6  M{     g)z7Broadcast a message with per-user localized card names.NrK   r   buffertable)rl   r   dictr   r   r   speak_l)	rz   r-  rK   r   r.  kwargsr   r   
msg_kwargss	            r:   _broadcast_cards_lScopaGame._broadcast_cards_l  s     llF ==(Dt!&\
$*4UKK*HJw'#)24)EJv&ZFF:F #r9   c                     [         R                  " U R                  R                  5      u  U l        n[
        R                  " / SQ5      nU R                  SU 35        g)zCreate and shuffle the deck.)zshuffle1.oggzshuffle2.oggzshuffle3.ogggame_cards/N)r   italian_deckrm   rO   rn   randomchoice
play_sound)rz   r   shuffle_sounds      r:   _create_deckScopaGame._create_deck   sD    "//0L0LM	1&VW+m_56r9   c                    U =R                   S-  sl         SU l        U R                  5        H  n/ Ul        / Ul        M     U R
                  R                  5         / U l        U R                  SU R                   S9  U R                  5       nU(       a  U R                  S-
  [        U5      -  OSU l	        U(       a  X R                     OSnU(       a  U R                  USS5        U R                  5         U R                  R                  5       nU(       a"  U R                  R                   [        U5      -  OSnUS:  a  XE-  OSnXF-
  nUS:  a  Xu-  OSU l        SU l        U R                  R&                  (       d  Sn[)        U5       H  n	U R                  R+                  U5      U l        [-        S	 U R                   5       5      n
S
U R                  R.                  -  nUS-  S-   nX::  a    OdU R                  R1                  U R                  5        U R                  R3                  5         M     O U R                  R+                  U5      U l        U R                  (       a  U R5                  SU R                  S9  OU R                  S5        U(       a   U R                  S-   [        U5      -  U l        U R9                  5         g)zStart a new round.r!   Nzgame-round-startroundr   zgame-you-dealzgame-player-dealsrJ   c              3   H   #    U  H  oR                   S :X  d  M  Sv   M     g7f)rJ   r!   N)rankr  s     r:   r   )ScopaGame._start_round.<locals>.<genexpr>2  s      M,<q",<s   "	"   r   zscopa-initial-table)rK   zscopa-no-initial-table)rr   rp   r  r/   r.   r'  reset_round_scoresro   broadcast_lrq   r  broadcast_personal_lr?  rn   sizerm   rL   rt   rs   rQ   r   drawsumrO   r   shuffler6  
turn_index_deal_cards)rz   r   r  dealerr  cards_for_playersinitial_tablecards_after_tablemax_attemptsr   
tens_count
total_tensmax_tenss                r:   r   ScopaGame._start_round  sg   a&*# --/F FOFK 0 	,,. 	+43E3EF 002M[T..2c.6IIab6D 1 12$ %%fo?RS 	 iinn&AODLL''#n*==UV 	 <Mq;P7VW'7FWZ[F[-Bab ||""L<(#'99>>-#@   MD,<,< MM
!=!==
%?Q.)		d../		!!# )  $yy~~m<D##$9AQAQ#R56 #0014N8KKDO 	r9   c                 2   U R                  5       nU(       a  U R                  R                  5       (       a  gU =R                  S-  sl        U R                  S:  a  U R	                  S5        U R                  SU R                  U R                  S9  U R                  R                  nU H9  nU R                  R                  U5      nUR                  R                  U5        M;     U R                  S-   [        U5      -  U l        U R                  5         g)z!Deal cards to all active players.Nr!   zgame_cards/small_shuffle.oggzgame-deal-counter)currenttotal)r  rn   is_emptyrs   r=  rI  rt   rm   rL   rL  r.   extendrq   r  rO  _start_turn)rz   r  cards_to_dealr   rK   s        r:   rP  ScopaGame._deal_cardsI  s    002!3!3!5!5 	a !OO:; 	,d6H6HPTPaPab33$FIINN=1EKKu% %  ,,q0C4GGr9   c                    U R                   nU(       d  gU R                  5         UR                  (       a*  [        R                  " U[
        R                  " SS5      S9  U R                  5         U R                  5         g)zStart a player's turn.N      ticks)	current_playerannounce_turnr   r   jolt_botr;  randintr	  rebuild_all_menusr   s     r:   r_  ScopaGame._start_turne  s[    $$ 	==vV^^B-CD%%' r9   c                    UR                    Vs/ s H   o3R                  UR                  :w  d  M  UPM"     snUl         [        R                  " / SQ5      nU R	                  SU 35        [        U R                  UR                  U R                  R                  5      nU(       a  [        U5      nU R                  XU5        OrU R                  R                  U5        U R                  U5      nU(       a$  UR                  S[        X'R                   5      SS9  U R#                  SX!R$                  US9  [&        R(                  " U [        R*                  " SS	5      S
9  U R-                  5         gs  snf )zHandle playing a card.)z	play1.oggz	play2.oggz	play3.oggz	play4.oggr9  zscopa-you-put-downr1  )r   r0  zscopa-player-puts-down)r   r   r.     rc  re  N)r.   r   r;  r<  r=  r"   ro   rE  rm   rQ   r#   _execute_capturer  r   r3  r   r   r6  r   r   	jolt_botsrj  	_end_turn)rz   r   r   r   r=  capturesbest_capturer   s           r:   
_play_cardScopaGame._play_cardt  s)    #)++A+Qq+A ]]#WX
+j\23 !!1!1499dll>Q>QR.x8L!!&= ##D) ==(D("45"   ##(tKKQW $  	Dq"(=>? Bs
   E1E1played_cardr/   c           	      x   U H@  nU R                    Vs/ s H   oUR                  UR                  :w  d  M  UPM"     snU l         MB     UR                  R                  U5        UR                  R	                  U5        UR                  U l        [        U5      n[        U R                   5      S:H  nU(       a  SnO[        SUS-
  S-  -   S5      nU R                  SUSS	9  S
n	U(       aE  U R                  R                  S:w  a)  Sn	U R                  R                  UR                  S5        OSn	U R                   H  n
U R                  U
5      nU(       d  M  [!        X;R"                  5      n[%        X+R"                  5      nU	(       a!  [&        R(                  " UR"                  U	5      OSnXL a%  [&        R(                  " UR"                  SUUS9U-   nO/[&        R(                  " UR"                  SUR                  UUS9U-   nUR+                  U5        M     U(       a  U R                  R                  S:w  a{  U R                  R,                  (       a_  U R                  R/                  UR                  5      nU(       a2  UR0                  U R                  R2                  :  a  [5        U U5        g
g
g
g
g
g
s  snf )zExecute a capture.r      d   r!   rJ      zmention.oggr=   )pitchvolumeNrU   zscopa-scopa-suffixzscopa-clear-table-suffixr   zscopa-you-collect)rK   r   zscopa-player-collects)r   rK   r   )ro   r   r/   r  r^  rp   r  minr=  rm   rY   r'  add_to_team_scorer   rl   r   r   r   r   r   r   speakrZ   get_teamtotal_scorerI   r'   )rz   r   rv  r/   r   r   num_capturedis_scopar{  
suffix_keyr`   usrcaptured_strcard_strsuffixmsgteams                    r:   ro  ScopaGame._execute_capture  sV   
 D+/+;+;O+;atttww+;OD  	{+x(&,ii# 8}t''(A-E |a/255s;EU2> 
||**k91
!!33FKKC7
 A--"C%h

;L jj9HAK\%%cjj*=QSF{ $$

+*%	   !$$

/%{{*%   IIcN= D ++{://$$--fkk:D((DLL,E,EEtT* Ft 0 ; A  Ps
   J7J7c                    U R                  5       n[        S U 5       5      nU(       aA  U R                  R                  5       (       a  U R	                  5         gU R                  5         gU R                  SS9  U R                  5         g)zHandle end of a player's turn.c              3   R   #    U  H  n[        UR                  5      S :H  v   M     g7f)r   N)r  r.   )r   r`   s     r:   r   &ScopaGame._end_turn.<locals>.<genexpr>  s     G1c!&&kQ.s   %'F)announceN)r  allrn   r]  
_end_roundrP  advance_turnr_  )rz   r  all_empty_handss      r:   rq  ScopaGame._end_turn  so    002 GGGyy!!##!   " u-r9   c                 z   U R                   (       ay  U R                  (       ah  U R                  U R                  5      nU(       aF  U R                  SUR                  S9  UR
                  R                  U R                   5        / U l         U R                  SU R                  S9  U R                  R                  S:w  a  [        U 5        U R                  R                  5         [        U 5      nU(       a  [        X5        gU R                  R!                  5         U R#                  5         U R%                  5         g)zHandle end of a round.zscopa-remaining-cards)r   zgame-round-endrB  rV   N)ro   rp   get_player_by_idrI  r   r/   r^  rr   rm   rY   r%   r'  commit_round_scoresr&   r'   rx   startr	  rk  )rz   last_capturerwinners      r:   r  ScopaGame._end_round  s      ; ; 11$2M2MNM  !8ASAS T&&--d.>.>?#% )1C1CD <<&&-7 	--/ d#4( ##%))+""$r9   c                    U R                   R                  SSS9n0 nU H,  nU R                   R                  U5      nUR                  X$'   M.     U(       a  US   OSn[	        U R                  5       [        R                  " 5       R                  5       U R                  U R                  5        Vs/ s H8  n[        UR                  UR                  UR                  [        USS5      S9PM:     snU(       a  U R                   R                  U5      OSU(       a  UR                  OSUU R                   U R"                  R$                  U R"                  R&                  S.S	9$ s  snf )
z/Build the game result with Scopa-specific data.T)by_score
descendingr   Nis_virtual_botF)r   player_namer   r  )winner_namewinner_scorefinal_scoresrounds_playedrI   rc   )	game_type	timestampduration_ticksplayer_resultscustom_data)r'  get_sorted_teamsget_team_namer  r   r   r   now	isoformatsound_scheduler_tickr  r   r   r   r   getattrrC  rm   rI   rc   )rz   sorted_teamsr  r  r   r  r`   s          r:   build_game_resultScopaGame.build_game_result  s<   ((994TX9Y  D$$2248D!%!1!1L ! %1admmolln..044 002 3A dd !88#*1.>#F	 3 KQt00>>vFVZ6< 2 2! ,!% $ 9 9!\\33
 	
s   0?E#resultr   c                    [         R                  " US5      /nUR                  R                  S0 5      n[        UR	                  5       S5       H7  u  nu  pg[         R                  " USUS9nUR                  U SU SU 35        M9     U$ )z%Format the end screen for Scopa game.zgame-final-scoresr  r!   zgame-pointscountz. z: )r   r   r  	enumerateitemsr  )	rz   r  r   linesr  r   r   r@   
points_strs	            r:   format_end_screenScopaGame.format_end_screen>  s    !!&*=>?))--nbA ),*<*<*> BA}%))&-uMJLLA3bb56 !C r9   c                    > [         TU ]  5         U R                  (       d  gU R                  R                  5         [        R                  " U 5        g)z1Called every tick. Handle bot AI and round timer.N)rv   on_tickr!  rx   r   ry   s    r:   r  ScopaGame.on_tickM  s9    !!#$r9   c                 D    [        U[        5      (       d  g[        X5      $ )z1Bot AI decision making - delegated to bot module.N)r   r*   r(   r   s     r:   r(   ScopaGame.bot_thinkW  s    &+..&&r9   c                 n  ^ [        U[        5      (       d  gU R                  U:w  a*  U R                  U5      nU(       a  UR	                  S5        g [        UR                  S5      5      m[        U4S jUR                   5       S5      nU(       a  U R                  X5        gg! [         a     gf = f)z8Handle playing a card - extracts card ID from action_id.Nzaction-not-your-turnr   c              3   J   >#    U  H  oR                   T:X  d  M  Uv   M     g 7fr   r   r   s     r:   r   .ScopaGame._action_play_card.<locals>.<genexpr>t  r   r   )r   r*   rg  r   r3  rf   removeprefixr   r   r.   rt  )rz   r   r   r   r   r   s        @r:   r   ScopaGame._action_play_carda  s    &+.. &(==(D34	)00>?G
 ??FOOF)   		s   B' '
B43B4c                     U R                  U5      nU(       aU  U R                  (       a2  [        U R                  UR                  5      nUR	                  U5        gUR                  S5        gg)zView all table cards.zscopa-table-emptyN)r   ro   r   r   r  r3  )rz   r   r   r   	cards_strs        r:   r   ScopaGame._action_view_tablex  sP    }}V$&t'7'7E	

9%01 r9   c                 `   U R                  U5      nU(       d  g [        UR                  SS5      5      nUS:X  a  SnU[	        U R
                  5      ::  a7  U R
                  US-
     nUR                  [        XSR                  5      5        gUR                  S5        g! [         a     gf = f)zView a specific table card.Nr   r   r   rJ   r!   zscopa-no-such-card)
r   rf   replacer   r  ro   r  r   r   r3  )rz   r   r   r   numr   s         r:   r   !ScopaGame._action_view_table_card  s    }}V$	i''(:B?@Cax #d&&''##C!G,DJJy{{34LL-.  		s   #B   
B-,B-c                     U R                  U5      nU(       a<  [        U[        5      (       a&  [        UR                  5      nUR                  SUS9  ggg)zView captured card count.zscopa-captured-countr  N)r   r   r*   r  r/   r3  )rz   r   r   r   r  s        r:   r   ScopaGame._action_view_captured  sE    }}V$Jv{33(ELL/uL= 44r9   c                     UR                   U R                  :X  a&  U R                  R                  UR                   5        gg)z&Handle pause timer action (host only).N)r   r   rx   toggle_pause)rz   r   r   s      r:   r   ScopaGame._action_pause_timer  s/    ;;$))#**6;;7 $r9   )rs   rx   rt   rr   rq   rn   r!  rp   r   ro   rO  )r}   N)F)NNN)Ir1   r2   r3   r4   r5   r   r6   rl   r*   r7   r<   rm   r   rn   ro   r   rp   rh   rq   rf   rr   rs   rt   rw   r   r   classmethodr   r   r   r   r   rg   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r	  tupler2  r  r+  r6  r?  r   rP  r_  rt  ro  rq  r  r   r  r  r  r(   r   r   r   r   r   r8   __classcell__)r{   s   @r:   rj   rj      s    "'t!<GT+<!,?G\? t,D$,#D9Kd9)-C$J-L#M3M3L#77       %S % %      Cs C# Ct CP[ C5[ 5Y 5t!
Nv #* !f ! !f t !V !
 !f t "V "
 "f   *; 4 8.4eCI.>(>#? @H $( &*GG DzD G Tk	G
 t#G 
G*7@D8!" "D "T "HM!M04M@DT
M	M^&%B!
: !
F	
 	C 	DI 	 ' '3: '* *3 *4 *.2 2C 2D 2/f / / /(>F >s >t >8& 8S 8T 8 8r9   rj   )7r5   dataclassesr   r   r   r;  baser   r   r	   registryr
   game_utils.actionsr   r   r   game_utils.bot_helperr   game_utils.cardsr   r   r   r   r   r   game_utils.game_resultr   r   game_utils.optionsr   r   r   r   r   game_utils.teamsr   game_utils.round_timerr   messages.localizationr   server.core.ui.keybindsr    capturer"   r#   r$   scoringr%   r&   r'   botr(   r*   r<   rj   r0   r9   r:   <module>r     s    )   , , $ ? ? .  ?  , : 1 0 J I > >  7& 7 7 m; m m` {8 {8  {8r9   