§
     ¿jƒ&  ã                   ó<  — d Z ddlZddlZddlZddlmZ  ee¦  «                             ¦   «         j        j        j        Z	e	dz  dz  Z
e
dz  dz  dz  Ze
dz  dz  d	z  Ze
dz  dz  d
z  Zdedefd„Z G d„ dej        ¦  «        Zedk    r ej        ¦   «          dS dS )aX  
Unit & Integration Test Suite: Player Death & Revival State Machine Verification.
Verifies:
1. When killed by a monster, player is flagged as dead (isDead = true) and takes no further damage.
2. Upon revival, player is cleanly teleported back to Safe Haven Hub (zone_boundless_sanctuary)
   with valid coordinates (0.0, 0.0), clearing wilderness procedural grids.
3. Player action locks, animState ('hurt' -> 'idle'), and inputs (joystick, keys, dirX/dirY)
   are fully restored so player can immediately walk, attack, and cast skills.
4. Player movement is not blocked by collision after reviving.
é    N)ÚPathÚclientÚwebappÚjsÚenginezcollision_engine.jszmonster_system.jszcombat_skills.jsÚscript_bodyÚreturnc           
      óþ  — dt          j        t          t          ¦  «        ¦  «        › dt          j        t          t          ¦  «        ¦  «        › dt          j        t          t
          ¦  «        ¦  «        › d| › d�	}t          j        ddd|gd	d	t          t          ¦  «        ¬
¦  «        }|j	        dk    rt          d|j        › d|j        › �¦  «        ‚t          j        |j                             ¦   «         ¦  «        S )z;Runs a simulated Node.js harness evaluating client scripts.a7
  
import fs from 'fs';
import path from 'path';

// Setup Mock DOM & Global Environment
const elements = {};
function mkElement(id) {
  const listeners = {};
  return {
    id,
    style: {},
    dataset: {},
    classList: {
      _classes: new Set(['hidden']),
      add(c) { this._classes.add(c); },
      remove(c) { this._classes.delete(c); },
      contains(c) { return this._classes.has(c); },
      toggle(c, force) {
        if (force === undefined) force = !this._classes.has(c);
        if (force) this.add(c); else this.remove(c);
        return force;
      }
    },
    innerText: '',
    innerHTML: '',
    value: '',
    appendChild(child) {},
    addEventListener(evt, fn) { (listeners[evt] = listeners[evt] || []).push(fn); },
    dispatchEvent(evt) { (listeners[evt.type] || []).forEach(fn => fn(evt)); },
    closest(sel) { return null; }
  };
}

const doc = {
  getElementById: (id) => (elements[id] = elements[id] || mkElement(id)),
  createElement: (tag) => mkElement(tag),
  querySelectorAll: () => [],
  addEventListener: () => {},
  removeEventListener: () => {}
};

const timeouts = [];
global.setTimeout = (fn, ms) => {
  timeouts.push(fn);
  return timeouts.length;
};
global.runAllTimeouts = () => {
  while (timeouts.length > 0) {
    const fn = timeouts.shift();
    fn();
  }
};
global.clearTimeout = () => {};

const win = {
  document: doc,
  addEventListener: () => {},
  removeEventListener: () => {},
  setTimeout: global.setTimeout,
  clearTimeout: global.clearTimeout,
  keys: { 'w': true, 'a': true },
  resetJoystick: () => { win.joystickResetCalled = true; }
};

global.window = win;
global.document = doc;
global.keys = win.keys;

// Mock audio / haptics / rendering functions
global.sfxEngine = new Proxy({}, { get: (target, prop) => () => {} });
global.playAudioFx = () => {};
global.triggerHaptic = () => {};
global.triggerScreenShake = () => {};
global.spawnDamageText = () => {};
global.spawnGoreAndBoneBurst = () => {};
global.spawnParticles = () => {};
global.spawnInfernalSlash = () => {};
global.spawnLightningStrike = () => {};
global.spawnGlacialSpikes = () => {};
global.particles = [];
global.groundDrops = [];
global.worldToIso = (wx, wy) => ({ x: wx * 32, y: wy * 16 });
global.updatePlayerHpUI = () => {};

