/* ======================================== CYST-KID — Shared Constants & Helpers ======================================== */ const COLS = 28; const ROWS = 22; /* 0=dot 1=wall 2=empty 3=ghostWall 4=ghostDoor 5=tunnel 8=ghostInside */ const MAP = [ [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],//0 [1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1],//1 [1,0,1,1,1,0,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1],//2 [1,0,1,1,1,0,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1],//3 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],//4 [1,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,1,1,1,1,0,1,0,1,1,1,0,1],//5 [1,0,0,0,0,0,1,0,0,0,0,1,0,1,1,0,1,0,0,0,0,1,0,0,0,0,0,1],//6 [1,1,1,1,1,0,1,1,1,1,0,1,0,1,1,0,1,0,1,1,1,1,0,1,1,1,1,1],//7 [1,1,1,1,1,0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,0,1,1,1,1,1],//8 [1,1,1,1,1,0,1,2,1,1,1,3,3,4,4,3,3,1,1,1,2,1,0,1,1,1,1,1],//9 [5,2,2,2,2,0,2,2,1,8,8,8,8,8,8,8,8,8,8,1,2,2,0,2,2,2,2,5],//10 [1,1,1,1,1,0,1,2,1,8,8,8,8,8,8,8,8,8,8,1,2,1,0,1,1,1,1,1],//11 [1,1,1,1,1,0,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,1],//12 [1,1,1,1,1,0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,0,1,1,1,1,1],//13 [1,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,1],//14 [1,0,1,1,1,0,1,1,0,1,1,0,1,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1],//15 [1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1],//16 [1,1,1,0,1,0,1,0,1,1,1,1,0,1,1,0,1,1,1,1,0,1,0,1,0,1,1,1],//17 [1,0,0,0,0,0,1,0,0,0,0,1,0,1,1,0,1,0,0,0,0,1,0,0,0,0,0,1],//18 [1,0,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,0,1,1,1,1,1,1,1,1,0,1],//19 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],//20 [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],//21 ]; const PL0 = {c:14,r:16}; const PH = [{c:12,r:10},{c:15,r:10},{c:12,r:11},{c:15,r:11}]; const MED_SPAWNS = [{r:13,c:14}]; const TILE = 16; const HUD_TOP = 44; const HUD_BOT = 44; const CW = COLS * TILE; const CH = ROWS * TILE + HUD_TOP + HUD_BOT; const FPS = 60; const TICK = 1000 / FPS; const BASE_SPD = 2; // ---- Challenge timing ---- const CHALL_FIRST_MIN = 7; // seconds before first challenge (min) const CHALL_FIRST_MAX = 13; // seconds before first challenge (max) const CHALL_NEXT_MIN = 8; // seconds between challenges (min) const CHALL_NEXT_MAX = 15; // seconds between challenges (max) const CHALL_DURATION = 10; // seconds player has to deliver the med // ---- Player / Ghost ---- const LIVES = 3; // starting lives const WIN_LEVEL = 3; // level at which the player wins const SPEED_MULT = 2; // sprint / super-mode speed multiplier const COLL_DIST = 0.8; // collision detection radius (in tiles) const GHOST_SPD_BASE = 1.2; // ghost base speed (tiles/frame) const GHOST_SPD_LEVEL = 0.2; // ghost speed increase per level const GHOST_SCARED_MULT = 0.55; // ghost speed while scared const GHOST_REL_INTERVAL = 80; // frames between ghost releases const GHOST_REL_OFFSET = 50; // frame offset for first ghost release // ---- Scoring ---- const SC_DOT = 1; // points per dot const SC_GHOST = 5; // points per scared ghost eaten const SC_CHALL = 25; // points for completing a challenge const CO = { bg:'#87CEEB', wall:'#8B5CF6', we:'#A78BFA', dot:'#FFF', cys:'#FFB300', cysE:'#FF8F00', bag:'#88CC44', bagS:'#222', pB:'#DD2222', pBo:'#FFD700', pSc:'#22CC66', kid:'#CC4444', kE:'#FFF', sup:'#00DDFF', hud:'#111133', hudT:'#FFF', gD:'#FFD700', gW:'#6D28D9' }; const T_ROW = 10; // tunnel row const DR={up:-1,down:1,left:0,right:0}; const DC={up:0,down:0,left:-1,right:1}; const OPP={up:'down',down:'up',left:'right',right:'left'}; const DIRS=['up','down','left','right']; // tile query helpers function tile(r,c){return(r>=0&&r=0&&c=COLS))return true; const t=tile(r,c);return t===0||t===2||t===5; } function painOk(r,c){ if(r===T_ROW&&(c<0||c>=COLS))return true; const t=tile(r,c);return t===0||t===2||t===5; }