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
+20
-27
@@ -4,8 +4,8 @@
|
||||
// stage legend (data/stages.json `tiles[glyph]`: height + buildable) and the stage devices:
|
||||
// 'melee' — LOW tile with buildable ALL/MELEE, or a 深水区 under an active 特制水上平台 (waterPlatform, "在水上建立可以
|
||||
// 部署任意单位的平台"): melee AND ranged chess may stand here ("所有行动内远程干员可部署在近战位").
|
||||
// 'ranged' — HIGH tile with buildable ALL/RANGED, or a tile under an active platform (射击台): ranged only (and elite
|
||||
// 歌蕾蒂娅 carrying HOK-Y, placeClass below).
|
||||
// 'ranged' — HIGH tile with buildable ALL/RANGED, or a tile under an active platform (射击台): ranged only (and the
|
||||
// melee chess whose trait reads 「可以放置于远程位」, positionClass below).
|
||||
// (absent) — not deployable (NONE, forbidden, road lanes, tiles under active crates/mounds, the 深水区 — the legend's
|
||||
// `buildable` is the effective type: tile_deepsea refuses deployment, PRTS 深水区 地形信息
|
||||
// "拒绝部署(待补充)", although its level buildableType is ALL; player report #3 after 0.1.0, 战场#08's
|
||||
@@ -23,10 +23,10 @@
|
||||
// (10–12, 8), which are '#' on the normal field. The result equals stages[id].deployTiles.bossLeft / bossRight
|
||||
// mapped to board coordinates (test/match/playtest5-deploy.test.js).
|
||||
//
|
||||
// Chess follow their `position` (MELEE ⇒ melee tiles, RANGED ⇒ any deployable), except elite 歌蕾蒂娅 carrying module
|
||||
// HOK-Y 淡金坠饰 (uniequip_003_glady: `placeClass` / shared/highGround.js ⇒ any deployable tile). The branch trait
|
||||
// 「可以放置于远程位」 is not read (owner's decision 2026-10-04, reversing DESIGN §22.6): 崖心, 见行者, a normal record,
|
||||
// any other module and no module are ground-only. The equipped module is the player's loadout at place time.
|
||||
// Chess follow their `position` (MELEE ⇒ melee tiles, RANGED ⇒ any deployable), except a MELEE chess whose trait reads
|
||||
// 「可以放置于远程位」 — the 钩索师 / 推击手 branch trait: 歌蕾蒂娅, 崖心, 见行者, normal and elite, any module or none
|
||||
// (shared/highGround.js ⇒ any deployable tile; the owner's decision of 2026-10-05, following PRTS). The loadout does
|
||||
// not change the class.
|
||||
// Tokens follow their own `position` (ALL ⇒ any deployable tile, MELEE ⇒ melee tiles, RANGED ⇒ any deployable).
|
||||
// A token whose text reads "只能部署在召唤者攻击范围内" (tokens.json `ownerRange`: the tacticians' 援军 — 伺夜's 狼群,
|
||||
// 缪尔赛思's 流形; PRTS 狼群 特性) also needs a tile of its owner's attack range: `ownerRangeKeys` = the owner's range
|
||||
@@ -135,37 +135,30 @@ export function buildDeployMap(stage, { deviceOverrides = {}, tileOverrides = {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Placement class of a chess / token record: 'melee' | 'ranged' | 'all'. Widened to 'all' only for elite 歌蕾蒂娅
|
||||
* carrying HOK-Y (`moduleId` = uniequip_003_glady, shared/highGround.js): she may stand on the ranged (高台) tiles.
|
||||
* Any other module, no module, and every other MELEE record stay 'melee'. `chess.json` has no `placement` field.
|
||||
* Placement class of a chess / token record: 'melee' | 'ranged' | 'all'. A MELEE chess whose trait reads
|
||||
* 「可以放置于远程位」 (shared/highGround.js: 歌蕾蒂娅, 崖心, 见行者, normal and elite) is widened to 'all': it may also
|
||||
* stand on the ranged (高台) tiles. Every other MELEE record stays 'melee'. `chess.json` has no `placement` field.
|
||||
* @param {object|null} rec
|
||||
* @param {string|null} [moduleId] equipped module; ignored for tokens and non-golden records
|
||||
*/
|
||||
export function positionClass(rec, moduleId = null) {
|
||||
return meleeOnHighGround(rec, moduleId) ? 'all' : basePositionClass(rec);
|
||||
export function positionClass(rec) {
|
||||
return meleeOnHighGround(rec) ? 'all' : basePositionClass(rec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Placement class of a record under a player's loadout (the module `ps.loadoutFor` resolves, defaults included).
|
||||
* Tokens and records without a chess id ignore the loadout.
|
||||
* @param {{ loadoutFor?: (rec: object) => { moduleId?: string|null }|null }|null} ps
|
||||
* Placement class of a record on a player's board — the server's single entry point for pieces (g.move, swaps, merges,
|
||||
* the audit, the invariants, the bot). Since the owner's decision of 2026-10-05 the player's loadout no longer changes
|
||||
* it (any module, or none), so this is `positionClass(rec)`.
|
||||
* @param {object|null} _ps the player (unused)
|
||||
* @param {object|null} rec
|
||||
*/
|
||||
export function placeClass(ps, rec) {
|
||||
if (!rec || !rec.chessId || !ps || typeof ps.loadoutFor !== 'function') return positionClass(rec);
|
||||
let moduleId = null;
|
||||
try {
|
||||
const lo = ps.loadoutFor(rec);
|
||||
moduleId = lo && typeof lo.moduleId === 'string' ? lo.moduleId : null;
|
||||
} catch {
|
||||
moduleId = null;
|
||||
}
|
||||
return positionClass(rec, moduleId);
|
||||
export function placeClass(_ps, rec) {
|
||||
return positionClass(rec);
|
||||
}
|
||||
|
||||
/**
|
||||
* The record's own position class ('melee' | 'ranged' | 'all'), without the placement widening — the class the battle
|
||||
* plays (a MELEE operator still blocks on a ground tile; on a 高台 it blocks nothing): the bots' blocker test and the
|
||||
* tiles they plan for it (bot.js).
|
||||
* plays (a MELEE operator still blocks on a ground tile; on a 高台 it blocks nothing): the bots' blocker test and their
|
||||
* 高台 preference for a widened melee chess (bot.js isBlocker / planLayoutSteps).
|
||||
*/
|
||||
export function basePositionClass(rec) {
|
||||
const p = rec && typeof rec.position === 'string' ? rec.position.toUpperCase() : 'ALL';
|
||||
|
||||
Reference in new issue
Block a user