Add Chencang siege campaign chapter

This commit is contained in:
2026-06-24 11:03:12 +09:00
parent f9689c0149
commit 779b639bdf
10 changed files with 834 additions and 75 deletions

View File

@@ -8,6 +8,7 @@ import fiftyThirdBattleMapUrl from '../../assets/images/battle/fifty-third-battl
import fiftyFourthBattleMapUrl from '../../assets/images/battle/fifty-fourth-battle-map.svg';
import fiftyFifthBattleMapUrl from '../../assets/images/battle/fifty-fifth-battle-map.svg';
import fiftyEighthBattleMapUrl from '../../assets/images/battle/fifty-eighth-battle-map.svg';
import fiftyNinthBattleMapUrl from '../../assets/images/battle/fifty-ninth-battle-map.svg';
import fiftySeventhBattleMapUrl from '../../assets/images/battle/fifty-seventh-battle-map.svg';
import fiftySixthBattleMapUrl from '../../assets/images/battle/fifty-sixth-battle-map.svg';
import fifthBattleMapUrl from '../../assets/images/battle/fifth-battle-map.svg';
@@ -114,6 +115,7 @@ export const battleMapAssets: Record<string, string> = {
'battle-map-fifty-fourth': fiftyFourthBattleMapUrl,
'battle-map-fifty-fifth': fiftyFifthBattleMapUrl,
'battle-map-fifty-eighth': fiftyEighthBattleMapUrl,
'battle-map-fifty-ninth': fiftyNinthBattleMapUrl,
'battle-map-fifty-seventh': fiftySeventhBattleMapUrl,
'battle-map-fifty-sixth': fiftySixthBattleMapUrl
};

View File

