§
    ¿jRI  ã                   ó  — d Z ddlZddlmZmZmZmZ ddlmZm	Z	m
Z
mZmZmZmZ ddlmZmZmZ ddlmZmZmZ ddlmZmZmZ  G d„ d	¦  «        Z G d
„ d¦  «        Z G d„ d¦  «        Z G d„ d¦  «        Z G d„ d¦  «        ZdS )a&  
Unit Test Suite for FreeExile Map Data, Server-Authoritative War-Fog,
Procedural Generation, and Anti-Bot Dynamic Obstacle Architecture.

Tests:
1. Map Biome Catalog and Tile Types (Savage Grimdark themes, no Xianxia).
2. Procedural Map Generator (BSP + Caves, 100% connectivity spawn to boss).
3. Anti-Bot Dynamic Obstacles (Destructibles, Debris, Mud pools, Spikes).
4. Real-time Obstacle Destruction and Walkable Grid Mutation.
5. Anti-Bot Path Complexity (Sinuosity ratio >= 1.25, non-linear corridors).
6. Server-Authoritative War-Fog Engine (FOV Line of Sight, Wall obstruction).
7. Anti-Maphack Entity Visibility Filtering (Hidden entities in fog never sent).
8. Fog Delta Compression (Run-Length Encoding / Bitmask efficiency).
9. Deceptive Dead-End and Ambush Pocket generation for bot trapping.
é    N)ÚListÚTupleÚDictÚAny)ÚTileTypeÚFogStateÚObstacleTypeÚTileCellÚObstacleInstanceÚMapGridDataÚPlayerVisibilityState)Ú
MAP_BIOMESÚget_biome_definitionÚlist_available_biomes)ÚWarFogEngineÚcompress_fog_rleÚdecompress_fog_rle)ÚProceduralMapEngineÚverify_path_connectivityÚcalculate_path_sinuosityc                   ó   — e Zd Zd„ Zd„ ZdS )ÚTestMapBiomeCatalogc                 ó  — t          ¦   «         }t          |¦  «        dk    sJ ‚g d¢}|D ]a}||v sJ ‚t          |¦  «        }|j        |k    sJ ‚|j        dk    sJ ‚t          |j        ¦  «        dk    sJ ‚d|j        vsJ ‚d|j        vsJ ‚ŒbdS )zJVerifies 5 canonical Savage Grimdark Biomes exist with correct attributes.é   )ÚSAVAGE_MANGROVE_SWAMPÚCRIMSON_BLOOD_FORESTÚBLEACHED_BONE_CANYONÚOUTCAST_MINE_SHAFTSÚCORRUPTED_FIEND_RUINSç      ð?é   u   TiÃªnu   Linh Tháº¡chN)r   Úlenr   Úbiome_idÚhazard_slow_factorÚobstacle_paletteÚnameÚdescription)ÚselfÚbiomesÚexpected_biomesÚbÚdefns        úCC:\Projects\FreeExile\tests\unit\test_war_fog_and_procedural_map.pyÚ)test_canonical_grimdark_biomes_registeredz=TestMapBiomeCatalog.test_canonical_grimdark_biomes_registered/   s×   € å&Ñ(Ô(ˆÝ�6‰{Œ{˜bÒ Ð Ð Ð ð
ð 
ð 
ˆð !ð 	:ð 	:ˆAØ˜�;�;�;�;Ý'¨Ñ*Ô*ˆDØ”= AÒ%Ð%Ð%Ð%ØÔ*¨cÒ1Ð1Ð1Ð1Ý�tÔ,Ñ-Ô-°Ò2Ð2Ð2Ð2à $¤)Ð+Ð+Ð+Ð+Ø!¨Ô)9Ð9Ð9Ð9Ð9Ð9ð	:ð 	:ó    c                 ó.  — t          ddt          j        dd¬¦  «        }|j        du sJ ‚|j        du sJ ‚t          ddt          j        dd¬¦  «        }|j        du sJ ‚|j        du sJ ‚t          ddt          j        ddd¬¦  «        }|j        dk    sJ ‚d	S )
z=Verifies tile cell attributes for floors, walls, and hazards.é   r!   TF©ÚxÚyÚ	tile_typeÚwalkableÚblocks_visioné   g       @)r3   r4   r5   r6   r7   Úmovement_costN)r
   r   ÚFLOORr6   r7   ÚWALLÚMUD_POOLr9   )r(   ÚfloorÚwallÚmuds       r-   Útest_tile_cell_attributesz-TestMapBiomeCatalog.test_tile_cell_attributesD   sÈ   € å˜1 ­X¬^ÀdÐZ_Ð`Ñ`Ô`ˆØŒ~ Ð%Ð%Ð%Ð%ØÔ" eÐ+Ð+Ð+Ð+å˜!˜q­H¬MÀEÐY]Ð^Ñ^Ô^ˆØŒ} Ð%Ð%Ð%Ð%ØÔ! TÐ)Ð)Ð)Ð)åØ�1¥Ô 1¸DÐPUÐehð
ñ 
ô 
ˆð Ô  CÒ'Ð'Ð'Ð'Ð'Ð'r/   N)Ú__name__Ú
__module__Ú__qualname__r.   r@   © r/   r-   r   r   .   s2   € € € € € ð:ð :ð :ð*(ð (ð (ð (ð (r/   r   c                   ó   — e Zd Zd„ Zd„ ZdS )ÚTestProceduralMapGenerationc                 ó�  — t          dd¬¦  «        }|                     dd¬¦  «        }|                     dd¬¦  «        }|j        |j        cxk    rdk    sn J ‚|j        |j        cxk    rdk    sn J ‚|j        |j        k    sJ ‚|j        |j        k    sJ ‚t          |j        ¦  «        t          |j        ¦  «        k    sJ ‚dS )z0Same seed must produce identical dungeon layout.é0   ©ÚwidthÚheighti90  r   ©Úseedr#   N)r   Úgenerate_maprJ   rK   Úspawn_pointÚ
boss_pointr"   Ú	obstacles)r(   ÚengineÚmap_aÚmap_bs       r-   Ú'test_deterministic_generation_with_seedzCTestProceduralMapGeneration.test_deterministic_generation_with_seedU   sñ   € å$¨2°bÐ9Ñ9Ô9ˆØ×#Ò#¨Ð9OÐ#ÑPÔPˆØ×#Ò#¨Ð9OÐ#ÑPÔPˆàŒ{˜eœkÐ/Ð/Ò/Ð/¨RÒ/Ð/Ð/Ð/Ð/Ð/ØŒ|˜uœ|Ð1Ð1Ò1Ð1¨rÒ1Ð1Ð1Ð1Ð1Ð1ØÔ  EÔ$5Ò5Ð5Ð5Ð5ØÔ 5Ô#3Ò3Ð3Ð3Ð3Ý�5”?Ñ#Ô#¥s¨5¬?Ñ';Ô';Ò;Ð;Ð;Ð;Ð;Ð;r/   c                 óÒ   — t          dd¬¦  «        }dD ]R}|                     |d¬¦  «        }t          ||j        |j        ¦  «        \  }}|du sJ ‚t          |¦  «        dk    sJ ‚ŒSdS )	z?Verifies 100% path connectivity from spawn point to boss arena.rH   rI   )éo   éÞ   iM  i¼  r   rL   Té   N)r   rN   r   rO   rP   r"   )r(   rR   rM   Úmap_dataÚ	connectedÚpaths         r-   Ú*test_guaranteed_connectivity_spawn_to_bosszFTestProceduralMapGeneration.test_guaranteed_connectivity_spawn_to_bossa   sŽ   € å$¨2°bÐ9Ñ9Ô9ˆØ(ð 	!ð 	!ˆDØ×*Ò*°Ð?UÐ*ÑVÔVˆHÝ6Ø˜(Ô.°Ô0Cñô ‰OˆI�tð  Ð$Ð$Ð$Ð$Ý�t‘9”9˜q’=�=�=�=�=ð	!ð 	!r/   N)rA   rB   rC   rU   r]   rD   r/   r-   rF   rF   T   s2   € € € € € ð
<ð 
<ð 
<ð	!ð 	!ð 	!ð 	!ð 	!r/   rF   c                   ó&   — e Zd Zd„ Zd„ Zd„ Zd„ ZdS )ÚTestAntiBotDynamicObstaclesc                 ób  — t          dd¬¦  «        }|                     dd¬¦  «        }t          |j        ¦  «        dk    sJ ‚t	          d„ |j                             ¦   «         D ¦   «         ¦  «        }t	          d„ |j                             ¦   «         D ¦   «         ¦  «        }|d	u sJ ‚|d	u sJ ‚d
S )zNVerifies that dynamic anti-bot obstacles are placed to break linear corridors.rH   rI   iÍ� r   rL   r   c              3   ó@   K  — | ]}|j         t          j        k    V — Œd S ©N)Úobstacle_typer	   ÚBARRICADE_WOOD_BONE©Ú.0Úobss     r-   ú	<genexpr>zVTestAntiBotDynamicObstacles.test_obstacle_injection_along_corridors.<locals>.<genexpr>t   sA   è è € ð 
ð 
àð Ô¥Ô!AÒAð
ð 
ð 
ð 
ð 
ð 
r/   c              3   ój   K  — | ].}|j         t          j        t          j        t          j        fv V — Œ/d S rb   )rc   r	   ÚDEBRIS_COLLAPSEÚMUD_QUAGMIREÚBONE_CLUSTERre   s     r-   rh   zVTestAntiBotDynamicObstacles.test_obstacle_injection_along_corridors.<locals>.<genexpr>x   sO   è è € ð  
ð  
àð Ô¥,Ô">ÅÔ@YÕ[gÔ[tÐ!uÐuð 
ð  
ð  
ð  
ð  
ð  
r/   TN)r   rN   r"   rQ   ÚanyÚvalues)r(   rR   rZ   Úhas_destructibleÚhas_debris_or_muds        r-   Ú'test_obstacle_injection_along_corridorszCTestAntiBotDynamicObstacles.test_obstacle_injection_along_corridorsn   së   € å$¨2°bÐ9Ñ9Ô9ˆØ×&Ò&¨EÐ<QÐ&ÑRÔRˆå�8Ô%Ñ&Ô&¨Ò*Ð*Ð*Ð*Ýð 
ð 
àÔ)×0Ò0Ñ2Ô2ð
ñ 
ô 
ñ 
ô 
Ðõ  ð  
ð  
àÔ)×0Ò0Ñ2Ô2ð 
ñ  
ô  
ñ 
ô 
Ðð   4Ð'Ð'Ð'Ð'Ø  DÐ(Ð(Ð(Ð(Ð(Ð(r/   c                 ó   — t          dd¬¦  «        }|                     dd¬¦  «        }d}|j                             ¦   «         D ]\  }}|j        t
          j        k    r|} nŒ|€J ‚|\  }}|                     ||¦  «        du sJ ‚|                     |||d¬	¦  «        \  }}	|du sJ ‚|	d
k    sJ ‚|                     ||¦  «        du sJ ‚|                     |||d¬	¦  «        \  }}	|du sJ ‚|	d
k    sJ ‚|                     ||¦  «        du sJ ‚dS )zQVerifies attacking a destructible barricade reduces HP and updates walkable grid.é    rI   é*   r   rL   NFé(   )Údamager   éd   T)	r   rN   rQ   Úitemsrc   r	   rd   Úis_walkableÚdamage_obstacle)
r(   rR   rZ   Úbarricade_coordÚcoordrg   ÚbxÚbyÚ	destroyedÚremaining_hps
             r-   Ú!test_attack_and_destroy_barricadez=TestAntiBotDynamicObstacles.test_attack_and_destroy_barricade   sƒ  € å$¨2°bÐ9Ñ9Ô9ˆØ×&Ò&¨BÐ9NÐ&ÑOÔOˆð ˆØ"Ô,×2Ò2Ñ4Ô4ð 	ð 	‰JˆE�3ØÔ ¥LÔ$DÒDÐDØ"'�Ø�ð Eð Ð*Ð*Ð*Ø ‰ˆˆBØ×#Ò# B¨Ñ+Ô+¨uÐ4Ð4Ð4Ð4ð #)×"8Ò"8¸À2ÀrÐRTÐ"8Ñ"UÔ"UÑˆ	�<Ø˜EÐ!Ð!Ð!Ð!Ø˜aÒÐÐÐØ×#Ò# B¨Ñ+Ô+¨uÐ4Ð4Ð4Ð4ð #)×"8Ò"8¸À2ÀrÐRUÐ"8Ñ"VÔ"VÑˆ	�<Ø˜DÐ Ð Ð Ð Ø˜qÒ Ð Ð Ð Ø×#Ò# B¨Ñ+Ô+¨tÐ3Ð3Ð3Ð3Ð3Ð3r/   c                 óØ   — t          dd¬¦  «        }|                     dd¬¦  «        }t          ||j        |j        ¦  «        \  }}t          ||j        |j        ¦  «        }|dk    sJ ‚dS )zMVerifies path between spawn and boss is non-linear (sinuosity ratio >= 1.25).rH   rI   é	  r   rL   g      ô?N)r   rN   r   rO   rP   r   )r(   rR   rZ   Ú_r\   Ú	sinuositys         r-   Ú'test_anti_bot_sinuosity_path_complexityzCTestAntiBotDynamicObstacles.test_anti_bot_sinuosity_path_complexity›   sv   € å$¨2°bÐ9Ñ9Ô9ˆØ×&Ò&¨CÐ:QÐ&ÑRÔRˆÝ*¨8°XÔ5IÈ8ÔK^Ñ_Ô_‰ˆˆ4Ý,¨T°8Ô3GÈÔI\Ñ]Ô]ˆ	Ø˜DÒ Ð Ð Ð Ð Ð r/   c                 óŠ   — t          dd¬¦  «        }|                     dd¬¦  «        }t          |j        ¦  «        dk    sJ ‚dS )zLVerifies deceptive branch dead-ends are created to deter naive pathing bots.rH   rI   i+  r   rL   r!   N)r   rN   r"   Údead_end_points)r(   rR   rZ   s      r-   Ú"test_deceptive_dead_ends_generatedz>TestAntiBotDynamicObstacles.test_deceptive_dead_ends_generated£   sO   € å$¨2°bÐ9Ñ9Ô9ˆØ×&Ò&¨CÐ:QÐ&ÑRÔRˆÝ�8Ô+Ñ,Ô,°Ò1Ð1Ð1Ð1Ð1Ð1r/   N)rA   rB   rC   rq   r�   r†   r‰   rD   r/   r-   r_   r_   m   sP   € € € € € ð)ð )ð )ð"4ð 4ð 4ð8!ð !ð !ð2ð 2ð 2ð 2ð 2r/   r_   c                   ó2   — e Zd Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ ZdS )ÚTestServerAuthoritativeWarFogc                 óÖ   — t          ¦   «         }|                     ddd¬¦  «        }|j        dk    sJ ‚|j        dk    sJ ‚|j        d         d         t
          j        j        k    sJ ‚dS )z7New visibility state begins with 100% unexplored tiles.Úp_testerrs   ©Ú	player_idrJ   rK   r   é
   N)r   Úcreate_player_visibilityÚexplored_tiles_countÚvisible_tiles_countÚ
fog_matrixr   Ú
UNEXPLOREDÚvalue)r(   Ú
fog_engineÚviss      r-   Ú%test_initial_fog_state_all_unexploredzCTestServerAuthoritativeWarFog.test_initial_fog_state_all_unexplored«   sw   € å!‘^”^ˆ
Ø×1Ò1¸JÈbÐY[Ð1Ñ\Ô\ˆØÔ'¨1Ò,Ð,Ð,Ð,ØÔ&¨!Ò+Ð+Ð+Ð+ØŒ~˜bÔ! "Ô%­Ô)<Ô)BÒBÐBÐBÐBÐBÐBr/   c                 ó>  ‡
— t          dd¬¦  «        }|                     dd¬¦  «        }t          ¦   «         }|                     ddd¬¦  «        Š
|j        \  }}|                     ‰
|||d¬	¦  «         ‰
j        |         |         t          j        j	        k    sJ ‚‰
j
        d
k    sJ ‚‰
j        ‰
j
        k    sJ ‚ˆ
fd„t          d¦  «        D ¦   «         }|j        \  }}|                     ‰
|||d¬	¦  «         t          ˆ
fd„|D ¦   «         ¦  «        }	|	d
k    sJ ‚dS )zBField of view expands around player and is blocked by solid walls.rs   rI   éç  r   rL   Úp_herorŽ   r�   )Úplayer_xÚplayer_yÚview_radiusr   c                 óˆ   •— g | ]>}t          d ¦  «        D ],}‰j        |         |         t          j        j        k    ¯(||f‘Œ-Œ?S )rs   )Úranger”   r   ÚVISIBLEr–   )rf   r4   r3   r˜   s      €r-   ú
<listcomp>zXTestServerAuthoritativeWarFog.test_fov_computation_and_wall_blocking.<locals>.<listcomp>Ã   sa   ø€ ð 
ð 
ð 
àÝ˜2‘Y”Yð
ð 
ð ØŒ~˜aÔ  Ô#¥xÔ'7Ô'=Ò=Ð=ð �ˆFð >Ð=Ð=Ð=r/   c              3   ón   •K  — | ]/\  }}‰j         |         |         t          j        j        k    ¯+d V — Œ0dS )r1   N)r”   r   ÚEXPLORED_FOGGEDr–   )rf   r3   r4   r˜   s      €r-   rh   zWTestServerAuthoritativeWarFog.test_fov_computation_and_wall_blocking.<locals>.<genexpr>Í   sL   øè è € ð  
ð  
Ù�1�a°´ÀÔ1BÀ1Ô1EÍÔIaÔIgÒ1gÐ1gˆAÐ1gÐ1gÐ1gÐ1gð 
ð  
r/   N)r   rN   r   r‘   rO   Úupdate_visibilityr”   r   r¢   r–   r“   r’   r¡   rP   Úsum)r(   rR   rZ   r—   ÚsxÚsyÚold_visible_cellsr}   r~   Údemoted_to_foggedr˜   s             @r-   Ú&test_fov_computation_and_wall_blockingzDTestServerAuthoritativeWarFog.test_fov_computation_and_wall_blocking³   s|  ø€ å$¨2°bÐ9Ñ9Ô9ˆØ×&Ò&¨CÐ:PÐ&ÑQÔQˆÝ!‘^”^ˆ
Ø×1Ò1¸HÈBÐWYÐ1ÑZÔZˆàÔ%‰ˆˆBØ×$Ò$ S¨(¸RÈ"ÐZ\Ð$Ñ]Ô]Ð]ð Œ~˜bÔ! "Ô%­Ô)9Ô)?Ò?Ð?Ð?Ð?ØÔ&¨Ò*Ð*Ð*Ð*ØÔ'¨3Ô+BÒBÐBÐBÐBð
ð 
ð 
ð 
å˜2‘Y”Yð
ñ 
ô 
Ðð Ô$‰ˆˆBØ×$Ò$ S¨(¸RÈ"ÐZ\Ð$Ñ]Ô]Ð]õ  ð  
ð  
ð  
ð  
Ø-ð 
ñ  
ô  
ñ 
ô 
Ðð ! 1Ò$Ð$Ð$Ð$Ð$Ð$r/   c                 ó²  — t          ¦   «         }|                     ddd¬¦  «        }t          j        j        |j        d         d<   t          j        j        |j        d         d<   t          j        j        |j        d         d<   ddddd	œd
dddd	œddddd	œg}|                     ||¦  «        }t          |¦  «        dk    sJ ‚|d         d         dk    sJ ‚dS )zLServer strictly filters out entities outside player's VISIBLE field of view.Ú	p_stealthrs   rŽ   rY   é   é   Úmob_nearÚMONSTER)Úidr3   r4   ÚtypeÚchest_in_fogÚCHESTÚboss_unexploredÚBOSSr1   r   r³   N)
r   r‘   r   r¢   r–   r”   r¥   r•   Úfilter_visible_entitiesr"   )r(   r—   r˜   Úall_entitiesÚfiltereds        r-   Ú"test_anti_maphack_entity_filteringz@TestServerAuthoritativeWarFog.test_anti_maphack_entity_filteringÒ   sñ   € å!‘^”^ˆ
Ø×1Ò1¸KÈrÐZ\Ð1Ñ]Ô]ˆõ  (Ô/Ô5ˆŒ�qÔ˜!ÑÝ!)Ô!9Ô!?ˆŒ�rÔ˜2ÑÝ!)Ô!4Ô!:ˆŒ�rÔ˜2Ñð  A¨A°yÐAÐAØ!¨°¸WÐEÐEØ$¨2°BÀÐGÐGð
ˆð ×5Ò5°c¸<ÑHÔHˆå�8‰}Œ} Ò!Ð!Ð!Ð!Ø˜Œ{˜4Ô  JÒ.Ð.Ð.Ð.Ð.Ð.r/   c                 ó|  — d„ t          d¦  «        D ¦   «         }t          dd¦  «        D ] }t          dd¦  «        D ]}d||         |<   ŒŒ!t          dd¦  «        D ] }t          dd¦  «        D ]}d||         |<   ŒŒ!t          |¦  «        }t          |t          ¦  «        sJ ‚t	          |dd¬¦  «        }||k    sJ ‚d	S )
zBFog matrix can be compressed with RLE and decompressed losslessly.c                 ó   — g | ]}d gdz  ‘Œ	S )r   é   rD   ©rf   r„   s     r-   r£   zJTestServerAuthoritativeWarFog.test_fog_rle_compression.<locals>.<listcomp>é   s   € Ð.Ð.Ð.˜q�1�#˜‘(Ð.Ð.Ð.r/   r¿   é   é   r!   é   r1   rI   N)r¡   r   Ú
isinstanceÚstrr   )r(   Úmatrixr4   r3   Ú
compressedÚdecompresseds         r-   Útest_fog_rle_compressionz6TestServerAuthoritativeWarFog.test_fog_rle_compressionç   sï   € à.Ð.¥E¨"¡I¤IÐ.Ñ.Ô.ˆÝ�q˜!‘”ð 	!ð 	!ˆAÝ˜1˜a‘[”[ð !ð !�Ø ��q”	˜!‘�ð!å�q˜"‘”ð 	!ð 	!ˆAÝ˜1˜a‘[”[ð !ð !�Ø ��q”	˜!‘�ð!õ & fÑ-Ô-ˆ
Ý˜*¥cÑ*Ô*Ð*Ð*Ð*Ý)¨*¸BÀrÐJÑJÔJˆØ˜vÒ%Ð%Ð%Ð%Ð%Ð%r/   c                 ó~  — t          ddd¬¦  «        d„ t          d¦  «        D ¦   «         k    sJ ‚t          ddd¬¦  «        d„ t          d¦  «        D ¦   «         k    sJ ‚t          ddd¬¦  «        d„ t          d¦  «        D ¦   «         k    sJ ‚t          d	dd¬¦  «        d
„ t          d¦  «        D ¦   «         k    sJ ‚dS )zQMalformed RLE input or dimension mismatch gracefully returns safe default matrix.Ú rÂ   rI   c                 ó   — g | ]}d gdz  ‘Œ	S ©r   rÂ   rD   rÀ   s     r-   r£   z[TestServerAuthoritativeWarFog.test_fog_rle_decompression_error_handling.<locals>.<listcomp>ù   s   € Ð<WÐ<WÐ<WÈ¸a¸SÀ1¹WÐ<WÐ<WÐ<Wr/   Ú	bad_tokenc                 ó   — g | ]}d gdz  ‘Œ	S rÍ   rD   rÀ   s     r-   r£   z[TestServerAuthoritativeWarFog.test_fog_rle_decompression_error_handling.<locals>.<listcomp>û   s   € ÐE`ÐE`ÐE`ÐRSÀqÀcÈAÁgÐE`ÐE`ÐE`r/   Úaxbc                 ó   — g | ]}d gdz  ‘Œ	S rÍ   rD   rÀ   s     r-   r£   z[TestServerAuthoritativeWarFog.test_fog_rle_decompression_error_handling.<locals>.<listcomp>ý   s   € Ð?ZÐ?ZÐ?ZÈAÀÀÀaÁÐ?ZÐ?ZÐ?Zr/   Ú0x10c                 ó   — g | ]}d gdz  ‘Œ	S rÍ   rD   rÀ   s     r-   r£   z[TestServerAuthoritativeWarFog.test_fog_rle_decompression_error_handling.<locals>.<listcomp>ÿ   s   € Ð@[Ð@[Ð@[ÈQÀ!ÀÀqÁÐ@[Ð@[Ð@[r/   N)r   r¡   )r(   s    r-   Ú)test_fog_rle_decompression_error_handlingzGTestServerAuthoritativeWarFog.test_fog_rle_decompression_error_handlingö   së   € õ " "¨A°aÐ8Ñ8Ô8Ð<WÐ<WÍeÐTUÉhÌhÐ<WÑ<WÔ<WÒWÐWÐWÐWå! +°Q¸qÐAÑAÔAÐE`ÐE`ÕW\Ð]^ÑW_ÔW_ÐE`ÑE`ÔE`Ò`Ð`Ð`Ð`å! %¨q¸Ð;Ñ;Ô;Ð?ZÐ?ZÕQVÐWXÑQYÔQYÐ?ZÑ?ZÔ?ZÒZÐZÐZÐZå! &°¸!Ð<Ñ<Ô<Ð@[Ð@[ÕRWÐXYÑRZÔRZÐ@[Ñ@[Ô@[Ò[Ð[Ð[Ð[Ð[Ð[r/   c                 ó@  — t          dd¬¦  «        }d„ t          d¦  «        D ¦   «         }|                     |ddddd¬¦  «         t          dd¦  «        D ]}||         |         j        d	u sJ ‚Œ|d         d         j        d
u sJ ‚|d         d         j        d
u sJ ‚dS )zP_carve_line carves clean corridor without creating accidental rectangular rooms.r¿   rI   c                 óF   ‡— g | ]Šˆfd „t          d¦  «        D ¦   «         ‘ŒS )c           	      óL   •— g | ] }t          |‰t          j        d d¬¦  «        ‘Œ!S )FTr2   )r
   r   r;   )rf   r3   r4   s     €r-   r£   zVTestServerAuthoritativeWarFog.test_carve_line_bresenham.<locals>.<listcomp>.<listcomp>  s0   ø€ ÐpÐpÐpÐab�X˜˜Q­(¬-À%ÐW[Ð\Ñ\Ô\ÐpÐpÐpr/   r¿   )r¡   )rf   r4   s    @r-   r£   zKTestServerAuthoritativeWarFog.test_carve_line_bresenham.<locals>.<listcomp>  sH   ø€ ð 
ð 
ð 
àð qÐpÐpÐpÕfkÐlnÑfoÔfoÐpÑpÔpð
ð 
ð 
r/   r!   r�   r1   )rJ   é   TFN)r   r¡   Ú_carve_liner6   )r(   rR   ÚtilesÚis       r-   Útest_carve_line_bresenhamz7TestServerAuthoritativeWarFog.test_carve_line_bresenham  sÏ   € å$¨2°bÐ9Ñ9Ô9ˆð
ð 
å˜2‘Y”Yð
ñ 
ô 
ˆð
 	×Ò˜5 ! Q¨¨B°aÐÑ8Ô8Ð8å�q˜"‘”ð 	0ð 	0ˆAØ˜”8˜A”;Ô'¨4Ð/Ð/Ð/Ð/Ð/à�QŒx˜Œ|Ô$¨Ð-Ð-Ð-Ð-Ø�RŒy˜Œ|Ô$¨Ð-Ð-Ð-Ð-Ð-Ð-r/   N)	rA   rB   rC   r™   r¬   r¼   rÉ   rÔ   rÜ   rD   r/   r-   r‹   r‹   ª   st   € € € € € ðCð Cð Cð%ð %ð %ð>/ð /ð /ð*&ð &ð &ð	\ð 	\ð 	\ð.ð .ð .ð .ð .r/   r‹   c                   ó2   — e Zd Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ ZdS )Ú!TestGrandBossArenaAndMapExpansionc                 ór  — dD ]³}t          ||¬¦  «        }|                     d|z   d¬¦  «        }|j        |k    sJ ‚|j        |k    sJ ‚t	          |j        ¦  «        dk    sJ ‚|j        €J ‚|j        j        du sJ ‚t          ||j	        |j
        ¦  «        \  }}|du sJ ‚t	          |¦  «        d	k    sJ ‚Œ´dS )
