Files
ark-stronghold-protocol/test/ui/ai-picks-last.test.js
T
anAtheist987 fd791a66cb feedback7 G-SMALL: co-op rooms can make AI teammates draft last (PR #368 by @anAtheist987)
Applied the host-only room option 「AI 队友最后选择」, default off. Off, the draft order and the random streams stay as they are. On, humans draft before AI seats after the existing shuffle, and a skip stays ahead of the AI seats.

Dropped docs/history/0.2.2.md and every §27 citation. The player-facing sentence is in docs/PLAYING.md. The room-option rule is in docs/design/match.md, docs/design/client.md and docs/design/network.md. The #338 per-bot faction and ban presets are not included.

Tests: node --test test/lobby-ai-last.test.js test/match/ai-picks-last.test.js test/ui/ai-picks-last.test.js — 18 pass. node --test test/lobby.test.js test/client-static.test.js — 378 pass. node tools/i18n.mjs check --all --strict — 1032/1032 in en, ja, ko and zh-TW, 0 errors.
2026-10-08 19:57:26 +08:00

39 lines
2.3 KiB
JavaScript

// The room screen's 「AI 队友最后选择」 switch (GitHub #338; server: room.setAiPicksLast, room.state.aiPicksLast): co-op
// rooms only, the host toggles it, everybody else sees its state read-only; the texts go through t() with English in
// public/i18n/en.json.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import path from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
const SRC = readFileSync(path.join(ROOT, 'public/js/screens/room.js'), 'utf8');
const EN = JSON.parse(readFileSync(path.join(ROOT, 'public/i18n/en.json'), 'utf8'));
const mod = () => import(pathToFileURL(path.join(ROOT, 'public/js/screens/room.js')).href);
const room = (o = {}) => ({
code: 'ABCD', hostId: 'h', mode: 'coop', difficulty: 'NORMAL', aiPicksLast: false,
seats: [{ seat: 0, playerId: 'h', name: 'Host', isBot: false, ready: false, connected: true }, { seat: 1, playerId: 'g', name: 'G', isBot: false, ready: false, connected: true }, null, null],
...o,
});
test('aiLastOption: hidden in solo, editable by the host only, the state from room.state (off when absent)', async () => {
const { aiLastOption } = await mod();
assert.equal(aiLastOption(room({ mode: 'solo' }), 'h'), null, 'solo: no AI teammates');
assert.deepEqual(aiLastOption(room(), 'h'), { on: false, editable: true });
assert.deepEqual(aiLastOption(room({ aiPicksLast: true }), 'h'), { on: true, editable: true });
assert.deepEqual(aiLastOption(room({ aiPicksLast: true }), 'g'), { on: true, editable: false });
assert.deepEqual(aiLastOption(room({ aiPicksLast: undefined }), 'g'), { on: false, editable: false }, 'an older server');
assert.equal(aiLastOption(null, 'h'), null);
});
test('room.js sends room.setAiPicksLast { on } and shows the switch through t(); en.json has the English', () => {
assert.match(SRC, /net\.request\('room\.setAiPicksLast', \{ on \}\)/);
for (const zh of ['AI 队友最后选择', '策略与机变轮选时,所有博士先于 AI 队友选择', '由创建者设置']) {
assert.ok(SRC.includes(`t('${zh}')`), zh);
assert.equal(typeof EN[zh], 'string', `en.json: ${zh}`);
assert.ok(EN[zh].length > 0 && !/[一-鿿]/.test(EN[zh]), `English for ${zh}`);
}
});