
    Ii                        S r SSKJr  SSKJr  SSKJr  SSKrSSKJ	r	  SS	K
JrJrJrJrJr  \(       a  SS
KJrJr  SS.SS j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)u:   Pusoy Dos bot AI — strategic card play and card passing.    )annotations)combinations)TYPE_CHECKINGN   )Card   )Comboevaluate_combo
sort_cards
card_valueget_rank_value)PusoyDosGamePusoyDosPlayerTallow_2c                  / nU  H(  n[        U/US9nU(       d  M  UR                  U5        M*     [        U S5       H0  n[        [        U5      US9nU(       d  M  UR                  U5        M2     [        U S5       H0  n[        [        U5      US9nU(       d  M  UR                  U5        M2     [	        U 5      S:  a@  [        U S5       H0  n[        [        U5      US9nU(       d  M  UR                  U5        M2     U$ )z&Generate all valid combos from a hand.)allow_2_in_straights   r      )r
   appendr   listlen)handr   combosccombocardss         8c:\Users\dbart\PlayPalace11\server\games\pusoydos\bot.pyget_all_valid_combosr      s    FsA5MM%  
 dA&tE{I5MM%  '
 dA&tE{I5MM%  '
 4yA~!$*E"4;WMEue$ +
 M    c                H    U R                   U R                  U R                  4$ )u@   Sort key: (tier, rank_value, suit_value) — higher is stronger.)tier
rank_value
suit_value)r   s    r   _combo_strengthr%   1   s    JJ((%*:*:;;r    c                     U R                   S:H  $ )Nr   )rank)cards    r   _is_twor)   ;   s    99>r    c                &    [        S U  5       5      $ )Nc              3  J   #    U  H  n[        U5      (       d  M  S v   M     g7f)r   N)r)   .0r   s     r   	<genexpr>_count_twos.<locals>.<genexpr>@   s     .%Q71:qq%s   #	#sum)r   s    r   _count_twosr2   ?   s    .%...r    c                &    [        S U  5       5      $ )z2Rough hand strength heuristic: sum of card values.c              3  8   #    U  H  n[        U5      v   M     g 7fN)r   r,   s     r   r.   !_hand_strength.<locals>.<genexpr>E   s     +dz!}}ds   r0   )r   s    r   _hand_strengthr7   C   s    +d+++r    c                   [        UR                  5      nU R                  nU R                  nU R                  R
                  n[        S U 5       5      nU(       a  U(       a~  [        X%S9nU Vs/ s H(  n[        S UR                   5       5      (       d  M&  UPM*     n	nU	(       a9  U	R                  S S9  U	S   R                   Vs/ s H  oR                  PM     sn$ [        X%S9nUc  [        X'5      $ U Vs/ s HK  n[        UR                  5      [        UR                  5      :X  d  M1  UR                  U5      (       d  MI  UPMM     n
nU
(       d  / $ [        X*5      $ s  snf s  snf s  snf )z/Return card IDs to play, or empty list to pass.c              3  j   #    U  H)  oR                   S :H  =(       a    UR                  S:H  v   M+     g7fr   r   Nr'   suitr,   s     r   r.   bot_think.<locals>.<genexpr>U   s&     ;d1,1,d   13r   c              3  j   #    U  H)  oR                   S :H  =(       a    UR                  S:H  v   M+     g7fr:   r;   )r-   r(   s     r   r.   r=   Y   s(     (_W^ta)JDIIN)JW^r>   c                l    [        U R                  5      * [        U R                  5      [        U 5      4$ r5   )r   r   r2   r%   r   s    r   <lambda>bot_think.<locals>.<lambda>^   s(    \M(#A&r    keyr   )r   r   current_combois_first_turnoptionsr   anyr   r   sortid_bot_free_playr   beats_bot_choose_play)gameplayerr   rF   rG   r   has_3c
all_combosr   valid_startsvalid_playss              r   	bot_thinkrU   M   sM   fkk"D&&M&&Mll//G ;d;;F)$@
!
!!S(_WXW^W^(_%_Az 	 
    #/q/"7"78"7QDD"788%d<Jd// aQWW]5H5H1I!IaggVcNd:   	D..9
 9s$   1%E%E%
E*=0E/1E/	E/c                \   U(       d  / $ [        U 5      nUS::  a.  [        U 5      nU(       a  U  Vs/ s H  oDR                  PM     sn$ U Vs/ s H   n[        UR                  5      S:X  d  M  UPM"     nnU(       a  US:  a  UR	                  [
        S9  U Vs/ s H   n[        UR                  5      S:X  d  M  UPM"     nnU(       a)  US   R                   Vs/ s H  oDR                  PM     sn$ US   R                   Vs/ s H  oDR                  PM     sn$ U Vs/ s H   n[        UR                  5      S:  d  M  UPM"     nnU(       a9  UR	                  S S9  US   R                   Vs/ s H  oDR                  PM     sn$ / $ s  snf s  snf s  snf s  snf s  snf s  snf s  snf )z3Choose what to lead with when starting a new trick.r   rD   r   c                B    [        U R                  5      [        U 5      4$ r5   )r2   r   r%   rA   s    r   rB    _bot_free_play.<locals>.<lambda>   s    AGG$"r    )r   r
   rK   r   rJ   r%   r2   )r   rR   
cards_left
full_combor   	five_cardnon_two_fivessmall_comboss           r   rL   rL   w   st   	TJ Q#D)
"&'$QDD$'' '<Jq#agg,!*;JI<Z!^?+$-KIqQWW1E1JIK"/"2"8"89"8QDD"899'l0010011  *>z!S\A-=AzL> 	 	
 +1o3343344I3 ( =
 L91 ? 5s;   FF.FF;FFF F$F$1F)c                ,   [        U 5      nU HD  n[        UR                  5      U:X  d  M  UR                   Vs/ s H  oDR                  PM     sns  $    U Vs/ s H   n[        UR                  5      S:X  d  M  UPM"     nnU(       a<  UR	                  [
        S9  US   R                   Vs/ s H  oDR                  PM     sn$ UR	                  [
        S9  US   R                   Vs/ s H  oDR                  PM     sn$ s  snf s  snf s  snf s  snf )zDChoose the best play from valid options that beat the current trick.r   rD   )r   r   rK   r2   rJ   r%   )r   rT   rY   r   r   non_two_playss         r   rN   rN      s    TJ u{{z)"'++.+QDD+..  !,I1{177/Cq/HQMI/+A.4454455 )%a.../.QDD.// / J 6 0s   DD;D.D*Dc                d    [        U 5      nUSU nU Vs/ s H  oDR                  PM     sn$ s  snf )zIChoose cards to give back during card passing (winner gives worst cards).N)r   rK   )r   countsorted_handgiver   s        r   bot_choose_give_cardsrd      s2    T"KvD$QDD$s   -)r   
list[Card]r   boolreturnlist[Combo])r   r	   rg   ztuple[int, int, int])r(   r   rg   rf   )r   re   rg   int)r   re   rg   float)rO   z'PusoyDosGame'rP   z'PusoyDosPlayer'rg   	list[int])r   re   rR   rh   rg   rk   )r   re   rT   rh   rg   rk   )r   re   ra   ri   rg   rk   )__doc__
__future__r   	itertoolsr   typingr   randomgame_utils.cardsr   	evaluatorr	   r
   r   r   r   rO   r   r   r   r%   r)   r2   r7   rU   rL   rN   rd    r    r   <module>rt      sX    @ " "    $ T T2 ?C 8</,'/T%P04 r    