feedback4: every melee chess whose trait reads 可以放置于远程位 may stand on a 高台, normal or elite, any module
The owner's decision of 2026-10-05 reverses the one of 2026-10-04 (elite 歌蕾蒂娅 with HOK-Y only) and follows PRTS: the line is the 钩索师 / 推击手 branch trait (歌蕾蒂娅, 崖心, 见行者, normal and elite) and every module keeps it, so the loadout no longer matters. Raised with the PRTS source in PR #69 by @sunstricken (its own change covered only 歌蕾蒂娅; its test page is not taken). GitHub #153. - shared/highGround.js: meleeOnHighGround(rec) reads the trait without a module (traitBase, else trait); no module id. - board.js positionClass(rec) widens those six records; placeClass(ps, rec) = positionClass(rec) for every server check (g.move, swaps, merge tile, evictions, audit, invariants). The client's piecePosition mirrors it. - bot.js: the existing 高台 preference (a 高台 whose range covers the road) now applies to all six; comments. - Docs: DESIGN §3 and §6.6, DATA (placement), PLAYING §4, META, research 03 C2, code comments. data/ unchanged (build-data --offline gives identical files). - Tests: board, feedback1-placement (each holder with default / no module / every module on each 高台, a 重装 refused, client highlights, swap, battle, bots), gameLogic. Golden: 16 scenarios moved, every one because tools/golden.mjs lays operators out by positionClass and now places 歌蕾蒂娅 (normal, or elite with HOK-X) beside the enemy path like a ranged operator instead of on the busiest melee tile, which shifts the others: roster-010, roster-012, roster-029, roster-040, roster-041; bond-deputShip-high, bond-indomShip-low, bond-preciShip-low, bond-preciShip-high, bond-suntShip-low, bond-swiftShip-high; boss-boss_2-pair, boss-boss_4-pair, boss-boss_6-pair, hidden-boss_8-pair, hidden-boss_10-pair. roster-031 (elite with HOK-Y, already widened) and all matches are unchanged.
This commit is contained in:
1 parent
02b76989fa
commit
83fc408a55
18 files changed
+734
-756
No files matched your search
@@ -808,9 +808,9 @@ function buildChess(ctx) {
|
||||
rec.subProfessionName = uniequip.subProfDict?.[char.subProfessionId]?.subProfessionName || null;
|
||||
rec.position = char.position;
|
||||
rec.nationId = char.nationId || null;
|
||||
// 高台 is not a data flag. The trait line 「可以放置于远程位」 is on every 钩索师 / 推击手 variant and is not
|
||||
// trusted: only elite 歌蕾蒂娅 carrying HOK-Y may stand there, decided at place time (shared/highGround.js,
|
||||
// owner's decision 2026-10-04, reversing DESIGN §22.6).
|
||||
// 高台 is not a data flag: a MELEE chess whose trait (no module: `traitBase` / `trait`) reads 「可以放置于远程位」
|
||||
// — the 钩索师 / 推击手 branch trait — may stand there, read at place time (shared/highGround.js; the owner's
|
||||
// decision of 2026-10-05, following PRTS).
|
||||
|
||||
// Module (only active on golden chess: equipLevel > 0).
|
||||
const modId = shop.defaultUniEquipId || null;
|
||||
@@ -3143,7 +3143,7 @@ function validateAll(f) {
|
||||
// DESIGN §16 loadout choices
|
||||
if (!Array.isArray(c.skills) || c.skills.filter((s) => s.isDefault).length !== 1 || c.skills.find((s) => s.isDefault)?.skillId !== c.skill?.skillId) err(`chess ${c.chessId}: skills[] without exactly one default = skill`);
|
||||
if (c.modules && (c.modules.filter((m) => m.isDefault).length !== (c.module?.active ? 1 : 0) || !c.statsBase || !c.traitBase || !c.talentsBase)) err(`chess ${c.chessId}: inconsistent module choices`);
|
||||
// 高台 legality is loadout-aware (shared/highGround.js), never a field on the record
|
||||
// 高台 legality is read from the trait text at place time (shared/highGround.js), never a field on the record
|
||||
if (c.placement !== undefined) err(`chess ${c.chessId}: placement is not a data field`);
|
||||
}
|
||||
// the deliberate trigger deviations (DESIGN §21.29, §22.10) still override an official TAKE_DAMAGE row, on the normal
|
||||
|
||||
+2
-2
@@ -320,12 +320,12 @@ function layout(gd, stageId, wanted, { field = 'normal', colOffset = 0, max = 12
|
||||
const rank = (r, c) => { const d = dist(r, c); return d === 0 ? 1.5 : d; }; // beside a path first, then on it
|
||||
return out.sort((a, b) => rank(a[0], a[1]) - rank(b[0], b[1]));
|
||||
};
|
||||
const isMelee = (w) => positionClass(data.chess[w.chessId], w.moduleId) === 'melee';
|
||||
const isMelee = (w) => positionClass(data.chess[w.chessId]) === 'melee';
|
||||
const order = wanted.slice().sort((a, b) => (isMelee(b) - isMelee(a)) || (isMelee(a) ? (data.chess[b.chessId].stats.blockCnt || 0) - (data.chess[a.chessId].stats.blockCnt || 0) : 0));
|
||||
let uid = uid0;
|
||||
for (const w of order) {
|
||||
const rec = data.chess[w.chessId];
|
||||
const free = units.length < max ? tiles(positionClass(rec, w.moduleId)) : [];
|
||||
const free = units.length < max ? tiles(positionClass(rec)) : [];
|
||||
if (!free.length) { rest.push(w); continue; }
|
||||
const [r, c] = free[0];
|
||||
used.add(tileKey(r, c));
|
||||
|
||||
Reference in new issue
Block a user