
    Ii0G              	         % S r SSKJr  SSKJrJr  SSKJr  SSKr\(       a  SSK	J
r
  SSKJr   " S	 S
\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S \5      r\" 5       r\" 5       r\" 5       r\" 5       r\" 5       r\" 5       r\" 5       r\" 5       r \" 5       r!\\\\\\\\ \!/	r"S!\#S"'   \" V s0 s H  o RH                  U _M     sn r%S#\#S$'   S*S% jr&S+S& jr'S,S' jr(S,S( jr)S,S) jr*gs  sn f )-a  
Skill System for Pirates of the Lost Seas.

Skills are stateless - they read/write state from the player's skill dicts.
This avoids complex serialization issues with polymorphic types.

Player stores skill state in simple dicts:
- skill_cooldowns: dict[str, int] - remaining cooldown turns
- skill_active: dict[str, int] - remaining active turns for buffs
- skill_uses: dict[str, int] - remaining uses for limited-use skills
    )annotations)ABCabstractmethod)TYPE_CHECKINGN   )PiratesGame)PiratesPlayerc                      \ rS rSr% SrSrS\S'   SrS\S'   SrS\S	'   Sr	S\S
'   \
SS j5       r\
SS j5       rSS jrSS jrSS jrSrg)Skill   z
Base class for all skills. Skills are stateless singletons.

State (cooldowns, active duration, uses) is stored on the player,
not on the skill instance.
 strnamedescriptionr   intrequired_levelskill_idc                    g)z%Check if this skill can be performed.N selfgameplayers      :c:\Users\dbart\PlayPalace11\server\games\pirates\skills.pycan_performSkill.can_perform)        	    c                    g)z4Execute the skill. Returns 'end_turn' or 'continue'.Nr   r   s      r   	do_actionSkill.do_action.   r   r   c                    g)z)Called at the start of the player's turn.Nr   r   s      r   on_turn_startSkill.on_turn_start3   s    r   c                    U R                   $ )z!Get the label for the skill menu.)r   r   r   s     r   get_menu_labelSkill.get_menu_label7   s    yyr   c                4    UR                   U R                  :  $ )z+Check if the player's level is high enough.)levelr   r&   s     r   is_unlockedSkill.is_unlocked;   s    ||t2222r   r   Nr   'PiratesGame'r   'PiratesPlayer'returnztuple[bool, str | None]r   r.   r   r/   r0   r   r   r.   r   r/   r0   Noner   r/   r0   r   r   r/   r0   bool)__name__
__module____qualname____firstlineno____doc__r   __annotations__r   r   r   r   r   r    r#   r'   r+   __static_attributes__r   r   r   r   r      se     D#NKNCHc   3r   r   c                  d    \ rS rSr% SrSrS\S'   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rg)CooldownSkill@   z&Base class for skills with a cooldown.r   r   max_cooldownc                N    UR                   R                  U R                  S5      $ )zGet remaining cooldown turns.r   )skill_cooldownsgetr   r&   s     r   get_cooldownCooldownSkill.get_cooldownE   s    %%))$--;;r   c                4    X!R                   U R                  '   g)zSet cooldown turns.N)rC   r   r   r   values      r   set_cooldownCooldownSkill.set_cooldownI   s    05t}}-r   c                *    U R                  U5      S:  $ )z,Check if the skill is currently on cooldown.r   )rE   r&   s     r   is_on_cooldownCooldownSkill.is_on_cooldownM   s      (1,,r   c                :    U R                  XR                  5        g)zStart the cooldown timer.N)rJ   rA   r&   s     r   start_cooldownCooldownSkill.start_cooldownQ   s    &"3"34r   c                \    U R                  U5      nUS:  a  U R                  XS-
  5        gg)zReduce cooldown by 1.r   r   N)rE   rJ   )r   r   cds      r   tick_cooldownCooldownSkill.tick_cooldownU   s0    v&6f1f- r   c                &    U R                  U5        g)z Tick the cooldown at turn start.N)rT   r   s      r   r#   CooldownSkill.on_turn_start[   s    6"r   r   Nr   r/   r0   r   r   r/   rI   r   r0   r3   r5   r   r/   r0   r3   r2   )r7   r8   r9   r:   r;   rA   r<   rE   rJ   rM   rP   rT   r#   r=   r   r   r   r?   r?   @   s-    0L#<6-5.#r   r?   c                  x    \ rS rSr% SrSrS\S'   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rg)	BuffSkill`   z4Base class for skills that provide a temporary buff.r   r   durationc                N    UR                   R                  U R                  S5      $ )zGet remaining active turns.r   )skill_activerD   r   r&   s     r   