zQVerifies procedural map engine dynamically scales for 32x32, 48x48, 64x64, 80x80.©rs   rH   é@   éP   rI   rt   r   rL   rÁ   NTrY   )r   rN   rJ   rK   r"   ÚroomsÚ	boss_roomÚis_boss_roomr   rO   rP   )r(   ÚdimrR   rZ   r[   r\   s         r-   Ú)test_scalable_map_dimensions_optimizationzKTestGrandBossArenaAndMapExpansion.test_scalable_map_dimensions_optimization  só   € à#ð 	!ð 	!ˆCÝ(¨s¸3Ð?Ñ?Ô?ˆFØ×*Ò*°°S±ÐCYÐ*ÑZÔZˆHØ”> SÒ(Ð(Ð(Ð(Ø”? cÒ)Ð)Ð)Ð)Ý�x”~Ñ&Ô&¨!Ò+Ð+Ð+Ð+ØÔ%Ð1Ð1Ð1ØÔ%Ô2°dÐ:Ð:Ð:Ð:å6°xÀÔAUÐW_ÔWjÑkÔk‰OˆI�tØ Ð$Ð$Ð$Ð$Ý�t‘9”9˜q’=�=�=�=�=ð	!ð 	!r/   c                 óê  ‡‡	‡
— t          dd¬¦  «        }|                     dd¬¦  «        Š
‰
j        }|€J ‚|j        dk    sJ ‚|j        du sJ ‚|j        d	k    r|j        d	k    sJ ‚|j        \  ŠŠ	‰
j        ‰	         ‰         j	        t          j        k    sJ ‚t          ˆˆ	ˆ
fd
„dD ¦   «         ¦  «        }|du sJ ‚‰
j        €J ‚‰
j        \  }}‰
j        |         |         j	        t          j        k    sJ ‚‰
j                             ||f¦  «        }|€J ‚|j        t$          j        k    sJ ‚|j        dk    sJ ‚d„ ‰
j                             ¦   «         D ¦   «         }t-          |¦  «        dk    sJ ‚dS )zVVerifies end-of-map boss room has altar, runic floor, braziers, and boss gate barrier.rH   rI   r›   r   rL   NÚbossTrÂ   c              3   ó’   •K  — | ]A}d D ]<}|dk    s|dk    ¯‰j         ‰|z            ‰|z            j        t          j        k    V — Œ=ŒBdS )©éÿÿÿÿr   r1   r   N)rÚ   r5   r   ÚRUNIC_FLOOR)rf   ÚdyÚdxÚbcxÚbcyrZ   s      €€€r-   rh   z\TestGrandBossArenaAndMapExpansion.test_grand_boss_room_arena_architecture.<locals>.<genexpr>2  sl   øè è € ð 
ð 
à¨:ð
ð 
à%'¸¸qº¸ÀBÈ!ÂGÀGð ŒN˜3 ™8Ô$ S¨2¡XÔ.Ô8½HÔ<PÒPØDKÀGÀGÀGÀGð
ð 
r/   rë   éÈ   c                 ó<   — g | ]}|j         t          j        k    ¯|‘ŒS rD   )rc   r	   ÚBONE_BRAZIERre   s     r-   r£   z]TestGrandBossArenaAndMapExpansion.test_grand_boss_room_arena_architecture.<locals>.<listcomp>B  s3   € ð 
ð 
ð 
ØØÔ ¥LÔ$=Ò=Ð=ð Ø=Ð=Ð=r/   r!   )r   rN   rä   Ú	room_typerå   ÚwÚhÚcenterrÚ   r5   r   Ú
BOSS_ALTARrm   Ú	boss_gateÚ	BOSS_GATErQ   Úgetrc   r	   ÚBOSS_SEAL_BARRIERÚhprn   r"   )r(   rR   ÚbrÚrunic_foundÚgxÚgyÚgate_obsÚbraziersrð   rñ   rZ   s           @@@r-   Ú'test_grand_boss_room_arena_architecturezITestGrandBossArenaAndMapExpansion.test_grand_boss_room_arena_architecture"  sá  øøø€ å$¨2°bÐ9Ñ9Ô9ˆØ×&Ò&¨CÐ:QÐ&ÑRÔRˆàÔˆØˆ~ˆ~ˆ~ØŒ|˜vÒ%Ð%Ð%Ð%ØŒ $Ð&Ð&Ð&Ð&ØŒt�qŠyˆy˜RœT QšY˜Y˜YÐ&ð ”9‰ˆˆSØŒ~˜cÔ" 3Ô'Ô1µXÔ5HÒHÐHÐHÐHõ ð 
ð 
ð 
ð 
ð 
ð 
à ð
ñ 
ô 
ñ 
ô 
ˆð ˜dÐ"Ð"Ð"Ð"ð Ô!Ð-Ð-Ð-ØÔ#‰ˆˆBØŒ~˜bÔ! "Ô%Ô/µ8Ô3EÒEÐEÐEÐEØÔ%×)Ò)¨2¨r¨(Ñ3Ô3ˆØÐ#Ð#Ð#ØÔ%­Ô)GÒGÐGÐGÐGØŒ{˜cÒ!Ð!Ð!Ð!ð
ð 
Ø#Ô-×4Ò4Ñ6Ô6ð
ñ 
ô 
ˆõ �8‰}Œ} Ò!Ð!Ð!Ð!Ð!Ð!r/   c                 óF  — t          dd¬¦  «        }|                     dd¬¦  «        }|j        €J ‚|j        \  }}|j        du sJ ‚|                     ||¦  «        du sJ ‚|                     |¦  «        }|du sJ ‚|j        du sJ ‚|                     ||¦  «        du sJ ‚dS )	zOVerifies breach_boss_gate unblocks the boss seal barrier and mutates map state.rH   rI   é{   r   rL   NFT)r   rN   rú   Úboss_gate_breachedry   Úbreach_boss_gate)r(   rR   rZ   r  r  Úbreacheds         r-   Útest_boss_gate_breach_mechanicz@TestGrandBossArenaAndMapExpansion.test_boss_gate_breach_mechanicH  sÞ   € å$¨2°bÐ9Ñ9Ô9ˆØ×&Ò&¨CÐ:QÐ&ÑRÔRˆàÔ!Ð-Ð-Ð-ØÔ#‰ˆˆBØÔ*¨eÐ3Ð3Ð3Ð3Ø×#Ò# B¨Ñ+Ô+¨uÐ4Ð4Ð4Ð4ð ×*Ò*¨8Ñ4Ô4ˆØ˜4ÐÐÐÐØÔ*¨dÐ2Ð2Ð2Ð2Ø×#Ò# B¨Ñ+Ô+¨tÐ3Ð3Ð3Ð3Ð3Ð3r/   c                 ó\  — t          dd¬¦  «        }|                     dd¬¦  «        }|                     dd¦  «        dk    sJ ‚|                     dd¦  «        d	k    sJ ‚|                     d
d
¦  «        dk    sJ ‚|j        }|€J ‚|j        \  }}|                     ||¦  «        du sJ ‚|                     |j        d         |j        d         ¦  «        du sJ ‚|                     ¦   «         }t          |¦  «        |j	        |j
        z  k    sJ ‚|                     ¦   «         dk    sJ ‚dS )z:Verifies spatial chunking and boss arena bounding helpers.rá   rI   rƒ   r   rL   r   )r   r   é   )r1   r1   é?   )r8   r8   NTr1   Frw   )r   rN   Úget_chunk_coordsrä   rø   Úis_in_boss_roomrO   Úget_boss_arena_cellsr"   rö   r÷   Úget_walkables_count)r(   rR   rZ   rÿ   rð   rñ   Úarena_cellss          r-   Ú+test_spatial_partitioning_and_arena_querieszMTestGrandBossArenaAndMapExpansion.test_spatial_partitioning_and_arena_queriesX  sY  € å$¨2°bÐ9Ñ9Ô9ˆØ×&Ò&¨CÐ:PÐ&ÑQÔQˆð ×(Ò(¨¨AÑ.Ô.°&Ò8Ð8Ð8Ð8Ø×(Ò(¨¨RÑ0Ô0°FÒ:Ð:Ð:Ð:Ø×(Ò(¨¨RÑ0Ô0°FÒ:Ð:Ð:Ð:ð ÔˆØˆ~ˆ~ˆ~Ø”9‰ˆˆSØ×'Ò'¨¨SÑ1Ô1°TÐ9Ð9Ð9Ð9Ø×'Ò'¨Ô(<¸QÔ(?ÀÔAUÐVWÔAXÑYÔYÐ]bÐbÐbÐbÐbà×3Ò3Ñ5Ô5ˆÝ�;ÑÔ 2¤4¨"¬$¡;Ò.Ð.Ð.Ð.Ø×+Ò+Ñ-Ô-°Ò3Ð3Ð3Ð3Ð3Ð3r/   c                 óÀ  — t          ¦   «         }|                     dddd¬¦  «        }t          dd¬¦  «        }|                     dd¬¦  «        }|j        \  }}|                     ||||¦  «         |                     |||¦  «        d	u sJ ‚|                     |||¦  «        d	u sJ ‚|                     |¦  «        d
