- { #if region.type === 'oasis' }
-
+
+ { #if region.type === WORLDMAP_TYPES.BOURGADE }
+
+ { :else if region.type === WORLDMAP_TYPES.OASIS }
+
+ { :else }
+ { region.id }
{ /if }
{ /each }
@@ -16,15 +34,35 @@
diff --git a/src/constants.ts b/src/constants.ts
index 782c886..fc87389 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -1 +1,3 @@
export const CULTURE_TO_WIN = 20000;
+export const WORLD_MAP_HEIGHT = 9;
+export const WORLD_MAP_WIDTH = 9;
diff --git a/src/hud/BuildingPanel.svelte b/src/hud/BuildingPanel.svelte
index e7db7b1..c59a496 100644
--- a/src/hud/BuildingPanel.svelte
+++ b/src/hud/BuildingPanel.svelte
@@ -6,11 +6,11 @@
import BuildingRecruitment from "./BuildingRecruitment.svelte";
import Cost from "./Cost.svelte";
+
function close() {
showBuildingPanel.set(null);
}
-
function upgrade() {
if ($showBuildingPanel === null) {
return;
diff --git a/src/hud/Game.svelte b/src/hud/Game.svelte
index 1e84f35..49c2687 100644
--- a/src/hud/Game.svelte
+++ b/src/hud/Game.svelte
@@ -14,6 +14,7 @@
import Units from "./Units.svelte";
import Victory from "./Victory.svelte";
import Quests from "./Quests.svelte";
+ import OasisRegionPanel from "../board/OasisRegionPanel.svelte";
onMount(() => {
@@ -57,6 +58,7 @@
diff --git a/src/missions.ts b/src/missions.ts
index e688355..090a2d2 100644
--- a/src/missions.ts
+++ b/src/missions.ts
@@ -1,9 +1,11 @@
-import type { OasisType, RegionType } from "./types";
-import { getUnitSource } from "./utils";
+import { WORLDMAP_TYPES, type OasisType, type RegionType } from "./types";
+import { assert, getUnitSource } from "./utils";
import type { VillageState } from "./village";
export function resolveMission(V: VillageState, region: RegionType) {
+ assert(region.type === WORLDMAP_TYPES.OASIS);
+
const mission = region.state.mission;
if (!mission) {
return;
@@ -11,7 +13,7 @@ export function resolveMission(V: VillageState, region: RegionType) {
switch (mission.type) {
case 'pillage':
- if (region.type === 'oasis') {
+ if (region.type === WORLDMAP_TYPES.OASIS) {
resolvePillageOasis(V, region);
}
break;
@@ -20,7 +22,7 @@ export function resolveMission(V: VillageState, region: RegionType) {
}
if (mission.repeat) {
- mission.remainingTime = region.distance * 10 * 1000;
+ mission.remainingTime = 1 * 10 * 1000;
}
else {
delete region.state.mission;
diff --git a/src/moves/pillage.ts b/src/moves/pillage.ts
index a649f0f..47731b1 100644
--- a/src/moves/pillage.ts
+++ b/src/moves/pillage.ts
@@ -1,4 +1,5 @@
-import { getRemainingUnitCount } from "../utils";
+import { WORLDMAP_TYPES } from "../types";
+import { assert, getRemainingUnitCount } from "../utils";
import type { VillageState } from "../village";
@@ -9,6 +10,8 @@ export default function pillage(V: VillageState, regionIndex: number, soldiersCo
const region = V.worldmap[regionIndex];
+ assert(region.type === WORLDMAP_TYPES.OASIS);
+
if (region.state.mission) {
return false;
}
@@ -17,7 +20,7 @@ export default function pillage(V: VillageState, regionIndex: number, soldiersCo
type: 'pillage',
unitType: 'soldier',
unitCount: soldiersCount,
- remainingTime: region.distance * 10 * 1000,
+ remainingTime: 1 * 10 * 1000,
repeat,
};
diff --git a/src/moves/toggleMissionRepeat.ts b/src/moves/toggleMissionRepeat.ts
index 2f763ca..a55403f 100644
--- a/src/moves/toggleMissionRepeat.ts
+++ b/src/moves/toggleMissionRepeat.ts
@@ -1,9 +1,13 @@
+import { WORLDMAP_TYPES } from "../types";
+import { assert } from "../utils";
import type { VillageState } from "../village";
export default function toggleMissionRepeat(V: VillageState, regionIndex: number) {
const region = V.worldmap[regionIndex];
+ assert(region.type === WORLDMAP_TYPES.OASIS);
+
if (!region.state.mission) {
return false;
}
diff --git a/src/stores/showOasisPanel.ts b/src/stores/showOasisPanel.ts
new file mode 100644
index 0000000..b4e581f
--- /dev/null
+++ b/src/stores/showOasisPanel.ts
@@ -0,0 +1,4 @@
+import { writable } from "svelte/store";
+
+
+export default writable
(null);
diff --git a/src/types.ts b/src/types.ts
index a904e0c..a82ceba 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -81,28 +81,40 @@ export interface MissionType {
repeat: boolean;
}
+
+export enum WORLDMAP_TYPES {
+ EMPTY,
+ OASIS,
+ BOURGADE,
+}
+
+
interface BaseRegionType {
- distance: number;
+ id: number;
+ type: WORLDMAP_TYPES;
+}
+
+
+export interface EmptyRegionType extends BaseRegionType {
+ type: WORLDMAP_TYPES.EMPTY;
+}
+
+
+export interface OasisType extends BaseRegionType {
+ type: WORLDMAP_TYPES.OASIS;
+ resource: keyof CostType;
state: {
- index: number;
mission?: MissionType;
};
}
-export interface OasisType extends BaseRegionType {
- type: 'oasis';
- resource: keyof CostType;
-}
-
-
export interface BourgadeType extends BaseRegionType {
- type: 'bourgade';
- distance: number;
+ type: WORLDMAP_TYPES.BOURGADE;
}
-export type RegionType = OasisType | BourgadeType;
+export type RegionType = EmptyRegionType | OasisType | BourgadeType;
export interface HeroType {
diff --git a/src/update.ts b/src/update.ts
index f56ec3e..5f9eb4c 100644
--- a/src/update.ts
+++ b/src/update.ts
@@ -4,7 +4,7 @@ import { CULTURE_TO_WIN } from './constants';
import { createQuest } from './create';
import { resolveMission } from './missions';
import type { ProductionType } from './types';
-import { getProduction, getStorage, shuffle } from './utils';
+import { getProduction, getRegionsWithMissions, getStorage, shuffle } from './utils';
import village, { type VillageState } from "./village";
@@ -36,7 +36,7 @@ export default function update(timestamp: number) {
});
// Advance missions.
- V.worldmap.forEach(region => {
+ getRegionsWithMissions(V).forEach(region => {
if (!region.state.mission) {
return;
}
diff --git a/src/utils.ts b/src/utils.ts
index d2f20f2..a3f7b32 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -1,5 +1,6 @@
+import { WORLD_MAP_HEIGHT, WORLD_MAP_WIDTH } from "./constants";
import units from "./data/units";
-import type { BuildingType, CostType, MissionType, ProductionType, ResourcesType } from "./types";
+import { WORLDMAP_TYPES, type BuildingType, type CostType, type OasisType, type ProductionType, type ResourcesType } from "./types";
import type { VillageState } from "./village";
@@ -88,9 +89,16 @@ export function getUnitSource(unitType: string) {
}
+export function getRegionsWithMissions(V: VillageState): OasisType[] {
+ return V.worldmap.filter(r => r.type === WORLDMAP_TYPES.OASIS);
+}
+
+
export function getRemainingUnitCount(V: VillageState, unitType: string) {
let total = V.units[unitType] || 0;
- const missions = V.worldmap.filter(r => r.state.mission?.unitType === unitType).map(r => r.state.mission);
+ const missions = getRegionsWithMissions(V)
+ .filter(r => r.state.mission?.unitType === unitType)
+ .map(r => r.state.mission);
missions.forEach(m => total -= m?.unitCount || 0);
return total;
}
@@ -170,3 +178,25 @@ export function getTownhall(V: VillageState): BuildingType {
}
return townhall;
}
+
+export function assert(condition: any, msg?: string): asserts condition {
+ if (!condition) {
+ throw new Error(msg);
+ }
+}
+
+
+export function getAdjacentWorldmapCells(cellIndex: number) {
+ const cells = [
+ cellIndex - WORLD_MAP_WIDTH - 1,
+ cellIndex - WORLD_MAP_WIDTH,
+ cellIndex - WORLD_MAP_WIDTH + 1,
+ cellIndex - 1,
+ cellIndex + 1,
+ cellIndex + WORLD_MAP_WIDTH - 1,
+ cellIndex + WORLD_MAP_WIDTH,
+ cellIndex + WORLD_MAP_WIDTH + 1,
+ ];
+
+ return cells.filter(c => c >= 0 && c < WORLD_MAP_WIDTH * WORLD_MAP_HEIGHT);
+}
diff --git a/src/village.ts b/src/village.ts
index 1278435..c54d642 100644
--- a/src/village.ts
+++ b/src/village.ts
@@ -3,8 +3,9 @@ import { writable } from "svelte/store";
import { createBuilding, createHero, createQuest } from "./create";
import worldmap from "./data/worldmap";
import { getTilesAtDistance, Hex } from "./hexgrid";
-import type { BuildingType, HeroType, QuestType, RegionType, ResourcesType } from "./types";
-import { getKeysAsNumbers, shuffle } from "./utils";
+import { WORLDMAP_TYPES, type BuildingType, type CostType, type HeroType, type QuestType, type RegionType, type ResourcesType } from "./types";
+import { getAdjacentWorldmapCells, getKeysAsNumbers, shuffle } from "./utils";
+import { WORLD_MAP_HEIGHT, WORLD_MAP_WIDTH } from "./constants";
type Board = {
@@ -68,15 +69,28 @@ function getInitialOutsideBoard() {
function getInitialWorldmap(): RegionType[] {
- return worldmap.map((r, index) => {
- const region = r as RegionType;
- return {
- ...region,
- state: {
- index,
- },
+ const board: RegionType[] = []
+ for (let i = 0; i < WORLD_MAP_WIDTH * WORLD_MAP_HEIGHT; i++) {
+ board[i] = {
+ id: i,
+ type: WORLDMAP_TYPES.EMPTY,
+ };
+ }
+ const centerIndex = Math.floor((WORLD_MAP_WIDTH * WORLD_MAP_HEIGHT) / 2);
+ board[centerIndex].type = WORLDMAP_TYPES.BOURGADE;
+
+ const adj = shuffle(getAdjacentWorldmapCells(centerIndex));
+ worldmap.forEach(c => {
+ const cellIndex = adj.pop() || 0;
+ board[cellIndex] = {
+ type: WORLDMAP_TYPES.OASIS,
+ id: cellIndex,
+ resource: c.resource as keyof CostType,
+ state: {},
};
});
+
+ return board;
}