All files / js stairs.js

72.28% Statements 120/166
76.47% Branches 26/34
50% Functions 9/18
72.28% Lines 120/166

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 16773x 73x 73x 73x 73x 73x 73x 73x 73x 402x 402x 402x 402x 402x 402x 402x 402x 402x 402x 402x 73x 73x 73x     73x 73x 73x 2094x 3608x 3608x 1382x 2094x 73x 73x 73x             73x 73x 73x 23x 39x 39x 39x 39x 39x 1x 23x 73x 73x 73x 71x 71x 71x   71x 73x 73x 73x           73x 73x 73x 1x 1x 3x 3x 3x   1x 73x 73x 73x 292x 292x 292x 292x 292x 292x 2x 2x 2x 292x 292x 292x 292x 246x 246x 246x 292x 73x 73x                     73x 73x 73x 1x 1x 1x     1x 73x 73x 73x 71x 71x 71x     71x 73x 73x 73x             73x 73x 73x 1784x 1784x 73x 73x 73x       73x 73x 73x       73x 73x 73x       73x 73x 73x      
// stairs.js — Staircase management (port of stairs.c)
// C ref: stairs.c — stairway linked list, hero placement on stairs
 
import { game } from './gstate.js';
import { LR_DOWNTELE, LR_UPTELE } from './const.js';
import { place_lregion } from './mkmaze.js';
 
// C ref: stairs.c:8 stairway_add() — add a stairway to the linked list
export function stairway_add(x, y, up, isladder, dest) {
    const stway = {
        sx: x,
        sy: y,
        up: !!up,
        isladder: !!isladder,
        u_traversed: false,
        tolev: { dnum: dest?.dnum ?? 0, dlevel: dest?.dlevel ?? 0 },
        next: game.stairs ?? null,
    };
    game.stairs = stway;
}
 
// C ref: stairs.c:27 stairway_free_all() — clear the stairway list
export function stairway_free_all() {
    game.stairs = null;
}
 
// C ref: stairs.c:39 stairway_at() — find stairway at position
export function stairway_at(x, y) {
    for (let s = game.stairs; s; s = s.next) {
        if (s.sx === x && s.sy === y) return s;
    }
    return null;
}
 
// C ref: stairs.c:50 stairway_find() — find stairway by destination level
export function stairway_find(fromdlev) {
    for (let s = game.stairs; s; s = s.next) {
        if (s.tolev.dnum === fromdlev.dnum && s.tolev.dlevel === fromdlev.dlevel)
            return s;
    }
    return null;
}
 
// C ref: stairs.c:63 stairway_find_from() — find by destination + type
export function stairway_find_from(fromdlev, isladder) {
    for (let s = game.stairs; s; s = s.next) {
        if (s.tolev.dnum === fromdlev.dnum
            && s.tolev.dlevel === fromdlev.dlevel
            && s.isladder === isladder)
            return s;
    }
    return null;
}
 
// C ref: stairs.c:78 stairway_find_dir() — find by direction
export function stairway_find_dir(up) {
    for (let s = game.stairs; s; s = s.next) {
        if (s.up === up) return s;
    }
    return null;
}
 
// C ref: stairs.c:88 stairway_find_type_dir() — find by type + direction
export function stairway_find_type_dir(isladder, up) {
    for (let s = game.stairs; s; s = s.next) {
        if (s.isladder === isladder && s.up === up) return s;
    }
    return null;
}
 
// C ref: stairs.c:98 stairway_find_special_dir() — find cross-dungeon stairs
export function stairway_find_special_dir(up) {
    const upBool = !!up;
    for (let s = game.stairs; s; s = s.next) {
        if (s.tolev.dnum !== (game.u?.uz?.dnum ?? 0) && s.up !== upBool)
            return s;
    }
    return null;
}
 
// C ref: dungeon.c:1568 u_on_newpos() — place hero at new position
export function u_on_newpos(x, y) {
    if (!game.u) return;
    game.u.ux = x;
    game.u.uy = y;
    game.u.uundetected = 0;
    // Ridden steed shares hero position
    if (game.u.usteed) {
        game.u.usteed.mx = x;
        game.u.usteed.my = y;
    }
    // When changing levels, initialize ux0/uy0
    if (game.u.uz && game.u.uz0
        && (game.u.uz.dnum !== game.u.uz0.dnum
            || game.u.uz.dlevel !== game.u.uz0.dlevel)) {
        game.u.ux0 = x;
        game.u.uy0 = y;
    }
}
 
// STUB: u_on_rndspot — random placement
async function u_on_rndspot(upflag) {
    const up = (upflag & 1) !== 0;
    const area = up ? (game.updest || {}) : (game.dndest || {});
    await place_lregion(
        area.lx || 0, area.ly || 0, area.hx || 0, area.hy || 0,
        area.nlx || 0, area.nly || 0, area.nhx || 0, area.nhy || 0,
        up ? LR_UPTELE : LR_DOWNTELE,
        null
    );
}
 
// C ref: stairs.c:113 u_on_sstairs() — place hero on special stairs
export async function u_on_sstairs(upflag) {
    const stway = stairway_find_special_dir(upflag);
    if (stway)
        u_on_newpos(stway.sx, stway.sy);
    else
        await u_on_rndspot(upflag);
}
 
// C ref: stairs.c:125 u_on_upstairs() — place hero on upstairs
export async function u_on_upstairs() {
    const stway = stairway_find_dir(true);
    if (stway)
        u_on_newpos(stway.sx, stway.sy);
    else
        await u_on_sstairs(0);
}
 
// C ref: stairs.c:136 u_on_dnstairs() — place hero on downstairs
export async function u_on_dnstairs() {
    const stway = stairway_find_dir(false);
    if (stway)
        u_on_newpos(stway.sx, stway.sy);
    else
        await u_on_sstairs(1);
}
 
// C ref: stairs.c:147 On_stairs() — is position on stairs?
export function On_stairs(x, y) {
    return stairway_at(x, y) !== null;
}
 
// C ref: stairs.c:153 On_ladder() — is position on a ladder?
export function On_ladder(x, y) {
    const stway = stairway_at(x, y);
    return !!(stway && stway.isladder);
}
 
// C ref: stairs.c:161 On_stairs_up() — is position on upstairs?
export function On_stairs_up(x, y) {
    const stway = stairway_at(x, y);
    return !!(stway && stway.up);
}
 
// C ref: stairs.c:169 On_stairs_dn() — is position on downstairs?
export function On_stairs_dn(x, y) {
    const stway = stairway_at(x, y);
    return !!(stway && !stway.up);
}
 
// C ref: stairs.c:179 known_branch_stairs()
export function known_branch_stairs(sway) {
    return !!(sway && sway.tolev.dnum !== (game.u?.uz?.dnum ?? 0) && sway.u_traversed);
}