§
    b¤½jr/  ã                   óŠ   — d Z ddlmZ ddlZddlmZmZ ddlmZ ddl	m
Z
mZ ej        defd„¦   «         Z G d	„ d
¦  «        ZdS )a•  
Unit tests for PoE2 Zone Spawning Purity & Encounter Rules in FreeExile.
Verifies that Safe Havens (Sanctuary & Hideout) NEVER spawn hostile monsters,
restricting safe zones strictly to inanimate training dummies, while outer
exploration maps and dungeons support dynamic hostile monster populations.
Also validates spatial grid initialization, entity isolation, and portal traversal
for Player Hideout.
é    )ÚPathN)ÚEntityÚSpatialGrid©Ú
ZoneEngine)ÚZoneEnvironmentÚZoneTypeÚreturnc                  ó   — t          ¦   «         S )Nr   © ó    úDC:\Projects\FreeExile\tests\unit\test_zone_monster_spawning_rules.pyÚzone_enginer      s   € å‰<Œ<Ðr   c                   óÊ   — e Zd ZdZdeddfd„Zdeddfd„Zdeddfd„Zdeddfd„Zdeddfd	„Z	deddfd
„Z
deddfd„Zdeddfd„Zdeddfd„Zdd„Zdd„Zdd„Zdd„Zdd„ZdS )ÚTestPoE2ZoneSpawningPurityz>Tests authoritative safe-zone purity and monster spawn gating.r   r
   Nc                 ó®   — |                      d¦  «        }|€J ‚|j        t          j        k    sJ ‚|j        t
          j        k    sJ ‚|j        dk    sJ ‚dS )z@Verifies that Outcast Encampment Hub is registered as SANCTUARY.Úzone_boundless_sanctuaryNé   )Úget_zoneÚ	zone_typer	   Ú	SANCTUARYÚenvironmentr   ÚNORMALÚ	min_level)Úselfr   Ú	sanctuarys      r   Ú%test_sanctuary_zone_type_is_sanctuaryz@TestPoE2ZoneSpawningPurity.test_sanctuary_zone_type_is_sanctuary   sj   € à×(Ò(Ð)CÑDÔDˆ	ØÐ$Ð$Ð$ØÔ"¥hÔ&8Ò8Ð8Ð8Ð8ØÔ$­Ô(>Ò>Ð>Ð>Ð>ØÔ" aÒ'Ð'Ð'Ð'Ð'Ð'r   c                 óH  — |                      d¦  «        }|€J ‚|j        dk    sJ ‚|j        t          j        k    sJ ‚|j        dk    sJ ‚|j        dk    sJ ‚|j        dk    sJ ‚|j        dk    sJ ‚|j	        dk    sJ ‚|j
        dk    sJ ‚d|j        v sJ ‚d|j        v sJ ‚dS )	uU   Verifies that Player Hideout (TiÃªn Phá»§ Ä�á»™ng ThiÃªn) is registered as SANCTUARY.Úzone_player_hideoutNu$   TiÃªn Phá»§ Ä�á»™ng ThiÃªn (Hideout)r   éd   g      ‰@Úwp_hideout_centralÚportal_hideout_to_sanctuary)r   Úzone_idr   r	   r   ÚnameÚdisplay_namer   Ú	max_levelÚbounds_widthÚbounds_heightÚ	waypointsÚportals)r   r   Úhideouts      r   Ú*test_player_hideout_zone_type_is_sanctuaryzETestPoE2ZoneSpawningPurity.test_player_hideout_zone_type_is_sanctuary"   só   € à×&Ò&Ð'<Ñ=Ô=ˆØÐ"Ð"Ð"ØŒÐ"7Ò7Ð7Ð7Ð7ØÔ ¥HÔ$6Ò6Ð6Ð6Ð6ØŒ|ÐEÒEÐEÐEÐEØÔ#Ð'MÒMÐMÐMÐMØÔ  AÒ%Ð%Ð%Ð%ØÔ  CÒ'Ð'Ð'Ð'ØÔ# uÒ,Ð,Ð,Ð,ØÔ$¨Ò-Ð-Ð-Ð-Ø# wÔ'8Ð8Ð8Ð8Ð8Ø,°´Ð?Ð?Ð?Ð?Ð?Ð?r   c                 ó¶   — |                      d¦  «        }|j        t          j        k    sJ ‚|                      d¦  «        }|j        t          j        k    sJ ‚dS )zAVerifies that wilderness maps are OPEN_WORLD where monsters roam.Úzone_tang_kiem_nhaiÚzone_ancient_sword_barrowN)r   r   r	   Ú
