// Execute actual leaderboard GSC functions with small data, player and clock shims. // This is a fixture check, not a GSC VM, linker or gameplay test. import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import vm from 'node:vm'; const root = new URL('../', import.meta.url); const bytes = (text) => Buffer.from(text, 'utf8').toString('latin1'); const text = (value) => Buffer.from(value, 'latin1').toString('utf8'); let checks = 0; function check(name, run) { try { run(); checks++; } catch (error) { throw new Error(name, { cause: error }); } } function functions(source) { // Protect literals/comments before rewriting the small shared language subset. const literals = []; const protectedSource = source.replace(/"(?:\\.|[^"\\])*"|\/\/[^\n]*|\/\*[\s\S]*?\*\//g, (token) => { if (token.startsWith('/')) return ''; literals.push(token); return `__literal_${literals.length - 1}__`; }); const found = new Map(); const headers = /^(lb_\w+)\(([^\n]*)\)\s*\n\{/gm; for (let match; (match = headers.exec(protectedSource));) { let end = headers.lastIndex, depth = 1; while (depth && end < protectedSource.length) { const ch = protectedSource[end++]; if (ch === '{') depth++; if (ch === '}') depth--; } assert.equal(depth, 0); let body = protectedSource.slice(headers.lastIndex, end - 1); // Each GSC function has its own implicit locals, including recursion. const locals = new Set([...body.matchAll(/(? x[1])); const coroutine = match[1] === 'lb_round_watcher'; body = body.replace(/\btypeof\(/g, 'gscType(').replace(/\.size\b/g, '.length') .replace(/\bwait\s+([\d.]+);/g, coroutine ? 'yield { milliseconds: $1 * 1000 };' : ';'); if (coroutine) body = body.replace(/level waittill\(([^;]+)\);/g, 'yield { entity: level, event: $1 };'); body = body.replace(/__literal_(\d+)__/g, (_, index) => literals[Number(index)]); found.set(match[1], `function${coroutine ? '*' : ''} ${match[1]}(${match[2]}) { var ${[...locals].join(', ') || 'unused'}; ${body} }`); } return found; } function engine(game) { const source = readFileSync(new URL(`${game}/scripts/tws_${game}_leaderboard.gsc`, root), 'utf8'); const all = functions(source); const excluded = new Set(['lb_worker', 'lb_welcome', 'lb_get', 'lb_collect', 'lb_log', 'lb_chat_listener', 'lb_request', 'lb_round_watcher', 'lb_round_start', 'lb_remind_player']); const table = []; for (let i = 1; i < 256; i++) table[String.fromCharCode(i)] = i; const dvars = { mapname: game === 't5' ? 'zombie_theater' : 'zm_transit', ui_gametype: 'zstandard', ui_zm_mapstartlocation: 'town' }; const logs = [], queries = [], responses = []; let now = 1000000; const context = vm.createContext({ level: { tws_lb_game: game, tws_lb_override: '', tws_lb_bytes: table }, GetDvar: (key) => dvars[key] ?? '', getTime: () => now, spawnStruct: () => ({}), isDefined: (value) => value !== undefined && value !== null, gscType: (value) => value === undefined || value === null ? 'undefined' : typeof value === 'object' ? 'array' : typeof value === 'number' ? (Number.isInteger(value) ? 'int' : 'float') : typeof value === 'boolean' ? 'int' : typeof value, toLower: (value) => value.toLowerCase(), getSubStr: (value, start, end) => { assert.equal(typeof value, 'string'); assert(start >= 0 && start <= value.length, `substring start ${start} exceeds ${value.length}`); return value.slice(start, end); }, strTok: (value, delimiter) => value.split(delimiter), int: (value) => Math.trunc(Number(value)), lb_log: (message) => logs.push(message), lb_get: (query) => { queries.push(query); assert(responses.length, 'unexpected request'); return responses.shift(); }, }); vm.runInContext([...all].filter(([name]) => !excluded.has(name)).map(([, code]) => code).join('\n'), context); return { context, all, source, dvars, responses, queries, logs, get now() { return now; }, setTime(value) { now = value; } }; } function roundRuntime(game) { const e = engine(game), c = e.context; const players = [], attempts = [], shown = [], records = [], notifications = [], endEvents = []; const current = (player, run) => { const prior = c.self; c.self = player; try { return run(); } finally { c.self = prior; } }; c.getPlayers = () => players; c.endon = (entity, event) => { assert.equal(entity, c.level); endEvents.push(event); }; c.playerReminder = (player, snapshot, message) => current(player, () => c.lb_remind_player(snapshot, message)); c.reminderService = (player, snapshot, message) => { const notice = { player, snapshot, message, round: c.level.round_number }; attempts.push(notice); if (player.busy) return false; shown.push(notice); return true; }; c.recordService = (player, snapshot) => records.push({ player, snapshot }); c.playerNotify = (player, event) => notifications.push({ player, event }); for (const name of ['lb_round_start', 'lb_remind_player', 'lb_request', 'lb_round_watcher']) { const code = e.all.get(name) .replace(/\b(?:self|level) endon\([^;]*\);/g, declaration => name === 'lb_round_watcher' ? declaration.replace('level endon(', 'endon(level, ') : '') .replace(/players\[i\] lb_remind_player\(/g, 'playerReminder(players[i], ') .replace(/self scripts\\(?:sp|zm)\\tws_t[56]_common::show_record_reminder\(/g, 'reminderService(self, ') .replace(/self scripts\\(?:sp|zm)\\tws_t[56]_common::show_record\(/g, 'recordService(self, ') .replace(/self notify\(/g, 'playerNotify(self, '); vm.runInContext(code, c); } let watcher, stopped = false; const resumeWatcher = () => { const step = watcher.next(); assert.equal(step.done, false); assert.equal(step.value.entity, c.level); assert.equal(step.value.event, 'start_of_round'); }; const startWatcher = () => { if (watcher) return; watcher = c.lb_round_watcher(); resumeWatcher(); }; return { ...e, players, attempts, shown, records, notifications, endEvents, get now() { return e.now; }, readyPlayer(fields = {}) { const player = { sessionstate: 'playing', tws_lb_last_request: e.now - 30000, ...fields }; players.push(player); return player; }, cache(round, saved_at = e.now) { return (c.level.tws_lb_cache = { round, saved_at, lines: ['Holder'] }); }, round(round) { c.level.round_number = round; c.lb_round_start(round); }, request(player, manual) { return current(player, () => c.lb_request(manual)); }, startWatcher, startRoundEvent(round) { c.level.round_number = round; if (stopped) return; startWatcher(); resumeWatcher(); }, end(event) { if (endEvents.includes(event)) { stopped = true; watcher.return(); } }, }; } function mapOption(game) { return game === 't5' ? { game, map: 'zombie_theater', key: 't5:zombie_theater', name: 'Kino Der Toten' } : { game, map: 'zm_transit', key: 't6:zm_transit:town', name: 'Town Survival' }; } function entry(option, guid, name = `Player ${guid}`, round = 52) { return { guid, name: bytes(name), rank: round === 52 ? 1 : 10, highestRound: round, records: { highestRound: { game: option.game, mapKey: option.key, value: round } } }; } function page(option, entries, total, offset = 0, limit = 3, round = 52) { return { entries, total, offset, limit, metric: 'highestRound', maps: [option], summary: { highestRound: round } }; } function discovery(option) { return page(option, [], 0, 0, 1, 0); } for (const game of ['t5', 't6']) { const { context: c, source, all, dvars, responses, queries } = engine(game); const option = mapOption(game); check(`${game} exactly one connect listener across modules`, () => { const common = readFileSync(new URL(`${game}/scripts/tws_${game}_common.gsc`, root), 'utf8'); assert.equal((common.match(/waittill\("connected"/g) ?? []).length, 1); assert(!source.includes('waittill("connected"')); assert(!all.get('lb_welcome').includes('spawned_player')); if (game === 't6') assert(!all.get('lb_welcome').includes('self.hasSpawned')); assert(source.includes('register_connect_handler(::lb_welcome)')); }); check(`${game} record replay uses only a fresh complete cache`, () => { assert.equal(c.lb_cached_record(), undefined); const snapshot = { saved_at: 1000000, round: 52, lines: ['Alice'] }; c.level.tws_lb_cache = snapshot; assert.equal(c.lb_cached_record(), snapshot); snapshot.saved_at = 100000; assert.equal(c.lb_cached_record(), snapshot); snapshot.saved_at--; assert.equal(c.lb_cached_record(), undefined); c.level.tws_lb_cache = { saved_at: 1000000, round: 0, lines: [] }; assert.equal(c.lb_cached_record().round, 0); c.level.tws_lb_cache = undefined; assert.equal(queries.length, 0); }); check(`${game} common owns the record service window`, () => { const commonPath = game === 't5' ? 'scripts\\sp\\tws_t5_common' : 'scripts\\zm\\tws_t6_common'; assert(source.includes(`self ${commonPath}::show_record(snapshot);`)); assert(!source.includes('lb_show_hud')); assert(!source.includes('lb_hud_')); assert(!source.includes('tws_help_elems')); assert(!source.includes('iPrintLnBold')); assert(!source.includes('make_text_elem')); assert(!source.includes('tws_t5_hud') && !source.includes('tws_t6_hud')); }); check(`${game} manual missing/stale requests cancel welcome and reach the service`, () => { const calls = []; c.self = { notify: (event) => calls.push(['notify', event]) }; c.recordService = (snapshot) => calls.push(['record', snapshot]); const request = all.get('lb_request') .replace(/\b(?:self|level) endon\([^;]*\);/g, '') .replace(/\bself notify\(/g, 'self.notify(') .replace(/\bself scripts\\(?:sp|zm)\\tws_t[56]_common::show_record\(/g, 'recordService('); vm.runInContext(request, c); for (const cached of [undefined, { saved_at: 1, round: 52, lines: ['Alice'] }]) { c.level.tws_lb_cache = cached; c.lb_request(false); assert.deepEqual(calls, []); c.lb_request(true); assert.deepEqual(calls, [['notify', 'tws_lb_requested'], ['record', undefined]]); calls.length = 0; } const snapshot = { saved_at: 1000000, round: 0, lines: [] }; c.level.tws_lb_cache = snapshot; c.lb_request(false); assert.deepEqual(calls, [['record', snapshot]]); calls.length = 0; c.lb_request(true); assert.deepEqual(calls, [['notify', 'tws_lb_requested'], ['record', snapshot]]); c.level.tws_lb_cache = undefined; }); for (const [record, expected] of [ [50, [30, 35, 40, 42, 44, 45, 46, 47, 48, 49, 50, 51]], [53, [33, 38, 43, 45, 47, 48, 49, 50, 51, 52, 53, 54]], ]) check(`${game} record ${record} reminders accelerate relative to the target`, () => { const e = roundRuntime(game); e.readyPlayer(); e.cache(record); for (let round = 1; round <= record + 10; round++) e.round(round); assert.deepEqual(e.shown.map(notice => notice.round), expected); assert.equal(e.shown[0].message, '20 rounds away from matching it'); assert.equal(e.shown.at(-3).message, '1 round away from matching it'); assert.equal(e.shown.at(-2).message, 'Record round reached!'); assert.equal(e.shown.at(-1).message, 'Recorded high round passed!'); assert.equal(e.context.level.tws_lb_chase_finished, true); assert.equal(e.queries.length, 0); }); check(`${game} low records avoid round-one history and handle short approaches`, () => { for (const record of [0, 1, 2, 6]) { const e = roundRuntime(game); e.readyPlayer(); e.cache(record); for (let round = 0; round <= record + 4; round++) e.round(round); const expected = record < 2 ? [] : Array.from({ length: record + 1 }, (_, i) => i + 1); assert.deepEqual(e.shown.map(notice => notice.round), expected); } }); check(`${game} absent, expired and empty caches skip reminders without fetching`, () => { const e = roundRuntime(game); e.readyPlayer(); for (const cached of [undefined, { round: 0, saved_at: e.now }, { round: 1, saved_at: e.now }, { round: 50, saved_at: e.now - 900001 }]) { e.context.level.tws_lb_cache = cached; e.round(30); e.round(51); assert.equal(e.context.level.tws_lb_chase_finished, undefined); } assert.equal(e.attempts.length, 0); const stillUsable = e.cache(50, e.now - 900000); e.round(30); assert.equal(e.shown.length, 1); assert.equal(e.shown[0].snapshot, stillUsable); assert.equal(e.queries.length, 0); }); check(`${game} the next round uses the latest cache without a mid-round announcement`, () => { const e = roundRuntime(game); e.readyPlayer(); const first = e.cache(50); e.round(35); const raised = e.cache(60); assert.equal(e.shown.length, 1); e.round(40); const corrected = e.cache(55); e.round(45); assert.deepEqual(e.shown.map(notice => notice.snapshot), [first, raised, corrected]); assert.deepEqual(e.shown.map(notice => notice.message), [ '15 rounds away from matching it', '20 rounds away from matching it', '10 rounds away from matching it', ]); assert.equal(e.queries.length, 0); }); check(`${game} overtaking finishes this match's chase even after cache changes or a busy client`, () => { const e = roundRuntime(game); e.readyPlayer(); e.cache(50); e.round(50); e.round(51); e.round(52); e.cache(70); e.round(55); e.round(70); e.round(71); assert.deepEqual(e.shown.map(notice => notice.round), [50, 51]); const busy = roundRuntime(game); const player = busy.readyPlayer({ busy: true }); busy.cache(50); busy.round(51); assert.equal(busy.attempts.length, 1); assert.equal(busy.shown.length, 0); player.busy = false; busy.round(52); assert.equal(busy.attempts.length, 1, 'a skipped milestone cannot become a delayed celebration'); }); check(`${game} each client must be ready and thirty seconds past welcome or manual replay`, () => { const e = roundRuntime(game); const playing = e.readyPlayer(); const spectator = e.readyPlayer({ sessionstate: 'spectator' }); e.readyPlayer({ tws_lb_last_request: undefined }); e.readyPlayer({ tws_lb_last_request: e.now - 29999 }); for (const sessionstate of [undefined, 'connecting', 'dead']) e.readyPlayer({ sessionstate }); e.cache(50); e.round(45); assert.deepEqual(e.shown.map(notice => notice.player), [playing, spectator]); assert.equal(e.context.lb_player_ready({ ...playing, tws_lb_last_request: e.now - 30000 }), true); }); check(`${game} welcome attempts and manual requests reset the reminder cooldown`, () => { const e = roundRuntime(game); const player = e.readyPlayer({ tws_lb_last_request: undefined }); e.request(player, false); assert.equal(player.tws_lb_last_request, e.now); assert.equal(e.records.length, 0, 'missing initial cache still releases the welcome readiness gate'); e.setTime(e.now + 29999); assert.equal(e.context.lb_player_ready(player), false); e.setTime(e.now + 1); assert.equal(e.context.lb_player_ready(player), true); e.cache(50); e.round(45); e.request(player, true); assert.equal(player.tws_lb_last_request, e.now); assert.equal(e.records.length, 1); assert.equal(e.notifications[0].event, 'tws_lb_requested'); e.round(46); assert.equal(e.shown.length, 1); e.setTime(e.now + 29999); assert.equal(e.context.lb_player_ready(player), false); e.setTime(e.now + 1); e.round(47); assert.deepEqual(e.shown.map(notice => notice.round), [45, 47]); }); check(`${game} reminder readiness follows the engine's spectator/introscreen rules`, () => { const e = roundRuntime(game), c = e.context; const player = e.readyPlayer({ sessionstate: 'spectator', hasSpawned: false }); if (game === 't5') { assert.equal(c.lb_player_ready(player), false); player.hasSpawned = true; assert.equal(c.lb_player_ready(player), true); delete player.hasSpawned; assert.equal(c.lb_player_ready(player), true); } else { assert.equal(c.lb_player_ready(player), true, 'T6 spectator newcomers keep hasSpawned false'); c.level.passed_introscreen = false; assert.equal(c.lb_player_ready(player), false); c.level.passed_introscreen = true; assert.equal(c.lb_player_ready(player), true); } }); check(`${game} watcher waits for real starts and suppresses repeats, decreases and skipped starts`, () => { const e = roundRuntime(game), observed = []; e.context.lb_round_start = round => observed.push(round); e.context.level.round_number = 30; e.startWatcher(); assert.deepEqual(observed, [], 'loading mid-round must not synthesize an announcement'); e.context.level.round_number = 31; assert.deepEqual(observed, [], 'a counter change before the actual start must not announce'); for (const round of [undefined, -1, 31, 31, 29, 30, 31, 34, 34]) e.startRoundEvent(round); assert.deepEqual(observed, [31, 34], 'a skipped round emits only the newly observed start'); const fresh = roundRuntime(game), initial = []; fresh.context.lb_round_start = round => initial.push(round); fresh.startRoundEvent(0); fresh.startRoundEvent(1); fresh.startRoundEvent(1); assert.deepEqual(initial, [1]); assert(source.includes('level thread lb_round_watcher();')); assert(!all.get('lb_round_watcher').includes('hud_round_changed')); assert(!all.get('lb_round_watcher').includes('tws_t5_hud')); assert(!all.get('lb_round_watcher').includes('tws_t6_hud')); }); for (const event of ['end_game', 'game_ended', 'intermission']) check(`${game} ${event} stops the independent round watcher`, () => { const e = roundRuntime(game); e.readyPlayer(); e.cache(50); e.context.level.round_number = 44; e.startWatcher(); e.startRoundEvent(45); assert.deepEqual(e.endEvents, ['end_game', 'game_ended', 'intermission']); e.end(event); e.startRoundEvent(46); assert.deepEqual(e.shown.map(notice => notice.round), [45]); }); check(`${game} unicode and URL encoding`, () => { assert.equal(c.lb_url_encode(bytes('t6:zm_transit:town /?&=#é')), 't6%3Azm_transit%3Atown%20%2F%3F%26%3D%23%C3%A9'); assert.equal(text(c.lb_display_text(bytes('^1Alice\n^7 René 🧟'), 64)), 'Alice René 🧟'); assert.equal(text(c.lb_display_text(bytes('abc🧟'), 6)), 'abc...'); assert.equal(text(c.lb_display_text(bytes('abc🧟'), 7)), 'abc🧟'); }); const valid = [discovery(option), { text: 'René 🧟 " \\ /\n\r\t\b\f', n: -1.23e-4, yes: true, no: false, empty: null }, [], {}, 0, -0.2, 'hello', true, null]; for (const value of valid) check(`${game} valid JSON ${JSON.stringify(value).slice(0, 60)}`, () => { assert.equal(c.lb_json_valid(bytes(JSON.stringify(value))), true); }); check(`${game} escaped unicode pair and whitespace`, () => { assert.equal(c.lb_json_valid(' \n{"s":"\\u00e9 \\uD83E\\uDDDF"}\t'), true); }); const invalid = ['', ' ', 'Error', '{', '{"a":}', '{"a":1,}', '[1,]', '[,1]', '{a:1}', 'true false', '{"a":"\\q"}', '{"a":"raw\nline"}', '"\\ud800"', '"\\udc00"', '"\\ud800\\u0041"', '"\\u0000"', '"\\uX001"', '"unterminated', '01', '-01', '+1', '.5', '1.', '1e', '1e+', '1e999', '1'.repeat(33), 'NaN', 'Infinity', '['.repeat(18) + '0' + ']'.repeat(18), '"' + 'a'.repeat(20480) + '"', '"\xc0\xaf"', '"\xed\xa0\x80"', '"\xf4\x90\x80\x80"', '"\xff"', '"\xc2"']; for (const value of invalid) check(`${game} malformed JSON ${JSON.stringify(value).slice(0, 50)}`, () => { assert.equal(c.lb_json_valid(value), false); }); check(`${game} every truncated prefix of a valid API response`, () => { const body = JSON.stringify(page(option, [entry(option, '000123')], 1)); for (let i = 0; i < body.length; i++) assert.equal(c.lb_json_valid(body.slice(0, i)), false, `accepted prefix ${i}`); }); check(`${game} success schema rejects API errors and bad field types`, () => { for (const value of [{ ok: false, error: 'bad request' }, [], null, 'oops', { ...discovery(option), entries: 'no' }, { ...discovery(option), metric: undefined }, { ...discovery(option), limit: "1" }, { ...discovery(option), total: -1 }]) { assert.equal(c.lb_page_valid(value, 0, 1), false); } }); check(`${game} one holder`, () => { responses.push(discovery(option), page(option, [entry(option, '000123', 'Alice')], 1)); const result = c.lb_refresh(); assert.equal(result.round, 52); assert.deepEqual(Array.from(result.names), ['Alice']); assert(queries.at(-1).includes(`map=${encodeURIComponent(option.key)}`)); }); check(`${game} every tie across pages, with repeated GUID and identical names`, () => { const tied = Array.from({ length: 8 }, (_, i) => entry(option, `${i}`, i < 2 ? 'Same name' : `Holder ${i}`)); tied.splice(3, 0, tied[2]); responses.push(discovery(option), page(option, tied.slice(0, 3), 10), page(option, tied.slice(3, 6), 10, 3), page(option, tied.slice(6, 9), 10, 6), page(option, [entry(option, 'lower', 'Lower', 51)], 10, 9)); const result = c.lb_refresh(); assert.equal(result.names.length, 8); assert.equal(result.names.filter((x) => x === 'Same name').length, 2); assert(!result.names.includes('Lower')); assert.equal(queries.at(-1).includes('offset=9'), true); }); check(`${game} no records versus missing response`, () => { responses.push(discovery(option), page(option, [], 0, 0, 3, 0)); assert.equal(c.lb_refresh().round, 0); responses.push({ ...discovery(option), maps: [] }); assert.equal(c.lb_refresh().round, 0); responses.push(undefined); assert.equal(c.lb_refresh(), undefined); }); check(`${game} failed later page never returns partial holders`, () => { responses.push(discovery(option), page(option, [entry(option, '1'), entry(option, '2'), entry(option, '3')], 4), undefined); assert.equal(c.lb_refresh(), undefined); }); check(`${game} changing top record / total rejects mixed pages`, () => { for (const [total, round] of [[4, 53], [5, 52]]) { responses.push(discovery(option), page(option, [entry(option, '1'), entry(option, '2'), entry(option, '3')], 4), page(option, [entry(option, '4')], total, 3, 3, round)); assert.equal(c.lb_refresh(), undefined); } }); check(`${game} wrong map evidence rejects response`, () => { const wrong = entry({ ...option, key: 'wrong' }, '1'); responses.push(discovery(option), page(option, [wrong], 1)); assert.equal(c.lb_refresh(), undefined); }); check(`${game} explicit key must match current game and map`, () => { c.level.tws_lb_override = 't6:zm_transit:town'; const wrong = { ...option, game: 'wrong', key: c.level.tws_lb_override }; responses.push(discovery(wrong)); assert.equal(c.lb_refresh(), undefined); c.level.tws_lb_override = ''; }); check(`${game} all holders fit bounded service rows`, () => { const names = Array.from({ length: 100 }, (_, i) => `Holder ${i}`); const lines = Array.from(c.lb_holder_lines(names)); assert(lines.every((line) => c.lb_holder_width(line) <= 16)); assert.deepEqual(lines.join(', ').split(', '), names); assert.deepEqual(Array.from(c.lb_holder_lines([])), []); assert.deepEqual(Array.from(c.lb_holder_lines(['Alex', 'Sam', 'Jamie'])), ['Alex, Sam, Jamie']); }); check(`${game} holder width counts glyphs and clips without breaking UTF-8`, () => { const samples = ['M'.repeat(64), 'é'.repeat(32), '🧟'.repeat(16), '玩家名字'.repeat(5), 'abcdefghijklééé', '^1Alice\n^7 René 🧟', '^1\n\t']; for (const sample of samples) { const value = c.lb_holder_name(bytes(sample)); assert(c.lb_holder_width(value) <= 16, sample); assert(c.lb_utf8_valid(value), sample); assert(!text(value).includes('\uFFFD'), sample); assert(!/[\x00-\x1f\x7f^]/.test(value), sample); assert(value.length > 0, sample); } assert.equal(c.lb_holder_name('M'.repeat(64)), 'M'.repeat(13) + '...'); assert.equal(text(c.lb_holder_name(bytes('🧟'.repeat(16)))), '🧟'.repeat(6) + '...'); assert.equal(c.lb_holder_name('^1\n\t'), 'Unknown player'); assert.equal(c.lb_holder_width(bytes('René 🧟')), 8); const names = Array(100).fill(bytes('同じ名前'.repeat(5))); const rows = Array.from(c.lb_holder_lines(names)); assert.equal(rows.length, names.length, 'identical long names still represent every holder'); assert(rows.every((line) => c.lb_holder_width(line) <= 16 && c.lb_utf8_valid(line))); }); if (game === 't6') { const variants = [ ['zm_transit', 'zclassic', 'transit', 'transit'], ['zm_transit', 'zstandard', 'town', 'town'], ['zm_transit', 'zstandard', 'farm', 'farm'], ['zm_transit', 'zstandard', 'transit', 'busdepot'], ['zm_nuked', 'zstandard', 'nuked', 'nuked'], ['zm_highrise', 'zclassic', 'rooftop', 'highrise'], ['zm_prison', 'zclassic', 'prison', 'prison'], ['zm_buried', 'zclassic', 'processing', 'buried'], ['zm_tomb', 'zclassic', 'tomb', 'tomb'], ['zm_transit', 'zgrief', 'town', 'towngrief'], ['zm_transit', 'zgrief', 'farm', 'farmgrief'], ['zm_transit', 'zgrief', 'transit', 'busdepotgrief'], ['zm_prison', 'zgrief', 'cellblock', 'cellblock'], ['zm_buried', 'zgrief', 'street', 'buriedgrief'], ['zm_transit_dr', 'zcleansed', 'diner', 'diner'], ['zm_buried', 'zcleansed', 'street', 'buriedturned'], ]; for (const [map, mode, location, slug] of variants) check(`T6 ${slug}`, () => { assert.equal(c.lb_t6_selection({ map }, mode, location).key, `t6:${map}:${slug}`); }); check('T6 unknown variant does not fall back to available Town', () => { dvars.ui_gametype = 'unknown'; assert.equal(c.lb_selection(), undefined); dvars.ui_gametype = 'zstandard'; }); check('T6 live stock settings take precedence over changed dvars', () => { c.level.scr_zm_ui_gametype = 'zclassic'; c.level.scr_zm_map_start_location = 'transit'; assert.equal(c.lb_selection().key, 't6:zm_transit:transit'); }); } assert.equal(responses.length, 0, `${game} unused responses`); } check('paired data helpers stay identical', () => { const t5 = functions(readFileSync(new URL('t5/scripts/tws_t5_leaderboard.gsc', root), 'utf8')); const t6 = functions(readFileSync(new URL('t6/scripts/tws_t6_leaderboard.gsc', root), 'utf8')); for (const [name, fn] of t5) { if (!['lb_selection', 'lb_welcome', 'lb_get', 'lb_log', 'lb_player_ready'].includes(name)) { const normalized = t6.get(name).replaceAll('scripts\\zm\\tws_t6_common::', 'scripts\\sp\\tws_t5_common::'); assert.equal(normalized, fn, name); } } }); console.log(`PASS ${checks} leaderboard fixture/static checks (both games). Engine linking and gameplay still require Plutonium.`);