Ported by hand into the split layout: -83fc408board.js placeClass: the player's loadout no longer counts, as in83fc408. feedback5's 补位 rule stays: a chess the player fields as its stand-in is placed by the stand-in's record (ps.fieldRecord). positionClass(rec) takes no module. -83fc408client piecePosition → public/js/ui/gameLogic/placement.js: meleeOnHighGround(rec) on the stand-in or chess record, no module. The gameLogic.js shim header and deployedModuleId's comment follow; deployedModuleId is kept, still exported and tested. -83fc408PlayerState._placementOf comment → server/match/player/placement.js. -83fc408tools/golden.mjs layout: positionClass without the module, on feedback5's stand-in body (recOf) and in diyLayout. - bonds/core.js (6ab9a06,8a2e0c7) applied cleanly; it equals 13808e3's plus feedback5's i18n toast. shared/highGround.js equals 13808e3's. - data/: only bonds.json (the 阿戈尔 spec text). node tools/build-data.mjs --offline on the merged tree rewrites all 15 files byte-identical. Golden regenerated: 16 scenarios moved, all by83fc408. Each fields 歌蕾蒂娅 (normal, or elite with HOK-X / no module), whom tools/golden.mjs now lays out beside the enemy path like a ranged operator instead of on the busiest melee tile: 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. This is the list in 83fc408's own message. With the 阿戈尔 commits reverted the digests are the same, so those two move nothing in this corpus. The standins, diy and matches families are unchanged: no stand-in or 自选 piece there is 歌蕾蒂娅, 崖心 or 见行者.
46 lines
4.6 KiB
JavaScript
46 lines
4.6 KiB
JavaScript
// Pure in-match UI logic (no DOM, no Preact) — unit-tested in Node (test/ui/*.test.js).
|
||
//
|
||
// Placement legality (`canPlace`) mirrors the server rules of DESIGN §3/§6.2 so the render view can
|
||
// light legal tiles while dragging; the server stays authoritative and may still refuse a move.
|
||
//
|
||
// Board = own normal field (GEO.FIELD rows 9–12, cols 2–10). Melee chess stand on `melee` deploy tiles
|
||
// (LOW, buildable ALL/MELEE) — a melee chess whose trait reads 「可以放置于远程位」 (shared/highGround.js: 歌蕾蒂娅, 崖心,
|
||
// 见行者, any module) on any deploy tile, the 高台 included (piecePosition 'ALL'); ranged chess on `melee ∪ rangedOnly` (stages.json → deployTiles.normal,
|
||
// derived from the tile legend when missing — the legend's `buildable` is the effective type: 深水区 tile_deepsea
|
||
// refuses deployment, PRTS 深水区 地形信息 "拒绝部署(待补充)", player report #3 after 0.1.0). Tokens follow their
|
||
// own `position`; a summon whose text reads "只能部署在召唤者攻击范围内" (tokens.json `ownerRange`: 伺夜's 狼群,
|
||
// 缪尔赛思's 流形) also needs a tile of its owner's attack range (`summonRange`, player report #9). In the prep of a
|
||
// boss round (最终攻势 / 隐秘核心) the tiles are the player's half of the boss field (`deployFieldOf`: 'bossL' /
|
||
// mirrored 'bossR', board (r, c) = stage tile (r − 7, c) / (r − 7, 20 − c)) like the server's deploy map
|
||
// (server/match/board.js field; user playtest #5 item 7) — board coordinates stay the same.
|
||
// Hand = 10 slots (index = col). Temp slots are server-filled only (no move target).
|
||
// Dropping onto an occupied tile/slot swaps (both pieces must be legal at their new spots);
|
||
// an EQUIP item dropped onto a chess piece equips it (tokens can't carry items); an Arts (MAGIC) item
|
||
// dropped on a field tile is used there (g.art). Deploy cap counts chess pieces on the board only
|
||
// (summons don't use a slot, research 00 §8 #11). Only PREP, alive and not-ready players may edit.
|
||
// A board piece dropped on its own tile is legal ('orient'): the direction wheel re-orients it in place
|
||
// (research 09 §1.2); board drops of units go through the wheel before g.move {uid, to, dir} (ui/facing.js).
|
||
//
|
||
// The bodies live in public/js/ui/gameLogic/*.js. Every name this file exported before the split is
|
||
// re-exported below, so existing imports keep working.
|
||
|
||
export { clamp, tileKey } from './gameLogic/shared.js';
|
||
export { phaseMode, isCombatPhase, showDeadPill, isBossPhase } from './gameLogic/phases.js';
|
||
export { prepCamera, prepCameraFor, foldCamera, deployFieldOf, fieldTile, boardTileOf, ownerBandId } from './gameLogic/camera.js';
|
||
export { phaseBanner, prepCapsuleLabel, countdownState, phaseTotalSeconds } from './gameLogic/phases.js';
|
||
export { STATUS_META } from './gameLogic/format.js';
|
||
export { sortedPlayers } from './gameLogic/shared.js';
|
||
export { ownFieldId, homeFieldId, cycleField, watchTarget, switcherLabel, fieldLabel, activeBubbles } from './gameLogic/watch.js';
|
||
export { sortBonds, bondTier, nextThreshold, grantedBonds, pieceBondIds, morphPairings, HARMONY_BOND, harmonyMembers, bondMembers, memberHeadCount, bannedPerBond, disabledBondSets, briefingBondTip, modeOffBonds, bandOffBonds, bandOffLine } from './gameLogic/bonds.js';
|
||
export { priceTone, mergeProgress, mergeTarget, handFull, completesMerge, offerHeader, shopBlockReason, readyFundsPrompt } from './gameLogic/shop.js';
|
||
export { deploySets, stageOverrides, deployMap, effectiveStage, indexPieces, placementContext, piecePosition, tileAllows, summonRange, canPlace, itemAttaches, equipMerges, boardTargets, dropIntent, dropFailureReason } from './gameLogic/placement.js';
|
||
export { normalizeDraft, normalizeSp } from './gameLogic/draft.js';
|
||
export { groupEnemies, PEN, penZoneTiles, penPlacement, previewEnemyKey, factionTypes } from './gameLogic/enemies.js';
|
||
export { snapHud, bossFrac, bossPctText, hasFlag, UF, attackInterval, fmtNum, rangeGridBox } from './gameLogic/format.js';
|
||
export { shortcutFor, closesOnFieldPress, shortcutBlocked } from './gameLogic/shortcuts.js';
|
||
export { DEFAULT_SETTINGS, sanitizeSettings } from './gameLogic/settings.js';
|
||
export { normalizeResult } from './gameLogic/result.js';
|
||
export { chessLoadout, unitLoadout } from './gameLogic/loadout.js';
|
||
export { standInIds, fieldsStandIn, standInOf, cardStandIn, standInGetter, standInLoadout, deployedRecord, deployedModuleId, standInLabel } from './gameLogic/standIn.js';
|
||
export { panelSide, panelSlots, PANEL_RIGHT_GAP, PANEL_RIGHT_BOTTOM, PANEL_RIGHT_BOTTOM_SHOP, BPOP, bondPopupPlace } from './gameLogic/panel.js';
|