// Mock player entity
global.player = {
  level: 1, maxHp: 100, hp: 100, isDead: false,
  wx: 10.0, wy: 10.0, dirX: 1.0, dirY: 0.5,
  animState: 'idle', facing: 1, speed: 5.5,
  attackTimer: 0.2, attackDuration: 0.32,
  destination: { wx: 15, wy: 15, active: true }
};
win.player = global.player;

// Load collision engine
(0, eval)(fs.readFileSync(aq  , 'utf8'));

// Import worldmap dungeons
const { teleportToZone, showNoticeModal } = await import('./client/webapp/js/ui/worldmap_dungeons.js');
global.teleportToZone = teleportToZone;
win.teleportToZone = teleportToZone;
global.showNoticeModal = showNoticeModal;
win.showNoticeModal = showNoticeModal;

// Load monster system in global scope
(0, eval)(fs.readFileSync(zM, 'utf8'));

// Load combat skills in global scope
(0, eval)(fs.readFileSync(z, 'utf8'));

ú
Únodez--input-type=modulez-eT)Úcapture_outputÚtextÚcwdr   zHarness failed:
)ÚjsonÚdumpsÚstrÚCOLLISION_ENGINE_JSÚMONSTER_SYSTEM_JSÚCOMBAT_SKILLS_JSÚ
subprocessÚrunÚPROJECT_ROOTÚ
returncodeÚRuntimeErrorÚstderrÚstdoutÚloadsÚstrip)r   ÚrunnerÚress      ú=C:\Projects\FreeExile\tests\unit\test_player_death_revival.pyÚrun_revival_node_harnessr"      s  € ðoõ~  œ:¥cÕ*=Ñ&>Ô&>Ñ?Ô?ðoð oõR  œ:¥cÕ*;Ñ&<Ô&<Ñ=Ô=ðSoð oõX  œ:¥cÕ*:Ñ&;Ô&;Ñ<Ô<ðYoð oð\ ð]oð oð o€Fõ` Œ.˜&Ð"7¸¸vÐFÐW[ÐbfÕloÕp|Ñl}Ôl}Ð
~Ñ
~Ô
~€CØ
„~˜ÒÐÝÐI¨s¬zÐIÐI¸S¼ZÐIÐIÑJÔJÐJÝŒ:�c”j×&Ò&Ñ(Ô(Ñ)Ô)Ð)ó    c                   ó   — e Zd ZdZd„ Zd„ ZdS )ÚTestPlayerDeathAndRevivalzUTest suite ensuring player death cleanly revives and restores all mobility & actions.c                 óª  — d}t          |¦  «        }|                      |d         |d         d¦  «         |                      |d         d¦  «         |                      |d         dd	¦  «         |                      |d
         d¦  «         |                      |d         dd¦  «         |                      |d         dd¦  «         |                      |d         d¦  «         |                      |d         dd¦  «         |                      |d         d¦  «         |                      |d         dd¦  «         |                      |d         dd¦  «         dS )zqWhen killed in a wilderness zone, player must respawn at sanctuary (0,0) with valid collision and idle animState.aP  
// Simulate player in wilderness zone with procedural grid loaded
window.currentZoneId = 'zone_tang_kiem_nhai';
window.currentMapWidth = 40;
window.currentMapHeight = 40;
window.currentMapGrid = new Uint8Array(40 * 40);
window.getTileAt = (tx, ty) => 1; // 1 = WALKABLE_DIRT

// Fatal attack on player
executeMonsterAttackOnPlayer({ attackDmg: 500, id: 'mob_hound', wx: 10, wy: 10 });

// Trigger the scheduled revival timeout(s)
global.runAllTimeouts();

