2024.js/island/generators.ts

107 lines
3.2 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 SMALL_BEACH: 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 low-lying beach that meets another island */
export const BIG_BEACH: LobeGeneratorConstructor = (
islands: IslandGrid,
basePos: number
) => {
let dropped = 0;
return () => {
const islandTiles = islands.floodSearch(basePos, (tile) => tile > WATER);
const shoreTiles = islandTiles.filter((pos) => islands.data[pos] == WATER);
islands.dropWithin(shoreTiles);
dropped++;
const landTiles = islandTiles.filter((pos) => islands.data[pos] > WATER);
return landTiles.length > dropped;
};
};
/** 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;
};
/** form low-lying beach with eroded sections */
export const NO_ISLAND: LobeGeneratorConstructor =
(islands: IslandGrid, basePos: number) => () => {
return true;
};
export const BIG_ISLANDS = [BIG_MOUNTAIN, BIG_BEACH];
export const ALL_ISLANDS = [
BIG_MOUNTAIN,
SMALL_BEACH,
BIG_BEACH,
FOREST_LOBE,
ERODED_LOBE,
];