
    Iih>              
       L   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  SS
K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Jr  SSKJrJrJr  SSKJ r J!r!  SSK"J#r#  SSK$J%r%  \ " S S\5      5       r&\ " S S\	5      5       r'\\ " S S\\\\5      5       5       r(g)z
Pig Game Implementation for PlayPalace v11.

Classic dice game: roll or bank, but don't get a 1!
Supports individual and team modes via TeamManager.
    )	dataclassfield)datetimeN   )GamePlayerGameOptions)register_game   )ActionGuardMixin)RoundBasedGameMixin)Action	ActionSet
Visibility)	BotHelper)PushYourLuckBotMixin)
GameResultPlayerResult)	IntOptionTeamModeOptionoption_field)TeamManagerTeamResultBuilder)Localization)KeybindStatec                   (    \ rS rSr% SrSr\\S'   Srg)	PigPlayer   zPlayer state for Pig game.r   round_score N)	__name__
__module____qualname____firstlineno____doc__r   int__annotations____static_attributes__r        4c:\Users\dbart\PlayPalace11\server\games\pig\game.pyr   r      s    $Kr)   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"S#95      r\\	S$'   S%rg&)'
PigOptions!   z5Options for Pig game using declarative option system.2   
   i  scorezgame-set-target-scorezgame-enter-target-scorezgame-option-changed-targetzpig-desc-target-score)defaultmin_valmax_val	value_keylabelprompt
change_msgdescriptiontarget_scorer   pointszpig-set-min-bankzpig-enter-min-bankzpig-option-changed-min-bankzpig-desc-min-bankmin_bank_points         sideszpig-set-dice-sideszpig-enter-dice-sideszpig-option-changed-dicezpig-desc-dice-sides
dice_sides
individualmodec                 0    [         R                  " SS5      $ )Nr   r=   )r   get_all_team_modes)gps     r*   <lambda>PigOptions.<lambda>M   s    !?!?1!Er)   zgame-set-team-modezgame-select-team-modezgame-option-changed-team)r1   r4   choicesr5   r6   r7   	team_moder    N)r!   r"   r#   r$   r%   r   r   r9   r&   r'   r;   r@   r   rJ   strr(   r    r)   r*   r,   r,   !   s    ?$),3/		
L#  ($'4+		
OS  #&)0-		
J  " E&*1	
	Is 	r)   r,   c            	         ^  \ rS rSr% Sr\" \S9r\\   \	S'   \" \
S9r\
\	S'   \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S.S\S\S\S\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/U 4S jjrS\S\SS4S jr S\S\SS4S jr!S\S\4S jr"S\\   4U 4S jjr#S\4S jr$S\SS4S jr%S\SS4S  jr&S\SS4S! jr'S\S"\S\4S# jr(S\S\S-  4S$ jr)S/S% jr*S\+4S& jr,S'\+S(\S\\   4S) jr-S0S*\S+\SS4S, jjr.S-r/U =r0$ )1PigGameU   a  
Pig dice game.

