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.
This commit is contained in:
1 parent
d31de31e31
commit
2eaef154d5
5 files changed
+98
-16
No files matched your search
+13
-13
@@ -1623,7 +1623,7 @@
|
||||
"boost": null,
|
||||
"setup": {"stageId":"act1autochess_m03","bossId":"boss_7","hiddenBossId":"boss_10","factions":["ELEMENT","INVISIBLE","REFLECTION"]},
|
||||
"end": {"victory":true,"roundsPassed":14,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":55,"bossPoolLeft":0,"virtualMs":122900},
|
||||
"rng": {"setup":25,"shop":461,"waves":0,"draft":34,"bots":16433,"meta":20},
|
||||
"rng": {"setup":25,"shop":503,"waves":0,"draft":34,"bots":16504,"meta":20},
|
||||
"errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0},
|
||||
"rounds": [
|
||||
{"round":1,"h_0":[1,27,4,0,0,5,1,"3e4697a0",0,"",5,5,0,3],"ai_0":[1,28,4,0,0,1,2,"a1734bc6",0,"sargonShip 0/2, soloShip 1/0",5,5,0,4]},
|
||||
@@ -1666,18 +1666,18 @@
|
||||
},
|
||||
{
|
||||
"round": 11,
|
||||
"h_0": [1,27,14,0,2,5,8,"7c42dc27",357,"arcaneShip 0/2, indomShip 1/16, preciShip 2/109, sargonShip 1/137, skillfulShip 1/8, steadShip 1/51, suntShip 1/0, victoriaShip 0/19, visiShip 1/36",19,19,0,105],
|
||||
"h_0": [1,27,14,0,2,6,8,"a5cfb056",363,"arcaneShip 0/2, indomShip 1/16, preciShip 2/116, sargonShip 1/139, steadShip 1/51, suntShip 1/0, swiftShip 1/5, victoriaShip 0/19, visiShip 1/36",19,19,0,106],
|
||||
"ai_0": [1,28,12,0,0,5,8,"fe5ac1a4",53,"sargonShip 0/4, siracusaShip 1/12, skillfulShip 1/12, soloShip 1/0, suntShip 2/0, visiShip 1/0, yanShip 1/29",19,19,0,99]
|
||||
},
|
||||
{
|
||||
"round": 12,
|
||||
"h_0": [1,27,16,0,2,6,8,"3cdb76eb",388,"arcaneShip 0/2, indomShip 2/16, preciShip 2/141, sargonShip 1/179, skillfulShip 0/8, steadShip 0/51, suntShip 1/0, victoriaShip 0/19, visiShip 1/52",33,33,0,122],
|
||||
"ai_0": [1,28,12,0,0,6,8,"547fcf92",67,"sargonShip 0/8, siracusaShip 1/16, skillfulShip 1/18, soloShip 1/0, suntShip 2/0, yanShip 1/33",16,33,17,112]
|
||||
"h_0": [1,27,16,0,2,6,8,"750c100e",381,"arcaneShip 0/2, emptyShip 1/0, indomShip 0/16, preciShip 2/148, sargonShip 1/181, steadShip 0/51, suntShip 1/0, swiftShip 0/5, victoriaShip 0/19, visiShip 1/52",33,33,0,125],
|
||||
"ai_0": [1,28,12,0,0,6,8,"d3c53bfd",63,"sargonShip 0/8, siracusaShip 1/12, skillfulShip 1/18, soloShip 1/0, suntShip 2/0, visiShip 1/0, yanShip 1/33",18,33,15,112]
|
||||
},
|
||||
{
|
||||
"round": 13,
|
||||
"h_0": [1,27,16,0,0,6,8,"d0f5bd71",508,"arcaneShip 0/2, indomShip 1/16, preciShip 2/173, sargonShip 1/239, skillfulShip 0/8, steadShip 0/51, suntShip 1/0, swiftShip 1/12, victoriaShip 0/19, visiShip 1/68",50,50,0,138],
|
||||
"ai_0": [1,28,12,0,0,6,8,"d2ff3200",90,"sargonShip 0/8, siracusaShip 1/24, skillfulShip 1/24, soloShip 1/0, suntShip 2/0, victoriaShip 0/5, yanShip 1/42",32,50,18,125]
|
||||
"h_0": [1,27,16,4,0,6,8,"d90306b7",486,"arcaneShip 0/2, indomShip 0/16, maniShip 1/0, preciShip 2/166, sargonShip 1/209, steadShip 0/51, suntShip 1/0, swiftShip 0/5, victoriaShip 1/31, visiShip 1/80",50,50,0,140],
|
||||
"ai_0": [1,28,12,0,0,6,8,"5700d2b4",81,"miraShip 1/0, sargonShip 0/8, siracusaShip 1/20, skillfulShip 1/24, soloShip 1/0, suntShip 2/0, visiShip 1/0, yanShip 1/37",14,50,36,124]
|
||||
}
|
||||
],
|
||||
"players": {
|
||||
@@ -1691,9 +1691,9 @@
|
||||
"title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"},
|
||||
"trophies": 4,
|
||||
"reward": 400,
|
||||
"stats": {"activatedLayers":534,"bossDamage":572474,"dmgDealt":4818483,"gold":154,"itemsEquipped":23,"kills":349,"leaks":0,"lpLost":0,"merges":4,"perfectRounds":13,"refreshes":23},
|
||||
"lineup": ["5_21_b@12,8[3_07_e_b+1_05_e_a]","5_22_a@11,7","4_20_b@11,8","5_02_a@10,5[5_01_e_a+6_01_e_a]","6_05_a@10,6[2_01_e_a+4_08_e_a]","6_06_a@10,8[1_01_e_a+3_04_e_a]","4_07_b@9,8[5_03_e_a+4_11_e_b]","4_23_b@9,9[4_04_e_a]"],
|
||||
"bonds": ["arcaneShip 0/2","indomShip 1/16","preciShip 2/173","sargonShip 1/239","skillfulShip 0/8","steadShip 0/51","suntShip 1/0","swiftShip 1/22","victoriaShip 0/19","visiShip 1/84"]
|
||||
"stats": {"activatedLayers":502,"bossDamage":596123,"dmgDealt":5126250,"gold":156,"itemsEquipped":23,"kills":364,"leaks":0,"lpLost":0,"merges":4,"perfectRounds":13,"refreshes":29},
|
||||
"lineup": ["6_05_a@12,8[2_01_e_a+4_08_e_a]","5_02_a@11,6[5_01_e_a+6_01_e_a]","6_08_a@11,7[3_09_e_a]","4_20_b@11,8[6_07_e_a+1_05_e_a]","6_11_a@10,6","5_21_b@10,8[3_04_e_a+6_09_e_a]","4_07_b@9,8[3_07_e_a+5_07_e_a]","4_23_b@9,9[4_04_e_b+4_11_e_a]"],
|
||||
"bonds": ["arcaneShip 0/2","indomShip 0/16","maniShip 1/0","preciShip 2/166","sargonShip 1/209","steadShip 0/51","suntShip 1/0","swiftShip 0/5","victoriaShip 1/31","visiShip 1/96"]
|
||||
},
|
||||
"ai_0": {
|
||||
"alive": true,
|
||||
@@ -1705,9 +1705,9 @@
|
||||
"title": {"id":"comment_3","name":"坚若磐石","picId":"comment_icon_3","text":"目标生命值损失最少"},
|
||||
"trophies": 4,
|
||||
"reward": 400,
|
||||
"stats": {"activatedLayers":113,"bossDamage":215026,"dmgDealt":2640057,"gold":137,"itemsEquipped":20,"kills":247,"leaks":46,"lpLost":0,"merges":6,"perfectRounds":8,"refreshes":13},
|
||||
"lineup": ["6_05_a@12,8[3_07_e_a+6_09_e_a]","2_04_b@11,7","1_07_b@11,8","6_11_a@10,6","3_03_b@10,8[3_11_e_b+2_04_e_a]","5_02_a@9,7[1_02_e_b]","1_08_b@9,8[4_06_e_a+1_05_e_a]","3_02_b@9,9[4_10_e_a+4_11_e_a]"],
|
||||
"bonds": ["maniShip 1/0","preciShip 1/0","sargonShip 1/8","siracusaShip 1/24","skillfulShip 1/30","soloShip 1/0","suntShip 2/0","victoriaShip 0/10","yanShip 1/51"]
|
||||
"stats": {"activatedLayers":105,"bossDamage":191377,"dmgDealt":2449031,"gold":135,"itemsEquipped":20,"kills":231,"leaks":62,"lpLost":0,"merges":6,"perfectRounds":8,"refreshes":12},
|
||||
"lineup": ["2_04_b@12,8[6_02_e_a+6_09_e_a]","5_02_a@11,7","6_05_a@11,8","5_20_a@10,5[1_05_e_a+1_02_e_b]","6_11_a@10,6","3_03_b@10,8[3_11_e_b+2_04_e_a]","1_08_b@9,8[4_06_e_a+4_11_e_a]","3_02_b@9,9[4_04_e_a]"],
|
||||
"bonds": ["maniShip 1/0","miraShip 1/0","preciShip 1/0","sargonShip 1/8","siracusaShip 1/28","skillfulShip 1/30","soloShip 1/0","suntShip 1/0","visiShip 1/0","yanShip 1/39"]
|
||||
}
|
||||
},
|
||||
"diy": {
|
||||
@@ -1730,7 +1730,7 @@
|
||||
[9,"",""],
|
||||
[10,"",""],
|
||||
[11,"",""],
|
||||
[12,"",""],
|
||||
[12,"","6_diy1_a→char_609_acguad"],
|
||||
[13,"",""]
|
||||
],
|
||||
"stock": {"chess_char_5_diy1_a":8,"chess_char_5_diy2_a":8,"chess_char_6_diy1_a":5,"chess_char_6_diy2_a":5}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// 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();
|
||||
});
|
||||
Reference in new issue
Block a user