@@ -31,6 +31,10 @@ import {
fiftySixthBattleMap,
fiftySixthBattleUnits,
fiftySixthBattleVictoryPages,
fiftyNinthBattleBonds,
fiftyNinthBattleMap,
fiftyNinthBattleUnits,
fiftyNinthBattleVictoryPages,
fiftySeventhBattleBonds,
fiftySeventhBattleMap,
fiftySeventhBattleUnits,
@@ -295,7 +299,8 @@ export type BattleScenarioId =
| 'fifty-fifth-battle-northern-qishan-road'
| 'fifty-sixth-battle-tianshui-advance'
| 'fifty-seventh-battle-jieting-crisis'
| 'fifty-eighth-battle-qishan-retreat';
| 'fifty-eighth-battle-qishan-retreat'
| 'fifty-ninth-battle-chencang-siege';
export type BattleObjectiveKind = 'defeat-leader' | 'pacify-leader' | 'keep-unit-alive' | 'secure-terrain' | 'quick-victory';
@@ -3861,6 +3866,87 @@ export const fiftyEighthBattleScenario: BattleScenarioDefinition = {
nextCampScene: 'CampScene'
};
export const fiftyNinthBattleScenario: BattleScenarioDefinition = {
id: 'fifty-ninth-battle-chencang-siege',
title: '진창 공성전',
victoryConditionLabel: '학소 진창 수비 압박과 왕쌍 추격 차단',
defeatConditionLabel: '제갈량 퇴각 또는 공성 진영 붕괴',
openingObjectiveLines: [
'기산에서 후퇴한 뒤 촉한군은 병사와 장부를 다시 묶어 진창 성채를 압박합니다. 학소가 성벽을 굳게 지키고 있어 성문 하나만 바라보는 공격은 오래 버티지 못합니다.',
'강유는 길을 알고, 왕평은 진영 표식을 보며, 위연은 돌파를 원합니다. 여기에 황권과 마량, 법정의 장부와 계책을 어떻게 넣을지에 따라 공성전의 무게가 달라집니다.',
'학소의 수비를 흔들고 왕쌍의 추격을 차단하십시오. 공성 진영과 군량 수레 길을 함께 지키면 다음 북방 계산으로 이어갈 수 있습니다.'
],
map: fiftyNinthBattleMap,
units: fiftyNinthBattleUnits,
bonds: fiftyNinthBattleBonds,
mapTextureKey: 'battle-map-fifty-ninth',
leaderUnitId: 'northern-fifth-leader-hao-zhao',
quickVictoryTurnLimit: 118,
baseVictoryGold: 17280,
objectives: [
{
id: 'pressure-hao-zhao',
kind: 'defeat-leader',
label: '학소 진창 수비 압박',
rewardGold: 12040,
unitId: 'northern-fifth-leader-hao-zhao'
},
{
id: 'halt-wang-shuang',
kind: 'defeat-leader',
label: '왕쌍 추격 차단',
rewardGold: 6000,
unitId: 'northern-fifth-officer-wang-shuang'
},
{
id: 'zhuge-liang',
kind: 'keep-unit-alive',
label: '제갈량 생존',
rewardGold: 3100,
unitId: 'zhuge-liang'
},
{
id: 'chencang-gate',
kind: 'secure-terrain',
label: '진창 성문 압박',
rewardGold: 6200,
terrain: 'fort'
},
{
id: 'siege-camps',
kind: 'secure-terrain',
label: '공성 진영 유지',
rewardGold: 5940,
terrain: 'camp'
},
{
id: 'grain-road',
kind: 'secure-terrain',
label: '군량 수레 길 확보',
rewardGold: 5820,
terrain: 'road'
},
{
id: 'rear-villages',
kind: 'secure-terrain',
label: '후방 마을 안정',
rewardGold: 5480,
terrain: 'village'
},
{
id: 'quick',
kind: 'quick-victory',
label: '118턴 이내 진창 압박 완료',
rewardGold: 3840,
maxTurn: 118
}
],
defeatConditions: [{ kind: 'unit-defeated', unitId: 'zhuge-liang' }],
itemRewards: ['금 104', '상처약 86', '군주 42', '진창 공성 장부 1', '왕쌍 추격 기록 1'],
victoryPages: fiftyNinthBattleVictoryPages,
nextCampScene: 'CampScene'
};
export const defaultBattleScenarioId: BattleScenarioId = firstBattleScenario.id;
export const battleScenarios: Record<BattleScenarioId, BattleScenarioDefinition> = {
@@ -3921,7 +4007,8 @@ export const battleScenarios: Record<BattleScenarioId, BattleScenarioDefinition>
'fifty-fifth-battle-northern-qishan-road': fiftyFifthBattleScenario,
'fifty-sixth-battle-tianshui-advance': fiftySixthBattleScenario,
'fifty-seventh-battle-jieting-crisis': fiftySeventhBattleScenario,
'fifty-eighth-battle-qishan-retreat': fiftyEighthBattleScenario
'fifty-eighth-battle-qishan-retreat': fiftyEighthBattleScenario,
'fifty-ninth-battle-chencang-siege': fiftyNinthBattleScenario
};
export const defaultBattleScenario = battleScenarios[defaultBattleScenarioId];

View File

@@ -12,6 +12,7 @@ import {
fiftyFourthBattleScenario,
fiftyFifthBattleScenario,
fiftySixthBattleScenario,
fiftyNinthBattleScenario,
fiftySeventhBattleScenario,
fortiethBattleScenario,
fortyFirstBattleScenario,
@@ -72,6 +73,8 @@ import {
fiftiethBattleVictoryPages,
fiftyEighthBattleIntroPages,
fiftyEighthBattleVictoryPages,
fiftyNinthBattleIntroPages,
fiftyNinthBattleVictoryPages,
fiftyFirstBattleIntroPages,
fiftyFirstBattleVictoryPages,
fiftySecondBattleIntroPages,
@@ -855,13 +858,24 @@ const sortieFlows: Record<string, SortieFlow> = {
},
[fiftyEighthBattleScenario.id]: {
afterBattleId: fiftyEighthBattleScenario.id,
eyebrow: '다음 장 준비',
title: '기산 후퇴로 이후',
eyebrow: '다음 장',
title: fiftyNinthBattleScenario.title,
description:
'기산 후퇴로에서 병사와 장부를 지켜 냈습니다. 그러나 이것은 북벌의 끝이 아니라 다음 출정을 위한 정비입니다. 강유의 첫 출전, 왕평의 물길 판단, 조운과 마대의 귀환선을 군영에서 다시 정리합니다.',
rewardHint: '다음 목표: 북벌 재정비 / 강유 첫 출전 평가',
pages: fiftyEighthBattleVictoryPages,
unavailableNotice: '기산 후퇴로 이후의 다음 북벌 전투는 이어지는 작업에서 확장합니다. 현재는 강유 첫 출전 후 군영 대화, 보급 정비, 출전 편성 방향을 확인할 수 있습니다.'
'기산 후퇴로에서 병사와 장부를 지켜 냈습니다. 이제 다시 북쪽을 보되, 진창 성채의 학소와 왕쌍의 추격을 상대해야 합니다. 강유의 길 판단과 공성 진영, 군량 수레를 함께 계산하십시오.',
rewardHint: `예상 보상: ${fiftyNinthBattleScenario.title} 개방 / 진창 공성 장부`,
nextBattleId: fiftyNinthBattleScenario.id,
campaignStep: 'fifty-ninth-battle',
pages: [...fiftyEighthBattleVictoryPages, ...fiftyNinthBattleIntroPages]
},
[fiftyNinthBattleScenario.id]: {
afterBattleId: fiftyNinthBattleScenario.id,
eyebrow: '다음 장 준비',
title: '진창 공성전 이후',
description:
'진창 성채를 압박하고 왕쌍의 추격을 끊었지만, 성을 오래 물고 늘어지는 북벌은 군량의 시간을 갉아먹습니다. 이것은 결말이 아니라 다음 북방 계산을 위한 경계선입니다.',
rewardHint: '다음 목표: 북벌 보급 재계산 / 진창 공성 평가',
pages: fiftyNinthBattleVictoryPages,
unavailableNotice: '진창 공성전 이후의 다음 북벌 전투는 이어지는 작업에서 확장합니다. 현재는 진창 공성 평가, 보급 재계산, 강유와 위연의 편성 방향을 확인할 수 있습니다.'
},
'northern-campaign-prep-camp-legacy': {
afterBattleId: fiftyFourthBattleScenario.id,

View File

@@ -3748,6 +3748,59 @@ export const fiftyEighthBattleVictoryPages: StoryPage[] = [
}
];
export const fiftyNinthBattleIntroPages: StoryPage[] = [
{
id: 'fifty-ninth-chencang-order',
bgm: 'story-dark',
chapter: '진창 성채',
background: 'story-militia',
speaker: '제갈량',
text: '기산에서 병사를 살렸기에 다시 북쪽을 볼 수 있습니다. 그러나 이번 길은 넓은 들이 아니라 진창의 굳은 성채입니다. 성문을 무리하게 깨기보다 공성 진영, 군량 수레, 퇴로를 함께 보아야 합니다.'
},
{
id: 'fifty-ninth-hao-zhao-wall',
bgm: 'battle-prep',
chapter: '학소의 성벽',
background: 'story-sortie',
speaker: '강유',
text: '진창의 수비장 학소는 성을 버리지 않을 사람입니다. 제가 앞길을 살피겠습니다만, 성벽만 바라보면 왕쌍의 기병이 뒤를 물 것입니다. 조운, 마대, 왕평 중 누구를 앞으로 세우느냐가 이번 편성의 무게입니다.'
},
{
id: 'fifty-ninth-supply-limit',
bgm: 'story-dark',
chapter: '군량의 시간',
background: 'story-three-heroes',
speaker: '황권',
text: '성채 하나에 오래 묶이면 북벌 전체가 굶습니다. 법정의 계책, 마량의 문서, 황권의 장부가 함께 있어야 공성전이 단순한 힘겨루기로 흐르지 않습니다. 진창을 압박하되 돌아갈 수 있는 시간을 남기십시오.'
}
];
export const fiftyNinthBattleVictoryPages: StoryPage[] = [
{
id: 'fifty-ninth-victory-chencang-pressure',
bgm: 'militia-theme',
chapter: '진창 압박',
background: 'story-sortie',
text: '촉한군은 진창의 외곽 진영과 보급로를 흔들었지만, 학소의 성벽은 끝내 쉽게 열리지 않았습니다. 승리라 부르기에는 조심스럽고 패배라 덮기에는 얻은 길이 분명한 전투였습니다.'
},
{
id: 'fifty-ninth-victory-wang-shuang-cut',
bgm: 'story-dark',
chapter: '왕쌍 추격 차단',
background: 'story-militia',
speaker: '조운',
text: '왕쌍의 기병은 공성 진영 뒤를 물려 했으나, 강유의 길 안내와 마대의 우회, 왕평의 진영 표식이 먼저 움직였습니다. 오래 버티는 성을 상대로도 물러날 때를 정하는 장수가 필요합니다.'
},
{
id: 'fifty-ninth-next-northern-plan',
bgm: 'story-dark',
chapter: '다음 북방 계산',
background: 'story-three-heroes',
speaker: '제갈량',
text: '진창은 북벌의 끝이 아니라, 무리한 공세가 어디서 멈춰야 하는지를 보여 준 성입니다. 다음 출정에서는 성을 치는 힘뿐 아니라 군량이 버틸 날, 돌아올 길, 장수의 고집을 모두 함께 계산해야 합니다.'
}
];
export const firstBattleMap: BattleMap = {
width: 20,
height: 18,
@@ -4241,6 +4294,12 @@ export const fiftyEighthBattleMap: BattleMap = {
terrain: createFiftyEighthBattleTerrain()
};
export const fiftyNinthBattleMap: BattleMap = {
width: 118,
height: 100,
terrain: createFiftyNinthBattleTerrain()
};
export const firstBattleUnits: UnitData[] = [
{
id: 'liu-bei',
@@ -17276,6 +17335,97 @@ export const fiftyEighthBattleUnits: UnitData[] = [
createThirtyFirstEnemyUnit('northern-fourth-leader-sima-yi', '사마의', '위군 본대 총지휘관', 'rebelLeader', 193, 1500, 352, 112, 27)
];
const fiftyNinthBattleAllyPositions: Record<string, { x: number; y: number }> = {
'guan-yu': { x: 18, y: 88 },
'zhang-fei': { x: 24, y: 90 },
'jian-yong': { x: 10, y: 95 },
'mi-zhu': { x: 14, y: 96 },
'sun-qian': { x: 19, y: 96 },
'zhao-yun': { x: 31, y: 86 },
'zhuge-liang': { x: 17, y: 85 },
'ma-liang': { x: 22, y: 82 },
'yi-ji': { x: 9, y: 98 },
'gong-zhi': { x: 27, y: 96 },
'huang-zhong': { x: 37, y: 84 },
'wei-yan': { x: 43, y: 86 },
'pang-tong': { x: 15, y: 81 },
'fa-zheng': { x: 27, y: 80 },
'wu-yi': { x: 45, y: 94 },
'yan-yan': { x: 49, y: 87 },
'li-yan': { x: 35, y: 79 },
'huang-quan': { x: 12, y: 84 },
'ma-chao': { x: 52, y: 83 },
'ma-dai': { x: 56, y: 90 },
'wang-ping': { x: 40, y: 79 },
'jiang-wei': { x: 33, y: 82 }
};
export const fiftyNinthBattleUnits: UnitData[] = [
...[
...firstBattleUnits.filter((unit) => unit.faction === 'ally' && unit.id !== 'liu-bei'),
...xuzhouRecruitUnits,
...caoBreakRecruitUnits,
...liuBiaoRecruitUnits,
...zhugeRecruitUnits,
...jingzhouRecruitUnits,
...guiyangRecruitUnits,
...wulingRecruitUnits,
...changshaRecruitUnits,
...yizhouRecruitUnits,
...fuPassRecruitUnits,
...luoCastleRecruitUnits,
...luoCastleProperRecruitUnits,
...chengduPressureRecruitUnits,
...chengduSurrenderRecruitUnits,
...hanzhongOpeningRecruitUnits,
...hanzhongScoutRecruitUnits,
...hanzhongMainRecruitUnits,
...jiangWeiRecruitUnits
].map((unit) => placeScenarioUnit(unit, fiftyNinthBattleAllyPositions[unit.id] ?? { x: unit.x, y: unit.y })),
createThirtyFirstEnemyUnit('northern-fifth-scout-a', '진창 외곽 척후병', '서쪽 수레길 정찰', 'bandit', 190, 960, 270, 49, 78),
createThirtyFirstEnemyUnit('northern-fifth-scout-b', '진창 외곽 척후병', '공성 진영 정찰', 'bandit', 190, 960, 270, 60, 74),
createThirtyFirstEnemyUnit('northern-fifth-scout-c', '진창 외곽 척후병', '중앙 낮은 길 정찰', 'bandit', 191, 972, 272, 72, 67),
createThirtyFirstEnemyUnit('northern-fifth-scout-d', '진창 외곽 척후병', '동쪽 성문 정찰', 'bandit', 191, 972, 272, 84, 60),
createThirtyFirstEnemyUnit('northern-fifth-scout-e', '진창 외곽 척후병', '학소 성벽 정찰', 'bandit', 192, 984, 274, 101, 42),
createThirtyFirstEnemyUnit('northern-fifth-scout-f', '진창 외곽 척후병', '북쪽 봉화 정찰', 'bandit', 192, 984, 274, 114, 25),
createThirtyFirstEnemyUnit('northern-fifth-infantry-a', '위군 진창 보병', '서쪽 공성로 보병', 'yellowTurban', 191, 1340, 324, 54, 73),
createThirtyFirstEnemyUnit('northern-fifth-infantry-b', '위군 진창 보병', '수레길 보병', 'yellowTurban', 191, 1340, 324, 64, 68),
createThirtyFirstEnemyUnit('northern-fifth-infantry-c', '위군 진창 보병', '중앙 보병', 'yellowTurban', 192, 1360, 328, 76, 62),
createThirtyFirstEnemyUnit('northern-fifth-infantry-d', '위군 진창 보병', '동문 앞 보병', 'yellowTurban', 192, 1360, 328, 88, 55),
createThirtyFirstEnemyUnit('northern-fifth-infantry-e', '위군 진창 보병', '성벽 아래 보병', 'yellowTurban', 193, 1380, 332, 100, 48),
createThirtyFirstEnemyUnit('northern-fifth-infantry-f', '위군 진창 보병', '학소 본영 보병', 'yellowTurban', 193, 1380, 332, 110, 36),
createThirtyFirstEnemyUnit('northern-fifth-infantry-g', '위군 진창 보병', '보급 차단 보병', 'yellowTurban', 194, 1400, 336, 92, 76),
createThirtyFirstEnemyUnit('northern-fifth-infantry-h', '위군 진창 보병', '북쪽 성벽 보병', 'yellowTurban', 194, 1400, 336, 115, 18),
createThirtyFirstEnemyUnit('northern-fifth-archer-a', '진창 성벽 궁병', '서쪽 성벽 궁병', 'archer', 191, 1010, 282, 60, 63),
createThirtyFirstEnemyUnit('northern-fifth-archer-b', '진창 성벽 궁병', '공성로 궁병', 'archer', 191, 1010, 282, 71, 58),
createThirtyFirstEnemyUnit('northern-fifth-archer-c', '진창 성벽 궁병', '중앙 성벽 궁병', 'archer', 192, 1022, 284, 84, 51),
createThirtyFirstEnemyUnit('northern-fifth-archer-d', '진창 성벽 궁병', '동문 궁병', 'archer', 193, 1034, 286, 96, 44),
createThirtyFirstEnemyUnit('northern-fifth-archer-e', '진창 성벽 궁병', '학소 본영 궁병', 'archer', 193, 1034, 286, 108, 31),
createThirtyFirstEnemyUnit('northern-fifth-archer-f', '진창 성벽 궁병', '봉화대 궁병', 'archer', 194, 1046, 288, 116, 16),
createThirtyFirstEnemyUnit('northern-fifth-cavalry-a', '왕쌍 추격 기병', '서쪽 추격 기병', 'cavalry', 192, 1388, 338, 50, 66),
createThirtyFirstEnemyUnit('northern-fifth-cavalry-b', '왕쌍 추격 기병', '수레길 추격 기병', 'cavalry', 192, 1388, 338, 63, 63),
createThirtyFirstEnemyUnit('northern-fifth-cavalry-c', '왕쌍 추격 기병', '중앙 돌파 기병', 'cavalry', 193, 1410, 342, 77, 56),
createThirtyFirstEnemyUnit('northern-fifth-cavalry-d', '왕쌍 추격 기병', '동쪽 우회 기병', 'cavalry', 194, 1432, 346, 91, 49),
createThirtyFirstEnemyUnit('northern-fifth-cavalry-e', '왕쌍 추격 기병', '성문 지원 기병', 'cavalry', 194, 1432, 346, 103, 41),
createThirtyFirstEnemyUnit('northern-fifth-cavalry-f', '왕쌍 추격 기병', '북쪽 추격 기병', 'cavalry', 195, 1454, 350, 114, 27),
createThirtyFirstEnemyUnit('northern-fifth-wall-guard-a', '진창 성벽 수비대', '서쪽 성벽 수비', 'yellowTurban', 192, 1360, 330, 44, 53),
createThirtyFirstEnemyUnit('northern-fifth-wall-guard-b', '진창 성벽 수비대', '중앙 성벽 수비', 'yellowTurban', 192, 1360, 330, 58, 47),
createThirtyFirstEnemyUnit('northern-fifth-wall-guard-c', '진창 성벽 수비대', '동문 수비', 'yellowTurban', 193, 1380, 334, 74, 39),
createThirtyFirstEnemyUnit('northern-fifth-wall-guard-d', '진창 성벽 수비대', '내성 수비', 'yellowTurban', 193, 1380, 334, 90, 32),
createThirtyFirstEnemyUnit('northern-fifth-wall-guard-e', '진창 성벽 수비대', '학소 본영 수비', 'yellowTurban', 194, 1400, 338, 104, 24),
createThirtyFirstEnemyUnit('northern-fifth-wall-guard-f', '진창 성벽 수비대', '북쪽 절벽 수비', 'yellowTurban', 194, 1400, 338, 116, 13),
createThirtyFirstEnemyUnit('northern-fifth-strategist-a', '위군 공성 대응 군리', '성벽 수리 군리', 'strategist', 192, 1080, 296, 72, 54),
createThirtyFirstEnemyUnit('northern-fifth-strategist-b', '위군 공성 대응 군리', '봉화 연락 군리', 'strategist', 193, 1092, 298, 86, 45),
createThirtyFirstEnemyUnit('northern-fifth-strategist-c', '위군 공성 대응 군리', '학소 본영 군리', 'strategist', 193, 1092, 298, 100, 36),
createThirtyFirstEnemyUnit('northern-fifth-strategist-d', '위군 공성 대응 군리', '군량 차단 군리', 'strategist', 194, 1104, 300, 106, 63),
createThirtyFirstEnemyUnit('northern-fifth-officer-wang-shuang', '왕쌍', '위군 추격 장수', 'rebelLeader', 196, 1480, 356, 87, 72),
createThirtyFirstEnemyUnit('northern-fifth-officer-fei-yao', '비요', '진창 지원 장수', 'rebelLeader', 194, 1440, 348, 101, 58),
createThirtyFirstEnemyUnit('northern-fifth-officer-guo-huai', '곽회', '북방 지원 장수', 'rebelLeader', 194, 1440, 348, 110, 68),
createThirtyFirstEnemyUnit('northern-fifth-officer-supply', '위군 군량 차단장', '공성 진영 압박 장수', 'rebelLeader', 193, 1420, 344, 78, 76),
createThirtyFirstEnemyUnit('northern-fifth-officer-wall', '진창 성벽 장수', '성문 수비 장수', 'rebelLeader', 194, 1440, 348, 112, 27),
createThirtyFirstEnemyUnit('northern-fifth-leader-hao-zhao', '학소', '진창 수비장', 'rebelLeader', 197, 1540, 362, 109, 35)
];
export const firstBattleBonds: BattleBond[] = [
{
id: 'liu-bei__guan-yu',
@@ -18513,6 +18663,46 @@ export const fiftyEighthBattleBonds: BattleBond[] = [
...northernFourthBattleBonds
].map(cloneBattleBondForScenario);
export const northernFifthBattleBonds: BattleBond[] = [
{
id: 'jiang-wei__fa-zheng_northern-fifth',
unitIds: ['jiang-wei', 'fa-zheng'],
title: '새 길과 오래된 계책',
level: 46,
exp: 0,
description: '강유의 진창 길 판단과 법정의 공성 계책이 맞물리면 성벽을 무리하게 치기보다 수비의 빈틈을 재는 힘이 생깁니다.'
},
{
id: 'wei-yan__jiang-wei_northern-fifth',
unitIds: ['wei-yan', 'jiang-wei'],
title: '돌파와 절제',
level: 42,
exp: 0,
description: '위연의 돌파 욕심과 강유의 길 계산을 함께 묶으면 성채 앞에서 밀어붙일 곳과 멈출 곳을 구분할 수 있습니다.'
},
{
id: 'huang-quan__ma-liang_northern-fifth',
unitIds: ['huang-quan', 'ma-liang'],
title: '군량과 문서',
level: 52,
exp: 0,
description: '황권의 군량 장부와 마량의 명분 문서가 함께 움직이면 진창 공성전이 오래 끌릴 때도 후방의 약속이 흔들리지 않습니다.'
},
{
id: 'wang-ping__ma-dai_northern-fifth',
unitIds: ['wang-ping', 'ma-dai'],
title: '진영 표식과 우회 기병',
level: 44,
exp: 0,
description: '왕평의 진영 표식과 마대의 우회 기병이 어울리면 왕쌍의 추격을 받기 전에 공성 진영을 접을 시간을 벌 수 있습니다.'
}
];
export const fiftyNinthBattleBonds: BattleBond[] = [
...fiftyEighthBattleBonds,
...northernFifthBattleBonds
].map(cloneBattleBondForScenario);
function createEighthBattleTerrain(): TerrainType[][] {
return Array.from({ length: 22 }, (_, y) =>
Array.from({ length: 26 }, (_, x): TerrainType => {
@@ -21681,6 +21871,81 @@ function createFiftyEighthBattleTerrain(): TerrainType[][] {
);
}
function createFiftyNinthBattleTerrain(): TerrainType[][] {
return Array.from({ length: 100 }, (_, y) =>
Array.from({ length: 118 }, (_, x): TerrainType => {
if (
(x >= 4 && x <= 10 && y >= 0 && y <= 99) ||
(x >= 60 && x <= 67 && y >= 20 && y <= 99) ||
(x >= 0 && x <= 117 && y >= 92)
) {
return 'river';
}
if (
(x >= 10 && x <= 78 && y >= 84 && y <= 90) ||
(x >= 24 && x <= 94 && y >= 72 && y <= 80) ||
(x >= 48 && x <= 106 && y >= 60 && y <= 70) ||
(x >= 72 && x <= 114 && y >= 47 && y <= 58) ||
(x >= 92 && x <= 117 && y >= 33 && y <= 44) ||
(x >= 30 && x <= 38 && y >= 66 && y <= 94) ||
(x >= 54 && x <= 62 && y >= 54 && y <= 86) ||
(x >= 84 && x <= 92 && y >= 39 && y <= 76)
) {
return 'road';
}
if (
(x >= 0 && x <= 34 && y >= 56 && y <= 88) ||
(x >= 42 && x <= 76 && y >= 70 && y <= 91) ||
(x >= 88 && x <= 117 && y >= 63 && y <= 88) ||
(x >= 14 && x <= 36 && y >= 40 && y <= 58)
) {
return 'forest';
}
if (
(x >= 0 && x <= 48 && y <= 36) ||
(x >= 46 && x <= 88 && y <= 30) ||
(x >= 86 && x <= 117 && y <= 48) ||
(x >= 98 && x <= 117 && y >= 42 && y <= 68)
) {
return 'hill';
}
if (
(x <= 2 && y <= 90) ||
(x >= 115 && y <= 84) ||
(x >= 37 && x <= 43 && y >= 0 && y <= 60) ||
(x >= 74 && x <= 80 && y >= 0 && y <= 42) ||
(x >= 58 && x <= 65 && y >= 82 && y <= 99)
) {
return 'cliff';
}
if (
(x >= 12 && x <= 27 && y >= 80 && y <= 90) ||
(x >= 44 && x <= 61 && y >= 68 && y <= 79) ||
(x >= 77 && x <= 94 && y >= 54 && y <= 66) ||
(x >= 98 && x <= 114 && y >= 39 && y <= 52)
) {
return 'village';
}
if (
(x >= 20 && x <= 44 && y >= 75 && y <= 88) ||
(x >= 54 && x <= 78 && y >= 62 && y <= 74) ||
(x >= 86 && x <= 108 && y >= 48 && y <= 61)
) {
return 'camp';
}
if (
(x >= 48 && x <= 66 && y >= 43 && y <= 58) ||
(x >= 72 && x <= 94 && y >= 33 && y <= 48) ||
(x >= 92 && x <= 114 && y >= 42 && y <= 58) ||
(x >= 100 && x <= 117 && y >= 12 && y <= 31)
) {
return 'fort';
}
return 'plain';
})
);
}
function placeScenarioUnit(unit: UnitData, position: { x: number; y: number }): UnitData {
return {
...cloneUnitForScenario(unit),