get_activeBuffSkill.get_activee   s    ""&&t}}a88r   c                4    X!R                   U R                  '   g)zSet active turns.N)r`   r   rH   s      r   
set_activeBuffSkill.set_activei   s    -2DMM*r   c                *    U R                  U5      S:  $ )z&Check if the buff is currently active.r   )ra   r&   s     r   	is_activeBuffSkill.is_activem   s    v&**r   c                \    U R                  XR                  5        U R                  U5        g)z%Activate the buff and start cooldown.N)rd   r^   rP   r&   s     r   activateBuffSkill.activateq   s     .F#r   c                    U R                  U5      nUS:  aC  U R                  X#S-
  5        US-
  S:X  a&  UR                  SUR                  U R                  S9  gg)z?Reduce active duration by 1. Returns True if buff just expired.r   r   zpirates-buff-expiredr   skillTF)ra   rd   broadcast_lr   )r   r   r   actives       r   tick_activeBuffSkill.tick_activev   sY    (A:OOFQJ/zQ  !7SWS\S\ ]r   c                H    U R                  X5        U R                  U5        g)z5Tick both active duration and cooldown at turn start.N)rq   rT   r   s      r   r#   BuffSkill.on_turn_start   s    &6"r   c                6   U R                  U5      (       d  SSU R                   34$ U R                  U5      (       a#  SU R                   SU R	                  U5       S34$ U R                  U5      (       a#  SU R                   SU R                  U5       S34$ g)z)Check if the buff skill can be activated.FRequires level z is already active (z turns remaining)z is on cooldown ( turns)TN)r+   r   rg   r   ra   rM   rE   r   s      r   r   BuffSkill.can_perform   s    ''OD,?,?+@AAA>>&!!99+1$//&2I1JJ[\  v&&TYYK'89J9J69R8SSZ[[[r   c                    U R                  U5      (       a!  U R                   SU R                  U5       S3$ U R                  U5      (       a!  U R                   SU R	                  U5       S3$ U R                   S3$ )z&Get dynamic menu label showing status.z
 (active: rw   z (cooldown: z (activate))rg   r   ra   rM   rE   r&   s     r   r'   BuffSkill.get_menu_label   sw    >>&!!ii[
4??6+B*C7KKv&&ii[T->->v-F,GwOO))K((r   r   NrX   rY   r5   rZ   )r   r.   r   r/   r0   r6   r2   r-   r4   )r7   r8   r9   r:   r;   r^   r<   ra   rd   rg   rj   rq   r#   r   r'   r=   r   r   r   r\   r\   `   s7    >Hc93+$
#
)r   r\   c                  <    \ rS rSrSrSrSrSrSrSS jr	SS jr
S	rg
)CannonballSkill   z/Cannonball Shot - Attack a player within range.zCannonball ShotzJFire a cannonball at a player within 5 tiles (10 with Double Devastation).r   
cannonballc                &    UR                   U:w  a  gg)N)FzNot your turnrx   )current_playerr   s      r   r   CannonballSkill.can_perform   s    &()r   c                $    UR                  U5      $ N)handle_cannonball_attackr   s      r   r    CannonballSkill.do_action   s    ,,V44r   r   Nr-   r1   r7   r8   r9   r:   r;   r   r   r   r   r   r    r=   r   r   r   r}   r}      s#    9D^KNH
5r   r}   c                  <    \ rS rSrSrSrSrSrSrSS jr	SS jr
S	rg
)SailorsInstinctSkill   z0Sailor's Instinct - Show map sector information.zSailor's Instinctz0Shows map sector information and charted status.
   instinctc                R    U R                  U5      (       d  SSU R                   34$ g)NFrv   rx   )r+   r   r   s      r   r    SailorsInstinctSkill.can_perform   s/    ''OD,?,?+@AAAr   c                  ^ [         R                  " SS5      nTR                  SU S3SS9  UR                  S-
  S-  nU[	        TR
                  5      :  a  TR
                  U   OSnS	UR                   S
U 3SS/n[        SS5       Hi  nUS-
  S-  S-   nUS-  n	[        U4S j[        XS-   5       5       5      n
U
S:X  a  SnOU
S:  a  SU
 S3nOSnUR                  SU SU SU	 SU 35        Mk     TR                  X&5        g)Nr      zgame_pirates/instinct.ogg<   volumer   UnknownzYour position: z in r   zMap Sectors:	      c              3  n   >#    U  H*  nTR                   R                  US 5      (       d  M&  Sv   M,     g7f)Fr   N)charted_tilesrD   ).0ir   s     r   	<genexpr>1SailorsInstinctSkill.do_action.<locals>.<genexpr>   s.       >a$BTBTBXBXYZ\aBb>s   %5	5zFully chartedr   zPartially charted (z/5)	UnchartedzSector z (-z): continue)
randomrandint
play_soundpositionlenselected_oceansrangesumappend
status_box)r   r   r   	sound_numocean_index
ocean_namelinessectorsector_start
sector_endcharted_countstatuss    `          r   r    SailorsInstinctSkill.do_action   s9   NN1a(	/	{$?K*r1 S!5!566   - 	 #6??"34
|Db.YAqkF"QJ!+a/L!J   A~>  M !(".}oSA$LL76("\N!J<s6(ST "  	&r   r   Nr-   r1   r   r   r   r   r   r      s#    :DDKNH
r   r   c                  J    \ 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rg)PortalSkill   z9Portal - Teleport to an ocean occupied by another player.PortalzETeleport to a random position in an ocean occupied by another player.   portal   c                    U R                  U5      (       d  SSU R                   34$ U R                  U5      (       a  SSU R                  U5       S34$ g)NFrv   zPortal is on cooldown (rw   rx   )r+   r   rM   rE   r   s      r   r   PortalSkill.can_perform   sa    ''OD,?,?+@AAAv&&3D4E4Ef4M3NgVVVr   c                Z    U R                  U5      (       a  SU R                  U5       S3$ g)NzPortal (cooldown: rw   z#Portal (teleport to occupied ocean)rM   rE   r&   s     r   r'   PortalSkill.get_menu_label   s1    v&&'(9(9&(A'B'JJ4r   c                $    UR                  X 5      $ r   )handle_portalr   s      r   r    PortalSkill.do_action   s    !!&//r   r   Nr-   r4   r1   r7   r8   r9   r:   r;   r   r   r   r   rA   r   r'   r    r=   r   r   r   r   r      s-    CDYKNHL5
0r   r   c                  ^    \ 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rg)GemSeekerSkill   z8Gem Seeker - Reveal the location of one uncollected gem.z
Gem SeekerzHReveals the location of one uncollected gem. Limited to 3 uses per game.(   
gem_seekerr   c                b    UR                   R                  U R                  U R                  5      $ )z4Get remaining uses. Defaults to max_uses if not set.)
skill_usesrD   r   max_usesr&   s     r   get_usesGemSeekerSkill.get_uses  s#      $$T]]DMMBBr   c                4    X!R                   U R                  '   g)zSet remaining uses.N)r   r   rH   s      r   set_usesGemSeekerSkill.set_uses  s    +0$--(r   c                ~    U R                  U5      (       d  SSU R                   34$ U R                  U5      S::  a  gg)NFrv   r   )FzNo uses remainingrx   )r+   r   r   r   s      r   r   GemSeekerSkill.can_perform	  sC    ''OD,?,?+@AAA== A%-r   c                >    U R                  U5      nUS::  a  gSU S3$ )Nr   zGem Seeker (no uses remaining)zGem Seeker (z uses left))r   )r   r   usess      r   r'   GemSeekerSkill.get_menu_label  s)    }}V$193dV;//r   c           	        U R                  X R                  U5      S-
  5        [        R                  " SS5      nUR	                  SU S3SS9  SSKJn  UR                  R                  5        HY  u  pVUS:w  d  M  UR                  US	5      nUR                  U5      nU(       a"  UR                  S
UUU R                  U5      SS9    g   g)Nr   r   zgame_pirates/gemseekerr   r   r   )	GEM_NAMESzunknown gemzpirates-gem-seeker-revealtable)gemr   r   bufferr   )r   r   r   r   r   gemsr   gem_positionsitemsrD   get_userspeak_l)	r   r   r   r   r   posgem_typegem_nameusers	            r   r    GemSeekerSkill.do_action  s    fmmF3a78NN1a(	04@L#!//557MC2~$===A}}V,LL3$!$!]]62& !   8 r   r   NrX   rY   r-   r4   r1   )r7   r8   r9   r:   r;   r   r   r   r   r   r   r   r   r'   r    r=   r   r   r   r   r      s8    BD\KNHHC10r   r   c                  >    \ 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rg)SwordFighterSkilli/  z,Sword Fighter - +4 attack bonus for 3 turns.zSword Fighterz#Grants +4 attack bonus for 3 turns.r   sword_fighter   r      c                   U R                  U5        UR                  SSS9  UR                  U5      nU(       a   UR                  SU R	                  U5      SS9  UR                  SUR                  U R                  US9  g	)
Nzgame_pirates/swordfighter.oggr   r   zpirates-sword-fighter-activatedr   turnsr   pirates-skill-activatedr   rn   excludeend_turnrj   r   r   r   ra   ro   r   r   r   r   r   s       r   r    SwordFighterSkill.do_action:  s    f7C}}V$LL1oof-  
 	%fkkTZ 	 	
 r   r   Nr1   )r7   r8   r9   r:   r;   r   r   r   r   rA   r^   attack_bonusr    r=   r   r   r   r   r   /  s-    6D7KNHLHLr   r   c                  >    \ 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rg)	PushSkilliL  z$Push - +3 defense bonus for 4 turns.Pushz$Grants +3 defense bonus for 4 turns.K   pushr   r   r   c                8   U R                  U5        [        R                  " SS5      nUR                  SU S3SS9  UR	                  U5      nU(       a   UR                  SU R                  U5      SS	9  UR                  S
UR                  U R                  US9  g)Nr   r   zgame_pirates/pushr   r   r   zpirates-push-activatedr   r   r   r   r   )	rj   r   r   r   r   r   ra   ro   r   )r   r   r   r   r   s        r   r    PushSkill.do_actionW  s    fNN1a(	+I;d;BG}}V$LL19PY`La%fkkTZ 	 	
 r   r   Nr1   )r7   r8   r9   r:   r;   r   r   r   r   rA   r^   defense_bonusr    r=   r   r   r   r   r   L  s-    .D8KNHLHMr   r   c                  B    \ rS 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rg)SkilledCaptainSkillif  z7Skilled Captain - +2 attack and +2 defense for 4 turns.zSkilled Captainz,Grants +2 attack and +2 defense for 4 turns.Z   skilled_captainr   r   r   c                   U R                  U5        UR                  SSS9  UR                  U5      nU(       a   UR                  SU R	                  U5      SS9  UR                  SUR                  U R                  US9  g	)
Nzgame_pirates/skilledcaptain.oggr   r   z!pirates-skilled-captain-activatedr   r   r   r   r   r   r   s       r   r    SkilledCaptainSkill.do_actionr  s    f9"E}}V$LL3oof-  
 	%fkkTZ 	 	
 r   r   Nr1   )r7   r8   r9   r:   r;   r   r   r   r   rA   r^   r   r   r    r=   r   r   r   r   r   f  s2    AD@KN HLHLMr   r   c                  J    \ 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rg)BattleshipSkilli  z.Battleship - Fire two cannonballs in one turn.
