2024.js/island/generators.ts

77 lines
2.4 KiB
TypeScript

import { BEACH, ICECAP, LIGHT_FOREST, MOUNTAIN, WATER } from "./data";
import { IslandGrid } from "./grid";
export type IsDone = boolean;
export type LobeGenerator = () => IsDone;
export type LobeGeneratorConstructor = (
islands: IslandGrid,
basePos: number
) => LobeGenerator;
/** form mountain with icecap */
export const BIG_MOUNTAIN: LobeGeneratorConstructor =
(islands: IslandGrid, basePos: number) => () => {
const mountainTiles = islands.floodSearch(
basePos,
(tile) => tile > MOUNTAIN
);
islands.dropWithin(mountainTiles);
return mountainTiles.some((pos) => islands.data[pos] == ICECAP);
};
/** form low-lying beach */
export const BEACH_LOBE: LobeGeneratorConstructor =
(islands: IslandGrid, basePos: number) => () => {
const islandTiles = islands.floodSearch(basePos, (tile) => tile > WATER);
const shoreTiles = islandTiles.filter((pos) => islands.data[pos] == WATER);
islands.dropWithin(shoreTiles);
return true;
};
/** form forested zone */
export const FOREST_LOBE: LobeGeneratorConstructor =
(islands: IslandGrid, basePos: number) => () => {
const islandTiles = islands.floodSearch(basePos, (tile) => tile > WATER);
// grow shore
const shoreTiles = islandTiles.filter((pos) => islands.data[pos] == WATER);
islands.dropWithin(shoreTiles);
// seed beach
const beachTiles = islandTiles.filter((pos) => islands.data[pos] == BEACH);
islands.dropWithin(beachTiles);
// expand forest
const forestLobe = islands.floodSearch(basePos, (tile) => tile > BEACH);
const forestTiles = forestLobe.filter(
(pos) => islands.data[pos] == LIGHT_FOREST
);
islands.dropWithin(forestTiles);
islands.dropWithin(forestTiles);
islands.dropWithin(forestTiles);
return true;
};
/** form low-lying beach with eroded sections */
export const ERODED_LOBE: LobeGeneratorConstructor =
(islands: IslandGrid, basePos: number) => () => {
const islandTiles = islands.floodSearch(basePos, (tile) => tile > WATER);
const shoreTiles = islandTiles.filter((pos) => islands.data[pos] == WATER);
islands.dropWithin(shoreTiles);
// erode
if (islandTiles.length > 1) {
const erodePos = islandTiles[islands.rng() % islandTiles.length];
islands.data[erodePos] = Math.max(islands.data[erodePos] - 1, WATER);
}
return true;
};
export const BIG_ISLANDS = [BIG_MOUNTAIN];
export const ALL_ISLANDS = [BIG_MOUNTAIN, BEACH_LOBE, FOREST_LOBE, ERODED_LOBE];