
    Ii              	          S r SSKJr  SSKJrJr  SSKJr  SSKJ	r	  SSK
Jr  SS jrSS	 jrSS
 jrSS jrSSSSSSSSS.r\ " S S\	5      5       r        SS jrSS.SS jjrSS.SS jjrg) uK   Pusoy Dos hand evaluator — combo detection, comparison, and instant wins.    )annotations)	dataclassfield)Counter)DataClassJSONMixin   )Cardc                "    U S:X  a  gU S:X  a  gU $ )z7Big Two rank value. 3 is lowest (3), 2 is highest (15).             ranks    >c:\Users\dbart\PlayPalace11\server\games\pusoydos\evaluator.pyget_rank_valuer      s    qyqyK    c                0    SSSSS.R                  U S5      $ )zCBig Two suit value. Diamonds(1) > Hearts(3) > Spades(4) > Clubs(2).   r   r   r   )r   r   r   r   r   )get)suits    r   get_suit_valuer      s    Q1#''a00r   c                ^    [        U R                  5      S-  [        U R                  5      -   $ )z-Combined value for sorting: rank * 10 + suit.
   )r   r   r   r   )cards    r   
card_valuer       s$    $))$r)N499,EEEr   c                    [        U [        S9$ )z1Sort cards by Big Two rank then suit (ascending).)key)sortedr   )cardss    r   
sort_cardsr"   %   s    %Z((r   r   r   r      )singlepairthree_of_a_kindstraightflush
full_housefour_of_a_kindstraight_flushc                  \    \ rS rSr% S\S'   S\S'   S\S'   S\S'   S	rS\S
'   S rSS jrSrg)Combo:   str	type_name
list[Card]r!   int
rank_value
suit_valuer   tierc                    [        U R                  5      U l        [        R                  U R                  S5      U l        g )Nr   )r"   r!   TIER_MAPr   r0   r5   )selfs    r   __post_init__Combo.__post_init__B   s(    

