§
    �Ë¾j   ã                   óö   — d Z ddlZddlZddlmZ ddlmZmZmZm	Z	m
Z
 ddlmZ ddlmZ dd	ed
ededededefd„Zdd	ededededededefd„Z G d„ dej        ¦  «        Zedk    r ej        ¦   «          dS dS )aë  
FreeExile M3 Unit Test Suite: Tile-Level Collision & Spawn Validation.
Covers:
1. Direct tile blocking: WALL, CHASM, WATER, BOSS_GATE, VOID.
2. Passable tiles: FLOOR, PATH, DENSE_TERRAIN, POI, ENCOUNTER_*.
3. 2-Axis sliding physics: Diagonal wall collision slides along orthogonal axis.
4. Corner sliding: Sliding along corner tiles without penetration.
5. Player collision radius: Edge penetration prevention at r = 0.35.
6. Out-of-bounds containment: Coordinates < 0 or >= W, H are blocked.
7. Boss Gate locked state blocks movement.
8. Boss Gate unlocking mutates tile to passable and clears collision.
9. Server validate_monster_spawn rejects impassable tiles.
10. Dodge/blink behavior on chasms.
11. Safe Haven purity (Sanctuary & Hideout).
é    N)Úpatch)ÚTileTypeÚTileCellÚMapGridDataÚObstacleInstanceÚObstacleType)Ú
ZoneEngine)ÚProceduralMapEngineçffffffÖ?FÚgridÚwxÚwyÚradiusÚis_dodgeÚreturnc                 ó  — t          t          j        ||z
  ¦  «        ¦  «        }t          t          j        ||z   ¦  «        ¦  «        }t          t          j        ||z
  ¦  «        ¦  «        }t          t          j        ||z   ¦  «        ¦  «        }t          ||dz   ¦  «        D ]à}	t          ||dz   ¦  «        D ]Ê}
|                      |
|	¦  «        s  dS | j        |	         |
         j        }|t          j        k    r|rŒG|t          j	        t          j        t          j
        t          j        t          j        fv s|                     ¦   «         s  dS | j                             |
|	f¦  «        }|r|j        s|j        r  dS ŒËŒádS )Né   TF)ÚintÚmathÚfloorÚrangeÚis_in_boundsÚtilesÚ	tile_typer   ÚCHASMÚWALLÚWATERÚ	BOSS_GATEÚVOIDÚis_passableÚ	obstaclesÚgetÚis_destroyedÚblocks_movement)r   r   r   r   r   Úmin_txÚmax_txÚmin_tyÚmax_tyÚtyÚtxÚtileÚobss                ú7C:\Projects\FreeExile\tests\unit\test_tile_collision.pyÚis_position_blockedr.      sŠ  € Ý•”˜B ™KÑ(Ô(Ñ)Ô)€FÝ•”˜B ™KÑ(Ô(Ñ)Ô)€FÝ•”˜B ™KÑ(Ô(Ñ)Ô)€FÝ•”˜B ™KÑ(Ô(Ñ)Ô)€Få�F˜F Q™JÑ'Ô'ð ð ˆÝ˜ ¨¡
Ñ+Ô+ð 
	ð 
	ˆBØ×$Ò$ R¨Ñ,Ô,ð Ø�t�t�tØ”:˜b”> "Ô%Ô/ˆDØ•x”~Ò%Ð%¨(Ð%ØØ�œ¥x¤~µx´~ÅxÔGYÕ[cÔ[hÐiÐiÐiÐqu÷  rBò  rBñ  rDô  rDÐiØ�t�t�tØ”.×$Ò$ b¨" XÑ.Ô.ˆCØð ˜3Ô+ð °Ô0Cð Ø�t�t�tøð
	ð ˆ5ó    Úcur_xÚcur_yÚdxÚdyc                 óT  — ||z   }||z   }t          | ||||¦  «        s||dfS |dk    ot          | ||z   |||¦  «         }	|dk    ot          | |||z   ||¦  «         }
