Add Red Cliffs vanguard chapter

This commit is contained in:
2026-06-23 06:59:33 +09:00
parent 0af7c9cfe8
commit 7f80600d0c
11 changed files with 1058 additions and 24 deletions

View File

@@ -39,6 +39,10 @@ import {
thirteenthBattleMap,
thirteenthBattleUnits,
thirteenthBattleVictoryPages,
twentyFirstBattleBonds,
twentyFirstBattleMap,
twentyFirstBattleUnits,
twentyFirstBattleVictoryPages,
twentiethBattleBonds,
twentiethBattleMap,
twentiethBattleUnits,
@@ -105,7 +109,8 @@ export type BattleScenarioId =
| 'seventeenth-battle-wolong-visit-road'
| 'eighteenth-battle-bowang-ambush'
| 'nineteenth-battle-changban-refuge'
| 'twentieth-battle-jiangdong-envoy';
| 'twentieth-battle-jiangdong-envoy'
| 'twenty-first-battle-red-cliffs-vanguard';
export type BattleObjectiveKind = 'defeat-leader' | 'keep-unit-alive' | 'secure-terrain' | 'quick-victory';
@@ -1225,6 +1230,69 @@ export const twentiethBattleScenario: BattleScenarioDefinition = {
nextCampScene: 'CampScene'
};
export const twentyFirstBattleScenario: BattleScenarioDefinition = {
id: 'twenty-first-battle-red-cliffs-vanguard',
title: '적벽 전초전',
victoryConditionLabel: '채모 퇴각',
defeatConditionLabel: '유비 또는 제갈량 퇴각',
openingObjectiveLines: [
'강동 회담이 결전으로 기울자 조조군 수군 선봉이 적벽 포구를 시험합니다. 첫 전선을 빼앗기면 손유 동맹의 사기가 크게 흔들립니다.',
'강 위의 전장은 강줄기와 배다리가 길을 나눕니다. 기동 장수로 강안 기병을 끊고, 전열 장수로 포구 수비대를 밀어내야 합니다.',
'채모를 퇴각시키고 제갈량을 지키십시오. 강동 포구를 확보하면 화공을 논할 발판이 마련됩니다.'
],
map: twentyFirstBattleMap,
units: twentyFirstBattleUnits,
bonds: twentyFirstBattleBonds,
mapTextureKey: 'battle-map-twenty-first',
leaderUnitId: 'redcliff-vanguard-leader-cai-mao',
quickVictoryTurnLimit: 30,
baseVictoryGold: 2540,
objectives: [
{
id: 'leader',
kind: 'defeat-leader',
label: '채모 퇴각',
rewardGold: 1660,
unitId: 'redcliff-vanguard-leader-cai-mao'
},
{
id: 'liu-bei',
kind: 'keep-unit-alive',
label: '유비 생존',
rewardGold: 520,
unitId: 'liu-bei'
},
{
id: 'zhuge-liang',
kind: 'keep-unit-alive',
label: '제갈량 생존',
rewardGold: 800,
unitId: 'zhuge-liang'
},
{
id: 'red-cliffs-port',
kind: 'secure-terrain',
label: '강동 포구 확보',
rewardGold: 900,
terrain: 'fort'
},
{
id: 'quick',
kind: 'quick-victory',
label: '30턴 이내 승리',
rewardGold: 680,
maxTurn: 30
}
],
defeatConditions: [
{ kind: 'unit-defeated', unitId: 'liu-bei' },
{ kind: 'unit-defeated', unitId: 'zhuge-liang' }
],
itemRewards: ['콩 8', '상처약 6', '탁주 3', '화공 논의 +1', '동맹 군의 기록 +1'],
victoryPages: twentyFirstBattleVictoryPages,
nextCampScene: 'CampScene'
};
export const defaultBattleScenarioId: BattleScenarioId = firstBattleScenario.id;
export const battleScenarios: Record<BattleScenarioId, BattleScenarioDefinition> = {
@@ -1247,7 +1315,8 @@ export const battleScenarios: Record<BattleScenarioId, BattleScenarioDefinition>
'seventeenth-battle-wolong-visit-road': seventeenthBattleScenario,
'eighteenth-battle-bowang-ambush': eighteenthBattleScenario,
'nineteenth-battle-changban-refuge': nineteenthBattleScenario,
'twentieth-battle-jiangdong-envoy': twentiethBattleScenario
'twentieth-battle-jiangdong-envoy': twentiethBattleScenario,
'twenty-first-battle-red-cliffs-vanguard': twentyFirstBattleScenario
};
export const defaultBattleScenario = battleScenarios[defaultBattleScenarioId];

View File

@@ -17,6 +17,7 @@ import {
seventeenthBattleScenario,
tenthBattleScenario,
thirteenthBattleScenario,
twentyFirstBattleScenario,
twentiethBattleScenario,
twelfthBattleScenario,
thirdBattleScenario,
@@ -56,6 +57,8 @@ import {
tenthBattleVictoryPages,
thirteenthBattleIntroPages,
thirteenthBattleVictoryPages,
twentyFirstBattleIntroPages,
twentyFirstBattleVictoryPages,
twentiethBattleIntroPages,
twentiethBattleVictoryPages,
twelfthBattleIntroPages,
@@ -277,13 +280,24 @@ const sortieFlows: Record<string, SortieFlow> = {
},
[twentiethBattleScenario.id]: {
afterBattleId: twentiethBattleScenario.id,
eyebrow: '다음 장 준비',
title: '적벽 첫 전투 준비',
eyebrow: '다음 장',
title: twentyFirstBattleScenario.title,
description:
'강동으로 향하는 길이 열렸습니다. 이제 제갈량과 손건 손권과 주유를 설득해야 하고, 유비군은 장강에서 조조의 대군을 맞을 준비를 시작합니다.',
rewardHint: '다음 장: 강동 회담과 적벽대전 첫 전투 준비 중',
pages: twentiethBattleVictoryPages,
unavailableNotice: '강동 회담과 적벽대전 첫 전투는 다음 작업에서 이어집니다. 군영에서 사절 문서, 화공 준비, 출전 후보를 정비하십시오.'
'강동으로 향하는 길이 열렸습니다. 제갈량과 손건 손권과 주유를 설득한 뒤, 조조군 수군 선봉을 상대로 손유 동맹의 첫 전선을 세워야 합니다.',
rewardHint: `예상 보상: ${twentyFirstBattleScenario.title} 개방 / 화공 논의 진전`,
nextBattleId: twentyFirstBattleScenario.id,
campaignStep: 'twenty-first-battle',
pages: [...twentiethBattleVictoryPages, ...twentyFirstBattleIntroPages]
},
[twentyFirstBattleScenario.id]: {
afterBattleId: twentyFirstBattleScenario.id,
eyebrow: '다음 장 준비',
title: '적벽 화공 준비',
description:
'조조군 수군 선봉을 밀어내며 손유 동맹의 첫 전선이 세워졌습니다. 이제 주유와 황개, 제갈량의 계책이 맞물려 본격적인 화공을 준비해야 합니다.',
rewardHint: '다음 장: 황개 고육계와 적벽 화공 준비 중',
pages: twentyFirstBattleVictoryPages,
unavailableNotice: '황개 고육계와 적벽 화공 장은 다음 작업에서 이어집니다. 군영에서 화공 논의, 공명, 보급을 정비하십시오.'
}
};

View File

@@ -1323,6 +1323,68 @@ export const twentiethBattleVictoryPages: StoryPage[] = [
}
];
export const twentyFirstBattleIntroPages: StoryPage[] = [
{
id: 'twenty-first-sun-quan-council',
bgm: 'story-dark',
chapter: '강동 회담',
background: 'story-liu-bei',
speaker: '제갈량',
text: '손권의 장막 안에서는 항복과 결전의 말이 맞섰습니다. 제갈량은 조조의 대군이 강을 건너면 강동도, 유비군도 설 곳을 잃는다는 사실을 차분히 짚었습니다.'
},
{
id: 'twenty-first-zhou-yu-decision',
bgm: 'battle-prep',
chapter: '주유의 결단',
background: 'story-three-heroes',
speaker: '주유',
text: '조조가 강 위에서 싸우는 법을 모른다면, 장강은 우리 편이 될 것입니다. 손권께서 결심하셨으니, 이제 말이 아니라 배와 불길로 답해야 합니다.'
},
{
id: 'twenty-first-liu-bei-alliance',
bgm: 'militia-theme',
chapter: '손유 동맹',
background: 'story-militia',
speaker: '유비',
portrait: 'liuBei',
text: '강동이 함께 선다면 조조의 군세도 처음으로 멈출 수 있소. 우리는 작은 군이지만, 장강의 바람과 백성을 지키는 뜻을 함께 세웁시다.'
},
{
id: 'twenty-first-red-cliffs-sortie',
bgm: 'battle-prep',
chapter: '적벽 전초전',
background: 'story-sortie',
speaker: '제갈량',
text: '조조군 수군 선봉이 강가 포구를 시험하고 있습니다. 채모의 선봉을 물리쳐야 강동 수군과 합류할 첫 자리를 지킬 수 있습니다.'
}
];
export const twentyFirstBattleVictoryPages: StoryPage[] = [
{
id: 'twenty-first-victory-river-line',
bgm: 'militia-theme',
chapter: '강 위의 첫 승리',
background: 'story-sortie',
text: '채모의 선봉이 물러서자 장강의 물결 위에 손유 동맹의 첫 전선이 세워졌습니다. 작은 승리였지만 조조군이 강 위에서 무적이 아님을 모두가 보았습니다.'
},
{
id: 'twenty-first-zhou-yu-fire-plan',
bgm: 'battle-prep',
chapter: '화공의 실마리',
background: 'story-militia',
speaker: '주유',
text: '조조군의 배는 많지만 서로를 믿지 못하고, 사슬로 묶으면 바람 앞에서 약점이 됩니다. 아직 때가 무르익지는 않았지만 불길의 길은 보이기 시작했습니다.'
},
{
id: 'twenty-first-zhuge-wind',
bgm: 'story-dark',
chapter: '바람을 기다리다',
background: 'story-three-heroes',
speaker: '제갈량',
text: '다음 싸움은 힘으로만 밀어붙일 수 없습니다. 황개의 결단, 주유의 수군, 그리고 바람의 때가 맞아야 조조의 대군을 무너뜨릴 수 있습니다.'
}
];
export const firstBattleMap: BattleMap = {
width: 20,
height: 18,
@@ -1588,6 +1650,12 @@ export const twentiethBattleMap: BattleMap = {
terrain: createTwentiethBattleTerrain()
};
export const twentyFirstBattleMap: BattleMap = {
width: 42,
height: 30,
terrain: createTwentyFirstBattleTerrain()
};
export const firstBattleUnits: UnitData[] = [
{
id: 'liu-bei',
@@ -7686,6 +7754,384 @@ export const twentiethBattleUnits: UnitData[] = [
}
];
const twentyFirstBattleAllyPositions: Record<string, { x: number; y: number }> = {
'liu-bei': { x: 4, y: 24 },
'guan-yu': { x: 6, y: 22 },
'zhang-fei': { x: 6, y: 25 },
'jian-yong': { x: 3, y: 26 },
'mi-zhu': { x: 5, y: 27 },
'sun-qian': { x: 8, y: 24 },
'zhao-yun': { x: 8, y: 21 },
'zhuge-liang': { x: 6, y: 23 }
};
export const twentyFirstBattleUnits: UnitData[] = [
...[
...firstBattleUnits.filter((unit) => unit.faction === 'ally'),
...xuzhouRecruitUnits,
...caoBreakRecruitUnits,
...liuBiaoRecruitUnits,
...zhugeRecruitUnits
].map((unit) => placeScenarioUnit(unit, twentyFirstBattleAllyPositions[unit.id] ?? { x: unit.x, y: unit.y })),
{
id: 'redcliff-vanguard-scout-a',
name: '조조 수군 척후',
faction: 'enemy',
className: '수군 척후',
classKey: 'bandit',
level: 26,
exp: 38,
hp: 74,
maxHp: 74,
attack: 29,
move: 4,
stats: { might: 106, intelligence: 78, leadership: 84, agility: 104, luck: 72 },
equipment: {
weapon: { itemId: 'yellow-turban-saber', level: 3, exp: 52 },
armor: { itemId: 'rebel-vest', level: 3, exp: 28 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 14,
y: 22
},
{
id: 'redcliff-vanguard-scout-b',
name: '조조 수군 척후',
faction: 'enemy',
className: '강변 척후',
classKey: 'bandit',
level: 26,
exp: 38,
hp: 74,
maxHp: 74,
attack: 29,
move: 4,
stats: { might: 106, intelligence: 78, leadership: 84, agility: 104, luck: 72 },
equipment: {
weapon: { itemId: 'yellow-turban-saber', level: 3, exp: 52 },
armor: { itemId: 'rebel-vest', level: 3, exp: 28 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 15,
y: 26
},
{
id: 'redcliff-vanguard-marine-a',
name: '조조 수군 보병',
faction: 'enemy',
className: '갑판 보병',
classKey: 'yellowTurban',
level: 26,
exp: 38,
hp: 96,
maxHp: 96,
attack: 31,
move: 3,
stats: { might: 116, intelligence: 80, leadership: 98, agility: 86, luck: 72 },
equipment: {
weapon: { itemId: 'iron-spear', level: 3, exp: 58 },
armor: { itemId: 'lamellar-armor', level: 3, exp: 34 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 19,
y: 20
},
{
id: 'redcliff-vanguard-marine-b',
name: '조조 수군 보병',
faction: 'enemy',
className: '갑판 보병',
classKey: 'yellowTurban',
level: 26,
exp: 38,
hp: 96,
maxHp: 96,
attack: 31,
move: 3,
stats: { might: 116, intelligence: 80, leadership: 98, agility: 86, luck: 72 },
equipment: {
weapon: { itemId: 'iron-spear', level: 3, exp: 58 },
armor: { itemId: 'lamellar-armor', level: 3, exp: 34 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 21,
y: 23
},
{
id: 'redcliff-vanguard-marine-c',
name: '조조 수군 보병',
faction: 'enemy',
className: '포구 보병',
classKey: 'yellowTurban',
level: 27,
exp: 40,
hp: 100,
maxHp: 100,
attack: 32,
move: 3,
stats: { might: 118, intelligence: 82, leadership: 100, agility: 88, luck: 73 },
equipment: {
weapon: { itemId: 'iron-spear', level: 3, exp: 64 },
armor: { itemId: 'reinforced-lamellar', level: 3, exp: 38 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 27,
y: 18
},
{
id: 'redcliff-vanguard-marine-d',
name: '조조 수군 보병',
faction: 'enemy',
className: '포구 보병',
classKey: 'yellowTurban',
level: 27,
exp: 40,
hp: 100,
maxHp: 100,
attack: 32,
move: 3,
stats: { might: 118, intelligence: 82, leadership: 100, agility: 88, luck: 73 },
equipment: {
weapon: { itemId: 'iron-spear', level: 3, exp: 64 },
armor: { itemId: 'reinforced-lamellar', level: 3, exp: 38 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 29,
y: 22
},
{
id: 'redcliff-vanguard-archer-a',
name: '조조 선상 궁병',
faction: 'enemy',
className: '선상 궁병',
classKey: 'archer',
level: 26,
exp: 38,
hp: 72,
maxHp: 72,
attack: 31,
move: 3,
stats: { might: 102, intelligence: 92, leadership: 90, agility: 100, luck: 74 },
equipment: {
weapon: { itemId: 'short-bow', level: 3, exp: 58 },
armor: { itemId: 'cloth-armor', level: 3, exp: 32 },
accessory: { itemId: 'wind-quiver', level: 1, exp: 0 }
},
x: 20,
y: 16
},
{
id: 'redcliff-vanguard-archer-b',
name: '조조 선상 궁병',
faction: 'enemy',
className: '선상 궁병',
classKey: 'archer',
level: 26,
exp: 38,
hp: 72,
maxHp: 72,
attack: 31,
move: 3,
stats: { might: 102, intelligence: 92, leadership: 90, agility: 100, luck: 74 },
equipment: {
weapon: { itemId: 'short-bow', level: 3, exp: 58 },
armor: { itemId: 'cloth-armor', level: 3, exp: 32 },
accessory: { itemId: 'wind-quiver', level: 1, exp: 0 }
},
x: 25,
y: 15
},
{
id: 'redcliff-vanguard-archer-c',
name: '조조 선상 궁병',
faction: 'enemy',
className: '강북 궁병',
classKey: 'archer',
level: 27,
exp: 40,
hp: 74,
maxHp: 74,
attack: 32,
move: 3,
stats: { might: 104, intelligence: 94, leadership: 92, agility: 102, luck: 74 },
equipment: {
weapon: { itemId: 'short-bow', level: 4, exp: 2 },
armor: { itemId: 'cloth-armor', level: 3, exp: 36 },
accessory: { itemId: 'wind-quiver', level: 1, exp: 0 }
},
x: 33,
y: 17
},
{
id: 'redcliff-vanguard-cavalry-a',
name: '조조 강안 기병',
faction: 'enemy',
className: '강안 기병',
classKey: 'cavalry',
level: 27,
exp: 40,
hp: 102,
maxHp: 102,
attack: 34,
move: 5,
stats: { might: 120, intelligence: 78, leadership: 96, agility: 114, luck: 74 },
equipment: {
weapon: { itemId: 'iron-spear', level: 4, exp: 2 },
armor: { itemId: 'lamellar-armor', level: 3, exp: 42 },
accessory: { itemId: 'bravery-token', level: 1, exp: 0 }
},
x: 17,
y: 25
},
{
id: 'redcliff-vanguard-cavalry-b',
name: '조조 강안 기병',
faction: 'enemy',
className: '강안 기병',
classKey: 'cavalry',
level: 27,
exp: 40,
hp: 102,
maxHp: 102,
attack: 34,
move: 5,
stats: { might: 120, intelligence: 78, leadership: 96, agility: 114, luck: 74 },
equipment: {
weapon: { itemId: 'iron-spear', level: 4, exp: 2 },
armor: { itemId: 'lamellar-armor', level: 3, exp: 42 },
accessory: { itemId: 'bravery-token', level: 1, exp: 0 }
},
x: 23,
y: 26
},
{
id: 'redcliff-vanguard-cavalry-c',
name: '조조 강안 기병',
faction: 'enemy',
className: '강안 기병',
classKey: 'cavalry',
level: 28,
exp: 42,
hp: 106,
maxHp: 106,
attack: 35,
move: 5,
stats: { might: 122, intelligence: 80, leadership: 98, agility: 116, luck: 75 },
equipment: {
weapon: { itemId: 'iron-spear', level: 4, exp: 8 },
armor: { itemId: 'reinforced-lamellar', level: 3, exp: 46 },
accessory: { itemId: 'bravery-token', level: 1, exp: 0 }
},
x: 31,
y: 24
},
{
id: 'redcliff-vanguard-guard-a',
name: '채모 친위',
faction: 'enemy',
className: '수군 친위',
classKey: 'yellowTurban',
level: 28,
exp: 42,
hp: 108,
maxHp: 108,
attack: 34,
move: 3,
stats: { might: 122, intelligence: 84, leadership: 106, agility: 90, luck: 75 },
equipment: {
weapon: { itemId: 'iron-spear', level: 4, exp: 10 },
armor: { itemId: 'reinforced-lamellar', level: 3, exp: 50 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 35,
y: 18
},
{
id: 'redcliff-vanguard-guard-b',
name: '채모 친위',
faction: 'enemy',
className: '수군 친위',
classKey: 'yellowTurban',
level: 28,
exp: 42,
hp: 108,
maxHp: 108,
attack: 34,
move: 3,
stats: { might: 122, intelligence: 84, leadership: 106, agility: 90, luck: 75 },
equipment: {
weapon: { itemId: 'iron-spear', level: 4, exp: 10 },
armor: { itemId: 'reinforced-lamellar', level: 3, exp: 50 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 36,
y: 21
},
{
id: 'redcliff-vanguard-strategist-a',
name: '수군 군리',
faction: 'enemy',
className: '수군 군리',
classKey: 'archer',
level: 27,
exp: 40,
hp: 76,
maxHp: 76,
attack: 31,
move: 3,
stats: { might: 80, intelligence: 100, leadership: 94, agility: 88, luck: 76 },
equipment: {
weapon: { itemId: 'short-bow', level: 4, exp: 6 },
armor: { itemId: 'cloth-armor', level: 3, exp: 42 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 34,
y: 15
},
{
id: 'redcliff-vanguard-strategist-b',
name: '수군 군리',
faction: 'enemy',
className: '수군 군리',
classKey: 'archer',
level: 27,
exp: 40,
hp: 76,
maxHp: 76,
attack: 31,
move: 3,
stats: { might: 80, intelligence: 100, leadership: 94, agility: 88, luck: 76 },
equipment: {
weapon: { itemId: 'short-bow', level: 4, exp: 6 },
armor: { itemId: 'cloth-armor', level: 3, exp: 42 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 37,
y: 16
},
{
id: 'redcliff-vanguard-leader-cai-mao',
name: '채모',
faction: 'enemy',
className: '조조 수군 선봉장',
classKey: 'rebelLeader',
level: 29,
exp: 46,
hp: 140,
maxHp: 140,
attack: 36,
move: 4,
stats: { might: 124, intelligence: 88, leadership: 116, agility: 92, luck: 78 },
equipment: {
weapon: { itemId: 'leader-axe', level: 4, exp: 14 },
armor: { itemId: 'reinforced-lamellar', level: 4, exp: 4 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 39,
y: 19
}
];
export const firstBattleBonds: BattleBond[] = [
{
id: 'liu-bei__guan-yu',
@@ -7838,6 +8284,7 @@ export const eighteenthBattleBonds: BattleBond[] = [...sixteenthBattleBonds, ...
);
export const nineteenthBattleBonds: BattleBond[] = [...eighteenthBattleBonds].map(cloneBattleBondForScenario);
export const twentiethBattleBonds: BattleBond[] = [...nineteenthBattleBonds].map(cloneBattleBondForScenario);
export const twentyFirstBattleBonds: BattleBond[] = [...twentiethBattleBonds].map(cloneBattleBondForScenario);
function createEighthBattleTerrain(): TerrainType[][] {
return Array.from({ length: 22 }, (_, y) =>
@@ -8458,6 +8905,65 @@ function createTwentiethBattleTerrain(): TerrainType[][] {
);
}
function createTwentyFirstBattleTerrain(): TerrainType[][] {
return Array.from({ length: 30 }, (_, y) =>
Array.from({ length: 42 }, (_, x): TerrainType => {
if ((x <= 4 && y >= 23 && y <= 28) || (x >= 5 && x <= 8 && y >= 25 && y <= 29)) {
return 'camp';
}
if ((x >= 35 && x <= 41 && y >= 16 && y <= 23) || (x >= 32 && x <= 35 && y >= 17 && y <= 20)) {
return 'fort';
}
if ((x >= 13 && x <= 16 && y >= 21 && y <= 23) || (x >= 29 && x <= 31 && y >= 17 && y <= 19)) {
return 'village';
}
if (
(y === 24 && x >= 3 && x <= 16) ||
(y === 21 && x >= 15 && x <= 27) ||
(y === 18 && x >= 27 && x <= 38) ||
(x === 35 && y >= 16 && y <= 24)
) {
return 'road';
}
if (
(x >= 6 && x <= 17 && y === 27 - Math.floor(x / 2)) ||
(x >= 18 && x <= 33 && y === Math.floor(x / 2) + 8) ||
(x >= 8 && x <= 14 && y === 25)
) {
return 'road';
}
if ((x === 20 || x === 21) && y >= 0 && y <= 29) {
return 'river';
}
if ((x === 28 || x === 29) && y >= 0 && y <= 16) {
return 'river';
}
if ((x === 24 || x === 25) && y >= 22 && y <= 29) {
return 'river';
}
if (
(x >= 5 && x <= 15 && y >= 9 && y <= 18) ||
(x >= 16 && x <= 20 && y >= 23 && y <= 29) ||
(x <= 9 && y <= 8) ||
(x >= 31 && x <= 40 && y <= 9)
) {
return 'forest';
}
if (
(x >= 10 && x <= 18 && y >= 2 && y <= 6) ||
(x >= 27 && x <= 35 && y >= 24 && y <= 29) ||
(x >= 33 && x <= 41 && y >= 3 && y <= 7)
) {
return 'hill';
}
if ((x <= 1 && y <= 14) || (x >= 40 && y <= 12) || (x >= 40 && y >= 24)) {
return 'cliff';
}
return 'plain';
})
);
}
function placeScenarioUnit(unit: UnitData, position: { x: number; y: number }): UnitData {
return {
...cloneUnitForScenario(unit),