OPEN_WORLD)r   r   Úbone_strandÚancient_swords       r   Ú+test_outer_exploration_zones_are_open_worldzFTestPoE2ZoneSpawningPurity.test_outer_exploration_zones_are_open_world1   s^   € à!×*Ò*Ð+@ÑAÔAˆØÔ$­Ô(;Ò;Ð;Ð;Ð;à#×,Ò,Ð-HÑIÔIˆØÔ&­(Ô*=Ò=Ð=Ð=Ð=Ð=Ð=r   c                 ó2  — |                      d¦  «        du sJ ‚|                      d¦  «        du sJ ‚|                      d¦  «        du sJ ‚|                      d¦  «        du sJ ‚|                      d¦  «        du sJ ‚|                      d¦  «        du sJ ‚d	S )
z7Verifies authoritative can_spawn_hostile_monsters rule.r   Fr   Úinvalid_unknown_zoner.   Tr/   Úzone_boundless_sandstormN)Úcan_spawn_hostile_monsters)r   r   s     r   Ú$test_can_spawn_hostile_monsters_gatez?TestPoE2ZoneSpawningPurity.test_can_spawn_hostile_monsters_gate9   sÔ   € ð ×5Ò5Ð6PÑQÔQÐUZÐZÐZÐZÐZØ×5Ò5Ð6KÑLÔLÐPUÐUÐUÐUÐUð ×5Ò5Ð6LÑMÔMÐQVÐVÐVÐVÐVð ×5Ò5Ð6KÑLÔLÐPTÐTÐTÐTÐTØ×5Ò5Ð6QÑRÔRÐVZÐZÐZÐZÐZØ×5Ò5Ð6PÑQÔQÐUYÐYÐYÐYÐYÐYÐYr   c                 ó–  — |                      dd¬¦  «        \  }}|du sJ ‚d|v sd|v sJ ‚|                      dd¬¦  «        \  }}|du sJ ‚d|v sd|v sJ ‚|                      dd¬¦  «        \  }}|du sJ ‚d|v sd	|v sJ ‚|                      dd¬¦  «        \  }}	|du sJ ‚d|	v sd	|	v sJ ‚|                      d
d¬¦  «        \  }
}|
du sJ ‚dS )zPVerifies validate_monster_spawn rejects hostile spawns in Sanctuary and Hideout.r   F)r#   Úis_dummyu   An ToÃ nÚ	Sanctuaryr   TzTarget Dummyu   KhÃ´i Lá»—ir.   N)Úvalidate_monster_spawn)r   r   Úcan_spawn_sancÚreason_sancÚcan_spawn_hideoutÚreason_hideoutÚcan_dummy_sancÚreason_dummy_sancÚcan_dummy_hideoutÚreason_dummy_hideoutÚcan_wildÚ_s               r   Ú'test_validate_monster_spawn_enforcementzBTestPoE2ZoneSpawningPurity.test_validate_monster_spawn_enforcementG   s¡  € ð '2×&HÒ&HØ.Øð 'Iñ '
ô '
Ñ#ˆ˜ð  Ð&Ð&Ð&Ð&Ø˜[Ð(Ð(¨K¸;Ð,FÐ,FÐ,FÐFð -8×,NÒ,NØ)Øð -Oñ -
ô -
Ñ)Ð˜>ð ! EÐ)Ð)Ð)Ð)Ø$¨Ð6Ð6¸+ÈÐ:WÐ:WÐ:WÐWð -8×,NÒ,NØ.Øð -Oñ -
ô -
Ñ)ˆÐ)ð  Ð%Ð%Ð%Ð%ØÐ!2Ð2Ð2°mÐGXÐ6XÐ6XÐ6XÐXð 3>×2TÒ2TØ)Øð 3Uñ 3
ô 3
Ñ/ÐÐ/ð ! DÐ(Ð(Ð(Ð(ØÐ!5Ð5Ð5¸ÐJ^Ð9^Ð9^Ð9^Ð^ð "×8Ò8Ø)Øð 9ñ 
ô 
‰ˆ�!ð ˜4ÐÐÐÐÐÐr   c                 ó*  — d}|                      |d¦  «        }|€J ‚|j        |k    sJ ‚|j        dk    sJ ‚|j        dk    sJ ‚|j        dk    sJ ‚|                     |¦  «        }|j        dk    sJ ‚|j        dk    sJ ‚|j        dk    sJ ‚d|j        v sJ ‚d|j        v sJ ‚|j        d         }|j        d         }|€J ‚t          |t          ¦  «        sJ ‚||usJ ‚|j	        dk    sJ ‚| 
                    |j        |j        ¦  «        }|dk    sJ ‚dS )z¿
        Verifies that spawning a player in the hideout succeeds without KeyError,
        sets valid player location coordinates, and guarantees hideout spatial grid initialization.
        Úplayer_hero_hideout_01r   Nç        r   g      P@)r   r   )Úspawn_playerÚ	player_idr#   ÚxÚyÚget_player_locationÚzone_spatial_gridsÚ