Battleshipz!Fire two cannonballs in one turn.}   
battleshipr   c                   U R                  U5      (       d  SSU R                   34$ U R                  U5      (       a  SSU R                  U5       S34$ [        R                  U5      (       a  gUR                  U5      nU(       d  gg)NFrv   zBattleship is on cooldown (rw   )Fz8Cannot use Battleship while Double Devastation is active)FzNo targets in rangerx   )r+   r   rM   rE   DOUBLE_DEVASTATIONrg   get_targets_in_range)r   r   r   targetss       r   r   BattleshipSkill.can_perform  s    ''OD,?,?+@AAAv&&78I8I&8Q7RRYZZZ ''//T ++F3/r   c                Z    U R                  U5      (       a  SU R                  U5       S3$ g)NzBattleship (cooldown: rw   zBattleship (fire extra shot)r   r&   s     r   r'   BattleshipSkill.get_menu_label  s1    v&&+D,=,=f,E+FgNN-r   c                F    U R                  U5        UR                  U5      $ r   )rP   handle_battleshipr   s      r   r    BattleshipSkill.do_action  s!    F#%%f--r   r   Nr-   r4   r1   r   r   r   r   r  r    s-    8D5KNHL".
.r   r  c                  >    \ 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rg)DoubleDevastationSkilli  zDDouble Devastation - Increases cannon range to 10 tiles for 3 turns.zDouble Devastationz/Increases cannon range to 10 tiles for 3 turns.   double_devastationr   r   r   c                   U R                  U5        UR                  SSS9  UR                  U5      nU(       a   UR                  SU R	                  U5      SS9  UR                  SUR                  U R                  US9  g	)
Nz"game_pirates/doubledevastation.oggr   r   z$pirates-double-devastation-activatedr   r   r   r   r   r   r   s       r   r     DoubleDevastationSkill.do_action  s    f<RH}}V$LL6oof-  
 	%fkkTZ 	 	
 r   r   Nr1   )r7   r8   r9   r:   r;   r   r   r   r   rA   r^   range_bonusr    r=   r   r   r   r  r    s-    NDCKN#HLHKr   r  list[Skill]