Players take turns rolling a die. Each roll adds to their round score,
but rolling a 1 loses all points for that round. Players can bank their
points at any time to add them to their total score and end their turn.
First player to reach the target score wins.
)default_factoryplayersoptionsreturnc                     g)NPigr    clss    r*   get_namePigGame.get_namee       r)   c                     g)Npigr    rU   s    r*   get_typePigGame.get_typei   rY   r)   c                     g)Nzcategory-dice-gamesr    rU   s    r*   get_categoryPigGame.get_categorym   s    $r)   c                     g)Nr   r    rU   s    r*   get_min_playersPigGame.get_min_playersq       r)   c                     g)Nr=   r    rU   s    r*   get_max_playersPigGame.get_max_playersu   rd   r)   	player_idnameis_botc                     [        XUSS9$ )z,Create a new player with Pig-specific state.r   )idri   rj   r   )r   )selfrh   ri   rj   s       r*   create_playerPigGame.create_playery   s    IQOOr)   playerNc                 $    U R                  U5      $ )z Check if roll action is enabled.)guard_turn_action_enabledrm   rp   s     r*   _is_roll_enabledPigGame._is_roll_enabled   s    --f55r)   c                 $    U R                  U5      $ )z/Roll is visible during play for current player.)turn_action_visibilityrs   s     r*   _is_roll_hiddenPigGame._is_roll_hidden   s    **622r)   c                     U R                  U5      nU(       a  U$ Un[        SU R                  R                  5      nUR                  U:  a  gg)z Check if bank action is enabled.   zpig-need-more-pointsN)rr   maxrQ   r;   r   )rm   rp   error
pig_playermin_requireds        r*   _is_bank_enabledPigGame._is_bank_enabled   sI    ..v6L &
1dll::;!!L0)r)   c                 ~    Un[        SU R                  R                  5      nU R                  XR                  U:  S9$ )z.Bank is hidden until player has enough points.r{   )extra_condition)r|   rQ   r;   rw   r   )rm   rp   r~   r   s       r*   _is_bank_hiddenPigGame._is_bank_hidden   sC     &
1dll::;**$:$:l$J + 
 	