isinstancer   Ú	cell_sizeÚget_cell_coords)r   r   rL   ÚlocÚcurrent_locÚhideout_gridÚsanctuary_gridÚcell_coordss           r   Ú-test_spawn_player_in_hideout_and_spatial_gridzHTestPoE2ZoneSpawningPurity.test_spawn_player_in_hideout_and_spatial_gridp   s|  € ð
 -ˆ	Ø×&Ò& yÐ2GÑHÔHˆØˆˆˆØŒ} 	Ò)Ð)Ð)Ð)ØŒ{Ð3Ò3Ð3Ð3Ð3ØŒu˜Š|ˆ|ˆ|ˆ|ØŒu˜Š|ˆ|ˆ|ˆ|ð "×5Ò5°iÑ@Ô@ˆØÔ"Ð&;Ò;Ð;Ð;Ð;ØŒ} Ò#Ð#Ð#Ð#ØŒ} Ò#Ð#Ð#Ð#ð %¨Ô(FÐFÐFÐFÐFØ)¨[Ô-KÐKÐKÐKÐKà"Ô5Ð6KÔLˆØ$Ô7Ð8RÔSˆàÐ'Ð'Ð'Ý˜,­Ñ4Ô4Ð4Ð4Ð4Ø >Ð1Ð1Ð1Ð1ØÔ%¨Ò-Ð-Ð-Ð-ð #×2Ò2°3´5¸#¼%Ñ@Ô@ˆØ˜fÒ$Ð$Ð$Ð$Ð$Ð$r   c                 ó,  — |j         d         }|j         d         }t          ddd¬¦  «        }|                     |¦  «         d|j        v sJ ‚d|j        vsJ ‚|                     ddd¬¦  «        }d|v sJ ‚|                     ddd¬¦  «        }d|vsJ ‚dS )	z±
        Verifies that entities within the player hideout spatial grid are isolated
        from the sanctuary encampment and cannot be observed across zone boundaries.
        r   r   ia"  rJ   )Ú	entity_idrM   rN   r   )Úradius_cellsN)rP   r   Ú
add_entityÚentitiesÚget_entities_in_aoi)r   r   rV   rW   Údummy_entityÚhideout_aoiÚsanctuary_aois          r   Ú7test_spatial_grid_entity_isolation_hideout_vs_sanctuaryzRTestPoE2ZoneSpawningPurity.test_spatial_grid_entity_isolation_hideout_vs_sanctuary“   sÑ   € ð
 #Ô5Ð6KÔLˆØ$Ô7Ð8RÔSˆå¨°°sÐ;Ñ;Ô;ˆØ×Ò Ñ-Ô-Ð-à�|Ô,Ð,Ð,Ð,Ð,Ø˜>Ô2Ð2Ð2Ð2Ð2ð #×6Ò6°s¸CÈaÐ6ÑPÔPˆØ�{Ð"Ð"Ð"Ð"ð '×:Ò:¸3ÀÐRSÐ:ÑTÔTˆØ˜=Ð(Ð(Ð(Ð(Ð(Ð(r   c                 ó^  — d}|                      |d¦  «         |                     |dd¬¦  «        \  }}}|du sJ ‚|dk    sJ ‚|                     |¦  «        j        dk    sJ ‚|                     |dd¬¦  «        \  }}}|du sJ ‚|dk    sJ ‚|                     |¦  «        j        dk    sJ ‚d	S )