ALL_SKILLSzdict[str, Skill]SKILLS_BY_IDc                h    [          Vs/ s H  oR                  U 5      (       d  M  UPM     sn$ s  snf )z,Get list of skills unlocked for this player.)r  r+   rm   s     r   get_available_skillsr    s%    )Gze->->v-FEzGGGs   //c                @    [          H  nUR                  X5        M     g)zBCalled at the start of a player's turn to update all skill timers.N)r  r#   )r   r   rn   s      r   r#   r#     s    D) r   c                    Sn[         R                  U 5      (       a  U[         R                  -  n[        R                  U 5      (       a  U[        R                  -  nU$ )z/Calculate total attack bonus from active buffs.r   )SWORD_FIGHTERrg   r   SKILLED_CAPTAINr   bonuss     r   get_attack_bonusr&    sN    Ev&&+++  ((---Lr   c                    Sn[         R                  U 5      (       a  U[         R                  -  n[        R                  U 5      (       a  U[        R                  -  nU$ )z0Calculate total defense bonus from active buffs.r   )PUSHrg   r   r#  r$  s     r   get_defense_bonusr)    sL    E~~f###  ((...Lr   c                d    Sn[         R                  U 5      (       a  U[         R                  -   $ U$ )zEGet the current attack range (base 5, or 10 with Double Devastation).r   )r  rg   r  )r   
base_ranges     r   get_attack_ranger,    s0    J##F++.::::r   )r   r/   r0   r  r2   rX   )+r;   
__future__r   abcr   r   typingr   r   r   r   r   r	   r   r?   r\   r}   r   r   r   r   r   r   r  r  
CANNONBALLSAILORS_INSTINCTPORTAL
GEM_SEEKERr"  r(  r#  
BATTLESHIPr  r  r<   r   r  r  r#   r&  r)  r,  )rn   s   0r   <module>r5     ss  
 # #   !%!3C !3H#E #@8) 8)@5e 5"+5 +\0- 024U 4n	 :	 4) <!.m !.HY B 
') 	
!#{%'
+-  


K 
 FP!PZE..%"7Z!P PH
*O "Qs   D>