|	r2|
r0t          |¦  «        t          |¦  «        k    r||z   |dfS |||z   dfS |	r||z   |dfS |
r|||z   dfS ||dfS )NFr   T)r.   Úabs)r   r0   r1   r2   r3   r   r   Útarget_xÚtarget_yÚcan_xÚcan_ys              r-   Úresolve_movement_with_slidingr:   1   s  € Ø�r‰z€HØ�r‰z€HÝ˜t X¨x¸ÀÑJÔJð )Ø˜ 5Ð(Ð(à�!ŠGÐZÕ/°°e¸b±jÀ%ÈÐQYÑZÔZÐZ€EØ�!ŠGÐZÕ/°°e¸UÀR¹ZÈÐQYÑZÔZÐZ€Eàð '�ð 'Ýˆr‰7Œ7•c˜"‘g”gÒÐØ˜2‘:˜u dÐ*Ð*Ø�e˜b‘j $Ð&Ð&Øð 'Ø�r‰z˜5 $Ð&Ð&Øð 'Ø�e˜b‘j $Ð&Ð&Ø�%˜ÐÐr/   c                   óV   — e Zd Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Z	d„ Z
d	„ Zd
„ Zd„ Zd„ ZdS )ÚTestTileCollisionc                 ó  ‡ — d\  ‰ _         ‰ _        ˆ fd„t          ‰ j        ¦  «        D ¦   «         ‰ _        t	          ‰ j         ‰ j        dd‰ j        ¬¦  «        ‰ _        t          ¦   «         ‰ _        t          j	        ¦   «          d S )N)é
   r>   c                 óR   •‡— g | ]"Šˆfd „t          ‰j        ¦  «        D ¦   «         ‘Œ#S )c                 óJ   •— g | ]}t          |‰t          j        d ¬¦  «        ‘Œ S )T)ÚxÚyr   Úwalkable)r   r   ÚFLOOR)Ú.0rA   rB   s     €r-   ú