r)   	action_idc                     UnU R                  U5      nU(       a  UR                  OSn[        R                  " USUR                  S9$ )z9Get dynamic label for bank action showing current points.enpig-bankr:   )get_userlocaler   getr   )rm   rp   r   r~   userr   s         r*   _get_bank_labelPigGame._get_bank_label   s=     &
}}V$ $$
:;Q;QRRr)   c                 (   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SS9SSSSS95        U$ )z(Create the turn action set for a player.r   turn)ri   rollzpig-roll_action_rollrt   rx   )rl   r5   handler
is_enabled	is_hiddenbankr   r   r   _action_bankr   r   r   )rl   r5   r   r   r   	get_label)r   r   r   addr   r   r   )rm   rp   r   r   
action_sets        r*   create_turn_action_setPigGame.create_turn_action_set   s    }}V$ $$F+
"&&vz:&-+	
 	"&&vz!D&-++		
 r)   c                    > [         TU ]  5         U R                  SSS/[        R                  S9  U R                  SSS/[        R                  S9  g)	z!Define all keybinds for the game.rz	Roll dicer   )statebzBank pointsr   N)supersetup_keybindsdefine_keybindr   ACTIVE)rm   	__class__s    r*   r   PigGame.setup_keybinds   sP     	  	Cvhl>Q>QRC@S@STr)   c                    UnU R                  SUR                  S9  U R                  S5        [        R                  " U[
        R                  " SS5      S9  [
        R                  " SU R                  R                  5      nUS:X  aN  U R                  S5        U R                  S	UR                  UR                  S
9  SUl	        U R                  5         gU=R                  U-  sl	        U R                  SXCR                  S9  g)zHandle roll action.z	pig-rollsrp   zgame_pig/roll.oggr/   r>   ticksr{   zgame_pig/lose.oggzpig-bust)rp   r:   r   zpig-roll-result)r   totalN)broadcast_lri   
play_soundr   jolt_botrandomrandintrQ   r@   r   end_turn)rm   rp   r   r~   r   s        r*   r   PigGame._action_roll   s     &
V[[9+, 	6B)?@~~a!8!8919OO/0ZJDZDZ[%&J"MMO""d*".TAWAWXr)   c                 f   UnU R                  S5        UR                  nU R                  R                  UR                  U5        U R                  R                  UR                  5      nU(       a  UR                  OSnSUl        U R                  SUR                  XFS9  U R                  5         g)zHandle bank action.zgame_pig/bank.oggr   zpig-bank-action)rp   r:   r   N)	r   r   _team_manageradd_to_team_scoreri   get_teamtotal_scorer   r   )rm   rp   r   r~   bankedteamr   s          r*   r   PigGame._action_bank   s     &
+,'' 	,,V[[&A!!**6;;7$(  a!"
*6;;v[r)   c                 v    U R                   R                  UR                  5      nU(       a  UR                  $ S$ )z,Get a player's total score from TeamManager.r   )r   r   ri   r   )rm   rp   r   s      r*   get_player_scorePigGame.get_player_score   s/    !!**6;;7#'t.Q.r)   c                   > [         TU ]  5       nU R                  U R                  R                  5      nU(       a  UR                  U5        U R                  R                  U R                  R                  :  a  UR                  S5        U$ )z,Validate game configuration before starting.zpig-error-min-bank-too-high)r   prestart_validate_validate_team_moderQ   rJ   appendr;   r9   )rm   errorsteam_mode_errorr   s      r*   r   PigGame.prestart_validate   sk    *, 224<<3I3IJMM/* <<''4<<+D+DDMM78r)   c                     U R                   R                  nSU;   d  [        S U 5       5      (       a  [        R                  " U5      nU$ )N c              3   P   #    U  H  oS :w  d  M
  UR                  5       v   M     g7f)vN)isupper).0cs     r*   	<genexpr>(PigGame.get_team_mode.<locals>.<genexpr>	  s     "N	1#X;199;;	s   	&&)rQ   rJ   anyr   parse_display_to_team_mode)rm   rJ   s     r*   get_team_modePigGame.get_team_mode  s?    LL**	)s"N	"NNN#>>yIIr)   c                     SUl         g Nr   r   rs   s     r*   _reset_player_for_gamePigGame._reset_player_for_game  
    r)   c                     SUl         g r   r   rs   s     r*   _reset_player_for_turnPigGame._reset_player_for_turn  r   r)   c                 &    U R                  U5        g )N)prepare_push_bot_turnrs   s     r*   _setup_bot_for_turnPigGame._setup_bot_for_turn  s    ""6*r)   targetc                 Z   U R                  5       nSnSnU R                  U5      nU Hl  nXq:w  d  M
  U R                  U5      nXR                  R                  :  a  Sn[	        XX5      nMC  XR                  R                  S-
  :  d  Ma  [	        XX5      nMn     U(       a	  US-   U-
  nOUS:  a  US-   U-
  nXaR
                  -   U R                  R                  S-
  :  aL  U(       dE  Sn	U H4  nXq:w  d  M
  U R                  U5      nXUR
                  -   S-
  :  d  M2  Sn	  O   U	(       a  SnU$ )z,Adjust the bot's target score for this turn.Fr   Tr{      )get_active_playersr   rQ   r9   r|   r   )
rm   rp   r   active_playerssomeone_hit_thresholdhighest_scoremy_scoreotherother_score	can_relaxs
             r*   _adjust_push_bot_targetPigGame._adjust_push_bot_target  s/    002 %((0#E"33E:,,";";;,0)$'$CM LL$=$=$AA$'$CM $ !"Q&1FQ"Q&1F )))LL%%)
'I'?"&"7"7">K"1C1C&Ca&GH$)	 ( r)   c                     [         R                  " U5      nUc  Sn[        SU R                  R                  5      nUR
                  U:  a  UR
                  U:  a  gg)z,Bot AI decision making. Called by BotHelper.   r{   r   r   )r   
get_targetr|   rQ   r;   r   )rm   rp   r   min_banks       r*   	bot_thinkPigGame.bot_think>  sU    %%f->F q$,,667'F,>,>(,Jr)   c                    U R                  5       n/ nSn[        5       nU H  nU R                  R                  UR                  5      nU(       a  UR
                  U;   a  MA  UR                  UR
                  5        UR                  nXpR                  R                  :  d  M  Xs:  a  U/nUnM  Xs:X  d  M  UR                  U5        M     [        U5      S:X  aR  U R                  S5        US   nU R                  R                  U5      n	U R                  SU	S9  U R                  5         g
[        U5      S:  Ga  U V
s/ s H  oR                  R                  U
5      PM     nn
U R                    HO  nU R#                  U5      nU(       d  M  [$        R&                  " UR(                  U5      nUR+                  SUSS9  MQ     U V
s1 s H  oR
                  iM     nn
U HH  nU R                  R                  UR                  5      nU(       a  UR
                  U;  d  MA  S	Ul        MJ     U R/                  5         g
U R/                  5         g
s  sn
f s  sn
f )zHandle end of a round.r   r{   zgame_pig/win.oggz
pig-winnerr   zgame-tiebreaker-playerstable)rP   bufferTN)r   setr   r   ri   indexr   r   rQ   r9   r   lenr   get_team_namer   finish_gamerP   r   r   format_list_andr   speak_lis_spectator_start_round)rm   r   winning_teams
high_scoreteams_checkedrp   r   r0   winning_team	team_namet
team_namesr   	names_strwinning_team_indicesrF   s                   r*   _on_round_endPigGame._on_round_endK  s    002
 $F%%..v{{;D4::6djj)$$E111%%)FM!&J(!((. % }"OO./(+L**88FI\)<!#GTU}!,,::1=}JU,,}}V,4 , < <T[[* UILL!:IV]L^	 ' 6C#C]GG] #C#))22166:tzz1EE%)AN $  # V $Ds   $I
Ic                 ^   [         R                  " U R                  5      u  p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 Pig-specific data.is_virtual_botF)rh   player_namerj   r  Nr   )winner_namewinner_scorefinal_scoresrounds_playedr9   rJ   )	game_type	timestampduration_ticksplayer_resultscustom_data)r   	summarizer   r   r\   r   now	isoformatsound_scheduler_tickr   r   rl   ri   rj   getattrr   r   roundrQ   r9   rJ   )rm   sorted_teamswinnerr  rF   s        r*   build_game_resultPigGame.build_game_result  s    ->-H-HI[I[-\*lmmolln..044 002 3A dd !88#*1.>#F	 3 LRt11??GW[6< 2 2! ,!% $ 9 9!\\33
 	
s   7?D*resultr   c                 f    UR                   R                  S0 5      n[        R                  " X#5      $ )z#Format the end screen for Pig game.r  )r  r   r   format_final_scores)rm   r!  r   r  s       r*   format_end_screenPigGame.format_end_screen  s+    ))--nbA 44VJJr)   jolt_minjolt_maxc                 v    [         R                  " U [        R                  " X5      S9  U R	                  5         g)z-Override to use Pig's turn advancement logic.r   N)r   	jolt_botsr   r   _on_turn_end)rm   r&  r'  s      r*   r   PigGame.end_turn  s'    Dx(JKr)   r    )F)rR   N)r>      )1r!   r"   r#   r$   r%   r   listrP   r   r'   r,   rQ   classmethodrK   rW   r\   r_   r&   rb   rf   boolrn   r   rt   r   rx   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r	  r   r  r$  r   r(   __classcell__)r   s   @r*   rM   rM   U   s     %T:GT)_:
;GZ;      %S % %      Ps P# Pt PPY P6v 6#* 63f 3 3	v 	#* 	
f 
 
Sf S S SY 9 6UY6 Yc Yd Y.6 c d "/y /S /
49 s Y 4 Y 4 +) + +&f &c &c &P	 cDj 2 h
: 
6K
 KC KDI K
 S $  r)   rM   ))r%   dataclassesr   r   r   r   baser   r   r	   registryr
   game_utils.action_guard_mixinr   !game_utils.round_based_game_mixinr   game_utils.actionsr   r   r   game_utils.bot_helperr   game_utils.push_your_luck_mixinr   game_utils.game_resultr   r   game_utils.optionsr   r   r   game_utils.teamsr   r   messages.localizationr   server.core.ui.keybindsr   r   r,   rM   r    r)   r*   <module>r>     s    )   , , $ = D ? ? . C > I I > 1 0    0 0 0f K"$46I4 K  Kr)   