
    Ii$                        S r SSKJr  SSKJr  SSKrSSKJr  \(       a  SSKJ	r	J
r
  S	rS
rSrSrSrSrSrSrSrSrSS jrSS jrSS jrSS jrSS jrSS jrSS jrSS jrSS jrg)zStrategic bot AI for LastCard.    )annotations)TYPE_CHECKINGN   )Card   )LastCardGameLastCardPlayer
                     c                   SnUR                   [        :X  a  SnO~UR                   [        :X  a  SnOgUR                   [        :X  a  SnOPUR                   [        :X  a  US:  a  SOSnO1UR                   [
        :X  a  US:  a  SOSnOS	UR                   S
-  -   nUS::  a:  UR                   [
        [        4;   a  US-  nU$ UR                   [        :  a  US-  nU$ )a  Score a card for priority (higher = play first).

Strategy:
- Play action cards early to disrupt opponents
- Save wilds for when you need them
- When hand is small, play high-value cards to reduce penalty risk
- Prefer cards that match the most cards in hand (color synergy)
g        g       @g      @g      @r   g      @g      "@g       @g      @皙?g      @)rankRANK_DRAW_TWO	RANK_SKIPRANK_REVERSERANK_WILD_DRAW_FOUR	RANK_WILD)gamecard	hand_sizescores       8c:\Users\dbart\PlayPalace11\server\games\lastcard\bot.py_card_priorityr      s     E yyM!	i		l	"	)	) 1}#	i	 1}# dii#o% A~99$788SLE L YY)#SLEL    c                  ^^ [         S[        S[        S[        S0m[         S[        S[        S[        S0mUR                   Hp  nUR
                  T;   d  M  TUR
                  ==   S-  ss'   UR                  [        :  a  TUR
                  ==   S-  ss'   MY  TUR
                  ==   S-  ss'   Mr     [        TR                  5       UU4S jS9nU$ )z-Choose the best color based on cards in hand.r   r   r   c                @   > TU    TU    [         R                   " 5       4$ )Nrandom)ccolor_countscolor_valuess    r   <lambda>#choose_best_color.<locals>.<lambda>O   s    LO\!_fmmo+^r   )key)
	COLOR_RED
COLOR_BLUECOLOR_GREENCOLOR_YELLOWhandsuitr   r   maxkeys)r   playerr   bestr%   r&   s       @@r   choose_best_colorr4   ?   s    q*aaqQLq*aaqQL99$#q(#yyI%TYY'1,'TYY'1,'  !^D Kr   c                d   UR                    Vs/ s H  o R                  X!5      (       d  M  UPM     nnU(       d  g[        UR                   5      n/ nU H;  n[        XU5      nUR	                  U[
        R
                  " 5       S-  -   U45        M=     UR                  SS S9  US   S   $ s  snf )z4Choose the best card to play from the player's hand.N      ?Tc                    U S   $ )Nr    )xs    r   r'   &choose_playable_card.<locals>.<lambda>a   s    AaDr   )reverser)   r   r   )r.   _is_card_playablelenr   appendr#   sort)r   r2   r   playabler   scoredprioritys          r   choose_playable_cardrC   T   s    !'U0F0Ft0THUFKK IF!$i8x&--/C"77>? 
 KK.K1!9Q< Vs
   B-B-c                &   [        UR                  5      nUS::  a  SnOUS::  a  SnOSnU R                  U R                  5      nU(       a/  [	        US5      (       a  [        UR                  5      S::  a  US-  n[
        R
                  " 5       U:  $ )zDecide whether to challenge a Wild Draw Four.

Strategy:
- If player has few cards, more likely to challenge (less to lose)
- Consider if the WD4 player likely had matching colors
- More aggressive when behind in score
r   g333333?   gffffff?g333333?r.   r   )r=   r.   get_player_by_idinterrupt_wd4_player_idhasattrr#   )r   r2   r   prob
wd4_players        r   _should_challenge_wd4rK   e   s     FKK I A~	a &&t'C'CDJgj&11z1$CKD==?T!!r   c                   U R                   nU(       d  gUR                   Vs/ s H<  o3R                  UR                  :X  d  M  UR                  UR                  :X  d  M:  UPM>     nnU(       d  g[	        UR                  5      nUS::  a  gUS   nUR                  [
        :  a  [        R                  " 5       S:  $ [        R                  " 5       S:  $ s  snf )z/Decide whether to jump in with a matching card.Fr   Tr   g?r6   )top_cardr.   r   r/   r=   r   r#   )r   r2   topr$   matchingr   r   s          r   _should_jump_inrP      s    
--C!;;T;a&&CHH*<388AS;HTFKK I A~ A;DyyI}}$$ ==?S  ! Us   CC Cc                2    [         R                   " 5       S:  $ )z4Decide whether to press the buzzer to catch someone.gffffff?r"   )r   r2   s     r   _should_catch_last_cardrR      s     ==?S  r   c                D   U R                   (       aG  U R                  U:X  a7  [        X5      n[        S[        S[
        S[        S0nUR                  US5      $ U R                  (       a  U R                  UR                  :X  a  U R                   Vs/ s H3  oDR                  (       a  M  UR                  UR                  :w  d  M1  UPM5     nnU(       ab  SnSn[        U5       HJ  u  p[        US5      (       d  M  [        UR                   5      U:  d  M3  [        UR                   5      nUnML     SU 3$ gU R                  U:X  a  U R"                  R$                  (       a  ['        X5      $ [        UR                   5      S	:X  aN  U R"                  R(                  (       a3  U R"                  R*                  (       a  UR,                  (       d  S
Ul        [/        X5      n	U	b  SU	R                   3$ U R0                  (       a  gU R3                  U5      (       a  gggs  snf )z2Main bot decision function for turn-based actions.	color_red
color_bluecolor_greencolor_yellowr   r.   swap_target_Nr   T
play_card_passdraw)awaiting_color_choicecurrent_playerr4   r*   r+   r,   r-   getawaiting_swap_targetswap_player_ididturn_playersis_spectator	enumeraterH   r=   r.   optionsallow_multiple_play_bot_think_multilast_card_calloutbuzzer_enabledcalled_last_cardrC   turn_has_drawn	_can_draw)
r   r2   color	color_mappactivebest_idx
best_countir   s
             r   	bot_thinkrt      s    !!d&9&9V&C!$/{.	
	 }}UK00   T%8%8FII%E!..[.nn!QWQZQZIZ!.[HJ!&)1f%%#aff+
*B!$QVVJ H * "(,, f$<<++#D11 !..++++&*F# $D1y))>>&!!S \s   H*HHc                   UR                   (       a  g[        X5      nUc*  U R                  (       a  gU R                  U5      (       a  gg[	        UR
                  5      nUR                  [        [        4;  a8  UR
                   Vs/ s H   oDR                  UR                  :X  d  M  UPM"     nnOU/n[	        UR
                  5      [	        U5      -
  nUS:X  aN  U R                  R                  (       a3  U R                  R                  (       a  UR                  (       d  SUl        U H(  nUR                   R                  UR                  5        M*     gs  snf )z;Bot logic for multi-play mode using toggle+confirm pattern.play_selectedrZ   r[   r   T)selected_cardsrC   rk   rl   r=   r.   r   r   r   re   rh   ri   rj   addra   )r   r2   r   remaining_afterr$   	same_ranks         r   rg   rg      s      -D|>>&!! &++&O yy$788 &C1vv/BQ	C	F	&++&Y7O 	1LL**LL''''"& !!!$$' % Ds   E)Ec                6   U R                   S:X  a  U R                  U R                  5      nU(       aa  [        US5      (       aP  UR                  UR                  :X  a  UR
                  (       d  g gUR
                  (       d  [        X5      (       a  ggU R                   S:X  aD  U R                  5       nU(       a,  UR                  UR                  :X  a  [        X5      (       a  gggU R                   S:X  a!  U R                  U:w  a  [        X5      (       a  gg)	zDBot reactions during interrupt windows (buzzer, challenge, jump-in).rh   r.   buzzerchallenge_wd4accept_drawjump_in_windowjump_inN)interrupt_phaserF   interrupt_target_idrH   ra   rj   rR   _next_playerrK   r]   rP   )r   r2   targetnext_ps       r   	bot_reactr     s     22&&t'?'?@gff--yyFII%..# /&  ..3J43X3X#  
			0""$fii699,$T22&$ 	 
		!1	1&(_T-J-Jr   )r   'LastCardGame'r   r   r   intreturnfloat)r   r   r2   'LastCardPlayer'r   r   )r   r   r2   r   r   zCard | None)r   r   r2   r   r   bool)r   r   r2   r   r   z
str | None)__doc__
__future__r   typingr   r#   game_utils.cardsr   r   r   r	   r   r   r   r   r   r*   r+   r,   r-   
COLOR_WILDr   r4   rC   rK   rP   rR   rt   rg   r   r8   r   r   <module>r      s    $ "    $2 		 	

!H*""6!2!9x&Rr   