zFVerifies bidirectional portal traversal between Sanctuary and Hideout.Úwayfarer_hideout_travelerr   Úportal_sanctuary_to_hideoutr   )Úplayer_levelTr   r"   N)rK   Útraverse_portalrO   r#   )r   r   rL   ÚokÚdestrF   Úok_backÚ	dest_backs           r   Ú1test_portal_traversal_sanctuary_hideout_roundtripzLTestPoE2ZoneSpawningPurity.test_portal_traversal_sanctuary_hideout_roundtrip©   sõ   € à/ˆ	Ø× Ò  Ð,FÑGÔGÐGà!×1Ò1°)Ð=ZÐijÐ1ÑkÔk‰ˆˆD�!Ø�TˆzˆzˆzˆzØÐ,Ò,Ð,Ð,Ð,Ø×.Ò.¨yÑ9Ô9ÔAÐEZÒZÐZÐZÐZà +× ;Ò ;ØÐ4À1ð !<ñ !
ô !
Ñˆ�˜Að ˜$ˆˆˆˆØÐ6Ò6Ð6Ð6Ð6Ø×.Ò.¨yÑ9Ô9ÔAÐE_Ò_Ð_Ð_Ð_Ð_Ð_r   c                 ó  — |                      d¦  «        }|€J ‚|j        t          j        k    sJ ‚|j        dk    sJ ‚|                      d¦  «        }|€J ‚|j        t          j        k    sJ ‚|                      d¦  «        }|�J ‚dS )zEVerifies deduplicated get_zone_definition method behaves as expected.r   Nr   Úzone_unknown_missing)Úget_zone_definitionr   r	   r   r#   )r   r   Úhideout_defÚsanctuary_defÚinvalid_defs        r   Útest_clean_get_zone_definitionz9TestPoE2ZoneSpawningPurity.test_clean_get_zone_definitionº   s«   € à!×5Ò5Ð6KÑLÔLˆØÐ&Ð&Ð&ØÔ$­Ô(:Ò:Ð:Ð:Ð:ØÔ"Ð&;Ò;Ð;Ð;Ð;à#×7Ò7Ð8RÑSÔSˆØÐ(Ð(Ð(ØÔ&­(Ô*<Ò<Ð<Ð<Ð<à!×5Ò5Ð6LÑMÔMˆØÐ"Ð"Ð"Ð"Ð"r   c                 óÐ   — t          d¦  «        }|                     ¦   «         s
J d¦   «         ‚|                     d¬¦  «        }d|vs
J d¦   «         ‚d|vs
J d¦   «         ‚d	|v sJ ‚d
S )zË
        Regression test on client JavaScript engine:
        Guarantees that monster_system.js does NOT spawn hellhounds or skeletons
        in zone_player_hideout or zone_boundless_sanctuary.
        ú)client/webapp/js/engine/monster_system.jszmonster_system.js must existúutf-8©ÚencodingÚhellhound_sanctuaryzrCRITICAL BUG: hellhound_sanctuary must NOT exist in monster_system.js! Safe zones must have zero hostile monsters.Úskeleton_sanctuaryzqCRITICAL BUG: skeleton_sanctuary must NOT exist in monster_system.js! Safe zones must have zero hostile monsters.zisDummy: trueN)r   ÚexistsÚ	read_text)r   Újs_pathÚcontents      r   Ú8test_client_monster_system_js_no_hostile_mobs_in_hideoutzSTestPoE2ZoneSpawningPurity.test_client_monster_system_js_no_hostile_mobs_in_hideoutÈ   s    € õ ÐBÑCÔCˆØ�~Š~ÑÔÐ?Ð?Ð!?Ñ?Ô?ÐØ×#Ò#¨WÐ#Ñ5Ô5ˆð %¨GÐ3Ð3Ð3ð:ñ 4Ô3Ð3ð $¨7Ð2Ð2Ð2ð:ñ 3Ô2Ð2ð  'Ð)Ð)Ð)Ð)Ð)Ð)r   c                 óp   — t          d¦  «                             d¬¦  «        }d|v sJ ‚d|v sJ ‚d|v sJ ‚dS )zÄ
        Verifies that client/webapp/js/engine/monster_system.js implements
        safe haven gating on spawnQAEnemy and spawnSpecificMonster with the exact
        warning notification.
        rv   rw   rx   u=   NghiÃªm cáº¥m sáº£n sinh quÃ¡i váº­t trong khu vá»±c An ToÃ nÚisSafeHavenZoneÚnotifySafeHavenBlockedN©r   r}   ©r   r   s     r   Ú0test_client_spawner_blocks_hostile_in_safe_havenzKTestPoE2ZoneSpawningPurity.test_client_spawner_blocks_hostile_in_safe_havenß   s^   € õ ÐBÑCÔC×MÒMÐW^ÐMÑ_Ô_ˆØNÐRYÐYÐYÐYÐYØ  GÐ+Ð+Ð+Ð+Ø'¨7Ð2Ð2Ð2Ð2Ð2Ð2r   c                 ód   — t          d¦  «                             d¬¦  «        }d|v sJ ‚d|v sJ ‚dS )z„
        Verifies that worldmap_dungeons.js flushes groundDrops and flying VFX projectiles
        upon zone teleportation.
        z(client/webapp/js/ui/worldmap_dungeons.jsrw   rx   ÚclearGroundDropsÚclearVfxProjectilesNr„   r…   s     r   Ú.test_client_zone_transition_drop_and_vfx_flushzITestPoE2ZoneSpawningPurity.test_client_zone_transition_drop_and_vfx_flushê   sL   € õ
 ÐAÑBÔB×LÒLÐV]ÐLÑ^Ô^ˆØ! WÐ,Ð,Ð,Ð,Ø$¨Ð/Ð/Ð/Ð/Ð/Ð/r   c                 ód   — t          d¦  «                             d¬¦  «        }d|v sJ ‚d|v sJ ‚dS )zg
        Verifies that monster_loot_dropper.js exposes clearGroundDrops and blocks dummy loot.
        z/client/webapp/js/engine/monster_loot_dropper.jsrw   rx   rˆ   zmonster.isDummyNr„   r…   s     r   Ú3test_client_monster_loot_dropper_clear_ground_dropszNTestPoE2ZoneSpawningPurity.test_client_monster_loot_dropper_clear_ground_dropsó   sL   € õ ÐHÑIÔI×SÒSÐ]dÐSÑeÔeˆØ! WÐ,Ð,Ð,Ð,Ø  GÐ+Ð+Ð+Ð+Ð+Ð+r   c                 ód   — t          d¦  «                             d¬¦  «        }d|v sJ ‚d|v sJ ‚dS )zV
        Verifies that vfx_renderer.js exports clearVfxProjectiles to window.
        z'client/webapp/js/engine/vfx_renderer.jsrw   rx   r‰   z1window.clearVfxProjectiles = clearVfxProjectiles;Nr„   r…   s     r   Ú.test_client_vfx_renderer_clear_vfx_projectileszITestPoE2ZoneSpawningPurity.test_client_vfx_renderer_clear_vfx_projectilesû   sL   € õ Ð@ÑAÔA×KÒKÐU\ÐKÑ]Ô]ˆØ$¨Ð/Ð/Ð/Ð/ØBÀgÐMÐMÐMÐMÐMÐMr   )r
   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r,   r3   r8   rG   rY   rc   rm   rt   r€   r†   rŠ   rŒ   rŽ   r   r   r   r   r      sÒ  € € € € € ØHÐHð(Àð (ÐPTð (ð (ð (ð (ð@Àjð @ÐUYð @ð @ð @ð @ð>Àzð >ÐVZð >ð >ð >ð >ðZÀ
ð ZÈtð Zð Zð Zð Zð' À:ð ' ÐRVð ' ð ' ð ' ð ' ðR!%Èð !%ÐX\ð !%ð !%ð !%ð !%ðF)ÐS]ð )Ðbfð )ð )ð )ð )ð,`ÈZð `Ð\`ð `ð `ð `ð `ð"#¸*ð #Èð #ð #ð #ð #ð*ð *ð *ð *ð.	3ð 	3ð 	3ð 	3ð0ð 0ð 0ð 0ð,ð ,ð ,ð ,ðNð Nð Nð Nð Nð Nr   r   )r’   Úpathlibr   ÚpytestÚserver.world.spatial_gridr   r   Úserver.world.zone_enginer   Úserver.world.zone_typesr   r	   Úfixturer   r   r   r   r   ú<module>r™      sÝ   ððð ð Ð Ð Ð Ð Ð Ø €€€à 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9Ø /Ð /Ð /Ð /Ð /Ð /Ø =Ð =Ð =Ð =Ð =Ð =Ð =Ð =ð „ð�Zð ð ð ñ „ððjNð jNð jNð jNð jNñ jNô jNð jNð jNð jNr   