Add an oasis pillaging move.
This commit is contained in:
parent
149a6b47f9
commit
2dffb2dcac
@ -1,7 +1,27 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import moves from "../moves";
|
||||||
import type { OasisType } from "../types";
|
import type { OasisType } from "../types";
|
||||||
|
import { getRemainingUnitCount } from "../utils";
|
||||||
|
import village from "../village";
|
||||||
|
|
||||||
export let region: OasisType;
|
export let region: OasisType;
|
||||||
|
|
||||||
|
|
||||||
|
let numberOfUnits = 0;
|
||||||
|
$: maximumUnits = getRemainingUnitCount($village, 'soldier');
|
||||||
|
$: if (numberOfUnits > maximumUnits) {
|
||||||
|
numberOfUnits = maximumUnits || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function setMaxUnits() {
|
||||||
|
numberOfUnits = maximumUnits;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function pillage() {
|
||||||
|
moves.pillage(region.state.index, numberOfUnits);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@ -10,10 +30,31 @@
|
|||||||
Oasis
|
Oasis
|
||||||
(→ { region.distance })
|
(→ { region.distance })
|
||||||
</h2>
|
</h2>
|
||||||
|
{ #if region.state.mission }
|
||||||
<div>
|
<div>
|
||||||
<button>Pillage</button>
|
<p>{ region.state.mission.unitCount } soldiers are on a mission here.</p>
|
||||||
<button>Conquer</button>
|
<p>Remaining: { Math.ceil(region.state.mission.remainingTime / 1000) }</p>
|
||||||
</div>
|
</div>
|
||||||
|
{ :else }
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
name="units"
|
||||||
|
min="0"
|
||||||
|
max={ maximumUnits }
|
||||||
|
bind:value={ numberOfUnits }
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="units"
|
||||||
|
min="0"
|
||||||
|
max={ maximumUnits }
|
||||||
|
bind:value={ numberOfUnits }
|
||||||
|
/>
|
||||||
|
<button on:click={ setMaxUnits }>↑</button>
|
||||||
|
<button on:click={ pillage } disabled={ numberOfUnits === 0 }>Pillage</button>
|
||||||
|
</div>
|
||||||
|
{ /if }
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import units from "../data/units";
|
import units from "../data/units";
|
||||||
|
import { getRemainingUnitCount } from "../utils";
|
||||||
import village from "../village";
|
import village from "../village";
|
||||||
|
|
||||||
$: currentUnits = Object.entries($village.units).map(([type, count]) => {
|
$: currentUnits = Object.entries($village.units).map(([type, count]) => {
|
||||||
@ -17,6 +18,6 @@
|
|||||||
|
|
||||||
<section>
|
<section>
|
||||||
{ #each currentUnits as unit }
|
{ #each currentUnits as unit }
|
||||||
<p>{ unit.name }: { unit.count }</p>
|
<p>{ unit.name }: { getRemainingUnitCount($village, unit.type) } / { unit.count }</p>
|
||||||
{ /each }
|
{ /each }
|
||||||
</section>
|
</section>
|
||||||
|
31
src/missions.ts
Normal file
31
src/missions.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import type { OasisType, RegionType } from "./types";
|
||||||
|
import type { VillageState } from "./village";
|
||||||
|
|
||||||
|
|
||||||
|
export function resolveMission(V: VillageState, region: RegionType) {
|
||||||
|
const mission = region.state.mission;
|
||||||
|
if (!mission) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mission.type) {
|
||||||
|
case 'pillage':
|
||||||
|
if (region.type === 'oasis') {
|
||||||
|
resolvePillageOasis(V, region);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown mission type: "${ mission.type }"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function resolvePillageOasis(V: VillageState, region: OasisType) {
|
||||||
|
const mission = region.state.mission;
|
||||||
|
if (!mission) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
V.resources[region.resource] += mission.unitCount * 40;
|
||||||
|
delete region.state.mission;
|
||||||
|
}
|
@ -4,6 +4,7 @@ import village, { type VillageState } from '../village';
|
|||||||
import build from './build';
|
import build from './build';
|
||||||
import upgradeBuilding from './upgradeBuilding';
|
import upgradeBuilding from './upgradeBuilding';
|
||||||
import recruitUnits from './recruitUnits';
|
import recruitUnits from './recruitUnits';
|
||||||
|
import pillage from './pillage';
|
||||||
|
|
||||||
|
|
||||||
// Encapsulates a move function into a store update, where the data is made
|
// Encapsulates a move function into a store update, where the data is made
|
||||||
@ -31,5 +32,6 @@ export function makeMove(move: (...args: any[]) => boolean) {
|
|||||||
export default {
|
export default {
|
||||||
build: makeMove(build),
|
build: makeMove(build),
|
||||||
upgradeBuilding: makeMove(upgradeBuilding),
|
upgradeBuilding: makeMove(upgradeBuilding),
|
||||||
|
pillage: makeMove(pillage),
|
||||||
recruitUnits: makeMove(recruitUnits),
|
recruitUnits: makeMove(recruitUnits),
|
||||||
};
|
};
|
||||||
|
24
src/moves/pillage.ts
Normal file
24
src/moves/pillage.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { getRemainingUnitCount } from "../utils";
|
||||||
|
import type { VillageState } from "../village";
|
||||||
|
|
||||||
|
|
||||||
|
export default function pillage(V: VillageState, regionIndex: number, soldiersCount: number) {
|
||||||
|
if (soldiersCount > getRemainingUnitCount(V, 'soldier')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const region = V.worldmap[regionIndex];
|
||||||
|
|
||||||
|
if (region.state.mission) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
region.state.mission = {
|
||||||
|
type: 'pillage',
|
||||||
|
unitType: 'soldier',
|
||||||
|
unitCount: soldiersCount,
|
||||||
|
remainingTime: region.distance * 10 * 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
12
src/types.ts
12
src/types.ts
@ -64,12 +64,18 @@ export interface UnitType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface MissionType {
|
||||||
|
type: string;
|
||||||
|
unitType: string;
|
||||||
|
unitCount: number;
|
||||||
|
remainingTime: number;
|
||||||
|
}
|
||||||
|
|
||||||
interface BaseRegionType {
|
interface BaseRegionType {
|
||||||
distance: number;
|
distance: number;
|
||||||
state: {
|
state: {
|
||||||
mission?: {
|
index: number;
|
||||||
type: string;
|
mission?: MissionType;
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { produce } from 'immer';
|
import { produce } from 'immer';
|
||||||
|
|
||||||
import { CULTURE_TO_WIN } from './constants';
|
import { CULTURE_TO_WIN } from './constants';
|
||||||
|
import { resolveMission } from './missions';
|
||||||
import type { ProductionType } from './types';
|
import type { ProductionType } from './types';
|
||||||
import { getProduction, getStorage, shuffle } from './utils';
|
import { getProduction, getStorage, shuffle } from './utils';
|
||||||
import village, { type VillageState } from "./village";
|
import village, { type VillageState } from "./village";
|
||||||
@ -32,6 +33,19 @@ export default function update(timestamp: number) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Advance missions.
|
||||||
|
V.worldmap.forEach(region => {
|
||||||
|
if (!region.state.mission) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mission = region.state.mission;
|
||||||
|
mission.remainingTime -= delta;
|
||||||
|
if (mission.remainingTime <= 0) {
|
||||||
|
resolveMission(V, region);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Make all buildings and units produce and consume.
|
// Make all buildings and units produce and consume.
|
||||||
const productionPerMinute = getProduction(V);
|
const productionPerMinute = getProduction(V);
|
||||||
const storage = getStorage(V);
|
const storage = getStorage(V);
|
||||||
|
10
src/utils.ts
10
src/utils.ts
@ -1,5 +1,5 @@
|
|||||||
import units from "./data/units";
|
import units from "./data/units";
|
||||||
import type { BuildingType, CostType, ProductionType, ResourcesType } from "./types";
|
import type { BuildingType, CostType, MissionType, ProductionType, ResourcesType } from "./types";
|
||||||
import type { VillageState } from "./village";
|
import type { VillageState } from "./village";
|
||||||
|
|
||||||
|
|
||||||
@ -88,6 +88,14 @@ export function getUnitSource(unitType: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
missions.forEach(m => total -= m?.unitCount || 0);
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getKeysAsNumbers(dict: Object): Array<number> {
|
export function getKeysAsNumbers(dict: Object): Array<number> {
|
||||||
return Object.keys(dict).map(i => parseInt(i)).sort((a, b) => a - b);
|
return Object.keys(dict).map(i => parseInt(i)).sort((a, b) => a - b);
|
||||||
}
|
}
|
||||||
|
@ -66,11 +66,13 @@ function getInitialOutsideBoard() {
|
|||||||
|
|
||||||
|
|
||||||
function getInitialWorldmap(): RegionType[] {
|
function getInitialWorldmap(): RegionType[] {
|
||||||
return worldmap.map(r => {
|
return worldmap.map((r, index) => {
|
||||||
const region = r as RegionType;
|
const region = r as RegionType;
|
||||||
return {
|
return {
|
||||||
...region,
|
...region,
|
||||||
state: {},
|
state: {
|
||||||
|
index,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user