Files
ark-stronghold-protocol/test/match/feedback5-we2-bot-diy.test.js
T
sganggs 2eaef154d5 feedback5 WE2: AI 托管 buys the player's own 自选 pieces more readily and levels toward them a round earlier (#13)
bot.js: the player's own slotted piece scores DIY_PIECE_BONUS (12) more; levelUp takes the
step that opens a slotted tier with copies left one round earlier (diyOpensAt). Bots field
no 自选 piece. Exports buyScoreOf / levelUp / diyOpensAt for the tests. Docs: DESIGN §6.6,
PLAYING. Golden: coop2-NORMAL-70-diy moved — the 自选 seat under AI 托管 reaches level 6 one
round earlier and fields its tier-6 Sharp at round 12.
2026-10-06 15:54:07 +08:00

59 lines
2.7 KiB
JavaScript

// test/match/feedback5-we2-bot-diy.test.js — 0.2.0 WE2 #13: AI 托管 of a human with 自选 picks buys the player's own slotted
// pieces more readily (bot.js buyScore +DIY_PIECE_BONUS) and levels the 调度中心 one round earlier for the step that opens a
// slotted tier (levelUp, diyOpensAt). Bots field no 自选 piece: nothing changes for them.
// Run: node --test test/match/feedback5-we2-bot-diy.test.js
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { buyScoreOf, levelUp, diyOpensAt, DIY_PIECE_BONUS } from '../../server/match/bot.js';
import { diyGameData } from '../../server/match/player/diy.js';
import { makeMatch, give, chessOfTier, checkInvariants } from './harness.js';
const T5A = 'chess_char_5_diy1_a';
const PICK = { charId: 'char_112_siege', skillIndex: 2, uniEquipId: 'uniequip_002_siege' }; // 推进之王
function prep(seed = 911) {
const seats = [
{ seat: 0, playerId: 'p_0', name: 'P0', isBot: false, connected: true, diy: { [T5A]: PICK } },
{ seat: 1, playerId: 'p_1', name: 'P1', isBot: false, connected: true },
];
const h = makeMatch({ mode: 'coop', difficulty: 'NORMAL', seats, seed }).start();
h.toPrep(1);
return { h, m: h.m, p0: h.ps('p_0'), p1: h.ps('p_1') };
}
test('#13 buyScore: the player\'s own 自选 piece scores DIY_PIECE_BONUS more than the same record without the 自选 mark', () => {
const { m, p0 } = prep();
const rec = p0.gd.chess(T5A);
assert.ok(rec.diyFor, 'a composed 自选 record');
const withMark = buyScoreOf(m, p0, T5A);
// the same player and record, only the 自选 mark taken off (a view of the match's data with that record)
const plain = { ...rec };
delete plain.diyFor;
const saved = p0.gd;
p0.gd = diyGameData(m.gd, new Map([[T5A, plain]]));
let without;
try { without = buyScoreOf(m, p0, T5A); } finally { p0.gd = saved; }
assert.equal(withMark - without, DIY_PIECE_BONUS);
checkInvariants(m);
m.dispose();
});
test('#13 levelUp: one round earlier for the step that opens a slotted tier (round 9: level 4 → 5 at a price above 2); a player without picks waits', () => {
const { m, p0, p1 } = prep(912);
m.round = 9;
for (const ps of [p0, p1]) {
ps.shop.level = 4;
ps.shop.upgradePrice = 5;
ps.funds = 6;
const ids = chessOfTier(1).filter((id) => m.pool.has(id) && m.pool.left(id) > 0).slice(0, 6);
for (const id of ids) give(m, ps, id, 'hand');
}
assert.ok(diyOpensAt(p0, 5) && !diyOpensAt(p1, 5) && !diyOpensAt(p0, 6));
levelUp(m, p0);
levelUp(m, p1);
assert.equal(p0.shop.level, 5, 'p_0 (a tier-5 自选 piece) levels now');
assert.equal(p1.shop.level, 4, 'p_1 waits for round 10 (LEVEL_TARGET)');
m.dispose();
});