// Check state after revival
const isBlocked = isPositionBlocked(player.wx, player.wy, 0.35);
const slideMove = resolveMovementWithSliding(player.wx, player.wy, 0.5, 0.0, 0.35);

const result = {
  hp: player.hp,
  maxHp: player.maxHp,
  isDead: player.isDead,
  animState: player.animState,
  wx: player.wx,
  wy: player.wy,
  zoneId: window.currentZoneId,
  mapGridCleared: window.currentMapGrid === null,
  isPositionBlocked: isBlocked,
  slideMovementAllowed: (slideMove.wx !== player.wx || slideMove.wy !== player.wy),
  destActive: player.destination?.active,
  dirX: player.dirX,
  dirY: player.dirY
};
console.log(JSON.stringify(result));
ÚhpÚmaxHpz-Player HP must be fully restored upon revivalÚisDeadz)Player isDead must be false after revivalÚzoneIdÚzone_boundless_sanctuaryz*Player must respawn at Boundless SanctuaryÚmapGridClearedz@Wilderness map grid must be cleared upon respawning in sanctuaryÚwxg        z*Player respawn wx must be 0.0 at SanctuaryÚwyz*Player respawn wy must be 0.0 at SanctuaryÚisPositionBlockedz6Player spawn location must NOT be blocked by collisionÚ	animStateÚidlez+Player animState must be idle after revivalÚ
destActivez*Old movement destination must be cancelledÚdirXr   z$dirX must be reset to 0 upon revivalÚdirYz$dirY must be reset to 0 upon revivalN)r"   ÚassertEqualÚassertFalseÚ
assertTrue©ÚselfÚscriptÚdatas      r!   Ú9test_revival_restores_mobility_and_clears_wilderness_gridzSTestPlayerDeathAndRevival.test_revival_restores_mobility_and_clears_wilderness_grid“   s_  € ð"ˆõF (¨Ñ/Ô/ˆà×Ò˜˜dœ T¨'¤]Ð4cÑdÔdÐdØ×Ò˜˜hœÐ)TÑUÔUÐUØ×Ò˜˜hœÐ)CÐEqÑrÔrÐrØ�Š˜Ð-Ô.Ð0rÑsÔsÐsØ×Ò˜˜dœ SÐ*VÑWÔWÐWØ×Ò˜˜dœ SÐ*VÑWÔWÐWØ×Ò˜Ð1Ô2Ð4lÑmÔmÐmØ×Ò˜˜kÔ*¨FÐ4aÑbÔbÐbØ×Ò˜˜lÔ+Ð-YÑZÔZÐZØ×Ò˜˜fœ qÐ*PÑQÔQÐQØ×Ò˜˜fœ qÐ*PÑQÔQÐQÐQÐQr#   c                 ó4  — d}t          |¦  «        }|                      |d         d         ¦  «         |                      |d         d         d¦  «         |                      |d         d¦  «         |                      |d         d	¦  «         |                      |d
         d¦  «         |                      |d         dd¦  «         |                      |d         d         ¦  «         |                      |d         d         |d         d         ¦  «         |                      |d         d         d¦  «         |                      |d         d         dd¦  «         |                      |d         d         d¦  «         |                      |d         d¦  «         dS )zpWhen player is dead, actions and skills are locked. After revival, attacks, dodge and potions function normally.a¯  
window.currentZoneId = 'zone_tang_kiem_nhai';
// 1. Kill player
executeMonsterAttackOnPlayer({ attackDmg: 500, id: 'mob_hound', wx: 10, wy: 10 });

const deadState = {
  isDead: player.isDead,
  hp: player.hp
};

// Try acting while dead
doPrimaryAttack();
const attackWhileDeadFired = (player.attackTimer > 0 || player.animState === 'attack');

doDodge();
const dodgeWhileDeadFired = !!player.isIFrame;

drinkHealthPotion();
const potionWhileDeadHealed = (player.hp > 0);

