
    IiP                    t    S SK Jr  S SKrS SKJr  SSKJr  \(       a  SSKJr  SSK	J
r
  S	rS
r " S S\5      rg)    )annotationsN)TYPE_CHECKING   )	BotHelper   )CoupGame)
CoupPlayer   333333?c                     \ rS rSrSr\SS j5       r\SS j5       r\        SS j5       r\SS j5       r	\SS j5       r
\SS j5       r\SS	 j5       r\SS
 j5       r\SS j5       r\SS j5       r\SS j5       rSrg)CoupBot   zDedicated Bot class for Coup.c                    UR                   R                  U5        [        UR                   5      [        :  a  UR                   [        * S Ul         gg)z>Push an action into the bot's history and trim to window size.N)action_historyappendlenACTION_HISTORY_WINDOW)clsplayeractions      4c:\Users\dbart\PlayPalace11\server\games\coup\bot.py_record_actionCoupBot._record_action   sK     	$$V,v$$%(==$*$9$9;P:P:Q$RF! >    c                :    [        UR                  5       5      S:H  $ )N   )r   get_alive_players)r   games     r   _is_two_playerCoupBot._is_two_player   s    4))+,11r   c                   U(       d  g 0 nU GH  nUR                  U5      nU(       d  M  SnUR                  S:  a  US-  nO+UR                  S:  a  US-  nOUR                  S:  a  US-  n[        UR                  5      nUS:X  a  US	-  nOUS
:X  a  US-  nUR                  S:X  a1  UR                  S:  a  US-  nOUR                  S
:X  a  US-  nOUS-  nUR                  S;   a  US
:X  a  US-  nU[
        R                  " SS5      -   XE'   GM     U(       d  [
        R                  " U5      $ [        XDR                  S9$ )Nr      2         r   
   r      r      steal(   d   )assassinatecoup   )key)
get_player_by_namecoinsr   live_influencesactive_actionrandomrandintchoicemaxget)	r   r   r   optionsthreat_scoresopttargetscorenum_lives	            r   select_best_targetCoupBot.select_best_target    sQ     C,,S1FE||q "" 6112H1}Q
 !!W,<<1$RKE\\Q&RKESLE !!%<<q=RKE!&2* "MI P ==)) =&7&788r   c                    UR                   (       d  g[        R                  " S[        UR                   5      S-
  5      nSU 3nUR	                  X$5        g)z%Bot picks a random influence to lose.Nr   r   lose_influence_)r2   r4   r5   r   execute_action)r   r   r   idx	action_ids        r   bot_lose_influenceCoupBot.bot_lose_influenceW   sJ     %%nnQF$:$: ;a ?@%cU+	F.r   c                H   [        UR                   Vs/ s H  o3R                  (       a  M  UPM     sn5      nUS-
  nUR                  n[        R
                  " U5        USU nXeS nUR                   Vs/ s H  o3R                  (       d  M  UPM     snU-   Ul        U H  nUR                  R                  U5        M      UR                  R                  5         UR                  S5        UR                  SUR                  S9  UR                  5         gs  snf s  snf )z%Bot resolves the Ambassador exchange.r   Nzgame_coup/exchange_complete.oggzcoup-exchange-complete)r   )r   
influencesis_revealedr2   r4   shuffledeckadd
play_soundbroadcast_lname	_end_turn)	r   r   r   c
live_counttarget_livecardskeepreturn_cardss	            r   bot_resolve_exchangeCoupBot.bot_resolve_exchange`   s     V%6%6L%6mm!%6LM
 !1n &&u\k"\*(.(9(9K(91]]Q(9KdRAIIMM! 		9:1&++F' M Ls   DD7DDc                  ^ ^^ TR                   (       a  TR                  (       a  gTR                  S;   ag  TR                  5        HR  nUR                  (       d  M  UR
                  TR                  :w  d  M2  T R                  UU4U U4S jjU4U4S jjS9  MT     gTR                  S:X  an  TR                  TR                  5      nU(       aK  UR                  (       a9  UR                  S:  a  U=R                  S-  sl
        gT R                  TU5        gggTR                  S	:X  a_  TR                  mT(       aK  TR                  (       a9  TR                  S:  a  T=R                  S-  sl
        gT R                  TT5        gggTR                  mT(       a0  TR                  (       a  T R                  TU UU4S
 jU UU4S jS9  ggg)zProcess bot actions for Coup.Naction_declaredwaiting_blockc                (   > TR                  TU 5      $ N	bot_think)pr   r   s    r   <lambda>!CoupBot.on_tick.<locals>.<lambda>   s    #--a2Hr   c                &   > TR                  X5      $ r_   )rC   )rE   rb   r   s     r   rc   rd      s    t?R?RST?`r   )botthink_fn
execute_fnlosing_influencer   r   
exchangingc                 (   > T R                  TT5      $ r_   r`   )r   currentr   s   r   rc   rd      s    S]]4%Ar   c                *   > TR                  TTU 5      $ r_   )_execute_and_record)rE   r   rl   r   s    r   rc   rd      s    1H1HwXa1br   )game_activeis_resolving
turn_phaser   is_botidactive_claimer_idprocess_bot_actionget_player_by_id_losing_player_idbot_think_ticksrF   current_playerrX   )r   r   r   r<   rl   s   ``  @r   on_tickCoupBot.on_tickx   sl    4#4#4 ??BB002===VYY$2H2H%H**"*0!H7=#` +  3 __ 22**4+A+ABF&--))A-**a/***48	 (v
 __,))G7>>**Q.++q0+,,T7;	 *w ))G7>>&&Ab '  *wr   c                H    U R                  X#5        UR                  X#5        g)z6Execute the action and record it in the bot's history.N)r   rC   )r   r   r   rE   s       r   rn   CoupBot._execute_and_record   s      	6-F.r   c                   UR                   (       a  g UR                  S;   a  UR                  UR                  :X  a  g UR	                  UR                  5      nU(       d  g U R                  XU5      nU(       a  gUR                  S:X  a  U R                  X5      nU(       a  U$ gUR                  S:X  a!  UR                  U:X  a  U R                  X5      $ g )Nr[   	challenger\   passmain)	is_deadrq   rs   rt   rv   _decide_challenge_decide_blockry   _decide_main_action)r   r   r   claimerchallenge_decisionblock_decisions         r   ra   CoupBot.bot_think   s    >> ??BByyD222++D,B,BCG "%!6!6tW!M!" "33!$!2!24!@!)) ??f$)<)<)F**488r   c                  ^ UR                  UR                  5      nUR                  S:X  aI  UR                  S:X  a  UR                  (       a  UR                  nOUR	                  UR                  5      nU(       d  g[        U[        5      (       a  UOU/n/ nUR                  5        HB  nUR                  UR                   Vs/ s H  oR                  R                  PM     sn5        MD     Sn	Sn
SnU Hd  mUR                  T5      n[        U4S jUR                   5       5      nX-   nUS:X  a  U	S-  n	US:  a  S	n
US
:X  a  US-  nMW  US:X  d  M_  US-  nMf     U	[        U5      :X  a  g	SnU
(       a  US-  nXS-  -  nUR                   UR"                  ;   aB  UR"                  UR                      n[        UR                  5      n[        U5      U:  a  US-  nUR$                  S:  a  US-  nUR&                  UR                   :X  a  UR                  S:X  a  US-  nUR&                  UR                   :H  nU R)                  U5      nU(       a  US-  nOeU(       d^  UR$                  nUR                  S:X  a  US-  nO+UR                  S:X  a  US
-  nOUR                  S:X  a  US
-  nUS:  a  US-  nOUS-  n[+        US5      n[,        R,                  " 5       U:  $ s  snf )zSmart logic for challenging.r]   r)   Fr   g        c              3  ^   >#    U  H"  oR                   R                  T:X  d  M  S v   M$     g7f)r   N)	charactervalue).0rR   rcs     r   	<genexpr>,CoupBot._decide_challenge.<locals>.<genexpr>   s%     V':!kk>O>OSU>UAA':s   -	-r   r   Tr         ?g?g?皙?      ?r"   333333?r,   333333?g?taxforeign_aidr   g?)"_get_required_character_for_actionr3   rq   _steal_block_claimed_role!_get_required_character_for_block
isinstancelistget_active_playersextenddead_influencesr   r   countsumr2   r   rs   player_claimsr1   active_target_idr   minr4   )r   r   rf   r   required_charreq_list
dead_cardsrb   rR   total_exhaustedbot_has_anyscarcity_score
dead_count	bot_counttotal_knownbase_chanceclaimsrS   	is_target
two_playerclaimer_coins_afterchallenge_chancer   s                         @r   r   CoupBot._decide_challenge   s    ??@R@RS??o-!!W,1O1O $ > > $ F FtGYGY Z$.}d$C$C=- 
((*A!:K:KL:KQ{{00:KLM + B#))"-JVs':':VVI$0Ka1$1}" a#%!#% " c(m+ 4K 	,,
 ::+++''

3FW445J6{Z't# ==A4K  CFF*t/A/A]/R4K ))SVV3	''-
3K")--!!U*#q(###}4#q(###w.#q(#"a's" s" {D1}}!111] Ms   K%
c                   UR                   R                  UR                  [        5       5      nUR                  S:X  a  UR
                  UR                  :X  a  SnUR                  S5      (       d  UR                  S5      (       a  SnO[        R                  " 5       S:  a  SnU(       aT  UR                  S5      (       a  gUR                  S5      (       a  gSU;   a  gSU;   a  g[        R                  " SS/5      $  gUR                  S	:X  aW  UR
                  UR                  :X  a=  UR                  S
5      (       a  gSnS
U;   a  Sn[        R                  " 5       U:  a  g gUR                  S:X  Ga[  UR                  UR                  5      nU(       a  UR                  S-   OSnUR                  (       a.  UR                   R                  UR                  [        5       5      O	[        5       nSU;   n	UR                  S5      (       ag  US:  a  [        R                  " 5       S:  a  g gUS:  a#  U	(       a  [        R                  " 5       S:  a  g g[        R                  " 5       S:  a  g gUS:  a&  SnSU;   a  Sn[        R                  " 5       U:  a  g gUS:  a+  U	(       a$  SnSU;   a  Sn[        R                  " 5       U:  a  gg)z}Smart logic for blocking actions targeting the bot or the table.

Returns the action ID to execute, or None if not blocking.
r)   Fcaptain
ambassadorTr   block_captainblock_ambassadorr,   contessablockffffff?g?r   r   r   assassinduker"   g?r   g?r   r   r   r   N)r   r8   rs   setr3   r   has_influencer4   r6   rv   rt   r1   )
r   r   rf   past_claimsshould_blockbluff_chancer   r   claimer_claimssuspects_assassins
             r   r   CoupBot._decide_block)  s    ((,,SVVSU;(T-B-Bcff-L L  ++s/@/@/N/N#4'#$$Y//*&&|44- !K/.%41%}}o?Q-RSS H k =0T5J5Jcff5T  ,,L[(#}}- .\ W =0++D,B,BCG9@7==1#4a
 )) ""&&t'='=suEU 
 !+n <  ((&!+}}-& .6 3 )A-2C}}-& .. ' }}-& .&  '!+#'L,'+}}5& 6  )A-2C#'L,'+}}5& r   c                F  ^^^^^^ TR                   UR                  R                  :  a  gTR                   S:  a  gU R                  U5      mSSSSSSS.mTR                   S::  a  STS	'   OS
TS	'   TR                   S:  a"  STS'   TR                   S:  a  TS==   S-  ss'   SnUR	                  5        H3  nUR
                  TR
                  :w  d  M  UR                   S:  d  M1  Sn  O   U(       a  STS'   STS'   TR                  S5      (       a  TS	==   S-  ss'   TR                  S5      (       a  TS==   S
-  ss'   TR                  S5      (       a  TS==   S
-  ss'   TR                  S5      (       a  TS==   S-  ss'   UR                  R                  TR
                  [        5       5      m/ mUR                  5        HB  nTR                  UR                   Vs/ s H  oUR                  R                  PM     sn5        MD     S#UUUUU4S jjnU" S	SS5        U" SSS5        U" SSS5        U" SSS5        TR                   S:  a  STS'   U(       d  STS'   T HL  nTU   S:  d  M  TR                  R!                  U5      nUS:  d  M1  [#        TU   [$        U-  -  5      TU'   MN     ['        TR(                  5      S:X  a  TR                   m[+        UU4S jUR	                  5        5       5      n	U	(       a\  TS:  aV  TS==   S-  ss'   TS==   S-  ss'   [-        S[#        TS   S-  5      5      TS'   [-        S[#        TS   S-  5      5      TS'   T(       a8  TS==   S-  ss'   TS	==   S-  ss'   [-        S[#        TS   S -  5      5      TS'   TR/                  5        V
Vs0 s H  u  pUS:  d  M  X_M     nn
n[1        UR3                  5       5      n[1        UR5                  5       5      n[6        R8                  " XS!S"9S   $ s  snf s  snn
f )$z-Smart logic for choosing a main phase action.r-   r"   r(   r.   r   )incomer   r   r,   r)   exchanger   r#   r   r%   r   r*   r,   r$   r'   FT#   r)   r   r   r   r   r   c                t  > TR                  U5      (       d  TR                  U5      nUS:X  a  ST	U '   g US:X  a  [        ST	U    S-
  5      T	U '   g UT;   a  T	U ==   [        US-  5      -  ss'   g T(       a  SOSn[        R                  " 5       U:  a  T	U ==   U-  ss'   g [        ST	U    S-
  5      T	U '   g g )	Nr   r   r   r'   g?r   r   r.   )r   r   r7   intr4   )
r   roleutility_bonusknown_countbluff_thresholdrf   r   r   r   	utilitiess
        r   apply_bluff_risk5CoupBot._decide_main_action.<locals>.apply_bluff_risk  s    $$T**(..t4!#()If% A%(+Ay/@2/E(FIf% {*!&)S1D-EE) 3=$$!==?_<%f->-03Ay7H27M0NIf-% +r      r&   c              3  x   >#    U  H/  oR                   TR                   :w  d  M  UR                  T:*  v   M1     g 7fr_   )rs   r1   )r   rb   rf   	bot_coinss     r   r   .CoupBot._decide_main_action.<locals>.<genexpr>  s0      .F$$RURXRX.$9$.Fs   ::r   r   r   r   r   )weightsk)r   strr   r   r   r   )r1   r9   mandatory_coup_thresholdr   r   rs   r   r   r8   r   r   r   r   r   r   r   r   r   REPETITION_DECAYr   r2   allr7   itemsr   keysvaluesr4   choices)r   r   rf   has_good_steal_targetrb   rR   r   r   repeats
is_richestr   vvalid_actionsactionsr   r   r   r   r   r   s     `            @@@@@r   r   CoupBot._decide_main_action}  s    99===99>''-
 
	 99>!Ie!Ie 99>')Im$yyA~-(( !&'')Attsvv~!''Q,(,% * !!#Ig
 !#	* V$$e"Z((m$*$Y''g"$\**j!R'! ((,,SVVSU;
((*A!:K:KL:KQ{{00:KLM +	O 	O* 	+
B7)R0\26 99q='(Im$$!"Ig  F 1$,,226:Q;(+If,=AQSZAZ,[(\If%	   s""#q(		I .2.D.D.F J i1n(#r)#-(B.(+.q#i6NQT6T2U+V	-(%(C	'0BS0H,I%J	'"  h2%e"$'3y/Ds/J+K$LIj! +4//*;E*;$!q1u*;E}))+,}++-.~~g!<Q??I M~ Fs   &P
5PP N)r   'CoupPlayer'r   r   returnNone)r   
'CoupGame'r   bool)r   r   r   r   r9   z	list[str]r   
str | None)r   r   r   r   r   r   )r   r   r   r   )r   r   r   r   rE   r   r   r   )r   r   r   r   r   r   )r   r   rf   r   r   r   r   r   )r   r   rf   r   r   r   )r   r   rf   r   r   r   )__name__
__module____qualname____firstlineno____doc__classmethodr   r   r?   rF   rX   rz   rn   ra   r   r   r   __static_attributes__r   r   r   r   r      s   'S S 2 2 4949'349>G49	49 49l / /  . % %N / /
  @ _2 _2B Q Qf B@ B@r   r   )
__future__r   r4   typingr   game_utils.bot_helperr   r   r   r   r	   r   r   r   r   r   r   <module>r      s8    "    ."   n@i n@r   