feedback5: merge W5E — a full hand refuses buys and reward picks, temp pieces fill freed slots (#82); 联防 plays on the official escaped maps (#41)

# Conflicts:
#	test/golden/fields.json
#	test/golden/matches.json
This commit is contained in:
sganggs committed 2026-10-05 18:19:36 +08:00
commit ece75b6853
37 files changed
+732 -265

No files matched your search

+29
View File
@@ -654,6 +654,7 @@ test('stages: player-facing names are clean Chinese "战场#NN…" labels (no re
// Regression: research 05 named act1 m01 '战场#01 (upper half #01)'; the English note reached the
// briefing BATTLEFIELD row. Names come from research only, so the build must strip such notes.
for (const s of Object.values(stages)) {
if (s.kind === 'unite') continue; // the two 联防 maps: the remake's own label, checked in the 联防 test below
assert.match(s.name, /^战场#\d{2}(?:\((?:上半|下半)\))?(?: \S.*)?$/, `${s.id}: name ${JSON.stringify(s.name)}`);
assert.doesNotMatch(s.name, /[A-Za-z]/, `${s.id}: Latin text in name ${JSON.stringify(s.name)}`);
assert.equal(s.name, s.name.trim().replace(/\s+/g, ' '), `${s.id}: stray whitespace in name`);
@@ -662,6 +663,34 @@ test('stages: player-facing names are clean Chinese "战场#NN…" labels (no re
assert.equal(stages.act2autochess_m01.name, '战场#05(下半) 源石流发生装置');
});
test('stages: the 联防 maps (GitHub #41) — the escaped template levels, one per helper count, never a match stage', () => {
// act2autochess constData escapedBattleTemplateMapSinglePlayer / MultiPlayer → config.unite.templates { 1, 2 }
assert.deepEqual(config.unite.templates, { 1: 'act1autochess_escaped_single', 2: 'act1autochess_escaped_multi' });
for (const [n, id] of Object.entries(config.unite.templates)) {
const s = stages[id];
assert.ok(s, id);
assert.equal(s.kind, 'unite');
assert.equal(s.helpers, Number(n));
assert.equal(s.active, false);
assert.equal(s.weight, 0);
assert.deepEqual(s.modes, []);
assert.ok(!Object.values(config.modes).some((m) => m.stages.includes(id)), `${id} in no mode's stage list`);
assert.equal(s.name, `联防阵地(${n}名玩家)`);
assert.deepEqual(s.devices, [], 'no crates, platforms or other devices');
assert.deepEqual(s.special, {}, 'no water, mire, smog or infection');
// the official level map (level_act1autochess_escaped_*.json): two road halves joined at col 10, not the round's stage
assert.deepEqual(s.rows.slice(9, 13), ['##ErrrrrrrSrrrrrrrS##', '###rrrrrrr#rrrrrrr###', '###rrrrrrr#rrrrrrr###', '###rrrrrrrSrrrrrrrS##']);
for (let r = 9; r <= 12; r++) for (const c of [19, 20]) assert.equal(s.tiles[s.rows[r][c]].groundPassable, false, `${id} (${r},${c}) is no ground`);
assert.ok(s.groundPaths['9,10->9,2'] && s.groundPaths['9,18->9,2'], 'walkable from both gates');
}
// the two maps are tile for tile the same: they differ in their routes (data/waves.json — 1 helper enters at col 10,
// 2 helpers at col 18 through the checkpoint (9,10))
assert.deepEqual(stages.act1autochess_escaped_single.rows, stages.act1autochess_escaped_multi.rows);
assert.deepEqual(waves.act1autochess_escaped_single.routes.map((r) => r.start), [[9, 10], [9, 10], [12, 10], [9, 10], [9, 10], [9, 10], [9, 10], [9, 10]]);
assert.deepEqual(waves.act1autochess_escaped_multi.routes.map((r) => r.start), [[9, 18], [9, 18], [12, 18], [9, 18], [9, 18], [9, 18], [9, 18], [9, 18]]);
assert.deepEqual(waves.act1autochess_escaped_multi.routes[3].checkpoints, [[9, 10]]);
});
test('official spot checks (hard-coded values from the zh_CN client data)', () => {
const st = (id) => { const s = chess[id].stats; return [s.maxHp, s.atk, s.def, s.res, s.blockCnt, s.cost]; };
assert.deepEqual(st('chess_char_6_11_b'), [1893, 492, 141, 0, 1, 15]); // 缪尔赛思 精锐 (E2 60 + module Lv3)
+1 -1
View File
@@ -16,7 +16,7 @@ through.
|---|---|
| `roster` | 49 battles: every visible chess record (normal and elite) with every selectable skill and module (DESIGN §16), 12 operators per battle on a real stage (all 11 in turn) against the round's real wave three times over, every non-leader enemy kind of `data/enemies.json` as extra spawns (half of them bounties), placeable summons on the board, every equipment item, band, battle-side 机变 card and stage map card in turn, bonds from the board |
| `bonds` | 46 battles: every bond at its activation threshold (1 layer) and at its top tier (999 layers) |
| `fields` | 22 battles: every Final Assault / Hidden Core leader on a pair and a solo template (shared pool, 200 s cap) and the 联防 field with 1 and 2 helpers (carried HP / SP, a knocked-out operator, two leakers' enemies) |
| `fields` | 22 battles: every Final Assault / Hidden Core leader on a pair and a solo template (shared pool, 200 s cap) and the 联防 field with 1 and 2 helpers on its own map (carried HP / SP, a knocked-out operator, two leakers' enemies) |
| `matches` | 16 bot-only matches to the end in virtual time: solo 标准 / 险境 / 绝境 / 终极 × 2 seeds, co-op 2 / 3 / 4, one server-run combat match, two runs boosted to the Hidden Core |
Battles go through the production BattleSpec path (`server/sim/spec.js`, as browsers and the server's headless fields
+39 -44
View File
@@ -1283,7 +1283,7 @@
"about": "联防 1 helper(s), 11 leaked: chess_char_6_03_b chess_char_6_06_b chess_char_6_07_b chess_char_6_01_b chess_char_6_02_b chess_char_6_04_b chess_char_6_05_b chess_char_6_08_b token_10017_skadi2_dedant",
"fast": true,
"kind": "unite",
"stageId": "act1autochess_m02",
"stageId": "act1autochess_escaped_single",
"modeId": "mode_multi_normal",
"round": 7,
"seed": 2621626757,
@@ -1295,34 +1295,33 @@
"total": 10,
"unspawned": 0,
"bossHpLeft": null,
"rngDraws": 24,
"rngDraws": 7,
"errors": {"count":0,"kinds":[]},
"players": {"p1":{"killed":10,"total":10,"perfect":true,"leaks":0,"leaksUncounted":1,"coins":3,"dmg":70502,"bossDmg":0,"heal":7510,"deaths":0,"layerGains":{}}},
"players": {"p1":{"killed":10,"total":10,"perfect":true,"leaks":0,"leaksUncounted":1,"coins":3,"dmg":70502,"bossDmg":0,"heal":4602,"deaths":2,"layerGains":{}}},
"units": [
["p1",1,"op","chess_char_6_03_b",2,"uniequip_002_yu",3430,1,2,0,0,0,0,0,0],
["p1",1,"op","chess_char_6_03_b",2,"uniequip_002_yu",3430,1,2,1,912,242,242,1,0],
["p1",2,"op","chess_char_6_06_b",2,"uniequip_002_pepe",1616.45,1,1,0,0,0,0,0,0],
["p1",3,"op","chess_char_6_07_b",2,"uniequip_002_siege2",3101,1,23,0,0,0,0,0,0],
["p1",4,"op","chess_char_6_01_b",2,"uniequip_002_lemuen",2352,1,4,3,17564,0,0,4,1],
["p1",5,"op","chess_char_6_02_b",2,"uniequip_002_sbell2",1933,1,7,1,7345,0,0,1,1],
["p1",6,"op","chess_char_6_04_b",2,"uniequip_002_skadi2",62.12,1,5,1,632,6072,7510,0,4],
["p1",7,"op","chess_char_6_05_b",2,"uniequip_002_pasngr",1442,1,8,4,29637,0,0,0,1],
["p1",8,"op","chess_char_6_08_b",2,"uniequip_002_reed2",1668,1,6,1,15325,0,0,8,1],
["p1",3,"op","chess_char_6_07_b",2,"uniequip_002_siege2",3101,1,22,0,0,0,0,0,0],
["p1",4,"op","chess_char_6_01_b",2,"uniequip_002_lemuen",2352,1,4,2,15306,0,0,8,1],
["p1",5,"op","chess_char_6_02_b",2,"uniequip_002_sbell2",1933,1,7,3,25379,126,0,5,1],
["p1",6,"op","chess_char_6_04_b",2,"uniequip_002_skadi2",311.72,1,23,0,2871,4383,4359,0,3],
["p1",7,"op","chess_char_6_05_b",2,"uniequip_002_pasngr",1442,1,25,4,26035,1404,0,0,1],
["p1",8,"op","chess_char_6_08_b",2,"uniequip_002_reed2",1668,1,6,0,0,0,0,0,0],
["p1",9,"token","token_10017_skadi2_dedant",null,null,100,0,9,0,0,0,0,0,null],
["p1","~1","token","token_10017_skadi2_dedant",null,null,100,0,22,0,0,0,0,0,null],
["p1","~2","token","token_10017_skadi2_dedant",null,null,100,0,24,0,0,0,0,0,null],
["p1","~3","token","token_10017_skadi2_dedant",null,null,100,1,25,0,0,0,0,0,null]
["p1","~1","token","token_10017_skadi2_dedant",null,null,100,0,24,0,0,0,0,0,null],
["p1","~2","token","token_10017_skadi2_dedant",null,null,100,1,26,0,0,0,0,0,null]
],
"enemies": {"enemy_10028_vtswd":[1,0,0,0,0],"enemy_1158_divman":[4,4,0,0,15206],"enemy_1160_hvyslr":[3,3,0,0,34560],"enemy_1161_tidmag":[3,3,0,0,20736]},
"hooks": [1,24,5100,13,13,48,136,293,10,14,8,8,7,11668,21,0,11,0,1,10,0,1,0],
"events": {"atk":15,"bounty":1,"deploy":13,"die":14,"dmg":60,"fx":58,"heal":124,"skill":16,"spawn":23,"status":65},
"fx": {"bombard":7,"bombardShell":7,"burst":1,"lightning":15,"lock":7,"lure":1,"scorchBurst":4,"snow":10,"storm":1,"talent":1,"tide":4},
"snaps": "d0a32c2d 14dc64f8 d9ffb8be 0e32f941 f5f88a89 f3e84df2 97783db6 49fb05e7 d960234b ef9c8339 304bd9e6 d7e7110a 8a0636b9 840cbf99 e365c522 1d462726 178ff4dc"
"enemies": {"enemy_10028_vtswd":[1,0,0,0,0],"enemy_1158_divman":[4,4,0,322,15206],"enemy_1160_hvyslr":[3,3,0,242,34560],"enemy_1161_tidmag":[3,3,0,1596,20736]},
"hooks": [1,25,5100,25,25,59,129,243,12,15,6,5,1,9905,13,1,11,0,1,12,0,1,0],
"events": {"atk":31,"bounty":1,"deploy":14,"die":15,"dmg":79,"fx":40,"heal":73,"skill":11,"spawn":22,"status":39},
"fx": {"bombard":1,"bombardShell":1,"burst":1,"camouflage":1,"lightning":14,"lock":1,"lure":1,"snow":14,"storm":1,"talent":1,"tide":3,"wanted":1},
"snaps": "55586847 bbe93dd8 5bb5e558 d2646601 7210f915 de297199 991f7dc7 b11d3b0a 9572d24f ca2b027d ff63e562 b8302479 9eb55590 bb0bba8a 5b8d04c8 cab0ad61 6aa45251"
},
"unite-2": {
"about": "联防 2 helper(s), 11 leaked: chess_char_6_15_b chess_char_6_17_b chess_char_6_09_b chess_char_6_11_b chess_char_6_12_b chess_char_6_13_b chess_char_6_14_b chess_char_6_16_b token_10030_mlyss_wtrman | chess_char_6_19_b chess_char_5_01_b chess_char_5_05_b chess_char_5_06_b chess_char_6_18_b chess_char_6_20_b chess_char_5_02_b chess_char_5_03_b",
"fast": true,
"kind": "unite",
"stageId": "act1autochess_m07",
"stageId": "act1autochess_escaped_multi",
"modeId": "mode_multi_hard",
"round": 11,
"seed": 1995382690,
@@ -1341,34 +1340,30 @@
"p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":11672,"bossDmg":0,"heal":10253,"deaths":0,"layerGains":{}}
},
"units": [
["p1",1,"op","chess_char_6_15_b",2,"uniequip_002_qiubai",4608,1,36,3,32640,4897,0,21,1],
["p1",2,"op","chess_char_6_17_b",2,"uniequip_002_nearl2",3593,1,39,0,19926,4671,0,15,1],
["p1",3,"op","chess_char_6_09_b",0,"uniequip_002_cello",1322,1,37,0,0,0,0,0,0],
["p1",4,"op","chess_char_6_11_b",2,"uniequip_002_mlyss",1893,1,13,0,0,0,0,0,0],
["p1",5,"op","chess_char_6_12_b",1,"uniequip_002_rosmon",2944.54,1,16,5,74645,0,0,15,1],
["p1",6,"op","chess_char_6_13_b",1,"uniequip_002_angel2",2192.85,1,18,0,0,5746,0,0,0],
["p1",7,"op","chess_char_6_14_b",2,"uniequip_002_lumen",3323.25,1,20,0,0,0,5334,72,1],
["p1",8,"op","chess_char_6_16_b",2,"uniequip_002_halo2",1439,1,11,0,9334,0,0,9,1],
["p1",9,"token","token_10030_mlyss_wtrman",null,null,2062,1,14,0,0,0,0,0,1],
["p2",10,"op","chess_char_6_19_b",2,"uniequip_002_blkkgt",2767,1,6,0,0,0,0,0,0],
["p2",11,"op","chess_char_5_01_b",1,"uniequip_002_excu2",1272.7,1,10,0,0,0,0,0,0],
["p2",12,"op","chess_char_5_05_b",2,"uniequip_002_ulpia",5905,1,38,0,0,0,0,0,0],
["p2",13,"op","chess_char_5_06_b",2,"uniequip_002_etlchi",776.63,1,19,0,0,0,0,0,0],
["p2",14,"op","chess_char_6_18_b",2,"uniequip_002_whitw2",1541,1,8,1,11672,0,0,0,1],
["p2",15,"op","chess_char_6_20_b",2,"uniequip_002_agoat2",1631.88,1,12,0,0,0,10253,25,2],
["p2",16,"op","chess_char_5_02_b",2,"uniequip_002_titi",1554.12,1,17,0,0,0,0,0,0],
["p2",17,"op","chess_char_5_03_b",2,"uniequip_002_blaze2",1589.76,1,21,0,0,0,0,0,0],
["-","~1","device","trap_1105_accrate",null,null,100,1,1,0,0,0,0,0,null],
["-","~2","device","trap_1105_accrate",null,null,100,1,2,0,0,0,0,0,null],
["-","~3","device","trap_1105_accrate",null,null,100,1,3,0,0,0,0,0,null],
["-","~4","device","trap_1105_accrate",null,null,100,1,4,0,0,0,0,0,null],
["p1","~1","token","token_10019_nearl2_sword",null,null,5720.79,0,35,1,27958,279,0,4,null]
["p1",1,"op","chess_char_6_15_b",2,"uniequip_002_qiubai",4608,1,32,3,32640,4897,0,21,1],
["p1",2,"op","chess_char_6_17_b",2,"uniequip_002_nearl2",3593,1,35,0,19926,4671,0,15,1],
["p1",3,"op","chess_char_6_09_b",0,"uniequip_002_cello",1322,1,33,0,0,0,0,0,0],
["p1",4,"op","chess_char_6_11_b",2,"uniequip_002_mlyss",1893,1,9,0,0,0,0,0,0],
["p1",5,"op","chess_char_6_12_b",1,"uniequip_002_rosmon",2944.54,1,12,5,74645,0,0,15,1],
["p1",6,"op","chess_char_6_13_b",1,"uniequip_002_angel2",2192.85,1,14,0,0,5746,0,0,0],
["p1",7,"op","chess_char_6_14_b",2,"uniequip_002_lumen",3323.25,1,16,0,0,0,5334,72,1],
["p1",8,"op","chess_char_6_16_b",2,"uniequip_002_halo2",1439,1,7,0,9334,0,0,9,1],
["p1",9,"token","token_10030_mlyss_wtrman",null,null,2062,1,10,0,0,0,0,0,1],
["p2",10,"op","chess_char_6_19_b",2,"uniequip_002_blkkgt",2767,1,2,0,0,0,0,0,0],
["p2",11,"op","chess_char_5_01_b",1,"uniequip_002_excu2",1272.7,1,6,0,0,0,0,0,0],
["p2",12,"op","chess_char_5_05_b",2,"uniequip_002_ulpia",5905,1,34,0,0,0,0,0,0],
["p2",13,"op","chess_char_5_06_b",2,"uniequip_002_etlchi",776.63,1,15,0,0,0,0,0,0],
["p2",14,"op","chess_char_6_18_b",2,"uniequip_002_whitw2",1541,1,4,1,11672,0,0,0,1],
["p2",15,"op","chess_char_6_20_b",2,"uniequip_002_agoat2",1631.88,1,8,0,0,0,10253,25,2],
["p2",16,"op","chess_char_5_02_b",2,"uniequip_002_titi",1554.12,1,13,0,0,0,0,0,0],
["p2",17,"op","chess_char_5_03_b",2,"uniequip_002_blaze2",1589.76,1,17,0,0,0,0,0,0],
["p1","~1","token","token_10019_nearl2_sword",null,null,5720.79,0,31,1,27958,279,0,4,null]
],
"enemies": {"enemy_10029_vtshld":[1,0,0,0,0],"enemy_1249_lysdb_2":[3,3,0,859,53748],"enemy_1251_lysyta":[4,4,0,0,32846],"enemy_1329_cbshld":[3,3,0,8987,89580]},
"hooks": [1,38,6900,174,174,313,539,506,11,16,9,7,0,19291,439,5,11,0,1,11,0,0,0],
"events": {"atk":274,"bounty":1,"deploy":23,"die":16,"dmg":310,"fx":164,"heal":199,"skill":16,"spawn":33,"status":89},
"hooks": [1,34,6900,174,174,313,539,506,11,16,9,7,0,19291,439,5,11,0,1,11,0,0,0],
"events": {"atk":274,"bounty":1,"deploy":23,"die":16,"dmg":310,"fx":164,"heal":199,"skill":16,"spawn":29,"status":89},
"fx": {"blink":2,"copy":1,"drone":139,"droneLock":9,"drones":2,"garrisonGrant":1,"link":1,"radiantSword":1,"shieldBreak":3,"summon":1,"sunBurst":1,"talent":3},
"snaps": "c4705ca6 4f56b578 010f8693 ca7897bc 279c768c 1d8c9741 d8ab925c 474e2aed 25e7c521 b15154e1 e04d02a8 7f359c91 a32c4824 d77cdf62 dc34029c 99bf46b2 277a7e2a 13be40dc 2eb06e0f f62c09c2 9b9bfcce b6a4c76c d5e7ff8a"
"snaps": "87a560e8 45db343c 0d5cd8db e792866d d5cc68e6 078f9bf4 c8fec815 474d7baf 079475d2 d3772234 c93b6998 574ad909 4ebd4b48 1081da2e 5c69184d e8708f8b 098ca455 4c75c9b4 eec01031 7a5056b5 087553f4 7686d406 9672a226"
}
}
}
+116 -123
View File
@@ -511,7 +511,7 @@
"combat": "client",
"boost": null,
"setup": {"stageId":"act2autochess_m04","bossId":"boss_3","hiddenBossId":"boss_8","factions":["FLY","TIMES","DOT"]},
"end": {"victory":true,"roundsPassed":14,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":55,"bossPoolLeft":0,"virtualMs":119900},
"end": {"victory":true,"roundsPassed":14,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":55,"bossPoolLeft":0,"virtualMs":121400},
"rng": {"setup":25,"shop":449,"waves":0,"draft":40,"bots":21634,"meta":8},
"errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0},
"rounds": [
@@ -568,17 +568,17 @@
{
"round": 11,
"ai_0": [1,45,12,0,2,5,8,"360613f3",118,"arcaneShip 2/34, miraShip 1/0, preciShip 0/10, sargonShip 0/10, siracusaShip 1/56, skillfulShip 0/10, soloShip 1/6, suntShip 1/0, swiftShip 1/22",23,23,0,99],
"ai_1": [1,28,12,0,0,5,8,"07be045d",135,"arcaneShip 2/28, kazimierzShip 1/24, kjeragShip 0/8, preciShip 1/40, sargonShip 0/10, steadShip 1/0, suntShip 1/0, swiftShip 1/43",23,23,0,104]
"ai_1": [1,28,12,0,0,5,8,"bfa85f5f",135,"arcaneShip 2/28, kazimierzShip 1/24, kjeragShip 0/8, preciShip 1/40, sargonShip 0/10, steadShip 1/0, suntShip 1/0, swiftShip 1/43",20,23,3,104]
},
{
"round": 12,
"ai_0": [1,45,14,0,0,6,8,"d434f9ef",168,"arcaneShip 2/46, miraShip 1/6, preciShip 0/10, sargonShip 0/10, siracusaShip 1/68, skillfulShip 1/18, soloShip 1/6, suntShip 1/0, swiftShip 1/24",105,105,0,113],
"ai_1": [1,28,12,0,0,6,8,"e37fca4e",161,"arcaneShip 2/28, kazimierzShip 1/32, kjeragShip 0/8, preciShip 1/45, sargonShip 0/10, soloShip 1/0, suntShip 1/0, swiftShip 1/56",105,105,0,115]
"ai_1": [1,28,12,0,0,6,8,"a81bef38",161,"arcaneShip 2/28, kazimierzShip 1/32, kjeragShip 0/8, preciShip 1/45, sargonShip 0/10, soloShip 1/0, suntShip 1/0, swiftShip 1/56",105,105,0,115]
},
{
"round": 13,
"ai_0": [1,37,12,0,2,6,8,"5deeb03a",214,"arcaneShip 2/70, miraShip 1/12, preciShip 0/10, sargonShip 0/10, siracusaShip 1/98, skillfulShip 1/28, soloShip 1/6, suntShip 1/0, swiftShip 0/32",26,34,8,125],
"ai_1": [1,18,12,0,0,6,8,"41dae901",195,"arcaneShip 2/36, kazimierzShip 1/40, kjeragShip 0/8, preciShip 1/50, sargonShip 0/10, steadShip 1/0, suntShip 1/0, swiftShip 1/69",24,34,10,127]
"ai_1": [1,18,12,0,0,6,8,"49c3b995",195,"arcaneShip 2/36, kazimierzShip 1/40, kjeragShip 0/8, preciShip 1/50, sargonShip 0/10, steadShip 1/0, suntShip 1/0, swiftShip 1/69",22,34,12,127]
}
],
"players": {
@@ -592,7 +592,7 @@
"title": {"id":"comment_2","name":"不朽盟约","picId":"comment_icon_2","text":"激活的盟约层数总和最高"},
"trophies": 4,
"reward": 400,
"stats": {"activatedLayers":250,"bossDamage":287418,"dmgDealt":2928162,"gold":139,"itemsEquipped":12,"kills":331,"leaks":9,"lpLost":8,"merges":5,"perfectRounds":11,"refreshes":23},
"stats": {"activatedLayers":250,"bossDamage":287418,"dmgDealt":3020132,"gold":139,"itemsEquipped":12,"kills":334,"leaks":9,"lpLost":8,"merges":5,"perfectRounds":11,"refreshes":23},
"lineup": ["3_19_b@11,7[2_04_e_b]","5_12_a@11,8","4_10_a@10,5[1_02_e_b+2_01_e_a]","6_06_a@9,4","1_08_b@9,5","6_16_a@9,7","5_20_a@9,8[3_05_e_a+3_02_e_b]","3_13_b@9,9"],
"bonds": ["arcaneShip 2/86","miraShip 1/12","preciShip 0/10","sargonShip 0/10","siracusaShip 1/110","skillfulShip 1/36","soloShip 1/6","suntShip 1/0","swiftShip 0/32"]
},
@@ -606,8 +606,8 @@
"title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"},
"trophies": 4,
"reward": 400,
"stats": {"activatedLayers":205,"bossDamage":421332,"dmgDealt":3168659,"gold":139,"itemsEquipped":16,"kills":317,"leaks":13,"lpLost":10,"merges":5,"perfectRounds":10,"refreshes":13},
"lineup": ["4_20_a@12,8[4_03_e_b+3_06_e_a]","1_17_b@11,7","4_02_b@11,8[4_08_e_a]","4_01_b@10,7[1_02_e_a]","6_17_a@10,8[4_06_e_a+1_05_e_a]","6_19_a@9,7[3_08_e_a+1_01_e_b]","4_14_a@9,8","5_07_a@9,9"],
"stats": {"activatedLayers":205,"bossDamage":421332,"dmgDealt":3034736,"gold":139,"itemsEquipped":16,"kills":312,"leaks":18,"lpLost":10,"merges":5,"perfectRounds":9,"refreshes":13},
"lineup": ["4_20_a@12,8[4_03_e_b+3_06_e_a]","1_17_b@11,7","4_02_b@11,8[4_08_e_a]","4_01_b@10,7[1_02_e_a]","6_17_a@10,8[1_01_e_b+4_06_e_a]","6_19_a@9,7[1_05_e_a+3_08_e_a]","4_14_a@9,8","5_07_a@9,9"],
"bonds": ["arcaneShip 2/36","kazimierzShip 1/40","kjeragShip 0/8","preciShip 2/55","raidShip 1/0","sargonShip 0/10","suntShip 1/0","swiftShip 1/74"]
}
}
@@ -664,22 +664,22 @@
{
"round": 8,
"ai_0": [1,25,11,0,0,4,8,"50b7d162",55,"kazimierzShip 1/16, kjeragShip 0/2, raidShip 1/20, skillfulShip 1/6, soloShip 1/3, steadShip 2/10, swiftShip 0/4",9,9,0,61],
"ai_1": [1,23,13,0,0,4,8,"bdd566ef",15,"arcaneShip 0/2, kazimierzShip 0/2, preciShip 2/15, sargonShip 0/4, siracusaShip 1/0, skillfulShip 1/0, soloShip 1/0, swiftShip 0/2",4,9,5,66]
"ai_1": [1,21,13,0,0,4,8,"bdd566ef",15,"arcaneShip 0/2, kazimierzShip 0/2, preciShip 2/15, sargonShip 0/4, siracusaShip 1/0, skillfulShip 1/0, soloShip 1/0, swiftShip 0/2",4,9,5,66]
},
{
"round": 9,
"ai_0": [1,25,12,0,2,4,8,"468d37f7",70,"kazimierzShip 1/19, kjeragShip 0/2, raidShip 1/28, skillfulShip 0/9, soloShip 1/3, steadShip 2/12, suntShip 1/0, swiftShip 1/8",23,23,0,73],
"ai_1": [1,19,12,0,1,4,8,"f01fb873",39,"arcaneShip 0/2, kazimierzShip 0/2, preciShip 1/28, sargonShip 0/4, siracusaShip 1/4, skillfulShip 1/0, soloShip 1/0, swiftShip 1/7",17,23,6,78]
"ai_1": [1,18,12,0,1,4,8,"f01fb873",39,"arcaneShip 0/2, kazimierzShip 0/2, preciShip 1/28, sargonShip 0/4, siracusaShip 1/4, skillfulShip 1/0, soloShip 1/0, swiftShip 1/7",17,23,6,78]
},
{
"round": 10,
"ai_0": [1,23,14,0,1,5,8,"eb530a8d",82,"kazimierzShip 1/25, kjeragShip 0/2, raidShip 1/28, skillfulShip 0/9, soloShip 1/3, steadShip 2/12, suntShip 1/0, swiftShip 1/14",6,8,2,88],
"ai_1": [1,15,13,0,0,5,8,"ad2dc598",61,"arcaneShip 0/2, kazimierzShip 0/2, preciShip 1/41, sargonShip 0/4, siracusaShip 1/4, skillfulShip 1/2, soloShip 1/0, suntShip 1/0, swiftShip 1/14",4,8,4,91]
"ai_1": [1,14,13,0,0,5,8,"ad2dc598",61,"arcaneShip 0/2, kazimierzShip 0/2, preciShip 1/41, sargonShip 0/4, siracusaShip 1/4, skillfulShip 1/2, soloShip 1/0, suntShip 1/0, swiftShip 1/14",4,8,4,91]
},
{
"round": 11,
"ai_0": [1,13,13,0,1,5,8,"cf13d02e",107,"kazimierzShip 1/33, kjeragShip 0/2, raidShip 1/33, skillfulShip 0/9, soloShip 1/3, steadShip 2/12, suntShip 1/0, swiftShip 1/26",9,27,18,100],
"ai_1": [1,5,12,0,0,5,8,"66c45cf0",83,"arcaneShip 0/2, kazimierzShip 0/2, preciShip 1/50, sargonShip 0/4, siracusaShip 1/8, skillfulShip 1/4, soloShip 1/0, suntShip 1/0, swiftShip 1/21",6,27,21,102]
"ai_1": [1,4,12,0,0,5,8,"66c45cf0",83,"arcaneShip 0/2, kazimierzShip 0/2, preciShip 1/50, sargonShip 0/4, siracusaShip 1/8, skillfulShip 1/4, soloShip 1/0, suntShip 1/0, swiftShip 1/21",6,27,21,102]
},
{
"round": 12,
@@ -703,7 +703,7 @@
"title": {"id":"comment_4","name":"精英云集","picId":"comment_icon_4","text":"晋升精锐次数最多"},
"trophies": 3,
"reward": 298,
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":2550230,"gold":126,"itemsEquipped":8,"kills":204,"leaks":88,"lpLost":32,"merges":4,"perfectRounds":9,"refreshes":13},
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":2497540,"gold":126,"itemsEquipped":8,"kills":203,"leaks":88,"lpLost":32,"merges":4,"perfectRounds":9,"refreshes":13},
"lineup": [],
"bonds": ["kazimierzShip 0/51","kjeragShip 0/2","miraShip 0/7","preciShip 0/8","raidShip 0/34","skillfulShip 0/9","soloShip 0/3","steadShip 0/17","swiftShip 0/38","yanShip 0/6"]
},
@@ -717,7 +717,7 @@
"title": {"id":"comment_5","name":"万事俱备","picId":"comment_icon_5","text":"装备配发数量最多"},
"trophies": 2,
"reward": 255,
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":1355731,"gold":114,"itemsEquipped":11,"kills":160,"leaks":73,"lpLost":31,"merges":3,"perfectRounds":5,"refreshes":19},
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":1355731,"gold":114,"itemsEquipped":11,"kills":160,"leaks":73,"lpLost":32,"merges":3,"perfectRounds":5,"refreshes":19},
"lineup": [],
"bonds": ["arcaneShip 0/2","kazimierzShip 0/2","preciShip 0/59","sargonShip 0/4","siracusaShip 0/8","skillfulShip 0/6","swiftShip 0/23"]
}
@@ -821,7 +821,7 @@
"title": {"id":"comment_4","name":"精英云集","picId":"comment_icon_4","text":"晋升精锐次数最多"},
"trophies": 2,
"reward": 255,
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":4759668,"gold":124,"itemsEquipped":17,"kills":280,"leaks":70,"lpLost":30,"merges":3,"perfectRounds":4,"refreshes":14},
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":4777308,"gold":124,"itemsEquipped":17,"kills":279,"leaks":70,"lpLost":30,"merges":3,"perfectRounds":4,"refreshes":14},
"lineup": [],
"bonds": ["deputShip 0/44","indomShip 0/16","kazimierzShip 0/2","kjeragShip 0/62","miraShip 0/12","siracusaShip 0/6","skillfulShip 0/69","soloShip 0/28","steadShip 0/55","suntShip 0/16","swiftShip 0/26"]
},
@@ -849,7 +849,7 @@
"title": {"id":"comment_5","name":"万事俱备","picId":"comment_icon_5","text":"装备配发数量最多"},
"trophies": 2,
"reward": 191,
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":1500871,"gold":86,"itemsEquipped":5,"kills":199,"leaks":45,"lpLost":28,"merges":2,"perfectRounds":4,"refreshes":14},
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":1500871,"gold":86,"itemsEquipped":5,"kills":199,"leaks":45,"lpLost":29,"merges":2,"perfectRounds":4,"refreshes":14},
"lineup": [],
"bonds": ["deputShip 0/10","miraShip 0/5","siracusaShip 0/84","soloShip 0/22","suntShip 0/6","swiftShip 0/23","yanShip 0/1"]
}
@@ -865,7 +865,7 @@
"combat": "client",
"boost": null,
"setup": {"stageId":"act1autochess_m01","bossId":"boss_3","hiddenBossId":null,"factions":["TIMES","ELEMENT","REFLECTION"]},
"end": {"victory":true,"roundsPassed":14,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":129,"bossPoolLeft":0,"virtualMs":133000},
"end": {"victory":true,"roundsPassed":14,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":130,"bossPoolLeft":0,"virtualMs":133000},
"rng": {"setup":16,"shop":893,"waves":0,"draft":25,"bots":35892,"meta":29},
"errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0},
"rounds": [
@@ -928,35 +928,35 @@
{
"round": 9,
"ai_0": [1,26,12,0,0,4,8,"fc454676",169,"deputShip 1/47, kjeragShip 0/2, preciShip 2/40, sargonShip 1/44, steadShip 1/38",30,30,0,74],
"ai_1": [1,44,12,0,0,4,8,"13fccde5",83,"deputShip 2/48, emptyShip 1/4, preciShip 0/4, sargonShip 0/2, siracusaShip 1/31, steadShip 0/4",26,30,4,70],
"ai_1": [1,45,12,0,0,4,8,"13fccde5",83,"deputShip 2/48, emptyShip 1/4, preciShip 0/4, sargonShip 0/2, siracusaShip 1/31, steadShip 0/4",26,30,4,70],
"ai_2": [1,28,12,0,0,4,8,"6965081a",70,"sargonShip 0/8, siracusaShip 1/58, swiftShip 1/12, visiShip 1/0, yanShip 0/1",30,30,0,72],
"ai_3": [1,31,13,0,0,4,8,"5f784848",153,"deputShip 1/16, emptyShip 1/12, kjeragShip 1/30, preciShip 1/72, siracusaShip 0/3, swiftShip 1/23, yanShip 0/1",30,30,0,76]
},
{
"round": 10,
"ai_0": [1,26,12,0,0,5,8,"2b6a123a",243,"deputShip 1/53, kjeragShip 0/2, preciShip 2/72, sargonShip 1/70, steadShip 1/48",29,29,0,86],
"ai_1": [1,44,12,0,0,5,8,"5bcc6998",105,"deputShip 2/58, emptyShip 1/8, preciShip 0/4, sargonShip 0/2, siracusaShip 1/39, steadShip 0/4",29,29,0,82],
"ai_1": [1,45,12,0,0,5,8,"5bcc6998",105,"deputShip 2/58, emptyShip 1/8, preciShip 0/4, sargonShip 0/2, siracusaShip 1/39, steadShip 0/4",29,29,0,82],
"ai_2": [1,28,12,0,0,5,8,"fe139ef2",72,"sargonShip 0/8, siracusaShip 2/60, swiftShip 1/12, visiShip 1/0, yanShip 0/1",29,29,0,83],
"ai_3": [1,31,12,0,0,5,8,"9ce217c6",161,"deputShip 1/18, emptyShip 0/12, kjeragShip 2/32, preciShip 1/81, siracusaShip 0/3, swiftShip 1/30, yanShip 0/1",29,29,0,88]
},
{
"round": 11,
"ai_0": [1,26,12,0,0,5,8,"5c1d4d08",291,"deputShip 1/55, kjeragShip 0/2, preciShip 1/88, sargonShip 1/90, steadShip 1/58",28,28,0,99],
"ai_1": [1,44,12,0,0,5,8,"28ba083d",133,"deputShip 2/68, emptyShip 1/15, preciShip 0/4, sargonShip 0/2, siracusaShip 1/50, steadShip 0/4",13,28,15,94],
"ai_1": [1,45,12,0,0,5,8,"28ba083d",133,"deputShip 2/68, emptyShip 1/15, preciShip 0/4, sargonShip 0/2, siracusaShip 1/50, steadShip 0/4",13,28,15,94],
"ai_2": [1,28,12,0,0,5,8,"8321f307",126,"emptyShip 1/0, sargonShip 0/8, siracusaShip 2/102, swiftShip 1/24, yanShip 0/1",28,28,0,95],
"ai_3": [1,31,12,0,0,5,7,"5e2bfa81",193,"deputShip 0/18, emptyShip 0/12, kjeragShip 2/66, preciShip 1/92, siracusaShip 0/3, swiftShip 1/35, visiShip 1/0, yanShip 0/1",28,28,0,98]
},
{
"round": 12,
"ai_0": [1,26,12,0,0,6,8,"934bb983",409,"deputShip 1/57, emptyShip 1/2, kjeragShip 0/2, preciShip 1/138, sargonShip 1/144, steadShip 1/68",46,46,0,111],
"ai_1": [1,44,12,0,0,6,8,"d4b1958d",155,"deputShip 2/78, emptyShip 1/19, preciShip 0/4, sargonShip 0/2, siracusaShip 1/58, steadShip 0/4",20,46,26,104],
"ai_1": [1,45,12,0,0,6,8,"d4b1958d",155,"deputShip 2/78, emptyShip 1/19, preciShip 0/4, sargonShip 0/2, siracusaShip 1/58, steadShip 0/4",20,46,26,104],
"ai_2": [1,28,12,0,0,6,8,"696f5ca3",172,"emptyShip 1/0, sargonShip 0/8, siracusaShip 2/148, swiftShip 1/24, yanShip 0/1",46,46,0,106],
"ai_3": [1,31,12,0,0,6,8,"2e3cd509",245,"deputShip 0/18, emptyShip 0/12, kjeragShip 2/106, preciShip 2/99, siracusaShip 0/3, swiftShip 1/40, visiShip 1/0, yanShip 0/1",46,46,0,110]
},
{
"round": 13,
"ai_0": [1,26,12,0,0,6,8,"2df19066",463,"deputShip 1/59, emptyShip 1/4, kjeragShip 0/7, preciShip 2/156, sargonShip 1/166, steadShip 1/78",32,32,0,126],
"ai_1": [1,44,12,0,2,6,8,"9346fb5a",177,"deputShip 1/86, emptyShip 1/21, preciShip 1/6, sargonShip 0/2, siracusaShip 1/64, steadShip 0/4",32,32,0,115],
"ai_1": [1,45,12,0,2,6,8,"9346fb5a",177,"deputShip 1/86, emptyShip 1/21, preciShip 1/6, sargonShip 0/2, siracusaShip 1/64, steadShip 0/4",32,32,0,115],
"ai_2": [1,28,12,0,0,6,8,"0236b2a3",238,"emptyShip 1/0, sargonShip 0/8, siracusaShip 2/214, swiftShip 1/24, yanShip 0/1",32,32,0,117],
"ai_3": [1,31,12,0,0,6,7,"ceba29b5",263,"deputShip 0/18, emptyShip 0/12, kjeragShip 1/114, preciShip 2/104, siracusaShip 0/3, swiftShip 1/45, yanShip 0/1",32,32,0,124]
}
@@ -972,7 +972,7 @@
"title": {"id":"comment_2","name":"不朽盟约","picId":"comment_icon_2","text":"激活的盟约层数总和最高"},
"trophies": 3,
"reward": 250,
"stats": {"activatedLayers":485,"bossDamage":46721,"dmgDealt":1702122,"gold":140,"itemsEquipped":25,"kills":327,"leaks":0,"lpLost":0,"merges":5,"perfectRounds":13,"refreshes":21},
"stats": {"activatedLayers":485,"bossDamage":46721,"dmgDealt":1699612,"gold":140,"itemsEquipped":25,"kills":328,"leaks":0,"lpLost":0,"merges":5,"perfectRounds":13,"refreshes":21},
"lineup": ["6_08_a@11,6[3_03_e_a+3_02_e_a]","6_12_a@11,7[4_08_e_a+6_07_e_b]","2_14_b@10,3","2_17_b@10,4[4_02_e_b+5_01_e_a]","2_08_a@9,3[4_04_e_a+1_01_e_b]","6_06_a@9,4[3_08_e_a+3_01_e_b]","1_06_b@9,8","5_02_b@9,9[5_02_e_a+3_06_e_b]"],
"bonds": ["deputShip 1/61","emptyShip 1/6","kjeragShip 0/7","preciShip 2/158","sargonShip 1/172","steadShip 1/88"]
},
@@ -981,12 +981,12 @@
"victory": true,
"roundsPassed": 14,
"eliminatedRound": null,
"lp": 44,
"lp": 45,
"bandId": "band_sarkazb",
"title": {"id":"comment_4","name":"精英云集","picId":"comment_icon_4","text":"晋升精锐次数最多"},
"title": {"id":"comment_3","name":"坚若磐石","picId":"comment_icon_3","text":"目标生命值损失最少"},
"trophies": 3,
"reward": 250,
"stats": {"activatedLayers":207,"bossDamage":11652,"dmgDealt":1287691,"gold":129,"itemsEquipped":20,"kills":237,"leaks":46,"lpLost":1,"merges":6,"perfectRounds":9,"refreshes":20},
"stats": {"activatedLayers":207,"bossDamage":11652,"dmgDealt":1287691,"gold":129,"itemsEquipped":20,"kills":237,"leaks":46,"lpLost":0,"merges":6,"perfectRounds":9,"refreshes":20},
"lineup": ["2_14_b@12,3","5_10_a@11,6[4_03_e_b+1_02_e_a]","6_01_a@11,7[3_05_e_a]","5_10_a@11,8[5_09_e_a+4_08_e_b]","6_14_a@10,3","4_16_a@10,8[4_11_e_a+4_04_e_b]","6_05_a@9,8[1_05_e_a+5_03_e_a]","2_16_a@9,9[5_02_e_a+4_05_e_b]"],
"bonds": ["deputShip 1/96","emptyShip 1/23","preciShip 1/14","sargonShip 0/2","siracusaShip 1/74","steadShip 0/4"]
},
@@ -997,10 +997,10 @@
"eliminatedRound": null,
"lp": 28,
"bandId": "band_mlyss",
"title": {"id":"comment_3","name":"坚若磐石","picId":"comment_icon_3","text":"目标生命值损失最少"},
"title": {"id":"comment_5","name":"万事俱备","picId":"comment_icon_5","text":"装备配发数量最多"},
"trophies": 3,
"reward": 250,
"stats": {"activatedLayers":260,"bossDamage":82751,"dmgDealt":1633721,"gold":127,"itemsEquipped":20,"kills":283,"leaks":0,"lpLost":0,"merges":3,"perfectRounds":13,"refreshes":16},
"stats": {"activatedLayers":260,"bossDamage":82751,"dmgDealt":1656521,"gold":127,"itemsEquipped":20,"kills":283,"leaks":0,"lpLost":0,"merges":3,"perfectRounds":13,"refreshes":16},
"lineup": ["4_25_a@12,3","1_07_b@11,7[1_01_e_a+1_05_e_a]","5_20_a@11,8[3_02_e_a+2_01_e_b]","6_18_a@10,3[2_01_e_b+4_03_e_b]","4_10_a@10,7[4_03_e_b]","3_18_b@9,4[3_07_e_b+3_11_e_a]","6_05_a@9,8","2_16_b@9,9[5_01_e_a+4_02_e_a]"],
"bonds": ["sargonShip 0/8","siracusaShip 2/236","swiftShip 1/24","yanShip 0/1"]
},
@@ -1030,109 +1030,102 @@
"combat": "client",
"boost": null,
"setup": {"stageId":"act2autochess_m01","bossId":"boss_1","hiddenBossId":"boss_8","factions":["DOT","INVISIBLE","REFLECTION"]},
"end": {"victory":false,"roundsPassed":11,"hiddenReached":false,"hiddenCleared":false,"reason":"eliminated","teamLp":null,"bossPoolLeft":null,"virtualMs":119300},
"rng": {"setup":25,"shop":460,"waves":0,"draft":65,"bots":18743,"meta":57},
"end": {"victory":false,"roundsPassed":10,"hiddenReached":false,"hiddenCleared":false,"reason":"eliminated","teamLp":null,"bossPoolLeft":null,"virtualMs":110050},
"rng": {"setup":25,"shop":504,"waves":0,"draft":65,"bots":17663,"meta":57},
"errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0},
"rounds": [
{
"round": 1,
"ai_0": [1,45,4,0,0,1,2,"cf5de4b4",0,"kazimierzShip 0/2, swiftShip 0/2",5,5,0,4],
"ai_1": [1,26,4,0,0,1,2,"59374416",0,"kazimierzShip 0/2, sargonShip 0/2, swiftShip 0/2",5,5,0,4],
"ai_2": [1,28,4,0,0,1,2,"eb0c1458",0,"deputShip 0/2, victoriaShip 0/2",2,5,3,4],
"ai_2": [1,25,4,0,0,1,2,"eb0c1458",0,"deputShip 0/2, victoriaShip 0/2",2,5,3,4],
"ai_3": [1,26,4,0,0,1,2,"ba03322a",0,"soloShip 1/0",5,5,0,4]
},
{
"round": 2,
"ai_0": [1,45,5,0,0,1,4,"62de86cd",4,"kazimierzShip 0/4, swiftShip 1/4",8,8,0,9],
"ai_1": [1,26,5,0,0,1,4,"a2ec5116",5,"kazimierzShip 0/5, sargonShip 0/2, soloShip 1/0, swiftShip 1/5",8,8,0,9],
"ai_2": [1,28,5,0,0,1,3,"70d74d61",0,"deputShip 0/4, kjeragShip 0/2, soloShip 1/0, victoriaShip 0/6",7,8,1,9],
"ai_2": [1,24,5,0,0,1,3,"70d74d61",0,"deputShip 0/4, kjeragShip 0/2, soloShip 1/0, victoriaShip 0/6",7,8,1,9],
"ai_3": [1,26,5,0,0,1,4,"9e98d014",0,"sargonShip 0/2, soloShip 1/0",8,8,0,9]
},
{
"round": 3,
"ai_0": [1,45,6,0,1,1,7,"a7d37d87",4,"arcaneShip 0/2, kazimierzShip 0/4, preciShip 0/2, swiftShip 1/4",9,9,0,15],
"ai_1": [1,26,6,0,1,1,7,"bf8932c2",5,"kazimierzShip 0/5, kjeragShip 0/2, sargonShip 0/4, soloShip 1/0, steadShip 0/2, swiftShip 1/5",11,11,0,15],
"ai_2": [1,28,6,0,1,1,6,"7363c3d8",0,"deputShip 0/4, kazimierzShip 0/2, kjeragShip 0/8, soloShip 1/0, steadShip 0/4, swiftShip 0/2, victoriaShip 0/8, yanShip 0/1",9,9,0,15],
"ai_2": [1,24,6,0,1,1,6,"7363c3d8",0,"deputShip 0/4, kazimierzShip 0/2, kjeragShip 0/8, soloShip 1/0, steadShip 0/4, swiftShip 0/2, victoriaShip 0/8, yanShip 0/1",9,9,0,15],
"ai_3": [1,26,6,0,2,1,7,"5051466d",1,"arcaneShip 0/2, preciShip 0/2, sargonShip 0/2, soloShip 1/1",9,9,0,15]
},
{
"round": 4,
"ai_0": [1,45,8,0,1,2,8,"822a03c7",6,"arcaneShip 0/8, kazimierzShip 0/4, preciShip 0/8, swiftShip 1/6",10,10,0,23],
"ai_1": [1,26,8,0,1,2,8,"f1865800",7,"arcaneShip 1/2, kazimierzShip 0/5, kjeragShip 0/2, preciShip 0/2, sargonShip 0/4, soloShip 1/0, steadShip 0/2, swiftShip 1/5",11,12,1,21],
"ai_2": [1,28,8,0,3,2,8,"38880204",9,"deputShip 1/7, kazimierzShip 0/2, kjeragShip 0/10, soloShip 1/2, steadShip 0/4, swiftShip 0/2, victoriaShip 0/10, yanShip 0/4",10,10,0,22],
"ai_3": [1,26,9,0,0,2,8,"00097ea6",4,"arcaneShip 1/3, preciShip 0/2, sargonShip 0/2, siracusaShip 1/0, soloShip 1/1",6,10,4,24]
"ai_1": [1,25,8,0,1,2,8,"f1865800",7,"arcaneShip 1/2, kazimierzShip 0/5, kjeragShip 0/2, preciShip 0/2, sargonShip 0/4, soloShip 1/0, steadShip 0/2, swiftShip 1/5",11,12,1,21],
"ai_2": [1,24,8,0,1,2,8,"38880204",9,"deputShip 1/7, kazimierzShip 0/2, kjeragShip 0/10, soloShip 1/2, steadShip 0/4, swiftShip 0/2, victoriaShip 0/10, yanShip 0/4",10,10,0,22],
"ai_3": [1,24,9,0,0,2,8,"00097ea6",4,"arcaneShip 1/3, preciShip 0/2, sargonShip 0/2, siracusaShip 1/0, soloShip 1/1",6,10,4,24]
},
{
"round": 5,
"ai_0": [1,35,9,0,0,3,8,"17121de7",8,"arcaneShip 0/8, kazimierzShip 0/4, preciShip 0/8, swiftShip 1/8",5,17,12,32],
"ai_1": [1,16,9,0,0,3,8,"0a827c34",8,"arcaneShip 1/2, kazimierzShip 0/5, kjeragShip 0/2, preciShip 0/2, sargonShip 0/4, soloShip 1/0, steadShip 0/2, swiftShip 1/6",5,17,12,30],
"ai_2": [1,21,11,0,0,3,8,"26900631",22,"deputShip 1/10, kazimierzShip 0/4, kjeragShip 0/10, skillfulShip 0/2, soloShip 1/4, steadShip 0/4, swiftShip 1/8, victoriaShip 0/10, yanShip 0/4",10,17,7,32],
"ai_3": [1,16,9,0,0,3,8,"2cd3b560",5,"arcaneShip 1/4, preciShip 0/2, sargonShip 0/2, siracusaShip 1/0, soloShip 1/1",2,17,15,33]
"ai_1": [1,15,9,0,0,3,8,"0a827c34",8,"arcaneShip 1/2, kazimierzShip 0/5, kjeragShip 0/2, preciShip 0/2, sargonShip 0/4, soloShip 1/0, steadShip 0/2, swiftShip 1/6",5,17,12,30],
"ai_2": [1,14,9,0,0,3,8,"6b698137",20,"deputShip 1/12, kazimierzShip 0/2, kjeragShip 0/12, soloShip 1/4, steadShip 0/4, swiftShip 1/4, victoriaShip 0/12, yanShip 0/4",7,17,10,31],
"ai_3": [1,14,9,0,0,3,8,"2cd3b560",5,"arcaneShip 1/4, preciShip 0/2, sargonShip 0/2, siracusaShip 1/0, soloShip 1/1",2,17,15,33]
},
{
"round": 6,
"ai_0": [1,35,9,0,0,3,8,"844b219a",33,"arcaneShip 0/8, kazimierzShip 0/4, kjeragShip 0/5, preciShip 2/20, suntShip 1/0, swiftShip 1/13",14,14,0,41],
"ai_1": [1,16,9,0,1,3,8,"3e9da7ea",26,"arcaneShip 1/2, kazimierzShip 1/11, kjeragShip 0/2, preciShip 0/2, sargonShip 0/4, siracusaShip 0/6, soloShip 1/0, steadShip 0/2, swiftShip 1/13",10,14,4,40],
"ai_2": [1,21,9,0,0,3,8,"524a7cff",51,"deputShip 1/12, egirShip 0/2, kazimierzShip 0/4, kjeragShip 0/12, raidShip 0/2, skillfulShip 0/4, soloShip 1/6, steadShip 2/18, swiftShip 1/15, victoriaShip 0/10, yanShip 0/4",14,14,0,41],
"ai_3": [1,16,10,0,0,3,8,"ae19c686",28,"arcaneShip 2/9, deputShip 1/2, preciShip 0/2, sargonShip 0/2, siracusaShip 1/11, soloShip 1/6",8,14,6,45]
"ai_0": [1,35,9,0,2,3,8,"03ec72c2",23,"arcaneShip 0/8, kazimierzShip 0/4, kjeragShip 0/5, preciShip 1/15, swiftShip 1/8",13,14,1,40],
"ai_1": [1,14,9,0,0,3,8,"390c0bbe",27,"arcaneShip 1/2, kazimierzShip 1/9, kjeragShip 0/2, preciShip 0/2, sargonShip 0/4, siracusaShip 0/6, soloShip 1/0, steadShip 0/2, swiftShip 1/16",13,14,1,39],
"ai_2": [1,14,9,0,0,3,8,"259dd8c0",49,"deputShip 1/14, egirShip 0/2, kazimierzShip 0/2, kjeragShip 0/14, raidShip 0/2, soloShip 1/8, steadShip 2/21, swiftShip 1/6, victoriaShip 0/12, yanShip 0/4",14,14,0,40],
"ai_3": [1,13,10,0,0,3,8,"22246bd2",20,"arcaneShip 2/7, preciShip 0/2, sargonShip 0/2, siracusaShip 1/9, skillfulShip 1/0, soloShip 1/4",11,14,3,45]
},
{
"round": 7,
"ai_0": [1,25,10,0,0,4,8,"fa19dc02",65,"arcaneShip 0/8, kazimierzShip 1/14, kjeragShip 0/5, preciShip 2/27, suntShip 1/0, swiftShip 1/24",8,21,13,52],
"ai_1": [1,6,11,0,0,4,8,"8016e17e",33,"arcaneShip 2/2, kazimierzShip 1/18, kjeragShip 0/2, preciShip 0/2, sargonShip 0/8, siracusaShip 0/6, steadShip 0/2, swiftShip 1/13",4,21,17,51],
"ai_2": [1,21,10,0,2,4,8,"4889cc01",78,"deputShip 1/16, egirShip 0/4, kazimierzShip 0/4, kjeragShip 0/12, raidShip 0/4, skillfulShip 0/6, soloShip 1/8, steadShip 2/33, swiftShip 1/21, victoriaShip 0/12, yanShip 0/4",21,21,0,51],
"ai_3": [1,6,11,0,0,4,8,"7ba63894",45,"arcaneShip 2/14, deputShip 1/4, preciShip 0/2, sargonShip 0/2, siracusaShip 1/19, soloShip 1/8",2,21,19,56]
"ai_0": [1,25,12,0,0,4,8,"81d63726",45,"arcaneShip 0/8, kazimierzShip 1/14, kjeragShip 0/5, preciShip 1/17, suntShip 1/0, swiftShip 1/14",6,21,15,53],
"ai_1": [1,4,10,0,0,4,8,"f1d0d89f",38,"arcaneShip 0/2, deputShip 1/2, kazimierzShip 1/15, kjeragShip 0/2, preciShip 0/2, sargonShip 0/4, siracusaShip 0/6, soloShip 1/2, steadShip 0/2, swiftShip 1/19",10,21,11,50],
"ai_2": [1,13,10,0,0,4,8,"1cee0d77",78,"deputShip 1/16, egirShip 0/4, kazimierzShip 0/2, kjeragShip 0/16, raidShip 0/4, soloShip 1/12, steadShip 2/42, swiftShip 1/8, victoriaShip 0/12, yanShip 0/4",20,21,1,51],
"ai_3": [1,3,11,0,0,4,8,"cae1e8d2",28,"arcaneShip 2/7, preciShip 0/2, sargonShip 0/2, siracusaShip 1/15, skillfulShip 1/2, soloShip 1/4",3,21,18,55]
},
{
"round": 8,
"ai_0": [1,19,11,0,0,4,8,"78106ce5",93,"arcaneShip 2/8, kazimierzShip 1/22, kjeragShip 0/5, preciShip 2/34, suntShip 1/0, swiftShip 1/29",3,9,6,63],
"ai_1": [0,0,11,0,0,4,0,"811c9dc5",0,"arcaneShip 0/2, kazimierzShip 0/25, kjeragShip 0/7, preciShip 0/2, sargonShip 0/8, siracusaShip 0/12, skillfulShip 0/5, steadShip 0/2, swiftShip 0/19",0,9,9,62],
"ai_2": [1,18,13,0,0,4,8,"eff86771",113,"deputShip 1/20, egirShip 0/6, kazimierzShip 0/4, kjeragShip 0/12, lateranoShip 0/2, raidShip 0/6, skillfulShip 0/6, soloShip 1/12, steadShip 2/46, swiftShip 1/35, victoriaShip 0/14, yanShip 0/4",6,9,3,64],
"ai_3": [0,0,12,0,0,4,0,"811c9dc5",0,"arcaneShip 0/18, deputShip 0/6, miraShip 0/4, preciShip 0/4, sargonShip 0/2, siracusaShip 0/31, skillfulShip 0/2, soloShip 0/10",2,9,7,68]
"ai_0": [1,20,11,0,0,4,8,"cdf4cd04",43,"arcaneShip 2/8, kazimierzShip 1/18, kjeragShip 0/10, preciShip 1/17, skillfulShip 0/5, suntShip 1/0, swiftShip 0/14",4,9,5,63],
"ai_1": [0,0,11,0,0,4,0,"811c9dc5",0,"arcaneShip 0/2, deputShip 0/6, kazimierzShip 0/27, kjeragShip 0/2, preciShip 0/2, sargonShip 0/8, siracusaShip 0/6, skillfulShip 0/4, soloShip 0/2, steadShip 0/2, swiftShip 0/34",0,9,9,62],
"ai_2": [1,9,11,0,0,4,8,"40e6f752",131,"deputShip 1/20, egirShip 0/4, indomShip 0/2, kazimierzShip 0/2, kjeragShip 1/23, raidShip 0/4, skillfulShip 0/5, soloShip 1/16, steadShip 1/52, suntShip 1/2, swiftShip 0/8, victoriaShip 1/18, visiShip 0/2, yanShip 0/12",5,9,4,62],
"ai_3": [0,0,12,0,0,4,0,"811c9dc5",0,"arcaneShip 0/13, deputShip 0/4, preciShip 0/4, sargonShip 0/2, siracusaShip 0/25, skillfulShip 0/4, soloShip 0/8",0,9,9,67]
},
{
"round": 9,
"ai_0": [1,18,12,0,1,4,8,"a359f7ee",121,"arcaneShip 1/8, indomShip 1/2, kazimierzShip 1/34, kjeragShip 0/5, preciShip 2/43, suntShip 1/0, swiftShip 1/34",6,19,13,76],
"ai_1": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/2, kazimierzShip 0/25, kjeragShip 0/7, preciShip 0/2, sargonShip 0/8, siracusaShip 0/12, skillfulShip 0/5, steadShip 0/2, swiftShip 0/19",null,null,null,62],
"ai_2": [1,18,12,0,1,4,8,"8df12b45",145,"deputShip 0/22, egirShip 0/6, kazimierzShip 0/4, kjeragShip 0/12, lateranoShip 0/2, preciShip 0/2, raidShip 0/6, skillfulShip 1/8, soloShip 1/12, steadShip 1/51, suntShip 1/0, swiftShip 1/49, victoriaShip 1/25, yanShip 0/13",19,19,0,76],
"ai_3": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/18, deputShip 0/6, miraShip 0/4, preciShip 0/4, sargonShip 0/2, siracusaShip 0/31, skillfulShip 0/2, soloShip 0/10",null,null,null,68]
"ai_0": [1,10,12,0,0,4,8,"4cd81c83",77,"arcaneShip 1/8, kazimierzShip 1/34, kjeragShip 1/10, preciShip 2/25, skillfulShip 0/5, suntShip 1/0, swiftShip 0/14",3,19,16,74],
"ai_1": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/2, deputShip 0/6, kazimierzShip 0/27, kjeragShip 0/2, preciShip 0/2, sargonShip 0/8, siracusaShip 0/6, skillfulShip 0/4, soloShip 0/2, steadShip 0/2, swiftShip 0/34",null,null,null,62],
"ai_2": [1,9,12,0,2,4,8,"614f615e",185,"deputShip 1/26, egirShip 0/4, indomShip 1/10, investShip 0/2, kazimierzShip 0/2, kjeragShip 1/29, raidShip 0/4, skillfulShip 1/9, soloShip 1/18, steadShip 1/63, suntShip 0/2, swiftShip 0/10, victoriaShip 1/30, visiShip 0/2, yanShip 0/12",19,19,0,74],
"ai_3": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/13, deputShip 0/4, preciShip 0/4, sargonShip 0/2, siracusaShip 0/25, skillfulShip 0/4, soloShip 0/8",null,null,null,67]
},
{
"round": 10,
"ai_0": [1,18,13,0,0,5,8,"1c690635",145,"arcaneShip 1/8, indomShip 1/4, kazimierzShip 1/42, kjeragShip 0/5, preciShip 2/52, suntShip 1/0, swiftShip 1/39",17,25,8,88],
"ai_1": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/2, kazimierzShip 0/25, kjeragShip 0/7, preciShip 0/2, sargonShip 0/8, siracusaShip 0/12, skillfulShip 0/5, steadShip 0/2, swiftShip 0/19",null,null,null,62],
"ai_2": [1,18,13,0,0,5,8,"0e4a12ab",175,"deputShip 0/24, egirShip 0/6, kazimierzShip 0/4, kjeragShip 0/12, lateranoShip 0/4, preciShip 0/2, raidShip 0/6, skillfulShip 1/12, soloShip 1/12, steadShip 1/57, suntShip 1/0, swiftShip 1/63, victoriaShip 1/31, yanShip 0/15",25,25,0,89],
"ai_3": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/18, deputShip 0/6, miraShip 0/4, preciShip 0/4, sargonShip 0/2, siracusaShip 0/31, skillfulShip 0/2, soloShip 0/10",null,null,null,68]
"ai_0": [1,6,12,0,0,5,8,"51650018",102,"arcaneShip 1/8, kazimierzShip 1/46, kjeragShip 1/15, preciShip 2/33, skillfulShip 0/10, suntShip 1/0, swiftShip 0/14",16,25,9,86],
"ai_1": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/2, deputShip 0/6, kazimierzShip 0/27, kjeragShip 0/2, preciShip 0/2, sargonShip 0/8, siracusaShip 0/6, skillfulShip 0/4, soloShip 0/2, steadShip 0/2, swiftShip 0/34",null,null,null,62],
"ai_2": [1,9,14,0,2,5,8,"76f0edb3",236,"deputShip 1/30, egirShip 0/4, indomShip 1/22, investShip 0/4, kazimierzShip 0/2, kjeragShip 1/35, raidShip 0/4, skillfulShip 1/11, soloShip 1/20, steadShip 1/72, suntShip 0/2, swiftShip 0/12, victoriaShip 1/46, visiShip 0/4, yanShip 0/12",25,25,0,90],
"ai_3": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/13, deputShip 0/4, preciShip 0/4, sargonShip 0/2, siracusaShip 0/25, skillfulShip 0/4, soloShip 0/8",null,null,null,67]
},
{
"round": 11,
"ai_0": [1,8,12,0,1,5,8,"88de4e65",205,"arcaneShip 1/8, indomShip 0/4, kazimierzShip 1/64, kjeragShip 0/5, preciShip 2/70, raidShip 1/12, suntShip 1/0, swiftShip 1/51",13,25,12,100],
"ai_1": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/2, kazimierzShip 0/25, kjeragShip 0/7, preciShip 0/2, sargonShip 0/8, siracusaShip 0/12, skillfulShip 0/5, steadShip 0/2, swiftShip 0/19",null,null,null,62],
"ai_2": [1,8,12,0,0,5,8,"81827b1b",175,"deputShip 0/24, egirShip 0/6, kazimierzShip 0/4, kjeragShip 0/14, lateranoShip 0/4, preciShip 0/4, raidShip 0/6, skillfulShip 1/16, soloShip 1/12, steadShip 0/59, suntShip 1/0, swiftShip 1/77, victoriaShip 1/35, yanShip 1/35",4,25,21,100],
"ai_3": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/18, deputShip 0/6, miraShip 0/4, preciShip 0/4, sargonShip 0/2, siracusaShip 0/31, skillfulShip 0/2, soloShip 0/10",null,null,null,68]
},
{
"round": 12,
"ai_0": [0,0,13,0,0,6,0,"811c9dc5",0,"arcaneShip 0/8, indomShip 0/4, kazimierzShip 0/80, kjeragShip 0/5, preciShip 0/79, raidShip 0/24, swiftShip 0/56",9,47,38,114],
"ai_1": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/2, kazimierzShip 0/25, kjeragShip 0/7, preciShip 0/2, sargonShip 0/8, siracusaShip 0/12, skillfulShip 0/5, steadShip 0/2, swiftShip 0/19",null,null,null,62],
"ai_2": [0,0,12,0,0,6,0,"811c9dc5",0,"deputShip 0/26, egirShip 0/6, kazimierzShip 0/4, kjeragShip 0/16, lateranoShip 0/4, preciShip 0/6, raidShip 0/6, skillfulShip 0/18, soloShip 0/12, steadShip 0/59, swiftShip 0/91, victoriaShip 0/43, yanShip 0/37",10,47,37,113],
"ai_3": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/18, deputShip 0/6, miraShip 0/4, preciShip 0/4, sargonShip 0/2, siracusaShip 0/31, skillfulShip 0/2, soloShip 0/10",null,null,null,68]
"ai_0": [0,0,12,0,0,5,0,"811c9dc5",0,"arcaneShip 0/14, kazimierzShip 0/54, kjeragShip 0/15, preciShip 0/42, skillfulShip 0/10, swiftShip 0/19",7,25,18,99],
"ai_1": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/2, deputShip 0/6, kazimierzShip 0/27, kjeragShip 0/2, preciShip 0/2, sargonShip 0/8, siracusaShip 0/6, skillfulShip 0/4, soloShip 0/2, steadShip 0/2, swiftShip 0/34",null,null,null,62],
"ai_2": [0,0,14,0,0,5,0,"811c9dc5",0,"deputShip 0/34, egirShip 0/4, indomShip 0/30, investShip 0/6, kazimierzShip 0/2, kjeragShip 0/41, raidShip 0/4, skillfulShip 0/13, soloShip 0/22, steadShip 0/82, suntShip 0/2, swiftShip 0/14, victoriaShip 0/58, visiShip 0/6, yanShip 0/12",11,25,14,102],
"ai_3": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/13, deputShip 0/4, preciShip 0/4, sargonShip 0/2, siracusaShip 0/25, skillfulShip 0/4, soloShip 0/8",null,null,null,67]
}
],
"players": {
"ai_0": {
"alive": false,
"victory": false,
"roundsPassed": 11,
"eliminatedRound": 12,
"roundsPassed": 10,
"eliminatedRound": 11,
"lp": 0,
"bandId": "band_sarkazb",
"title": {"id":"comment_4","name":"精英云集","picId":"comment_icon_4","text":"晋升精锐次数最多"},
"trophies": 2,
"reward": 255,
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":2923937,"gold":114,"itemsEquipped":8,"kills":107,"leaks":102,"lpLost":47,"merges":5,"perfectRounds":5,"refreshes":9},
"reward": 213,
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":1538413,"gold":99,"itemsEquipped":11,"kills":86,"leaks":76,"lpLost":49,"merges":2,"perfectRounds":4,"refreshes":12},
"lineup": [],
"bonds": ["arcaneShip 0/8","indomShip 0/4","kazimierzShip 0/80","kjeragShip 0/5","preciShip 0/79","raidShip 0/24","swiftShip 0/56"]
"bonds": ["arcaneShip 0/14","kazimierzShip 0/54","kjeragShip 0/15","preciShip 0/42","skillfulShip 0/10","swiftShip 0/19"]
},
"ai_1": {
"alive": false,
@@ -1144,23 +1137,23 @@
"title": null,
"trophies": 1,
"reward": 149,
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":649468,"gold":62,"itemsEquipped":3,"kills":55,"leaks":43,"lpLost":29,"merges":1,"perfectRounds":3,"refreshes":5},
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":822006,"gold":62,"itemsEquipped":5,"kills":63,"leaks":34,"lpLost":31,"merges":2,"perfectRounds":3,"refreshes":5},
"lineup": [],
"bonds": ["arcaneShip 0/2","kazimierzShip 0/25","kjeragShip 0/7","preciShip 0/2","sargonShip 0/8","siracusaShip 0/12","skillfulShip 0/5","steadShip 0/2","swiftShip 0/19"]
"bonds": ["arcaneShip 0/2","deputShip 0/6","kazimierzShip 0/27","kjeragShip 0/2","preciShip 0/2","sargonShip 0/8","siracusaShip 0/6","skillfulShip 0/4","soloShip 0/2","steadShip 0/2","swiftShip 0/34"]
},
"ai_2": {
"alive": false,
"victory": false,
"roundsPassed": 11,
"eliminatedRound": 12,
"roundsPassed": 10,
"eliminatedRound": 11,
"lp": 0,
"bandId": "band_bldsk",
"title": {"id":"comment_5","name":"万事俱备","picId":"comment_icon_5","text":"装备配发数量最多"},
"title": {"id":"comment_6","name":"挥金如土","picId":"comment_icon_6","text":"消耗资金最多"},
"trophies": 2,
"reward": 255,
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":4317948,"gold":113,"itemsEquipped":11,"kills":172,"leaks":72,"lpLost":30,"merges":3,"perfectRounds":6,"refreshes":9},
"reward": 213,
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":3090544,"gold":102,"itemsEquipped":10,"kills":143,"leaks":33,"lpLost":29,"merges":2,"perfectRounds":5,"refreshes":14},
"lineup": [],
"bonds": ["deputShip 0/26","egirShip 0/6","kazimierzShip 0/4","kjeragShip 0/16","lateranoShip 0/4","preciShip 0/6","raidShip 0/6","skillfulShip 0/18","soloShip 0/12","steadShip 0/59","swiftShip 0/91","victoriaShip 0/43","yanShip 0/37"]
"bonds": ["deputShip 0/34","egirShip 0/4","indomShip 0/30","investShip 0/6","kazimierzShip 0/2","kjeragShip 0/41","raidShip 0/4","skillfulShip 0/13","soloShip 0/22","steadShip 0/82","suntShip 0/2","swiftShip 0/14","victoriaShip 0/58","visiShip 0/6","yanShip 0/12"]
},
"ai_3": {
"alive": false,
@@ -1169,12 +1162,12 @@
"eliminatedRound": 8,
"lp": 0,
"bandId": "band_cathy",
"title": {"id":"comment_6","name":"挥金如土","picId":"comment_icon_6","text":"消耗资金最多"},
"title": {"id":"comment_5","name":"万事俱备","picId":"comment_icon_5","text":"装备配发数量最多"},
"trophies": 1,
"reward": 149,
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":627044,"gold":68,"itemsEquipped":10,"kills":45,"leaks":51,"lpLost":27,"merges":1,"perfectRounds":3,"refreshes":6},
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":535076,"gold":67,"itemsEquipped":9,"kills":44,"leaks":49,"lpLost":32,"merges":0,"perfectRounds":3,"refreshes":8},
"lineup": [],
"bonds": ["arcaneShip 0/18","deputShip 0/6","miraShip 0/4","preciShip 0/4","sargonShip 0/2","siracusaShip 0/31","skillfulShip 0/2","soloShip 0/10"]
"bonds": ["arcaneShip 0/13","deputShip 0/4","preciShip 0/4","sargonShip 0/2","siracusaShip 0/25","skillfulShip 0/4","soloShip 0/8"]
}
}
},
@@ -1188,8 +1181,8 @@
"combat": "server",
"boost": null,
"setup": {"stageId":"act1autochess_m01","bossId":"boss_1","hiddenBossId":"boss_9","factions":["FLY","DOT","REFLECTION"]},
"end": {"victory":false,"roundsPassed":12,"hiddenReached":false,"hiddenCleared":false,"reason":"eliminated","teamLp":null,"bossPoolLeft":null,"virtualMs":115150},
"rng": {"setup":25,"shop":411,"waves":0,"draft":34,"bots":17567,"meta":104},
"end": {"victory":false,"roundsPassed":12,"hiddenReached":false,"hiddenCleared":false,"reason":"eliminated","teamLp":null,"bossPoolLeft":null,"virtualMs":114800},
"rng": {"setup":25,"shop":383,"waves":0,"draft":34,"bots":16823,"meta":105},
"errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0},
"rounds": [
{
@@ -1230,32 +1223,32 @@
{
"round": 8,
"ai_0": [1,19,11,0,0,4,8,"7c223b06",60,"arcaneShip 1/6, emptyShip 1/0, kjeragShip 0/7, preciShip 1/7, siracusaShip 1/30, soloShip 1/11, steadShip 0/2, swiftShip 1/6",23,23,0,64],
"ai_1": [1,17,12,0,0,4,8,"2243ec88",26,"arcaneShip 1/8, indomShip 1/1, kjeragShip 0/4, preciShip 0/2, siracusaShip 1/10, soloShip 1/0, steadShip 2/7",18,23,5,61]
"ai_1": [1,16,12,0,0,4,8,"2243ec88",26,"arcaneShip 1/8, indomShip 1/1, kjeragShip 0/4, preciShip 0/2, siracusaShip 1/10, soloShip 1/0, steadShip 2/7",18,23,5,61]
},
{
"round": 9,
"ai_0": [1,19,12,0,1,4,8,"588666d3",72,"arcaneShip 1/12, emptyShip 1/0, indomShip 0/8, kjeragShip 0/7, preciShip 2/7, siracusaShip 1/36, soloShip 1/11, steadShip 0/2, suntShip 1/0, swiftShip 1/6, victoriaShip 0/8, visiShip 0/8",16,16,0,78],
"ai_1": [1,17,12,0,0,4,8,"0f3cf873",67,"arcaneShip 1/14, indomShip 1/10, kjeragShip 0/4, preciShip 0/2, siracusaShip 1/32, soloShip 1/0, steadShip 1/11, victoriaShip 0/8, visiShip 0/8",14,15,1,73]
"ai_1": [1,15,12,0,0,4,8,"0f3cf873",67,"arcaneShip 1/14, indomShip 1/10, kjeragShip 0/4, preciShip 0/2, siracusaShip 1/32, soloShip 1/0, steadShip 1/11, victoriaShip 0/8, visiShip 0/8",14,15,1,73]
},
{
"round": 10,
"ai_0": [1,17,13,0,0,5,8,"bb29d023",80,"arcaneShip 1/16, emptyShip 1/0, indomShip 0/8, kjeragShip 0/7, preciShip 2/7, siracusaShip 1/40, soloShip 1/11, steadShip 0/2, suntShip 1/0, swiftShip 1/6, victoriaShip 0/8, visiShip 0/8",22,24,2,91],
"ai_1": [1,16,12,0,0,5,8,"34e3de0f",83,"arcaneShip 1/14, indomShip 1/20, kjeragShip 0/8, preciShip 0/2, siracusaShip 1/32, soloShip 1/0, steadShip 1/17, suntShip 1/0, victoriaShip 0/8, visiShip 0/8",22,23,1,85]
"ai_1": [1,14,12,0,0,5,8,"34e3de0f",83,"arcaneShip 1/14, indomShip 1/20, kjeragShip 0/8, preciShip 0/2, siracusaShip 1/32, soloShip 1/0, steadShip 1/17, suntShip 1/0, victoriaShip 0/8, visiShip 0/8",22,23,1,85]
},
{
"round": 11,
"ai_0": [1,17,12,0,0,5,8,"f0ff6294",86,"arcaneShip 1/22, emptyShip 1/0, indomShip 0/8, kjeragShip 0/7, preciShip 1/7, siracusaShip 2/46, soloShip 1/11, steadShip 0/2, suntShip 1/0, swiftShip 0/6, victoriaShip 0/8, visiShip 0/8",23,23,0,104],
"ai_1": [1,16,12,0,0,5,8,"f020d91c",137,"arcaneShip 1/20, indomShip 1/40, kjeragShip 0/8, preciShip 0/2, siracusaShip 1/58, soloShip 1/0, steadShip 1/19, suntShip 1/0, victoriaShip 0/8, visiShip 0/8",17,23,6,97]
"ai_1": [1,8,12,0,0,5,8,"f020d91c",137,"arcaneShip 1/20, indomShip 1/40, kjeragShip 0/8, preciShip 0/2, siracusaShip 1/58, soloShip 1/0, steadShip 1/19, suntShip 1/0, victoriaShip 0/8, visiShip 0/8",17,23,6,97]
},
{
"round": 12,
"ai_0": [1,7,12,0,0,6,8,"09ffe6d0",86,"arcaneShip 1/22, emptyShip 1/0, indomShip 0/8, kjeragShip 0/7, preciShip 2/7, siracusaShip 1/46, soloShip 1/11, steadShip 0/2, suntShip 1/0, swiftShip 0/6, victoriaShip 0/8, visiShip 0/8",35,47,12,116],
"ai_1": [1,6,12,0,0,6,8,"d9bd3d27",160,"arcaneShip 1/20, indomShip 1/60, kjeragShip 0/8, preciShip 0/2, siracusaShip 1/58, soloShip 1/0, steadShip 1/22, suntShip 1/0, victoriaShip 0/8, visiShip 0/8",17,46,29,109]
"ai_1": [0,0,12,0,0,6,0,"811c9dc5",0,"arcaneShip 0/20, indomShip 0/60, kjeragShip 0/8, preciShip 0/2, siracusaShip 0/58, steadShip 0/22, victoriaShip 0/8, visiShip 0/8",17,46,29,109]
},
{
"round": 13,
"ai_0": [0,0,12,0,0,6,0,"811c9dc5",0,"arcaneShip 0/36, indomShip 0/8, kjeragShip 0/7, miraShip 0/3, preciShip 0/9, siracusaShip 0/58, soloShip 0/11, steadShip 0/2, swiftShip 0/6, victoriaShip 0/8, visiShip 0/8, yanShip 0/6",21,39,18,127],
"ai_1": [0,0,12,0,0,6,0,"811c9dc5",0,"arcaneShip 0/26, indomShip 0/60, kjeragShip 0/8, miraShip 0/4, preciShip 0/2, siracusaShip 0/84, steadShip 0/23, victoriaShip 0/8, visiShip 0/8",19,39,20,120]
"ai_0": [0,0,12,0,0,6,0,"811c9dc5",0,"arcaneShip 0/36, indomShip 0/8, kjeragShip 0/7, miraShip 0/3, preciShip 0/9, siracusaShip 0/58, soloShip 0/11, steadShip 0/2, swiftShip 0/6, victoriaShip 0/8, visiShip 0/8, yanShip 0/6",21,39,18,128],
"ai_1": [0,0,0,0,0,6,0,"811c9dc5",0,"arcaneShip 0/20, indomShip 0/60, kjeragShip 0/8, preciShip 0/2, siracusaShip 0/58, steadShip 0/22, victoriaShip 0/8, visiShip 0/8",null,null,null,109]
}
],
"players": {
@@ -1269,23 +1262,23 @@
"title": {"id":"comment_4","name":"精英云集","picId":"comment_icon_4","text":"晋升精锐次数最多"},
"trophies": 3,
"reward": 280,
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":3037907,"gold":127,"itemsEquipped":14,"kills":238,"leaks":49,"lpLost":33,"merges":3,"perfectRounds":8,"refreshes":17},
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":2825652,"gold":128,"itemsEquipped":14,"kills":230,"leaks":49,"lpLost":33,"merges":3,"perfectRounds":8,"refreshes":18},
"lineup": [],
"bonds": ["arcaneShip 0/36","indomShip 0/8","kjeragShip 0/7","miraShip 0/3","preciShip 0/9","siracusaShip 0/58","soloShip 0/11","steadShip 0/2","swiftShip 0/6","victoriaShip 0/8","visiShip 0/8","yanShip 0/6"]
},
"ai_1": {
"alive": false,
"victory": false,
"roundsPassed": 12,
"eliminatedRound": 13,
"roundsPassed": 11,
"eliminatedRound": 12,
"lp": 0,
"bandId": "band_malkie",
"title": {"id":"comment_5","name":"万事俱备","picId":"comment_icon_5","text":"装备配发数量最多"},
"trophies": 3,
"reward": 280,
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":2410241,"gold":120,"itemsEquipped":16,"kills":196,"leaks":73,"lpLost":32,"merges":2,"perfectRounds":6,"refreshes":18},
"trophies": 2,
"reward": 240,
"stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":1887768,"gold":109,"itemsEquipped":16,"kills":176,"leaks":53,"lpLost":30,"merges":2,"perfectRounds":6,"refreshes":14},
"lineup": [],
"bonds": ["arcaneShip 0/26","indomShip 0/60","kjeragShip 0/8","miraShip 0/4","preciShip 0/2","siracusaShip 0/84","steadShip 0/23","victoriaShip 0/8","visiShip 0/8"]
"bonds": ["arcaneShip 0/20","indomShip 0/60","kjeragShip 0/8","preciShip 0/2","siracusaShip 0/58","steadShip 0/22","victoriaShip 0/8","visiShip 0/8"]
}
}
},
@@ -1300,7 +1293,7 @@
"boost": {"lp":400,"layers":300},
"setup": {"stageId":"act1autochess_m02","bossId":"boss_5","hiddenBossId":"boss_10","factions":["TIMES","ELEMENT","DOT"]},
"end": {"victory":true,"roundsPassed":15,"hiddenReached":true,"hiddenCleared":true,"reason":"victory","teamLp":399,"bossPoolLeft":0,"virtualMs":113700},
"rng": {"setup":25,"shop":346,"waves":0,"draft":42,"bots":10350,"meta":3},
"rng": {"setup":25,"shop":356,"waves":0,"draft":42,"bots":10350,"meta":3},
"errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0},
"rounds": [
{
@@ -1353,7 +1346,7 @@
},
{
"round": 13,
"ai_0": [1,399,12,0,2,6,8,"eb5e835a",1944,"arcaneShip 2/360, deputShip 0/300, egirShip 0/300, emptyShip 0/300, indomShip 0/308, investShip 0/300, kazimierzShip 0/308, kjeragShip 0/300, lateranoShip 1/310, maniShip 0/300, miraShip 0/300, preciShip 0/302, raidShip 0/300, sargonShip 0/300, siracusaShip 1/332, skillfulShip 1/335, soloShip 1/307, steadShip 0/300, suntShip 1/300, swiftShip 0/316, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",35,35,0,151]
"ai_0": [1,399,12,0,2,6,8,"5091cd4e",1944,"arcaneShip 2/360, deputShip 0/300, egirShip 0/300, emptyShip 0/300, indomShip 0/308, investShip 0/300, kazimierzShip 0/308, kjeragShip 0/300, lateranoShip 1/310, maniShip 0/300, miraShip 0/300, preciShip 0/302, raidShip 0/300, sargonShip 0/300, siracusaShip 1/332, skillfulShip 1/335, soloShip 1/307, steadShip 0/300, suntShip 1/300, swiftShip 0/316, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",35,35,0,150]
}
],
"players": {
@@ -1367,9 +1360,9 @@
"title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"},
"trophies": 0,
"reward": 425,
"stats": {"activatedLayers":2269,"bossDamage":1145000,"dmgDealt":3047851,"gold":176,"itemsEquipped":26,"kills":366,"leaks":1,"lpLost":1,"merges":5,"perfectRounds":12,"refreshes":34},
"lineup": ["4_02_b@12,7[3_08_e_a+6_03_e_a]","6_01_a@12,8[3_03_e_a+3_02_e_a]","6_16_a@11,5[1_05_e_b+1_02_e_b]","3_18_a@11,8[4_11_e_a+4_05_e_b]","4_10_a@10,4[4_07_e_a+3_03_e_b]","6_05_a@10,5[1_02_e_a]","4_01_b@10,6[4_06_e_a+4_05_e_a]","1_08_b@9,9[4_10_e_a]"],
"bonds": ["arcaneShip 2/389","deputShip 0/300","egirShip 0/300","emptyShip 0/300","indomShip 0/308","investShip 0/300","kazimierzShip 0/308","kjeragShip 0/300","lateranoShip 1/310","maniShip 0/300","miraShip 0/300","preciShip 1/302","raidShip 0/300","sargonShip 0/300","siracusaShip 1/345","skillfulShip 0/335","soloShip 1/307","steadShip 0/300","suntShip 1/300","swiftShip 1/316","victoriaShip 0/300","visiShip 0/300","yanShip 0/300"]
"stats": {"activatedLayers":2283,"bossDamage":1145000,"dmgDealt":3047851,"gold":175,"itemsEquipped":26,"kills":366,"leaks":1,"lpLost":1,"merges":6,"perfectRounds":12,"refreshes":35},
"lineup": ["4_02_b@12,7[3_08_e_a+3_03_e_b]","6_01_a@12,8[3_02_e_a]","6_16_a@11,5[1_05_e_b+3_03_e_a]","3_18_a@11,8[4_11_e_a+4_05_e_b]","4_10_b@10,4[4_07_e_a+1_02_e_b]","6_05_a@10,5","4_01_b@10,6[6_03_e_a+4_06_e_a]","1_08_b@9,9"],
"bonds": ["arcaneShip 2/395","deputShip 0/300","egirShip 0/300","emptyShip 0/300","indomShip 0/308","investShip 0/300","kazimierzShip 0/308","kjeragShip 0/300","lateranoShip 1/310","maniShip 0/300","miraShip 0/300","preciShip 1/302","raidShip 0/300","sargonShip 0/300","siracusaShip 1/353","skillfulShip 0/343","soloShip 1/307","steadShip 0/300","suntShip 1/300","swiftShip 1/316","victoriaShip 0/300","visiShip 0/300","yanShip 0/300"]
}
}
},
@@ -1383,8 +1376,8 @@
"combat": "client",
"boost": {"lp":400,"layers":300},
"setup": {"stageId":"act2autochess_m04","bossId":"boss_5","hiddenBossId":"boss_9","factions":["FLY","ELEMENT","INVISIBLE"]},
"end": {"victory":true,"roundsPassed":15,"hiddenReached":true,"hiddenCleared":true,"reason":"victory","teamLp":800,"bossPoolLeft":0,"virtualMs":124650},
"rng": {"setup":25,"shop":658,"waves":0,"draft":61,"bots":22084,"meta":147},
"end": {"victory":true,"roundsPassed":15,"hiddenReached":true,"hiddenCleared":true,"reason":"victory","teamLp":800,"bossPoolLeft":0,"virtualMs":126150},
"rng": {"setup":25,"shop":674,"waves":0,"draft":61,"bots":22077,"meta":140},
"errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0},
"rounds": [
{
@@ -1435,22 +1428,22 @@
{
"round": 10,
"ai_0": [1,400,12,0,0,5,8,"5e407c98",2262,"arcaneShip 2/320, deputShip 0/304, egirShip 1/334, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/314, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/320, raidShip 1/338, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/332, suntShip 0/300, swiftShip 0/306, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",12,12,0,93],
"ai_1": [1,400,15,0,0,5,8,"fa4268ad",2207,"arcaneShip 0/302, deputShip 1/318, egirShip 0/300, emptyShip 0/300, indomShip 1/308, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 0/309, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 1/304, soloShip 1/316, steadShip 1/343, suntShip 1/302, swiftShip 0/300, victoriaShip 1/316, visiShip 0/300, yanShip 0/310",12,12,0,99]
"ai_1": [1,400,15,0,0,5,8,"1cb9c2e4",1583,"arcaneShip 0/302, deputShip 1/318, egirShip 0/300, emptyShip 0/300, indomShip 1/308, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 0/309, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 1/304, soloShip 0/314, steadShip 1/342, suntShip 0/300, swiftShip 0/300, victoriaShip 1/311, visiShip 0/300, yanShip 0/305",12,12,0,97]
},
{
"round": 11,
"ai_0": [1,400,12,0,2,5,8,"e2bf7b5d",2634,"arcaneShip 1/323, deputShip 0/304, egirShip 1/345, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/322, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/329, raidShip 1/360, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/336, suntShip 0/300, swiftShip 1/315, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",34,34,0,105],
"ai_1": [1,400,12,0,1,5,8,"5dc25201",2235,"arcaneShip 0/302, deputShip 1/320, egirShip 0/300, emptyShip 0/300, indomShip 1/310, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/313, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/304, soloShip 1/318, steadShip 1/350, suntShip 1/304, swiftShip 0/300, victoriaShip 1/320, visiShip 0/300, yanShip 0/310",34,34,0,111]
"ai_0": [1,400,12,0,2,5,8,"cfd3ac7b",2321,"arcaneShip 1/323, deputShip 0/304, egirShip 1/352, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/322, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/324, raidShip 1/360, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/336, suntShip 0/300, swiftShip 0/310, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",34,34,0,105],
"ai_1": [1,400,12,0,1,6,8,"b6bd931e",2209,"arcaneShip 0/302, deputShip 1/320, egirShip 0/300, emptyShip 0/300, indomShip 1/312, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 0/309, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 1/306, soloShip 0/314, steadShip 1/349, suntShip 1/302, swiftShip 0/300, victoriaShip 1/316, visiShip 1/304, yanShip 0/305",34,34,0,120]
},
{
"round": 12,
"ai_0": [1,400,14,0,0,6,8,"e09e9634",2679,"arcaneShip 1/326, deputShip 0/304, egirShip 1/351, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/330, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/342, raidShip 1/370, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/336, suntShip 0/300, swiftShip 1/320, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",6,14,8,119],
"ai_1": [1,400,13,0,2,6,8,"13f2f54b",2259,"arcaneShip 0/302, deputShip 1/322, egirShip 0/300, emptyShip 0/300, indomShip 1/312, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/317, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/304, soloShip 1/320, steadShip 1/358, suntShip 1/306, swiftShip 0/300, victoriaShip 1/324, visiShip 0/300, yanShip 0/310",15,15,0,124]
"ai_0": [1,400,14,0,0,6,8,"e7a322b8",2348,"arcaneShip 1/323, deputShip 0/304, egirShip 1/353, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/330, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/332, raidShip 1/370, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/336, suntShip 0/300, swiftShip 0/310, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",6,14,8,119],
"ai_1": [1,400,13,0,1,6,8,"58fdf70d",2235,"arcaneShip 0/302, deputShip 1/322, egirShip 0/300, emptyShip 0/300, indomShip 2/314, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 0/309, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 1/308, soloShip 0/314, steadShip 1/357, suntShip 1/304, swiftShip 0/300, victoriaShip 1/324, visiShip 1/306, yanShip 0/310",15,15,0,134]
},
{
"round": 13,
"ai_0": [1,400,12,0,0,6,8,"871ba326",3034,"arcaneShip 1/333, deputShip 0/304, egirShip 1/369, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/333, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/354, raidShip 1/376, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/340, suntShip 1/300, swiftShip 1/325, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",41,41,0,130],
"ai_1": [1,400,14,0,2,6,8,"0e053b02",2595,"arcaneShip 0/302, deputShip 1/324, egirShip 0/300, emptyShip 0/300, indomShip 1/318, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/319, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/304, soloShip 1/322, steadShip 1/366, suntShip 2/308, swiftShip 0/300, victoriaShip 1/332, visiShip 1/306, yanShip 0/310",41,41,0,170]
"ai_0": [1,400,12,0,0,6,8,"feef54ce",2706,"arcaneShip 2/330, deputShip 0/304, egirShip 1/368, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/334, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/340, raidShip 1/390, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/340, suntShip 1/300, swiftShip 0/310, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",41,41,0,133],
"ai_1": [1,400,13,0,2,6,8,"6a6f946a",1962,"arcaneShip 0/302, deputShip 1/324, egirShip 0/300, emptyShip 0/300, indomShip 2/322, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 0/309, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 1/310, soloShip 0/314, steadShip 1/366, suntShip 1/306, swiftShip 0/300, victoriaShip 1/334, visiShip 0/306, yanShip 0/310",36,41,5,150]
}
],
"players": {
@@ -1461,12 +1454,12 @@
"eliminatedRound": null,
"lp": 400,
"bandId": "band_sarkazb",
"title": {"id":"comment_2","name":"不朽盟约","picId":"comment_icon_2","text":"激活的盟约层数总和最高"},
"title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"},
"trophies": 8,
"reward": 425,
"stats": {"activatedLayers":3054,"bossDamage":2388329,"dmgDealt":11201551,"gold":156,"itemsEquipped":15,"kills":287,"leaks":8,"lpLost":0,"merges":6,"perfectRounds":12,"refreshes":28},
"lineup": ["4_09_b@11,5","4_14_a@11,8","5_07_a@10,4[1_01_e_a]","2_18_a@10,5","1_19_b@10,8[4_04_e_b+1_02_e_b]","3_09_a@9,7[2_01_e_a+3_08_e_a]","4_20_a@9,8","3_05_a@9,9[4_07_e_a+5_02_e_a]"],
"bonds": ["arcaneShip 1/333","deputShip 0/304","egirShip 1/369","emptyShip 0/300","indomShip 0/300","investShip 0/300","kazimierzShip 1/333","kjeragShip 0/302","lateranoShip 0/300","maniShip 0/300","miraShip 0/300","preciShip 1/364","raidShip 1/376","sargonShip 0/300","siracusaShip 0/300","skillfulShip 0/300","soloShip 1/304","steadShip 1/340","suntShip 1/300","swiftShip 1/335","victoriaShip 0/300","visiShip 0/300","yanShip 0/300"]
"stats": {"activatedLayers":2986,"bossDamage":4110836,"dmgDealt":14169113,"gold":158,"itemsEquipped":18,"kills":295,"leaks":8,"lpLost":0,"merges":7,"perfectRounds":12,"refreshes":25},
"lineup": ["4_09_b@11,5[4_11_e_a+6_09_e_a]","6_11_a@11,8","5_07_a@10,4[1_01_e_b+1_02_e_b]","1_19_b@10,8[5_02_e_a+4_04_e_a]","3_09_b@9,6[3_08_e_a+4_10_e_a]","6_05_a@9,7","4_20_a@9,8[2_01_e_a]","3_05_a@9,9[4_07_e_a+4_06_e_a]"],
"bonds": ["arcaneShip 1/330","deputShip 0/304","egirShip 1/368","emptyShip 0/300","indomShip 0/300","investShip 0/300","kazimierzShip 1/334","kjeragShip 0/302","lateranoShip 0/300","maniShip 1/300","miraShip 0/300","preciShip 1/345","raidShip 1/390","sargonShip 0/300","siracusaShip 0/300","skillfulShip 0/300","soloShip 1/304","steadShip 0/340","suntShip 1/300","swiftShip 1/315","victoriaShip 0/300","visiShip 0/300","yanShip 0/300"]
},
"ai_1": {
"alive": true,
@@ -1475,12 +1468,12 @@
"eliminatedRound": null,
"lp": 400,
"bandId": "band_doberm",
"title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"},
"title": {"id":"comment_3","name":"坚若磐石","picId":"comment_icon_3","text":"目标生命值损失最少"},
"trophies": 8,
"reward": 425,
"stats": {"activatedLayers":2623,"bossDamage":4551311,"dmgDealt":18984249,"gold":197,"itemsEquipped":35,"kills":283,"leaks":1,"lpLost":0,"merges":6,"perfectRounds":12,"refreshes":35},
"lineup": ["1_13_b@11,5[4_06_e_b+4_09_e_a]","6_11_a@11,8[3_08_e_a+5_01_e_a]","6_08_a@10,3[1_05_e_b+2_01_e_b]","3_16_b@10,4[3_10_e_b+2_03_e_b]","4_01_a@10,7[3_01_e_a+6_09_e_a]","4_07_b@10,8[3_10_e_a+5_09_e_a]","6_01_a@9,8[3_05_e_b+3_02_e_b]","1_06_b@9,9[3_11_e_a+2_03_e_b]"],
"bonds": ["arcaneShip 0/302","deputShip 1/328","egirShip 0/300","emptyShip 0/300","indomShip 1/322","investShip 0/300","kazimierzShip 0/300","kjeragShip 0/300","lateranoShip 1/304","maniShip 1/304","miraShip 0/300","preciShip 1/323","raidShip 0/300","sargonShip 0/300","siracusaShip 0/300","skillfulShip 0/304","soloShip 0/322","steadShip 1/390","suntShip 1/312","swiftShip 0/300","victoriaShip 1/340","visiShip 0/306","yanShip 0/310"]
"stats": {"activatedLayers":2322,"bossDamage":2829244,"dmgDealt":16856376,"gold":174,"itemsEquipped":28,"kills":280,"leaks":6,"lpLost":0,"merges":4,"perfectRounds":11,"refreshes":40},
"lineup": ["2_17_a@12,8[3_08_e_a+4_02_e_a]","5_03_a@11,8[3_02_e_a+3_10_e_a]","1_10_b@10,4[4_11_e_a+2_01_e_b]","4_11_a@10,5[2_03_e_b+3_10_e_b]","5_06_a@10,8[3_01_e_b+5_02_e_a]","3_16_a@9,3[2_03_e_b+3_09_e_a]","6_20_a@9,6[1_05_e_a+4_08_e_b]","1_06_b@9,9[3_08_e_b+1_05_e_b]"],
"bonds": ["arcaneShip 0/302","deputShip 1/328","egirShip 0/300","emptyShip 0/300","indomShip 1/326","investShip 0/300","kazimierzShip 0/300","kjeragShip 0/300","lateranoShip 0/300","maniShip 0/300","miraShip 0/300","preciShip 0/309","raidShip 0/300","sargonShip 0/300","siracusaShip 0/300","skillfulShip 1/314","soloShip 1/318","steadShip 2/384","suntShip 1/310","swiftShip 0/300","victoriaShip 1/342","visiShip 0/306","yanShip 0/310"]
}
}
}
+18 -3
View File
@@ -5,6 +5,14 @@ import { ERR, PHASE } from '../../shared/constants.js';
import { GameData } from '../../server/match/gamedata.js';
import { DATA, makeMatch, give, giveItem, checkInvariants, chessOfTier } from './harness.js';
/** Fill every free hand slot with distinct plain equipment (nothing merges), so a piece put into temp stays there. */
function fillHand(ps) {
const plain = Object.values(DATA.items).filter((i) => i.itemType === 'EQUIP' && !i.isGolden && i.kind === 'passive').map((i) => i.itemId ?? i.id);
let k = 0;
for (let i = 0; i < ps.hand.length; i++) if (ps.hand[i] == null) ps.hand[i] = ps.newPiece('item', plain[k++]);
ps.recompute();
}
test('income = min(3 + r, 12) in every mode; funds are lost at prep end (band_cannot keeps them)', () => {
for (const modeId of ['mode_single_funny', 'mode_multi_normal', 'mode_multi_abyss']) {
const gd = new GameData(DATA, modeId);
@@ -190,16 +198,21 @@ test('selling: +1 (normal and elite, board or hand), items return to the hand, i
m.dispose();
});
test('ready gating: temp must be empty; unready allowed until everyone is ready; actions locked while ready', () => {
test('ready gating: temp must be empty (a freed hand slot pulls the temp piece in); unready allowed until everyone is ready; actions locked while ready', () => {
const h = makeMatch({ mode: 'coop', humans: 2, seed: 10 }).start();
h.toPrep(1);
const m = h.m;
const a = h.ps('p_0');
fillHand(a);
const t = give(m, a, chessOfTier(1).find((x) => m.pool.has(x)), 'temp');
assert.ok(a.temp.includes(t), 'a full hand: it waits in temp');
assert.equal(a.privateView().canReady, false);
assert.deepEqual(m.handle('p_0', { t: 'g.ready', ready: true }), { error: ERR.TEMP_NOT_EMPTY });
const free = a.hand.findIndex((x) => x == null);
assert.deepEqual(m.handle('p_0', { t: 'g.move', uid: t.uid, to: { area: 'hand', idx: free } }), { ok: true });
// destroying a hand item frees its slot: the temp piece moves in by itself (PRTS 卫戍协议/帮助 §手牌区, GitHub #82)
const freed = a.hand[3];
assert.deepEqual(m.handle('p_0', { t: 'g.destroy', uid: freed.uid }), { ok: true });
assert.equal(a.hand[3], t);
assert.ok(a.tempEmpty);
assert.equal(a.privateView().canReady, true);
assert.deepEqual(m.handle('p_0', { t: 'g.ready', ready: true }), { ok: true });
assert.deepEqual(m.handle('p_0', { t: 'g.refresh' }), { error: ERR.WRONG_PHASE, detail: 'ready' });
@@ -222,7 +235,9 @@ test('prep deadline (co-op): unready players are auto-readied and their temp is
const a = h.ps('p_0');
const id = chessOfTier(1).find((x) => m.pool.has(x));
const left = m.pool.left(id);
fillHand(a);
give(m, a, id, 'temp');
assert.ok(!a.tempEmpty, 'a full hand: it waits in temp');
assert.ok(m.deadline > h.sched.now(), 'co-op prep is timed');
assert.equal(Math.round((m.deadline - h.sched.now()) / 1000), m.gd.prepTime(1));
h.sched.advance(m.deadline - h.sched.now() + 1);
+151
View File
@@ -0,0 +1,151 @@
// GitHub #82 (second part): the hand rules of PRTS 卫戍协议/帮助 §手牌区 — "手牌区域分为10个常规手牌区和5个临时手牌区。当
// 常规手牌区全满无空位时,玩家将无法执行使手牌溢出的操作" ("例如招募/购入等通常情况下会增加手牌的操作") and "溢出单位会自动
// 进入临时手牌区,常规手牌区出现空位时自动移入".
// * a full regular hand refuses every purchase and reward pick — also one whose copy would complete a merge at once
// (the reporter's first-hand check in the official game; BWIKI 盟约 "无法进行涉及到整备区的操作(购买、撤回等)")
// * a free regular slot pulls a temp piece in at once (PlayerState._fillHandFromTemp, run by every recompute): after a
// sale, a deployment from the hand, a merge that consumed hand copies, an item destroyed / equipped from the hand, a
// summon stack removed with its owner. The temp row empties right → left (the order it fills) [ASSUMED]; each piece
// takes the hand's next free slot right → left.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { ERR } from '../../shared/constants.js';
import { DATA, makeMatch, give, giveItem, checkInvariants, chessOfTier, legalTileFor } from './harness.js';
/** Plain equipment (no equip / merge side effects), all different: hand fillers that never merge with each other. */
const PLAIN = Object.values(DATA.items)
.filter((i) => i.itemType === 'EQUIP' && !i.isGolden && i.kind === 'passive')
.map((i) => i.itemId ?? i.id).filter(Boolean);
/** Solo 标准 (untimed) PREP R1 with an empty board and hand, 100 funds, a known stage. */
function prep(seed) {
const h = makeMatch({ mode: 'solo', difficulty: 'NORMAL', seed }).start();
h.toPrep(1);
h.setStage('act2autochess_m04');
const ps = h.ps('p_0');
for (const p of [...ps.board.values(), ...ps.hand.filter(Boolean)]) if (p.kind === 'chess') ps.returnCopies(p);
ps.board.clear();
ps.hand.fill(null);
ps.recompute();
ps.funds = 100;
return { h, m: h.m, ps };
}
/** Fill every free hand slot with plain equipment (skipping `skip` ids). */
function fillHand(ps, skip = []) {
const ids = PLAIN.filter((id) => !skip.includes(id));
let k = 0;
while (ps.hand.some((x) => x == null)) giveItem(ps.m, ps, ids[k++]);
}
const mergeable = (m) => chessOfTier(1, (c) => c.position === 'MELEE').find((id) => m.pool.has(id) && m.gd.mergeCount(id) === 3);
test('a full hand refuses a purchase / pick that would complete a merge (chess, item, reward); nothing is spent', () => {
const { m, ps } = prep(8201);
const id = mergeable(m);
give(m, ps, id, 'hand', 0);
give(m, ps, id, 'hand', 1);
const twin = PLAIN[0];
giveItem(m, ps, twin, 'hand', 2);
fillHand(ps, [twin]);
assert.ok(ps.completesChessMerge(id) && ps.completesItemMerge(twin));
ps.shop.slots[0] = { kind: 'chess', id, basePrice: m.gd.chessPrice(id), frozen: false, sold: false };
const itemSlot = ps.shop.slots.findIndex((s, i) => i > 0 && s && s.kind === 'item');
ps.shop.slots[itemSlot] = { kind: 'item', id: twin, basePrice: 2, frozen: false, sold: false };
const left = m.pool.left(id);
assert.deepEqual(m.handle('p_0', { t: 'g.buy', slot: 0 }), { error: ERR.HAND_FULL }, 'the third copy of a held pair');
assert.deepEqual(m.handle('p_0', { t: 'g.buy', slot: itemSlot }), { error: ERR.HAND_FULL }, 'an item whose twin is in the hand');
ps.pushRewardOffer('merge', { ids: [id] });
assert.deepEqual(m.handle('p_0', { t: 'g.reward', idx: 0 }), { error: ERR.HAND_FULL }, 'a merge-completing reward pick');
assert.equal(ps.funds, 100, 'nothing spent');
assert.equal(m.pool.left(id), left, 'no copy taken');
assert.ok(!ps.shop.slots[0].sold && !ps.shop.slots[itemSlot].sold);
assert.equal(ps.countCopies(m.gd.baseIdOf(id)), 2, 'no merge');
// a free slot (an item destroyed) lets the purchase through: it completes the merge, the elite goes to the hand
assert.deepEqual(m.handle('p_0', { t: 'g.destroy', uid: ps.hand[9].uid }), { ok: true });
assert.deepEqual(m.handle('p_0', { t: 'g.buy', slot: 0 }), { ok: true });
assert.ok(ps.hand.some((p) => p && p.id === m.gd.goldenIdOf(id)), 'the elite in the hand');
assert.equal(ps.hand.filter(Boolean).length, 8, '10 − the destroyed item − 2 copies + the elite');
checkInvariants(m);
m.dispose();
});
test('selling / destroying from a full hand pulls the temp pieces in, rightmost first, into the freed slot; Ready follows', () => {
const { m, ps } = prep(8202);
const sold = give(m, ps, chessOfTier(2).find((x) => m.pool.has(x)), 'hand', 4);
fillHand(ps);
const ids = chessOfTier(3).filter((x) => m.pool.has(x));
const first = give(m, ps, ids[0], 'temp', 4); // the first overflow takes the rightmost temp slot (stow → freeSlot)
const second = give(m, ps, ids[1], 'temp', 3);
assert.ok(ps.temp.includes(first) && ps.temp.includes(second), 'a full hand: both wait in temp');
assert.equal(ps.privateView().canReady, false);
checkInvariants(m);
assert.deepEqual(m.handle('p_0', { t: 'g.sell', uid: sold.uid }), { ok: true });
assert.equal(ps.hand[4], first, 'the rightmost temp piece moves into the freed slot');
assert.ok(ps.temp.includes(second) && !ps.temp.includes(first));
assert.equal(ps._tempDue.has(first.uid), false, 'no longer due at the prep deadline');
assert.equal(ps.privateView().canReady, false, 'one left in temp');
checkInvariants(m);
const item = ps.hand[7];
assert.equal(item.kind, 'item');
assert.deepEqual(m.handle('p_0', { t: 'g.destroy', uid: item.uid }), { ok: true });
assert.equal(ps.hand[7], second);
assert.ok(ps.tempEmpty);
assert.equal(ps.privateView().canReady, true);
assert.deepEqual(m.handle('p_0', { t: 'g.ready', ready: true }), { ok: true });
checkInvariants(m);
m.dispose();
});
test('deploying a card from a full hand, or equipping an item from it, pulls a temp piece into the freed slot', () => {
const { m, ps } = prep(8203);
const id = chessOfTier(1, (c) => c.position === 'MELEE' && !m.gd.placeableTokens(c.chessId).length).find((x) => m.pool.has(x));
const card = give(m, ps, id, 'hand', 9);
fillHand(ps);
const t1 = give(m, ps, chessOfTier(2).find((x) => m.pool.has(x)), 'temp', 4);
const t2 = giveItem(m, ps, PLAIN[PLAIN.length - 1], 'temp', 3);
const [r, c] = legalTileFor(m, ps, id);
assert.deepEqual(m.handle('p_0', { t: 'g.move', uid: card.uid, to: { area: 'board', row: r, col: c } }), { ok: true });
assert.equal(ps.hand[9], t1, 'the deployed card\'s slot took the temp piece');
checkInvariants(m);
const it = ps.hand[0];
assert.deepEqual(m.handle('p_0', { t: 'g.equip', itemUid: it.uid, targetUid: card.uid }), { ok: true });
assert.equal(ps.hand[0], t2, 'the equipped item\'s slot took the temp piece');
assert.ok(ps.tempEmpty);
checkInvariants(m);
m.dispose();
});
test('a gain that merges two hand copies: the elite takes one freed slot, the other pulls a temp piece in', () => {
const { m, ps } = prep(8204);
const id = mergeable(m);
give(m, ps, id, 'hand', 0);
give(m, ps, id, 'hand', 1);
fillHand(ps);
const ids = chessOfTier(3).filter((x) => m.pool.has(x));
const t1 = give(m, ps, ids[0], 'temp', 4);
const t2 = give(m, ps, ids[1], 'temp', 3);
const elite = ps.acquireChess(id, { source: 'grant' });
assert.ok(elite && m.gd.isGolden(elite.id));
assert.equal(ps.hand[1], elite, 'the elite: the hand\'s next free slot (right → left)');
assert.equal(ps.hand[0], t1, 'the other freed slot: the rightmost temp piece');
assert.deepEqual(ps.temp.filter(Boolean), [t2], 'the hand is full again: the other waits');
checkInvariants(m);
m.dispose();
});
test('selling a deployed summoner removes its summon stack from the hand: that slot pulls a temp piece in', () => {
const { m, ps } = prep(8205);
const owner = Object.values(DATA.chess).find((c) => c.visible && !c.isGolden && m.pool.has(c.chessId) && m.gd.placeableTokens(c.chessId).length && legalTileFor(m, ps, c.chessId));
assert.ok(owner, 'a chess with a manually deployable summon');
const op = give(m, ps, owner.chessId, 'board', legalTileFor(m, ps, owner.chessId));
const stackAt = ps.hand.findIndex((p) => p && p.kind === 'token' && p.ownerUid === op.uid);
assert.ok(stackAt >= 0, 'its summon stack joined the hand');
fillHand(ps);
const t = give(m, ps, chessOfTier(2).find((x) => m.pool.has(x)), 'temp', 4);
assert.deepEqual(m.handle('p_0', { t: 'g.sell', uid: op.uid }), { ok: true });
assert.equal(ps.hand[stackAt], t, 'the stack\'s slot took the temp piece');
assert.ok(ps.tempEmpty);
checkInvariants(m);
m.dispose();
});
+129
View File
@@ -0,0 +1,129 @@
// GitHub #41 (item 3): the 联防 field was the round's own stage — its water, crates and devices included — opened to both
// halves. Official: act2autochess constData escapedBattleTemplateMapSinglePlayer / MultiPlayer = level_act1autochess_
// escaped_single / _multi, the level of the 联防 battle and its map (two road halves joined at col 10). One helper →
// escaped_single (enemies enter at col 10), two helpers → escaped_multi (enemies enter at col 18 and pass (9,10)); the
// helpers' pieces stand on their prep tiles ("按休整期位置部署在场"), the first of two shifted 8 columns onto the right half
// ("率先迎敌(即位于右侧阵地)"). data/stages.json holds both maps (kind 'unite'); server/match/unite.js uniteStageId.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { GEO, PHASE } from '../../shared/constants.js';
import { Battle } from '../../server/sim/Battle.js';
import { createBattleFromSpec } from '../../server/sim/spec.js';
import { DataSource } from '../../server/sim/simdata.js';
import { uniteStageId } from '../../server/match/unite.js';
import { FakeBattle } from './fakeBattle.js';
import { DATA, makeMatch, give, chessOfTier, legalTileFor, checkInvariants } from './harness.js';
/** A real battle that only ends by its time limit (the check follows the enemies, whatever the helpers do). */
class NoFinish extends Battle {
constructor(o) { super({ ...o, autoFinish: false }); }
}
/**
* Co-op on 战场#01 (its row 9 is fenced off at cols 5–7: "##Err###rrSrr###rrS##"): p_0 leaks 3 enemies, the other
* players are perfect — 1 helper with 2 humans, 2 helpers with 3. Each helper fields one ranged operator in its corner.
*/
function scenario({ humans, clientCombat }) {
const h = makeMatch({
mode: 'coop', humans, seed: 4101 + humans, fake: true, clientCombat,
script: (b) => (b.kind === 'normal' ? { leaks: { p_0: 3 } } : {}),
}).start();
const m = h.m;
h.toPrep(1);
h.setStage('act1autochess_m01');
const ranged = chessOfTier(1, (c) => c.position === 'RANGED').filter((x) => m.pool.has(x));
const helpers = [];
for (let i = 1; i < humans; i++) {
const ps = h.ps(`p_${i}`);
const id = ranged[i];
helpers.push({ ps, piece: give(m, ps, id, 'board', legalTileFor(m, ps, id)) });
}
h.drive(() => m.phase === PHASE.UNITE);
return { h, m, helpers };
}
/** The 联防 field's spec / options as the match built them, and a real battle over them. */
function uniteField(m, clientCombat) {
if (clientCombat) {
const f = m.fields[0];
return { opts: f.spec, battle: createBattleFromSpec(f.spec, new DataSource(DATA, null), { BattleClass: NoFinish, recordEvents: false }) };
}
const u = FakeBattle.instances.find((b) => b.kind === 'unite');
return { opts: u.opts, battle: new NoFinish({ ...u.opts, data: m.ds, logger: { warn() {}, error() {}, info() {}, debug() {} } }) };
}
for (const clientCombat of [true, false]) {
test(`联防 with 1 helper (${clientCombat ? 'client-side combat' : 'server-run'}): escaped_single, not the round's stage — enemies enter at col 10 and walk row 9`, () => {
const { m, helpers } = scenario({ humans: 2, clientCombat });
assert.deepEqual(m.unitePlan.helpers.map((p) => p.playerId), ['p_1']);
const { opts, battle: b } = uniteField(m, clientCombat);
assert.equal(opts.stageId, 'act1autochess_escaped_single');
assert.equal(uniteStageId(m.gd, 1), 'act1autochess_escaped_single');
assert.deepEqual(opts.rect, GEO.UNITE_RECT, 'the whole 19×21 map\'s field rows (both halves are road on it)');
assert.equal(b.stage.id, 'act1autochess_escaped_single');
assert.deepEqual(b.stage.devices, [], 'no crates or devices of 战场#01');
// the map: row 9 is road from the gate (9,10) to the objective (9,2); on 战场#01 cols 5–7 are fenced off
for (let c = 3; c <= 9; c++) assert.ok(b.grid.groundPassable(9, c), `(9,${c}) is road`);
assert.equal(m.stage.rows[9].slice(5, 8), '###', '战场#01 itself has no ground there');
for (const c of [19, 20]) assert.ok(!b.grid.groundPassable(9, c), `(9,${c}) is no ground`);
// the routes of escaped_single: every one starts at col 10
assert.ok(opts.routes.every((r) => (r.start ?? [r.startPosition?.row, r.startPosition?.col])[1] === 10));
// the helper's piece stands on its prep tile
const { ps, piece } = helpers[0];
const [r, c] = [...ps.board.entries()].find(([, p]) => p === piece)[0].split(',').map(Number);
b.step();
const u = b.allyUnits.find((x) => x.uid === piece.uid && x.ownerId === 'p_1');
assert.deepEqual([u.tileR, u.tileC], [r, c]);
// a walker crosses the tiles 战场#01 fences off
const crossed = new Set();
while (b.time < 60 && !b.finished) {
b.step();
for (const e of b.enemies) if (e.alive && e.motion !== 'FLY') crossed.add(`${Math.round(e.y)},${Math.round(e.x)}`);
}
assert.ok(['9,5', '9,6', '9,7'].some((k) => crossed.has(k)), `a walker on row 9 cols 5–7 (${[...crossed].sort().join(' ')})`);
assert.equal(b.errorCount || 0, 0);
checkInvariants(m);
m.dispose();
});
}
test('联防 with 2 helpers: escaped_multi — the first helper on the right half (col + 8), enemies enter at col 18 through (9,10); the client draws the field\'s map', () => {
const { h, m, helpers } = scenario({ humans: 3, clientCombat: false });
const order = m.unitePlan.helpers.map((p) => p.playerId);
assert.equal(order.length, 2);
const { opts, battle: b } = uniteField(m, false);
assert.equal(opts.stageId, 'act1autochess_escaped_multi');
assert.equal(b.stage.id, 'act1autochess_escaped_multi');
assert.deepEqual(opts.players.map((p) => [p.playerId, p.colOffset]), [[order[0], 8], [order[1], 0]]);
assert.ok(opts.routes.every((r) => r.start[1] === 18), 'every route enters at col 18');
assert.ok(opts.routes.filter((r) => r.motion === 'WALK').every((r) => r.checkpoints.some(([rr, cc]) => rr === 9 && cc === 10)), 'walkers pass (9,10)');
b.step();
for (const { ps, piece } of helpers) {
const [r, c] = [...ps.board.entries()].find(([, p]) => p === piece)[0].split(',').map(Number);
const u = b.allyUnits.find((x) => x.uid === piece.uid && x.ownerId === ps.playerId);
const off = ps.playerId === order[0] ? 8 : 0;
assert.deepEqual([u.tileR, u.tileC], [r, c + off], `${ps.playerId}: its prep tile${off ? ' on the right half' : ''}`);
assert.equal(b.stage.rows[r][c + off], 'r', 'a road tile of the 联防 map');
}
// what a watching browser receives: the m.field of the 联防 carries the map it is drawn on
m.handle('p_0', { t: 'g.watch', fieldId: 'u' });
const meta = h.lastTo('p_0', 'm.field');
assert.equal(meta && meta.stageId, 'act1autochess_escaped_multi');
assert.equal(m.stageId, 'act1autochess_m01', 'the match stage (m.public stageId, the boards) stays the round\'s');
checkInvariants(m);
m.dispose();
});
test('degraded data without the 联防 maps: the field keeps the round\'s stage', () => {
const stages = Object.fromEntries(Object.entries(DATA.stages).filter(([, s]) => s.kind !== 'unite'));
const h = makeMatch({ mode: 'coop', humans: 2, seed: 4199, fake: true, data: { ...DATA, stages }, script: (b) => (b.kind === 'normal' ? { leaks: { p_0: 2 } } : {}) }).start();
const m = h.m;
h.toPrep(1);
assert.equal(uniteStageId(m.gd, 1), null);
const ps = h.ps('p_1');
const id = chessOfTier(1, (c) => c.position === 'RANGED').find((x) => m.pool.has(x));
give(m, ps, id, 'board', legalTileFor(m, ps, id));
h.drive(() => m.phase === PHASE.UNITE);
assert.equal(FakeBattle.instances.find((b) => b.kind === 'unite').opts.stageId, m.stageId);
m.dispose();
});
+9 -4
View File
@@ -85,7 +85,10 @@ test('merge with a full hand and a full temp: the elite takes its deployed copy\
for (let i = 0; i < 5; i++) give(m, ps, fillers[10 + i], 'temp', i);
ps.shop.slots[0] = { kind: 'chess', id, basePrice: m.gd.chessPrice(id), frozen: false, sold: false };
checkInvariants(m);
assert.deepEqual(m.handle('p_0', { t: 'g.buy', slot: 0 }), { ok: true }, 'a purchase that completes a merge is allowed with a full hand');
// a full hand refuses the purchase, also one that would complete the merge (PRTS 卫戍协议/帮助 §手牌区, GitHub #82);
// a gain (an effect's grant) still completes it
assert.deepEqual(m.handle('p_0', { t: 'g.buy', slot: 0 }), { error: 'HAND_FULL' }, 'a full hand refuses the merge-completing purchase');
assert.ok(ps.acquireChess(id, { source: 'grant' }), 'the gained copy completes the merge');
const elite = [...ps.board.values()].find((p) => p.id === m.gd.goldenIdOf(id));
assert.ok(elite, 'the elite stands on a consumed copy\'s tile');
assert.equal(ps.find(elite.uid).key, `${t1[0]},${t1[1]}`, 'the copy that deploys first (legalTileFor walks the top row left to right: on one row, the deploy order)');
@@ -260,7 +263,7 @@ test('garrisonHooks widens a garrison to extra hooks ("<进入休整期时><休
m.dispose();
});
test('ctx.offerItems queues an item offer; g.reward takes the item (full hand refused unless it merges)', () => {
test('ctx.offerItems queues an item offer; g.reward takes the item (a full hand refuses it, also when it would merge)', () => {
const reg = builtins();
const { m, ps } = prepSolo({ seed: 913, registry: reg });
const ctx = makeCtx(m, ps, { kind: 'band', key: 'band:test' }, 'onLevelUp');
@@ -269,8 +272,10 @@ test('ctx.offerItems queues an item offer; g.reward takes the item (full hand re
const view = ps.privateView().shop.rewardOffer;
assert.deepEqual(view.slots.map((s) => [s.kind, s.id, s.price]), [['item', 'chess_item_1_01_e_a', 0], ['item', 'chess_item_2_03_e_a', 0]]);
const fillers = chessOfTier(1).filter((c) => m.pool.has(c));
for (let i = 0; i < 10; i++) give(m, ps, fillers[i], 'hand', i);
assert.equal(m.handle('p_0', { t: 'g.reward', idx: 0 }).error, 'HAND_FULL');
for (let i = 0; i < 9; i++) give(m, ps, fillers[i], 'hand', i);
giveItem(m, ps, 'chess_item_1_01_e_a', 'hand', 9);
assert.equal(ps.completesItemMerge('chess_item_1_01_e_a'), true);
assert.equal(m.handle('p_0', { t: 'g.reward', idx: 0 }).error, 'HAND_FULL', 'refused although it would merge (PRTS 卫戍协议/帮助 §手牌区)');
ps.hand[0] && ps.returnCopies(ps.hand[0]);
ps.hand[0] = null;
ps.recompute();
+22 -10
View File
@@ -67,7 +67,7 @@ test('3 copies (board + hand + bought) merge into 1 elite on the board copy\'s t
m.dispose();
});
test('elites never merge; 风丸 merges with 2 copies; a full hand still buys the merge-completing copy', () => {
test('elites never merge; 风丸 merges with 2 copies; a full hand refuses the merge-completing copy too (GitHub #82)', () => {
const { m, ps } = prep(22);
const id = chessOfTier(2).find((x) => m.pool.has(x) && x !== 'chess_char_2_11_a');
const golden = DATA.chess[id].goldenId;
@@ -83,7 +83,9 @@ test('elites never merge; 风丸 merges with 2 copies; a full hand still buys th
m.handle('p_0', { t: 'g.buy', slot: 0 });
assert.ok(ps.hand.some((p) => p && p.id === DATA.chess.chess_char_2_11_a.goldenId), '风丸 elite after 2 copies');
}
// full hand + 2 copies in the hand: buying the 3rd completes the merge (net −1)
// full hand + 2 copies in the hand: the 3rd copy is refused like any purchase (PRTS 卫戍协议/帮助 §手牌区 "当常规手牌区
// 全满无空位时,玩家将无法执行使手牌溢出的操作" — "例如招募/购入"; GitHub #82); a sale frees a slot, then the purchase
// completes the merge (the elite in the hand)
for (const p of ps.hand) if (p) ps.returnCopies(p);
ps.hand.fill(null);
const x = chessOfTier(1).filter((c) => m.pool.has(c));
@@ -95,15 +97,19 @@ test('elites never merge; 风丸 merges with 2 copies; a full hand still buys th
stock(m, ps, x[20] || x[x.length - 1], 1);
assert.deepEqual(m.handle('p_0', { t: 'g.buy', slot: 1 }), { error: ERR.HAND_FULL });
stock(m, ps, target, 0);
assert.deepEqual(m.handle('p_0', { t: 'g.buy', slot: 0 }), { error: ERR.HAND_FULL }, 'the merge-completing copy too');
assert.ok(!ps.hand.some((p) => p && p.id === DATA.chess[target].goldenId));
const filler = ps.hand.find((p) => p && p.id !== target);
assert.deepEqual(m.handle('p_0', { t: 'g.sell', uid: filler.uid }), { ok: true });
assert.deepEqual(m.handle('p_0', { t: 'g.buy', slot: 0 }), { ok: true });
assert.ok(ps.hand.some((p) => p && p.id === DATA.chess[target].goldenId));
assert.equal(ps.hand.filter(Boolean).length, 9);
assert.equal(ps.hand.filter(Boolean).length, 8, '10 − the sold filler − 2 copies + the elite');
assert.ok(ps.tempEmpty);
checkInvariants(m);
m.dispose();
});
test('merge from two board copies with a full hand: the elite takes the copy that deploys first (no overflow, one tile freed)', () => {
test('merge from two board copies with a full hand (a gained copy; a purchase is refused): the elite takes the copy that deploys first (no overflow, one tile freed)', () => {
const { m, ps } = prep(23);
const ids = chessOfTier(1, (c) => c.position === 'MELEE').filter((c) => m.pool.has(c));
const id = ids[0];
@@ -115,7 +121,8 @@ test('merge from two board copies with a full hand: the elite takes the copy tha
for (let i = 0; ps.hand.some((p) => p == null); i++) give(m, ps, others[i]);
stock(m, ps, id);
assert.equal(ps.deployCount, 2);
assert.deepEqual(m.handle('p_0', { t: 'g.buy', slot: 0 }), { ok: true });
assert.deepEqual(m.handle('p_0', { t: 'g.buy', slot: 0 }), { error: ERR.HAND_FULL }, 'a full hand refuses the purchase (GitHub #82)');
assert.ok(ps.acquireChess(id, { source: 'grant' }), 'a gain (an effect\'s grant) completes the merge');
// deploy order = by column from the left (col asc, then row desc; Battle.start): (9,3) before (9,4) — [ASSUMED] the copy
// the battle deploys first
const elite = ps.board.get('9,3');
@@ -134,12 +141,14 @@ test('merge whose copies are not deployed (temp) with a full hand overflows the
const { m, ps } = prep(23);
const ids = chessOfTier(1, (c) => c.position === 'MELEE').filter((c) => m.pool.has(c));
const id = ids[0];
give(m, ps, id, 'temp', 0);
give(m, ps, id, 'temp', 1);
const others = chessOfTier(2).filter((c) => m.pool.has(c));
for (let i = 0; ps.hand.some((p) => p == null); i++) give(m, ps, others[i]);
stock(m, ps, id);
assert.deepEqual(m.handle('p_0', { t: 'g.buy', slot: 0 }), { ok: true });
// with the hand full they wait in temp (a free hand slot would pull them in, PRTS 卫戍协议/帮助 §手牌区)
give(m, ps, id, 'temp', 0);
give(m, ps, id, 'temp', 1);
assert.equal(ps.temp.filter(Boolean).length, 2);
// a gain completes the merge (a purchase is refused with a full hand)
assert.ok(ps.acquireChess(id, { source: 'grant' }));
assert.ok(ps.temp.some((p) => p && p.id === DATA.chess[id].goldenId), 'elite overflowed into temp');
assert.equal(ps.board.size, 0, 'nothing was deployed');
assert.deepEqual(m.handle('p_0', { t: 'g.ready', ready: true }), { error: ERR.TEMP_NOT_EMPTY });
@@ -187,11 +196,14 @@ test('equipment: max 2 (a third replaces the oldest), identical normal items mer
assert.ok(ps.hand.some((p) => p && p.id === 'chess_item_1_02_e_b'), 'golden item in the hand');
assert.ok(!a.items.some((x) => x.id === 'chess_item_1_02_e_a'));
assert.equal(ps.stats.itemMerges, 1);
// buying an item whose twin is in the hand merges immediately (and works with a full hand)
// buying an item whose twin is in the hand merges immediately — but a full hand refuses the purchase all the same
// (PRTS 卫戍协议/帮助 §手牌区, GitHub #82)
const i5 = giveItem(m, ps, 'chess_item_2_03_e_a');
const others = chessOfTier(1).filter((c) => m.pool.has(c));
for (let i = 0; ps.hand.some((p) => p == null); i++) give(m, ps, others[i]);
ps.shop.slots[0] = { kind: 'item', id: 'chess_item_2_03_e_a', basePrice: 2, frozen: false, sold: false };
assert.deepEqual(m.handle('p_0', { t: 'g.buy', slot: 0 }), { error: ERR.HAND_FULL });
assert.deepEqual(m.handle('p_0', { t: 'g.sell', uid: ps.hand.find((p) => p && p.kind === 'chess' && p !== a).uid }), { ok: true });
assert.deepEqual(m.handle('p_0', { t: 'g.buy', slot: 0 }), { ok: true });
assert.ok(ps.hand.some((p) => p && p.id === 'chess_item_2_03_e_b'));
assert.ok(!ps.find(i5.uid));
+2
View File
@@ -223,6 +223,7 @@ describe('#7 audit: every stage × deploy field (server = official level data =
// buildableType (PRTS 深水区 地形信息 "地形机制:拒绝部署(待补充)" — player report #3 after 0.1.0, 战场#08's pool)
const ROLE = { trap_1105_accrate: 'block', trap_032_mound: 'block', trap_1106_achplat: 'platform', trap_040_canoe: 'water' };
for (const [id, st] of Object.entries(DATA.stages)) {
if (st.kind === 'unite') continue; // the 联防 maps: nobody deploys or prepares on them (no bench, no boss halves)
const lv = JSON.parse(readFileSync(levelFile(id), 'utf8'));
const map = lv.mapData.map, tiles = lv.mapData.tiles, H = map.length;
const dev = new Map();
@@ -259,6 +260,7 @@ describe('#7 audit: every stage × deploy field (server = official level data =
test('carry-over: a tile legal on the normal board is legal (same class) on both boss halves of every active stage', () => {
for (const [id, st] of Object.entries(DATA.stages)) {
if (st.kind === 'unite') continue; // the 联防 maps have no boss field
const n = buildDeployMap(st);
for (const field of ['bossL', 'bossR']) {
const b = buildDeployMap(st, { field });
+2 -1
View File
@@ -199,7 +199,8 @@ test('equipment with the hand and temp full: the elite keeps up to its 2 equip s
const warn = m.log.warn;
m.log.warn = (s) => { warns.push(String(s)); };
stock(m, ps, id);
assert.deepEqual(m.handle('p_0', { t: 'g.buy', slot: 0 }), { ok: true }, 'a merge-completing buy needs no hand slot');
assert.equal(m.handle('p_0', { t: 'g.buy', slot: 0 }).error, 'HAND_FULL', 'a full hand refuses the purchase, also a merge-completing one (GitHub #82)');
assert.ok(ps.acquireChess(id, { source: 'grant' }), 'a gained copy completes the merge');
m.log.warn = warn;
const elite = ps.board.get(want);
assert.ok(elite && m.gd.isGolden(elite.id), 'the elite took the first deployed copy\'s tile');
+6 -1
View File
@@ -7,7 +7,7 @@
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { GEO, PHASE } from '../../shared/constants.js';
import { makeMatch, give, giveItem, legalTileFor, chessOfTier } from './harness.js';
import { DATA, makeMatch, give, giveItem, legalTileFor, chessOfTier } from './harness.js';
const MELEE = (c) => c.position === 'MELEE' && c.profession === 'TANK';
@@ -98,7 +98,12 @@ test("PR #129 review: moving a hand piece to another slot is a scout change (x f
b.recompute();
const id = chessOfTier(1, MELEE).find((x) => m.pool.has(x));
const a = give(m, b, id, 'hand', 0);
// a full hand (distinct plain equipment: nothing merges), so the temp piece stays in temp — a free hand slot would pull
// it in (PRTS 卫戍协议/帮助 §手牌区 "常规手牌区出现空位时自动移入")
const plain = Object.values(DATA.items).filter((i) => i.itemType === 'EQUIP' && !i.isGolden && i.kind === 'passive').map((i) => i.itemId ?? i.id);
for (let i = 1; i < b.hand.length; i++) b.hand[i] = b.newPiece('item', plain[i]);
const c = give(m, b, id, 'temp', 0); // 临时整备区: PRTS 帮助把它算进手牌区,一起侦察
assert.ok(b.temp.includes(c));
assert.deepEqual(m.handle('p_0', { t: 'g.watch', fieldId: 'n:p_1' }), { ok: true });
const first = h.lastTo('p_0', 'm.field');
+2 -1
View File
@@ -12,7 +12,8 @@ import { bossFieldPlacement } from '../../server/match/finalAssault.js';
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
const STAGES = JSON.parse(readFileSync(path.join(ROOT, 'data/stages.json'), 'utf8'));
const stageList = Object.values(STAGES.stages || STAGES);
// the battle stages (the two 联防 maps, kind 'unite', have no preview pen: nobody prepares on them)
const stageList = Object.values(STAGES.stages || STAGES).filter((s) => s.kind !== 'unite');
const stage = (STAGES.stages || STAGES).act2autochess_m01;
const E = (enemyKey, count, gate, t, extra = {}) => ({ enemyKey, count, gate, t, fly: false, elite: false, boss: false, source: 'wave', ...extra });
+3 -1
View File
@@ -26,9 +26,11 @@ describe('parseStage', () => {
assert.ok(t.alpha > 0 && t.alpha <= 1);
}
}
// the own board is always drawn and playable; hand slots are raised benches
// the own board is always drawn and playable; hand slots are raised benches (the two 联防 maps, kind 'unite', have
// no bench: nobody prepares on them)
for (let r = 9; r <= 12; r++) for (let c = 3; c <= 8; c++) assert.ok(g[r][c].drawn, `${id} board ${r},${c}`);
for (let c = 0; c < 10; c++) {
if (st.kind === 'unite') { assert.equal(g[7][c].glyph, '#', `${id} no hand ${c}`); continue; }
assert.equal(g[7][c].glyph, 'a', `${id} hand ${c}`);
assert.equal(g[7][c].h, TILE_H.bench);
}
+7 -4
View File
@@ -247,16 +247,19 @@ describe('full hand: shop and promotion cards', () => {
const privFull = { alive: true, ready: false, funds: 20, board: [], temp: new Array(GEO.TEMP_SIZE).fill(null), shop: {},
hand: fullHand([{ uid: 1, kind: 'chess', id: MELEE, items: [] }, { uid: 2, kind: 'chess', id: MELEE, items: [] }]) };
const o = { priv: privFull, editable: true, getChess, getItem };
test('a card that needs a slot is blocked with 整备区已满; one completing a merge is not', () => {
test('every card is blocked with 整备区已满, one completing a merge too (PRTS 卫戍协议/帮助 §手牌区, GitHub #82)', () => {
assert.equal(handFull(privFull), true);
assert.equal(shopBlockReason('buy', { ...o, slot: { kind: 'chess', id: other, price: 1 } }), '整备区已满');
assert.equal(completesMerge(privFull, { kind: 'chess', id: MELEE }, o), true);
assert.equal(shopBlockReason('buy', { ...o, slot: { kind: 'chess', id: MELEE, price: 1 } }), null);
assert.equal(shopBlockReason('buy', { ...o, slot: { kind: 'chess', id: MELEE, price: 1 } }), '整备区已满', 'the third copy of a held pair');
assert.equal(shopBlockReason('reward', { ...o, slot: { kind: 'chess', id: other, price: 0 } }), '整备区已满');
// the hand is filled with a mergeable equipment: buying another copy merges instead of needing a slot
assert.equal(shopBlockReason('buy', { ...o, slot: { kind: 'item', id: 'chess_item_1_01_e_a', price: 1 } }), null);
assert.equal(shopBlockReason('reward', { ...o, slot: { kind: 'chess', id: MELEE, price: 0 } }), '整备区已满', 'a merge-completing pick');
// the hand is filled with a mergeable equipment: another copy would merge, but the purchase is refused all the same
assert.equal(completesMerge(privFull, { kind: 'item', id: 'chess_item_1_01_e_a' }, o), true);
assert.equal(shopBlockReason('buy', { ...o, slot: { kind: 'item', id: 'chess_item_1_01_e_a', price: 1 } }), '整备区已满');
const notFull = { ...privFull, hand: privFull.hand.map((p, i) => (i === 5 ? null : p)) };
assert.equal(shopBlockReason('buy', { ...o, priv: notFull, slot: { kind: 'chess', id: other, price: 1 } }), null);
assert.equal(shopBlockReason('buy', { ...o, priv: notFull, slot: { kind: 'chess', id: MELEE, price: 1 } }), null);
});
});