Add Hanzhong decisive battle chapter

This commit is contained in:
2026-06-23 14:09:12 +09:00
parent 24b7db0b14
commit b4c34afeed
11 changed files with 894 additions and 41 deletions

View File

@@ -1736,7 +1736,7 @@ try {
if (
progressTabState?.activeTab !== 'progress' ||
progressTabState.campaignProgress?.completedKnown !== 17 ||
progressTabState.campaignProgress?.totalKnown !== 36 ||
progressTabState.campaignProgress?.totalKnown !== 37 ||
progressTabState.campaignProgress?.activeChapter?.title !== '적벽대전' ||
progressTabState.campaignProgress?.latestBattleTitle !== '융중 방문로' ||
progressTabState.campaignProgress?.nextBattleTitle !== '박망파 매복전'
@@ -1888,7 +1888,7 @@ try {
if (
postBowangProgressState?.activeTab !== 'progress' ||
postBowangProgressState.campaignProgress?.completedKnown !== 18 ||
postBowangProgressState.campaignProgress?.totalKnown !== 36 ||
postBowangProgressState.campaignProgress?.totalKnown !== 37 ||
postBowangProgressState.campaignProgress?.activeChapter?.title !== '적벽대전' ||
postBowangProgressState.campaignProgress?.latestBattleTitle !== '박망파 매복전' ||
postBowangProgressState.campaignProgress?.nextBattleTitle !== '장판파 피난로'
@@ -2026,7 +2026,7 @@ try {
if (
postChangbanProgressState?.activeTab !== 'progress' ||
postChangbanProgressState.campaignProgress?.completedKnown !== 19 ||
postChangbanProgressState.campaignProgress?.totalKnown !== 36 ||
postChangbanProgressState.campaignProgress?.totalKnown !== 37 ||
postChangbanProgressState.campaignProgress?.activeChapter?.title !== '적벽대전' ||
postChangbanProgressState.campaignProgress?.latestBattleTitle !== '장판파 피난로' ||
postChangbanProgressState.campaignProgress?.nextBattleTitle !== '강동 사절로'
@@ -2164,7 +2164,7 @@ try {
if (
postJiangdongProgressState?.activeTab !== 'progress' ||
postJiangdongProgressState.campaignProgress?.completedKnown !== 20 ||
postJiangdongProgressState.campaignProgress?.totalKnown !== 36 ||
postJiangdongProgressState.campaignProgress?.totalKnown !== 37 ||
postJiangdongProgressState.campaignProgress?.activeChapter?.title !== '적벽대전' ||
postJiangdongProgressState.campaignProgress?.latestBattleTitle !== '강동 사절로' ||
postJiangdongProgressState.campaignProgress?.nextBattleTitle !== '적벽 전초전'
@@ -2304,7 +2304,7 @@ try {
if (
postRedCliffsProgressState?.activeTab !== 'progress' ||
postRedCliffsProgressState.campaignProgress?.completedKnown !== 21 ||
postRedCliffsProgressState.campaignProgress?.totalKnown !== 36 ||
postRedCliffsProgressState.campaignProgress?.totalKnown !== 37 ||
postRedCliffsProgressState.campaignProgress?.activeChapter?.title !== '적벽대전' ||
postRedCliffsProgressState.campaignProgress?.latestBattleTitle !== '적벽 전초전' ||
postRedCliffsProgressState.campaignProgress?.nextBattleTitle !== '적벽 화공전'
@@ -2444,7 +2444,7 @@ try {
if (
postFireAttackProgressState?.activeTab !== 'progress' ||
postFireAttackProgressState.campaignProgress?.completedKnown !== 22 ||
postFireAttackProgressState.campaignProgress?.totalKnown !== 36 ||
postFireAttackProgressState.campaignProgress?.totalKnown !== 37 ||
postFireAttackProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postFireAttackProgressState.campaignProgress?.latestBattleTitle !== '적벽 화공전' ||
postFireAttackProgressState.campaignProgress?.nextBattleTitle !== '형주 남부 진입전'
@@ -2587,7 +2587,7 @@ try {
if (
postJingzhouProgressState?.activeTab !== 'progress' ||
postJingzhouProgressState.campaignProgress?.completedKnown !== 23 ||
postJingzhouProgressState.campaignProgress?.totalKnown !== 36 ||
postJingzhouProgressState.campaignProgress?.totalKnown !== 37 ||
postJingzhouProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postJingzhouProgressState.campaignProgress?.latestBattleTitle !== '형주 남부 진입전' ||
postJingzhouProgressState.campaignProgress?.nextBattleTitle !== '계양 설득전'
@@ -2729,7 +2729,7 @@ try {
if (
postGuiyangProgressState?.activeTab !== 'progress' ||
postGuiyangProgressState.campaignProgress?.completedKnown !== 24 ||
postGuiyangProgressState.campaignProgress?.totalKnown !== 36 ||
postGuiyangProgressState.campaignProgress?.totalKnown !== 37 ||
postGuiyangProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postGuiyangProgressState.campaignProgress?.latestBattleTitle !== '계양 설득전' ||
postGuiyangProgressState.campaignProgress?.nextBattleTitle !== '무릉 산길 확보전'
@@ -2872,7 +2872,7 @@ try {
if (
postWulingProgressState?.activeTab !== 'progress' ||
postWulingProgressState.campaignProgress?.completedKnown !== 25 ||
postWulingProgressState.campaignProgress?.totalKnown !== 36 ||
postWulingProgressState.campaignProgress?.totalKnown !== 37 ||
postWulingProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postWulingProgressState.campaignProgress?.latestBattleTitle !== '무릉 산길 확보전' ||
postWulingProgressState.campaignProgress?.nextBattleTitle !== '장사 노장 대면전'
@@ -3021,7 +3021,7 @@ try {
if (
postChangshaProgressState?.activeTab !== 'progress' ||
postChangshaProgressState.campaignProgress?.completedKnown !== 26 ||
postChangshaProgressState.campaignProgress?.totalKnown !== 36 ||
postChangshaProgressState.campaignProgress?.totalKnown !== 37 ||
postChangshaProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postChangshaProgressState.campaignProgress?.latestBattleTitle !== '장사 노장 대면전' ||
postChangshaProgressState.campaignProgress?.nextBattleTitle !== '익주 원군로'
@@ -3166,7 +3166,7 @@ try {
if (
postYizhouProgressState?.activeTab !== 'progress' ||
postYizhouProgressState.campaignProgress?.completedKnown !== 27 ||
postYizhouProgressState.campaignProgress?.totalKnown !== 36 ||
postYizhouProgressState.campaignProgress?.totalKnown !== 37 ||
postYizhouProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postYizhouProgressState.campaignProgress?.latestBattleTitle !== '익주 원군로' ||
postYizhouProgressState.campaignProgress?.nextBattleTitle !== '부수관 진입전'
@@ -3313,7 +3313,7 @@ try {
if (
postFuPassProgressState?.activeTab !== 'progress' ||
postFuPassProgressState.campaignProgress?.completedKnown !== 28 ||
postFuPassProgressState.campaignProgress?.totalKnown !== 36 ||
postFuPassProgressState.campaignProgress?.totalKnown !== 37 ||
postFuPassProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postFuPassProgressState.campaignProgress?.latestBattleTitle !== '부수관 진입전' ||
postFuPassProgressState.campaignProgress?.nextBattleTitle !== '낙성 외곽전'
@@ -3462,7 +3462,7 @@ try {
if (
postLuoProgressState?.activeTab !== 'progress' ||
postLuoProgressState.campaignProgress?.completedKnown !== 29 ||
postLuoProgressState.campaignProgress?.totalKnown !== 36 ||
postLuoProgressState.campaignProgress?.totalKnown !== 37 ||
postLuoProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postLuoProgressState.campaignProgress?.latestBattleTitle !== '낙성 외곽전' ||
postLuoProgressState.campaignProgress?.nextBattleTitle !== '낙봉파 매복전'
@@ -3608,7 +3608,7 @@ try {
if (
postLuofengProgressState?.activeTab !== 'progress' ||
postLuofengProgressState.campaignProgress?.completedKnown !== 30 ||
postLuofengProgressState.campaignProgress?.totalKnown !== 36 ||
postLuofengProgressState.campaignProgress?.totalKnown !== 37 ||
postLuofengProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postLuofengProgressState.campaignProgress?.latestBattleTitle !== '낙봉파 매복전' ||
postLuofengProgressState.campaignProgress?.nextBattleTitle !== '낙성 본성 공략'
@@ -3760,7 +3760,7 @@ try {
if (
postLuoMainProgressState?.activeTab !== 'progress' ||
postLuoMainProgressState.campaignProgress?.completedKnown !== 31 ||
postLuoMainProgressState.campaignProgress?.totalKnown !== 36 ||
postLuoMainProgressState.campaignProgress?.totalKnown !== 37 ||
postLuoMainProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postLuoMainProgressState.campaignProgress?.latestBattleTitle !== '낙성 본성 공략' ||
postLuoMainProgressState.campaignProgress?.nextBattleTitle !== '면죽관 압박전'
@@ -3913,7 +3913,7 @@ try {
if (
postMianzhuProgressState?.activeTab !== 'progress' ||
postMianzhuProgressState.campaignProgress?.completedKnown !== 32 ||
postMianzhuProgressState.campaignProgress?.totalKnown !== 36 ||
postMianzhuProgressState.campaignProgress?.totalKnown !== 37 ||
postMianzhuProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postMianzhuProgressState.campaignProgress?.latestBattleTitle !== '면죽관 압박전' ||
postMianzhuProgressState.campaignProgress?.nextBattleTitle !== '성도 항복 권고전'
@@ -4067,7 +4067,7 @@ try {
if (
postChengduProgressState?.activeTab !== 'progress' ||
postChengduProgressState.campaignProgress?.completedKnown !== 33 ||
postChengduProgressState.campaignProgress?.totalKnown !== 36 ||
postChengduProgressState.campaignProgress?.totalKnown !== 37 ||
postChengduProgressState.campaignProgress?.activeChapter?.title !== '촉한 건국' ||
postChengduProgressState.campaignProgress?.latestBattleTitle !== '성도 항복 권고전' ||
postChengduProgressState.campaignProgress?.nextBattleTitle !== '가맹관 마초 대면전'
@@ -4222,7 +4222,7 @@ try {
if (
postJiamengProgressState?.activeTab !== 'progress' ||
postJiamengProgressState.campaignProgress?.completedKnown !== 34 ||
postJiamengProgressState.campaignProgress?.totalKnown !== 36 ||
postJiamengProgressState.campaignProgress?.totalKnown !== 37 ||
postJiamengProgressState.campaignProgress?.activeChapter?.title !== '촉한 건국' ||
postJiamengProgressState.campaignProgress?.latestBattleTitle !== '가맹관 마초 대면전' ||
postJiamengProgressState.campaignProgress?.nextBattleTitle !== '양평관 정찰전'
@@ -4378,7 +4378,7 @@ try {
if (
postYangpingProgressState?.activeTab !== 'progress' ||
postYangpingProgressState.campaignProgress?.completedKnown !== 35 ||
postYangpingProgressState.campaignProgress?.totalKnown !== 36 ||
postYangpingProgressState.campaignProgress?.totalKnown !== 37 ||
postYangpingProgressState.campaignProgress?.activeChapter?.title !== '촉한 건국' ||
postYangpingProgressState.campaignProgress?.latestBattleTitle !== '양평관 정찰전' ||
postYangpingProgressState.campaignProgress?.nextBattleTitle !== '정군산 전초전'
@@ -4535,15 +4535,168 @@ try {
if (
postDingjunProgressState?.activeTab !== 'progress' ||
postDingjunProgressState.campaignProgress?.completedKnown !== 36 ||
postDingjunProgressState.campaignProgress?.totalKnown !== 36 ||
postDingjunProgressState.campaignProgress?.totalKnown !== 37 ||
postDingjunProgressState.campaignProgress?.activeChapter?.title !== '촉한 건국' ||
postDingjunProgressState.campaignProgress?.latestBattleTitle !== '정군산 전초전' ||
postDingjunProgressState.campaignProgress?.nextBattleTitle !== '준비 중'
postDingjunProgressState.campaignProgress?.nextBattleTitle !== '한중 결전'
) {
throw new Error(`Expected post-Dingjun progress tab to complete Wang Ping chapter and pause on the next Hanzhong step: ${JSON.stringify(postDingjunProgressState?.campaignProgress)}`);
throw new Error(`Expected post-Dingjun progress tab to complete Wang Ping chapter and open the Hanzhong decisive battle: ${JSON.stringify(postDingjunProgressState?.campaignProgress)}`);
}
await page.screenshot({ path: 'dist/verification-post-dingjun-progress.png', fullPage: true });
await page.mouse.click(1120, 38);
await page.waitForTimeout(180);
const hanzhongSortieState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
if (
!hanzhongSortieState?.sortieVisible ||
!hanzhongSortieState.sortiePlan?.objectiveLine?.includes('한중 결전') ||
hanzhongSortieState.sortiePlan?.maxCount !== 7 ||
hanzhongSortieState.sortiePlan?.recommendedTotal !== 7 ||
!hanzhongSortieState.sortieRoster?.some((unit) => unit.id === 'wang-ping' && unit.recruited && unit.recommended)
) {
throw new Error(`Expected Hanzhong decisive sortie prep to use a seven-officer roster and recommend Wang Ping: ${JSON.stringify(hanzhongSortieState)}`);
}
assertSortieTacticalRoster(hanzhongSortieState, [
'liu-bei',
'guan-yu',
'zhang-fei',
'jian-yong',
'mi-zhu',
'sun-qian',
'zhao-yun',
'zhuge-liang',
'ma-liang',
'yi-ji',
'gong-zhi',
'huang-zhong',
'wei-yan',
'pang-tong',
'fa-zheng',
'wu-yi',
'yan-yan',
'li-yan',
'huang-quan',
'ma-chao',
'ma-dai',
'wang-ping'
]);
const hanzhongPriorityUnits = ['huang-zhong', 'fa-zheng', 'wang-ping', 'ma-chao', 'ma-dai', 'zhuge-liang'];
for (const unitId of hanzhongPriorityUnits) {
const currentSortieState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
if (!currentSortieState.sortieRoster?.some((unit) => unit.id === unitId && unit.selected)) {
const removable = currentSortieState.sortieRoster?.find(
(unit) => unit.selected && unit.id !== 'liu-bei' && !hanzhongPriorityUnits.includes(unit.id)
);
if (removable) {
await clickSortieRosterUnit(page, removable.id);
}
await clickSortieRosterUnit(page, unitId);
}
}
const hanzhongSortieReadyState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
if (
!hanzhongPriorityUnits.every((unitId) =>
hanzhongSortieReadyState.sortieRoster?.some((unit) => unit.id === unitId && unit.selected)
) ||
hanzhongSortieReadyState.sortiePlan?.selectedCount !== 7 ||
hanzhongSortieReadyState.sortiePlan?.recommendedSelectedCount < 7
) {
throw new Error(`Expected Hanzhong decisive sortie to deploy Huang Zhong, Fa Zheng, Wang Ping, Ma Chao, Ma Dai, and Zhuge Liang with seven-officer pressure: ${JSON.stringify(hanzhongSortieReadyState)}`);
}
await page.screenshot({ path: 'dist/verification-hanzhong-decisive-sortie.png', fullPage: true });
await page.mouse.click(1068, 646);
await page.waitForFunction(() => {
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
return activeScenes.includes('StoryScene');
});
await page.screenshot({ path: 'dist/verification-hanzhong-decisive-story.png', fullPage: true });
for (let i = 0; i < 55; i += 1) {
const enteredThirtySeventhBattle = await page.evaluate(() => {
const state = window.__HEROS_DEBUG__?.battle();
return state?.scene === 'BattleScene' && state?.battleId === 'thirty-seventh-battle-hanzhong-decisive';
});
if (enteredThirtySeventhBattle) {
break;
}
await page.keyboard.press('Space');
await page.waitForTimeout(320);
}
await page.waitForFunction(() => {
const state = window.__HEROS_DEBUG__?.battle();
return state?.scene === 'BattleScene' && state?.battleId === 'thirty-seventh-battle-hanzhong-decisive' && state?.battleOutcome === null && state?.phase === 'idle';
});
await page.screenshot({ path: 'dist/verification-thirty-seventh-battle.png', fullPage: true });
const thirtySeventhBattleState = await page.evaluate(() => window.__HEROS_DEBUG__?.battle());
const thirtySeventhEnemies = thirtySeventhBattleState.units.filter((unit) => unit.faction === 'enemy');
const thirtySeventhAllies = thirtySeventhBattleState.units.filter((unit) => unit.faction === 'ally');
const thirtySeventhEnemyBehaviors = new Set(thirtySeventhEnemies.map((unit) => unit.ai));
if (
thirtySeventhBattleState.camera?.mapWidth !== 74 ||
thirtySeventhBattleState.camera?.mapHeight !== 56 ||
thirtySeventhBattleState.victoryConditionLabel !== '조조 본진 격파' ||
thirtySeventhEnemies.length < 30 ||
!thirtySeventhEnemyBehaviors.has('aggressive') ||
!thirtySeventhEnemyBehaviors.has('guard') ||
!thirtySeventhEnemyBehaviors.has('hold') ||
!thirtySeventhEnemies.some((unit) => unit.id === 'hanzhong-leader-cao-cao') ||
!thirtySeventhEnemies.some((unit) => unit.id === 'hanzhong-officer-zhang-he') ||
!thirtySeventhEnemies.some((unit) => unit.id === 'hanzhong-officer-xu-huang') ||
!thirtySeventhAllies.some((unit) => unit.id === 'huang-zhong') ||
!thirtySeventhAllies.some((unit) => unit.id === 'fa-zheng') ||
!thirtySeventhAllies.some((unit) => unit.id === 'wang-ping') ||
!thirtySeventhAllies.some((unit) => unit.id === 'ma-chao') ||
!thirtySeventhAllies.some((unit) => unit.id === 'ma-dai') ||
!thirtySeventhAllies.some((unit) => unit.id === 'zhuge-liang')
) {
throw new Error(`Expected thirty-seventh battle to use Hanzhong map, Cao Cao objective, Wang Ping terrain pressure, selected allied officers, and mixed AI: ${JSON.stringify(thirtySeventhBattleState)}`);
}
await page.evaluate(() => window.__HEROS_DEBUG__?.forceBattleOutcome('victory'));
await page.waitForFunction(() => {
const state = window.__HEROS_DEBUG__?.battle();
return state?.battleOutcome === 'victory' && state?.phase === 'resolved' && state?.resultVisible === true;
});
await page.mouse.click(738, 642);
await page.waitForFunction(() => {
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
return activeScenes.includes('CampScene');
});
const thirtySeventhCampState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
if (
thirtySeventhCampState?.campBattleId !== 'thirty-seventh-battle-hanzhong-decisive' ||
thirtySeventhCampState.campTitle !== '한중 결전 후 군영' ||
thirtySeventhCampState.availableDialogueIds?.length !== 3 ||
!thirtySeventhCampState.availableDialogueIds.every((id) => id.endsWith('hanzhong-decisive')) ||
thirtySeventhCampState.availableVisitIds?.length !== 2 ||
!thirtySeventhCampState.campaign?.roster?.some((unit) => unit.id === 'wang-ping') ||
thirtySeventhCampState.rosterCollection?.total < 22
) {
throw new Error(`Expected thirty-seventh camp to expose Hanzhong decisive dialogue/visit sets and preserve Wang Ping roster: ${JSON.stringify(thirtySeventhCampState)}`);
}
await page.screenshot({ path: 'dist/verification-hanzhong-decisive-camp.png', fullPage: true });
await page.mouse.click(966, 38);
await page.waitForTimeout(180);
const postHanzhongProgressState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
if (
postHanzhongProgressState?.activeTab !== 'progress' ||
postHanzhongProgressState.campaignProgress?.completedKnown !== 37 ||
postHanzhongProgressState.campaignProgress?.totalKnown !== 37 ||
postHanzhongProgressState.campaignProgress?.activeChapter?.title !== '촉한 건국' ||
postHanzhongProgressState.campaignProgress?.latestBattleTitle !== '한중 결전' ||
postHanzhongProgressState.campaignProgress?.nextBattleTitle !== '준비 중'
) {
throw new Error(`Expected post-Hanzhong progress tab to complete the decisive battle and pause on Shu-Han foundation prep: ${JSON.stringify(postHanzhongProgressState?.campaignProgress)}`);
}
await page.screenshot({ path: 'dist/verification-post-hanzhong-progress.png', fullPage: true });
await page.evaluate(() => {
const game = window.__HEROS_GAME__;
game?.scene.stop('CampScene');
@@ -4562,7 +4715,7 @@ try {
return activeScenes.includes('CampScene');
});
console.log(`Verified title-to-thirty-sixth-battle flow, recruited officer sortie selection, Ma Liang, Yi Ji, Gong Zhi, Huang Zhong, Wei Yan, Pang Tong, Fa Zheng, Wu Yi, Yan Yan, Li Yan, Huang Quan, Ma Chao, Ma Dai, and Wang Ping joins, Luofeng, Luo main gate, Mianzhu, Chengdu surrender, Jiameng Pass, Yangping scout, and Dingjun vanguard battles, result states, and debug API at ${targetUrl}`);
console.log(`Verified title-to-thirty-seventh-battle flow, recruited officer sortie selection, Ma Liang, Yi Ji, Gong Zhi, Huang Zhong, Wei Yan, Pang Tong, Fa Zheng, Wu Yi, Yan Yan, Li Yan, Huang Quan, Ma Chao, Ma Dai, and Wang Ping joins, Luofeng, Luo main gate, Mianzhu, Chengdu surrender, Jiameng, Yangping, Dingjun, and Hanzhong decisive battles, result states, and debug API at ${targetUrl}`);
} finally {
await browser?.close();
if (serverProcess && !serverProcess.killed) {