k    sJ ‚|                     |¦  «        dk    sJ ‚dS )zPVerifies WarFogEngine get_explored_ratio, is_cell_visible, and is_cell_explored.Ú	p_explorers   é   )rJ   rK   rŸ   rI   ix  r   rL   Tg        r    N)	r   r‘   r   rN   rO   r¦   Úis_cell_visibleÚis_cell_exploredÚget_explored_ratio)r(   r—   r˜   rR   rZ   r¨   r©   s          r-   Ú#test_war_fog_ratio_and_cell_querieszETestGrandBossArenaAndMapExpansion.test_war_fog_ratio_and_cell_queriesm  s  € å!‘^”^ˆ
Ø×1Ò1°+ÀRÐPRÐ`aÐ1ÑbÔbˆÝ$¨2°bÐ9Ñ9Ô9ˆØ×&Ò&¨CÐ:OÐ&ÑPÔPˆàÔ%‰ˆˆBØ×$Ò$ S¨(°B¸Ñ;Ô;Ð;à×)Ò)¨#¨r°2Ñ6Ô6¸$Ð>Ð>Ð>Ð>Ø×*Ò*¨3°°BÑ7Ô7¸4Ð?Ð?Ð?Ð?Ø×,Ò,¨SÑ1Ô1°CÒ7Ð7Ð7Ð7Ø×,Ò,¨SÑ1Ô1°SÒ8Ð8Ð8Ð8Ð8Ð8r/   c           	      óò  ‡— dD �]ñ}dD �]ê}t          ||¬¦  «        }|                     |d¬¦  «        Š‰j        }|€J ‚‰j        €J ‚‰j        \  }}g }t	          |j        |j        |j        z   ¦  «        D ]2}|                     ||j        f||j        |j	        z   dz
  fg¦  «         Œ3t	          |j        dz   |j        |j	        z   dz
  ¦  «        D ]2}	|                     |j        |	f|j        |j        z   dz
  |	fg¦  «         Œ3ˆfd„|D ¦   «         }
t          |
¦  «        dk    s J d	t          |
¦  «        › d
|› d|› �¦   «         ‚|
d         ||fk    sJ ‚‰j        |         |         j        t          j        k    sJ ‚t          ‰‰j        ‰j        d¬¦  «        \  }}|du sJ d|› d|› d�¦   «         ‚|                     ‰¦  «        }|du sJ ‚t          ‰‰j        ‰j        d¬¦  «        \  }}|du sJ ‚�Œì�ŒódS )zqVerifies 100% of perimeter cells around Boss Arena are solid walls except exactly 1 boss gate, preventing bypass.rà   )ée   éÊ   i/  rI   r   rL   Nr1   c                 ój   •— g | ]/\  }}‰j         |         |         j        t          j        k    ¯+||f‘Œ0S rD   )rÚ   r5   r   r;   )rf   ÚpxÚpyrZ   s      €r-   r£   znTestGrandBossArenaAndMapExpansion.test_zero_boss_gate_bypass_and_single_perimeter_entrance.<locals>.<listcomp>Ž  sG   ø€ ð ð ð Ù!) " bØ”~ bÔ)¨"Ô-Ô7½8¼=ÒHÐHð ˜�HØHÐHÐHr/   z&Expected 1 entrance on perimeter, got z	 at seed z, dim r   F)Úallow_sealed_boss_gatezBoss gate bypassed at seed ú!T)r   rN   rä   rú   r¡   r3   rö   Úextendr4   r÷   r"   rÚ   r5   r   rû   r   rO   rP   r	  )r(   ræ   rM   rR   rÿ   r  r  Úperimeter_cellsr3   r4   Ú	non_wallsÚunbreached_connectedr„   Ú	breach_okÚbreached_connectedrZ   s                  @r-   Ú8test_zero_boss_gate_bypass_and_single_perimeter_entrancezZTestGrandBossArenaAndMapExpansion.test_zero_boss_gate_bypass_and_single_perimeter_entrance|  sµ  ø€ à#ð $	2ñ $	2ˆCØ'ð #2ñ #2�Ý,°3¸sÐCÑCÔC�Ø!×.Ò.°DÐCZÐ.Ñ[Ô[�ØÔ'�Ø�~�~�~ØÔ)Ð5Ð5Ð5Ø!Ô+‘��Bð #%�Ý˜rœt R¤T¨B¬D¡[Ñ1Ô1ð Nð N�AØ#×*Ò*¨Q°´¨I¸¸2¼4À"Ä$¹;È¹?Ð7KÐ+LÑMÔMÐMÐMÝ˜rœt a™x¨¬°´©°q©Ñ9Ô9ð Nð N�AØ#×*Ò*¨R¬T°1¨I¸¼¸r¼t¹Àa¹ÈÐ7KÐ+LÑMÔMÐMÐMðð ð ð Ø-<ðñ ô �	õ ˜9‘~”~¨Ò*Ð*Ð*Ð,ÕUXÐYbÑUcÔUcÐ,Ð,ÐnrÐ,Ð,Ðz}Ð,Ð,Ñ*Ô*Ð*Ø  ”|¨¨B xÒ/Ð/Ð/Ð/Ø”~ bÔ)¨"Ô-Ô7½8Ô;MÒMÐMÐMÐMõ +CØ˜hÔ2°HÔ4GÐ`eð+ñ +ô +Ñ'Ð$ að ,¨uÐ4Ð4Ð4Ð6fÐTXÐ6fÐ6fÐ`cÐ6fÐ6fÐ6fÑ4Ô4Ð4ð #×3Ò3°HÑ=Ô=�	Ø  DÐ(Ð(Ð(Ð(Ý(@Ø˜hÔ2°HÔ4GÐ`eð)ñ )ô )Ñ%Ð" Að *¨TÐ1Ð1Ð1Ð1Ñ1ñG#2ð$	2ð $	2r/   N)	rA   rB   rC   rç   r  r  r  r  r*  rD   r/   r-   rÞ   rÞ     so   € € € € € ð!ð !ð !ð$"ð $"ð $"ðL4ð 4ð 4ð 4ð 4ð 4ð*9ð 9ð 9ð&2ð &2ð &2ð &2ð &2r/   rÞ   ) Ú__doc__ÚpytestÚtypingr   r   r   r   Úserver.world.map_data_typesr   r   r	   r
   r   r   r   Úserver.world.map_biome_catalogr   r   r   Úserver.world.war_fog_enginer   r   r   Ú"server.world.procedural_map_enginer   r   r   r   rF   r_   r‹   rÞ   rD   r/   r-   ú<module>r2     s  ððð ð  €€€Ø )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )ðð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ðð ð ð ð ð ð ð ð ð ð
ð ð ð ð ð ð ð ð ð ð
ð ð ð ð ð ð ð ð ð ð#(ð #(ð #(ð #(ð #(ñ #(ô #(ð #(ðL!ð !ð !ð !ð !ñ !ô !ð !ð2:2ð :2ð :2ð :2ð :2ñ :2ô :2ð :2ðze.ð e.ð e.ð e.ð e.ñ e.ô e.ð e.ðPP2ð P2ð P2ð P2ð P2ñ P2ô P2ð P2ð P2ð P2r/   