// Extra hit while dead should be ignored
executeMonsterAttackOnPlayer({ attackDmg: 200, id: 'mob_hound', wx: 10, wy: 10 });
const hitWhileDeadHp = player.hp;

// 2. Complete revival
global.runAllTimeouts();

const revivedState = {
  isDead: player.isDead,
  hp: player.hp,
  maxHp: player.maxHp,
  animState: player.animState
};

// 3. Act after revival
doPrimaryAttack();
const attackAfterRevival = {
  attackTimer: player.attackTimer,
  animState: player.animState
};

doDodge();
const dodgeAfterRevival = !!player.isIFrame;

console.log(JSON.stringify({
  deadState,
  attackWhileDeadFired,
  dodgeWhileDeadFired,
  potionWhileDeadHealed,
  hitWhileDeadHp,
  revivedState,
  attackAfterRevival,
  dodgeAfterRevival
}));
Ú	deadStater)   r'   r   ÚattackWhileDeadFiredz'Attacking while dead must be prohibitedÚdodgeWhileDeadFiredz%Dodging while dead must be prohibitedÚpotionWhileDeadHealedz-Drinking potion while dead must be prohibitedÚhitWhileDeadHpz*Taking damage while dead must not alter HPÚrevivedStater(   r0   r1   ÚattackAfterRevivalÚattackTimerz+Player must be able to attack after revivalÚattackÚdodgeAfterRevivalz*Player must be able to dodge after revivalN)r"   r7   r5   r6   ÚassertGreaterr8   s      r!   Ú;test_dead_player_actions_locked_and_revival_restores_combatzUTestPlayerDeathAndRevival.test_dead_player_actions_locked_and_revival_restores_combatÆ   s™  € ð6ˆõn (¨Ñ/Ô/ˆØ�Š˜˜[Ô)¨(Ô3Ñ4Ô4Ð4Ø×Ò˜˜kÔ*¨4Ô0°!Ñ4Ô4Ð4Ø×Ò˜Ð4Ô5Ð7`ÑaÔaÐaØ×Ò˜Ð3Ô4Ð6]Ñ^Ô^Ð^Ø×Ò˜Ð5Ô6Ð8gÑhÔhÐhØ×Ò˜Ð.Ô/°Ð4`ÑaÔaÐaà×Ò˜˜nÔ-¨hÔ7Ñ8Ô8Ð8Ø×Ò˜˜nÔ-¨dÔ3°T¸.Ô5IÈ'Ô5RÑSÔSÐSØ×Ò˜˜nÔ-¨kÔ:¸FÑCÔCÐCà×Ò˜4Ð 4Ô5°mÔDÀaÐIvÑwÔwÐwØ×Ò˜Ð2Ô3°KÔ@À(ÑKÔKÐKØ�Š˜Ð0Ô1Ð3_Ñ`Ô`Ð`Ð`Ð`r#   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r<   rI   © r#   r!   r%   r%   �   sF   € € € € € Ø_Ð_ð1Rð 1Rð 1RðfGað Gað Gað Gað Gar#   r%   Ú__main__)rM   r   r   ÚunittestÚpathlibr   Ú__file__ÚresolveÚparentr   Ú
WEBAPP_DIRr   r   r   r   Údictr"   ÚTestCaser%   rJ   ÚmainrN   r#   r!   ú<module>rY      sA  ðð	ð 	ð €€€Ø Ð Ð Ð Ø €€€Ø Ð Ð Ð Ð Ð àˆt�H‰~Œ~×%Ò%Ñ'Ô'Ô.Ô5Ô<€Ø˜HÑ$ xÑ/€
Ø  4Ñ'¨(Ñ2Ð5JÑJÐ Ø Ñ%¨Ñ0Ð3FÑFÐ Ø Ñ$ xÑ/Ð2DÑDÐ ðu*¨#ð u*°$ð u*ð u*ð u*ð u*ðp}að }að }að }að }a Ô 1ñ }aô }að }að@ ˆzÒÐØ€H„M�O„O€O€O€Oð Ðr#   