<listcomp>z6TestTileCollision.setUp.<locals>.<listcomp>.<listcomp>I   s,   ø€ Ð`Ð`Ð`ÈQ�X˜˜Q­(¬.À4ÐHÑHÔHÐ`Ð`Ð`r/   )r   Úw)rE   rB   Úselfs    @€r-   rF   z+TestTileCollision.setUp.<locals>.<listcomp>H   sL   øø€ ð 
ð 
ð 
àð aÐ`Ð`Ð`ÕRWÐX\ÔX^ÑR_ÔR_Ð`Ñ`Ô`ð
ð 
ð 
r/   r   ÚBLEACHED_BONE_CANYON)ÚwidthÚheightÚseedÚbiomer   )
rG   Úhr   r   r   r   r	   Úenginer
   Úclear_zone_maps©rH   s   `r-   ÚsetUpzTestTileCollision.setUpF   s‡   ø€ Ø‰ˆŒ�”ð
ð 
ð 
ð 
å˜4œ6‘]”]ð
ñ 
ô 
ˆŒ
õ   d¤f°T´VÀ!ÐKaÐimÔisÐtÑtÔtˆŒ	Ý ‘l”lˆŒÝÔ+Ñ-Ô-Ð-Ð-Ð-r/   c                 óX  — t           j        t           j        t           j        t           j        t           j        fD ]o}|                      |                     ¦   «         ¦  «         || j        j	        d         d         _
        |                      t          | j        dd¦  «        ¦  «         Œpd S ©Né   ç      @)r   r   r   r   r   r   ÚassertFalser    r   r   r   Ú
assertTruer.   )rH   Ú
impassables     r-   Útest_01_direct_tile_blockingz.TestTileCollision.test_01_direct_tile_blockingP   s‘   € Ý#œ=­(¬.½(¼.Í(ÔJ\Õ^fÔ^kÐlð 	Fð 	FˆJØ×Ò˜Z×3Ò3Ñ5Ô5Ñ6Ô6Ð6Ø.8ˆDŒIŒO˜AÔ˜qÔ!Ô+Ø�OŠOÕ/°´	¸3ÀÑDÔDÑEÔEÐEÐEð	Fð 	Fr/   c                 óX  — t           j        t           j        t           j        t           j        t           j        fD ]o}|                      |                     ¦   «         ¦  «         || j        j	        d         d         _
        |                      t          | j        dd¦  «        ¦  «         Œpd S rT   )r   rD   ÚPATHÚDENSE_TERRAINÚPOIÚENCOUNTER_LOWrX   r    r   r   r   rW   r.   )rH   Úpassables     r-   Ú%test_02_passable_tiles_allow_movementz7TestTileCollision.test_02_passable_tiles_allow_movementV   s“   € Ý!œ­¬½Ô8NÕPXÔP\Õ^fÔ^tÐuð 	Gð 	GˆHØ�OŠO˜H×0Ò0Ñ2Ô2Ñ3Ô3Ð3Ø.6ˆDŒIŒO˜AÔ˜qÔ!Ô+Ø×ÒÕ0°´¸CÀÑEÔEÑFÔFÐFÐFð	Gð 	Gr/   c                 óN  — t          | j        ¦  «        D ])}t          j        | j        j        d         |         _        Œ*d\  }}t          | j        ||dd¦  «        \  }}}|                      |¦  «         |  	                    |dd¬¦  «         |  	                    |dd¬¦  «         d S )Né   )g      @rV   gš™™™™™Ù?g333333@é   )ÚplacesrV   )
r   rG   r   r   r   r   r   r:   rX   ÚassertAlmostEqual)rH   rA   r0   r1   Únew_xÚnew_yÚslidings          r-   Ú&test_03_two_axis_sliding_diagonal_wallz8TestTileCollision.test_03_two_axis_sliding_diagonal_wall\   s¬   € Ý�t”v‘”ð 	<ð 	<ˆAÝ.6¬mˆDŒIŒO˜AÔ˜qÔ!Ô+Ð+Ø‰ˆˆuÝ =¸d¼iÈÐPUÐWZÐ\_Ñ `Ô `Ñˆˆu�gØ�Š˜Ñ Ô Ð Ø×Ò˜u c°!ÐÑ4Ô4Ð4Ø×Ò˜u c°!ÐÑ4Ô4Ð4Ð4Ð4r/   c                 óÞ   — t           j        | j        j        d         d         _        t          | j        dddd¦  «        \  }}}|                      t          | j        ||¦  «        ¦  «         d S )NrU   gÍÌÌÌÌÌ@g333333@g      à?gš™™™™™¹¿)r   r   r   r   r   r:   rW   r.   )rH   rg   rh   Ú_s       r-   Ú*test_04_corner_sliding_without_penetrationz<TestTileCollision.test_04_corner_sliding_without_penetratione   sa   € Ý*2¬-ˆŒ	Œ˜Ô˜1ÔÔ'Ý7¸¼	À3ÈÈSÐRVÑWÔW‰ˆˆu�aØ×ÒÕ,¨T¬Y¸¸uÑEÔEÑFÔFÐFÐFÐFr/   c                 ó   — t           j        | j        j        d         d         _        |                      t          | j        ddd¬¦  «        ¦  «         |                      t          | j        ddd¬¦  «        ¦  «         d S )NrU   r   g333333ó?rV   r   )r   gffffffö?)r   r   r   r   r   rX   r.   rW   rQ   s    r-   Ú0test_05_player_collision_radius_edge_penetrationzBTestTileCollision.test_05_player_collision_radius_edge_penetrationj   sn   € Ý*2¬-ˆŒ	Œ˜Ô˜1ÔÔ'Ø�ŠÕ+¨D¬I°s¸CÈÐMÑMÔMÑNÔNÐNØ×ÒÕ,¨T¬Y¸¸SÈÐNÑNÔNÑOÔOÐOÐOÐOr/   c                 óN  — |                       t          | j        dd¦  «        ¦  «         |                       t          | j        dd¦  «        ¦  «         |                       t          | j        dd¦  «        ¦  «         |                       t          | j        dd¦  «        ¦  «         d S )Ng      à¿g      @g      %@)rX   r.   r   rQ   s    r-   Ú!test_06_out_of_bounds_containmentz3TestTileCollision.test_06_out_of_bounds_containmento   sŒ   € Ø�ŠÕ+¨D¬I°t¸SÑAÔAÑBÔBÐBØ�ŠÕ+¨D¬I°t¸SÑAÔAÑBÔBÐBØ�ŠÕ+¨D¬I°s¸DÑAÔAÑBÔBÐBØ�ŠÕ+¨D¬I°s¸DÑAÔAÑBÔBÐBÐBÐBr/   c                 óü   — t           j        | j        j        d         d         _        t          dddt          j        d¬¦  «        | j        j        d<   |  	                    t          | j        dd¦  «        ¦  «         d S )Né   Úobs_gateT©r$   ©rs   rs   ç      @)r   r   r   r   r   r   r   ÚBOSS_SEAL_BARRIERr!   rX   r.   rQ   s    r-   Ú(test_07_boss_gate_locked_blocks_movementz:TestTileCollision.test_07_boss_gate_locked_blocks_movementu   sh   € Ý*2Ô*<ˆŒ	Œ˜Ô˜1ÔÔ'Ý&6°zÀ1ÀaÍÔIgÐy}Ð&~Ñ&~Ô&~ˆŒ	Ô˜FÑ#Ø�ŠÕ+¨D¬I°s¸CÑ@Ô@ÑAÔAÐAÐAÐAr/   c                 ó¦  — t           j        | j        j        d         d         _        t          dddt          j        d¬¦  «        | j        j        d<   t           j	        | j        j        d         d         _        d| j        j        d         _
        d| j        j        d         _        |                      t          | j        dd¦  «        ¦  «         d S )Nrs   rt   Tru   rv   Frw   )r   r   r   r   r   r   r   rx   r!   rD   r#   r$   rW   r.   rQ   s    r-   Ú=test_08_boss_gate_unlocking_mutates_tile_and_clears_collisionzOTestTileCollision.test_08_boss_gate_unlocking_mutates_tile_and_clears_collisionz   s¦   € Ý*2Ô*<ˆŒ	Œ˜Ô˜1ÔÔ'Ý&6°zÀ1ÀaÍÔIgÐy}Ð&~Ñ&~Ô&~ˆŒ	Ô˜FÑ#Ý*2¬.ˆŒ	Œ˜Ô˜1ÔÔ'Ø37ˆŒ	Ô˜FÔ#Ô0Ø6;ˆŒ	Ô˜FÔ#Ô3Ø×ÒÕ,¨T¬Y¸¸SÑAÔAÑBÔBÐBÐBÐBr/   c                 óÜ  — t          j        t          dt          j        ¬¦  «        5  | j                             ddd¬¦  «        \  }}|                      |¦  «         |                      d|¦  «         d d d ¦  «         n# 1 swxY w Y   t          j        t          dt          j	        ¬¦  «        5  | j                             ddd¦  «        \  }}|                      |¦  «         d d d ¦  «         n# 1 swxY w Y   t          j        t          dt          j
        ¬¦  «        5  | j                             ddd¬¦  «        \  }}|                      |¦  «         d d d ¦  «         n# 1 swxY w Y   t          j        t          dt          j        ¬¦  «        5  | j                             ddd¬¦  «        \  }}|                      |¦  «         d d d ¦  «         n# 1 swxY w Y   t          j        t          dt          j        ¬¦  «        5  | j                             ddd¬¦  «        \  }}|                      |¦  «         |                      d|¦  «         d d d ¦  «         d S # 1 swxY w Y   d S )NÚget_tile_type)Úreturn_valueÚzone_tang_kiem_nhairU   )r*   r)   u   khÃ´ng thá»ƒ Ä‘i quau
   há»£p lá»‡)r   Úobjectr
   r   r   rO   Úvalidate_monster_spawnrW   ÚassertInr   r   r   rD   rX   )rH   ÚallowedÚreasonrl   s       r-   Ú8test_09_server_validate_monster_spawn_rejects_impassablezJTestTileCollision.test_09_server_validate_monster_spawn_rejects_impassable‚   s|  € ÝŒ\Õ-¨ÍXÌ]Ð[Ñ[Ô[ð 	:ð 	:Ø"œk×@Ò@ÐAVÐ[\ÐabÐ@ÑcÔc‰OˆG�VØ×Ò˜WÑ%Ô%Ð%Ø�MŠMÐ0°&Ñ9Ô9Ð9ð	:ð 	:ð 	:ñ 	:ô 	:ð 	:ð 	:ð 	:ð 	:ð 	:ð 	:øøøð 	:ð 	:ð 	:ð 	:õ Œ\Õ-¨ÍXÌ^Ð\Ñ\Ô\ð 	&ð 	&Øœ×;Ò;Ð<QÐSTÐVWÑXÔX‰JˆG�QØ×Ò˜WÑ%Ô%Ð%ð	&ð 	&ð 	&ñ 	&ô 	&ð 	&ð 	&ð 	&ð 	&ð 	&ð 	&øøøð 	&ð 	&ð 	&ð 	&õ Œ\Õ-¨ÍXÌ^Ð\Ñ\Ô\ð 	&ð 	&Øœ×;Ò;Ð<QÐVWÐ\]Ð;Ñ^Ô^‰JˆG�QØ×Ò˜WÑ%Ô%Ð%ð	&ð 	&ð 	&ñ 	&ô 	&ð 	&ð 	&ð 	&ð 	&ð 	&ð 	&øøøð 	&ð 	&ð 	&ð 	&õ Œ\Õ-¨ÍXÔM_Ð`Ñ`Ô`ð 	&ð 	&Øœ×;Ò;Ð<QÐVWÐ\]Ð;Ñ^Ô^‰JˆG�QØ×Ò˜WÑ%Ô%Ð%ð	&ð 	&ð 	&ñ 	&ô 	&ð 	&ð 	&ð 	&ð 	&ð 	&ð 	&øøøð 	&ð 	&ð 	&ð 	&õ Œ\Õ-¨ÍXÌ^Ð\Ñ\Ô\ð 	0ð 	0Ø"œk×@Ò@ÐAVÐ[\ÐabÐ@ÑcÔc‰OˆG�VØ�OŠO˜GÑ$Ô$Ð$Ø�MŠM˜,¨Ñ/Ô/Ð/ð	0ð 	0ð 	0ñ 	0ô 	0ð 	0ð 	0ð 	0ð 	0ð 	0ð 	0ð 	0øøøð 	0ð 	0ð 	0ð 	0ð 	0ð 	0s[   §AA?Á?BÂBÂ05C1Ã1C5Ã8C5Ä"6E$Å$E(Å+E(Æ6GÇGÇGÈAI!É!I%É(I%c                 ó¤  — t           j        | j        j        d         d         _        |                      t          | j        ddd¬¦  «        ¦  «         |                      t          | j        ddd¬¦  «        ¦  «         t           j        | j        j        d         d         _        |                      t          | j        ddd¬¦  «        ¦  «         d S )Né   g      @F)r   T)	r   r   r   r   r   rX   r.   rW   r   rQ   s    r-   Ú&test_10_dodge_blink_behavior_on_chasmsz8TestTileCollision.test_10_dodge_blink_behavior_on_chasms•   s¬   € Ý*2¬.ˆŒ	Œ˜Ô˜1ÔÔ'Ø�ŠÕ+¨D¬I°s¸CÈ%ÐPÑPÔPÑQÔQÐQØ×ÒÕ,¨T¬Y¸¸SÈ4ÐPÑPÔPÑQÔQÐQÝ*2¬-ˆŒ	Œ˜Ô˜1ÔÔ'Ø�ŠÕ+¨D¬I°s¸CÈ$ÐOÑOÔOÑPÔPÐPÐPÐPr/   c                 ó®  — |                       | j                             dd¬¦  «        d         ¦  «         |                       | j                             dd¬¦  «        d         ¦  «         |                      | j                             dd¬¦  «        d         ¦  «         |                      | j                             dd¬¦  «        d         ¦  «         d S )NÚzone_player_hideoutF)Úis_dummyr   Úzone_boundless_sanctuaryT)rW   rO   r�   rX   rQ   s    r-   Ú test_11_safe_haven_strict_purityz2TestTileCollision.test_11_safe_haven_strict_purityœ   sÈ   € Ø×Ò˜œ×;Ò;Ð<QÐ\aÐ;ÑbÔbÐcdÔeÑfÔfÐfØ×Ò˜œ×;Ò;Ð<VÐafÐ;ÑgÔgÐhiÔjÑkÔkÐkØ�Š˜œ×:Ò:Ð;PÐ[_Ð:Ñ`Ô`ÐabÔcÑdÔdÐdØ�Š˜œ×:Ò:Ð;UÐ`dÐ:ÑeÔeÐfgÔhÑiÔiÐiÐiÐir/   N)Ú__name__Ú
__module__Ú__qualname__rR   rZ   ra   rj   rm   ro   rq   ry   r{   r…   rˆ   r�   © r/   r-   r<   r<   E   så   € € € € € ð.ð .ð .ðFð Fð FðGð Gð Gð5ð 5ð 5ðGð Gð Gð
Pð Pð Pð
Cð Cð CðBð Bð Bð
Cð Cð Cð0ð 0ð 0ð&Qð Qð Qðjð jð jð jð jr/   r<   Ú__main__)r   F)Ú__doc__r   ÚunittestÚunittest.mockr   Úserver.world.map_data_typesr   r   r   r   r   Úserver.world.zone_enginer	   Ú"server.world.procedural_map_enginer
   ÚfloatÚboolr.   r:   ÚTestCaser<   rŽ   Úmainr‘   r/   r-   ú<module>r�      sœ  ððð ð  €€€Ø €€€Ø Ð Ð Ð Ð Ð ðð ð ð ð ð ð ð ð ð ð ð ð ð ð 0Ð /Ð /Ð /Ð /Ð /Ø BÐ BÐ BÐ BÐ BÐ Bðð ˜kð ¨uð ¸%ð Èð Ðaeð Ðrvð ð ð ð ð*ð ¨ð ¸Eð È%ð ÐUZð Ð`eð Ðotð ð  HLð ð ð ð ð([jð [jð [jð [jð [j˜Ô)ñ [jô [jð [jð| ˆzÒÐØ€H„M�O„O€O€O€Oð Ðr/   