+
LL3	r   c                0   [        U R                  5      [        UR                  5      :w  a  g[        U R                  5      S:X  Ga  U R                  UR                  :w  a  U R                  UR                  :  $ U R                  S;   aL  U R                  UR                  :w  a  U R                  UR                  :  $ U R
                  UR
                  :  $ U R                  S:X  aL  U R
                  UR
                  :w  a  U R
                  UR
                  :  $ U R                  UR                  :  $ U R                  UR                  :  $ U R                  UR                  :w  a  U R                  UR                  :  $ U R
                  UR
                  :  $ )z(Return True if this combo beats *other*.Fr#   )r'   r+   r(   )lenr!   r5   r0   r3   r4   )r8   others     r   beatsCombo.beatsF   s5   tzz?c%++..tzz?ayyEJJ&yy5::--~~!????e&6&66??U-=-===)9)9997*??e&6&66??U-=-===)9)999)9)999 ??e...??U%5%555!1!111r   )r!   r5   N)r=   r-   returnbool)	__name__
__module____qualname____firstlineno____annotations__r5   r9   r>   __static_attributes__r   r   r   r-   r-   :   s*    NOOD#M42r   r-   c                b   U(       d  SU ;   a  gU [        [        U S   U S   S-   5      5      :X  a  SU S   [        US   R                  5      4$ U(       aD  U / SQ:X  a<  U H6  n[	        UR
                  5      S:X  d  M  SS[        UR                  5      4s  $    U(       aD  U / SQ:X  a<  U H6  n[	        UR
                  5      S	:X  d  M  SS	[        UR                  5      4s  $    U(       aD  U / S
Q:X  a<  U H6  n[	        UR
                  5      S:X  d  M  SS[        UR                  5      4s  $    g)zReturn (is_straight, high_rank, high_suit) for a 5-card hand.

*ranks* must be the rank_values of *sorted_cards* in ascending order.
When allow_2 is False, the 2 (rank_value 15) cannot appear in any straight.
r   )Fr   r   r   r#   Tr   )r   r   r#   r   r   )r   r   r#      r   rI   )         r   r   )listranger   r   r   r   )rankssorted_cardsallow_2cs       r   _detect_straightrS   e   s    rU{ U58U1X\233U1X~l1o.B.BCCC 5--Aaff%*Qqvv 666  5,,Aaff%*Qqvv 666  500Aaff%+R!777  r   T)allow_2_in_straightsc                  [        U 5      nUS;  a  g[        U 5      nUS:X  a:  [        SU [        US   R                  5      [        US   R                  5      5      $ US:X  a{  US   R                  US   R                  :X  aZ  [        SU [        US   R                  5      [        [        US   R                  5      [        US   R                  5      5      5      $ gUS:X  a\  US   R                  US   R                  s=:X  a  US   R                  :X  a'  O  g[        S	U [        US   R                  5      S5      $ gU Vs/ s H  n[        UR                  5      PM     nn[        U  Vs1 s H  oDR                  iM     sn5      S:H  n[        XSU5      u  pxn	[        S
 U  5       5      n
[        U
R                  5       5      nUSS/:X  a7  [        S U
R                  5        5       5      n[        SU [        U5      S5      $ USS/:X  a7  [        S U
R                  5        5       5      n[        SU [        U5      S5      $ U(       a  U(       a  [        SXU	5      $ U(       a:  [        SU [        US   R                  5      [        US   R                  5      5      $ U(       a  [        SXU	5      $ gs  snf s  snf )z@Evaluate a list of cards and return a Combo if valid, else None.)r   r   r   r#   Nr   r$   r   r   r%   r   r&   c              3  8   #    U  H  oR                   v   M     g 7fNr   .0rR   s     r   	<genexpr>!evaluate_combo.<locals>.<genexpr>   s     0%Q&&%   r   c              3  :   #    U  H  u  pUS :X  d  M  Uv   M     g7f)r   Nr   rY   rcnts      r   rZ   r[      s     I)<vqq)<   	r*   c              3  :   #    U  H  u  pUS :X  d  M  Uv   M     g7f)r   Nr   r^   s      r   rZ   r[      s     J*=!!*=ra   r)   r+   r(   r'   )r<   r"   r-   r   r   r   r   maxrS   r   r    valuesnextitems)r!   rT   nscrR   rO   is_flushis_straightstraight_highstraight_suitrank_countscounts	four_rank
three_ranks                 r   evaluate_comborq      so   E
A	E	BAvXunRUZZ&@.QSTUQVQ[Q[B\]]Ava5::A#r!uzz*N2a5::.r!uzz0JK	  Ava5::A1r!uzz1 *E>"Q%**3MqQQ .00R^AFF#RE0E*EqFFE*+q0H0@L`0a-K0%00KK&&()F !QI):):)<II	%unY.GKK !QJ+*;*;*=JJ
\5.*DaHH x%u]KK We^BqEJJ%?PRSTPUPZPZA[\\ Z}EE; 1*s   J7/J<c                  [        U 5      S:w  a  gU  Vs1 s H  o"R                  iM     nn[        U5      S:X  a  gU  Vs/ s H  o"R                  S:X  d  M  UPM     nn[        U5      S:X  a  g[        S U  5       5      n[        UR                  5       5      nUR	                  SS5      S	:X  a&  UR	                  S
S5      S
:X  a  [        U5      S:X  a  ggs  snf s  snf )zCheck if a 13-card hand qualifies for an instant win.

Returns the instant win type name or None:
  - "dragon": 13-card straight (3 through 2, all 13 ranks)
  - "four_twos": all four 2s in hand
  - "six_pairs": exactly six pairs + one single
rL   Ndragonr   r   	four_twosc              3  8   #    U  H  oR                   v   M     g 7frW   r   rX   s     r   rZ   %detect_instant_win.<locals>.<genexpr>   s     /$Q&&$r\   r   rI   r      	six_pairs)r<   r   r   rd   r   )handrT   rR   rO   twosrm   
count_dists          r   detect_instant_winr|      s     4yB ""TVVTE"
5zR +t!vv{AtD+
4yA~ /$//K++-.J~~aq Z^^Aq%9Q%>3{CSWXCX #
 ,s   C CCN)r   r2   r@   r2   )r   r2   r@   r2   )r   r	   r@   r2   )r!   r1   r@   r1   )rO   z	list[int]rP   r1   rQ   rA   r@   ztuple[bool, int, int])r!   r1   rT   rA   r@   zCombo | None)ry   r1   rT   rA   r@   z
str | None)__doc__
__future__r   dataclassesr   r   collectionsr   mashumaro.mixins.jsonr   game_utils.cardsr	   r   r   r   r"   r7   r-   rS   rq   r|   r   r   r   <module>r      s    Q " (  4 $1
F
) 	 "2 "2 "2T%%$.%9=%%Z GK 8@ JN  r   