Factor out generators
This commit is contained in:
parent
a7e0145736
commit
4fc076d80c
2 changed files with 101 additions and 49 deletions
74
island/generators.ts
Normal file
74
island/generators.ts
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
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;
|
||||||
|
};
|
|
@ -1,13 +1,17 @@
|
||||||
import { Prng, mulberry32 } from "../lib/prng";
|
import { Prng, mulberry32 } from "../lib/prng";
|
||||||
import { BEACH, ICECAP, LIGHT_FOREST, MOUNTAIN, WATER } from "./data";
|
import { BEACH, ICECAP, LIGHT_FOREST, MOUNTAIN, WATER } from "./data";
|
||||||
|
import {
|
||||||
|
BEACH_LOBE,
|
||||||
|
BIG_MOUNTAIN,
|
||||||
|
FOREST_LOBE,
|
||||||
|
LobeGenerator,
|
||||||
|
} from "./generators";
|
||||||
|
|
||||||
export class IslandGrid {
|
export class IslandGrid {
|
||||||
data: number[];
|
data: number[];
|
||||||
rng: Prng;
|
rng: Prng;
|
||||||
|
|
||||||
basePos: number;
|
generators: LobeGenerator[] = [];
|
||||||
lobePos1: number;
|
|
||||||
lobePos2: number;
|
|
||||||
|
|
||||||
done = false;
|
done = false;
|
||||||
|
|
||||||
|
@ -15,14 +19,24 @@ export class IslandGrid {
|
||||||
this.data = Array(width * height).fill(0);
|
this.data = Array(width * height).fill(0);
|
||||||
this.rng = mulberry32(seed);
|
this.rng = mulberry32(seed);
|
||||||
|
|
||||||
this.basePos = this.data.length >> 1;
|
this.generators.push(BIG_MOUNTAIN(this, this.data.length >> 1));
|
||||||
this.lobePos1 = this.xy(
|
this.generators.push(
|
||||||
|
FOREST_LOBE(
|
||||||
|
this,
|
||||||
|
this.xy(
|
||||||
(width >> 1) + (this.rng() % 48) - 24,
|
(width >> 1) + (this.rng() % 48) - 24,
|
||||||
(height >> 1) + (this.rng() % 48) - 24
|
(height >> 1) + (this.rng() % 48) - 24
|
||||||
|
)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
this.lobePos2 = this.xy(
|
this.generators.push(
|
||||||
|
BEACH_LOBE(
|
||||||
|
this,
|
||||||
|
this.xy(
|
||||||
(width >> 1) + (this.rng() % 48) - 24,
|
(width >> 1) + (this.rng() % 48) - 24,
|
||||||
(height >> 1) + (this.rng() % 48) - 24
|
(height >> 1) + (this.rng() % 48) - 24
|
||||||
|
)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,44 +126,8 @@ export class IslandGrid {
|
||||||
}
|
}
|
||||||
|
|
||||||
public step() {
|
public step() {
|
||||||
const lowlandTiles1 = this.floodSearch(
|
this.done = this.generators
|
||||||
this.lobePos1,
|
.map((generator) => generator())
|
||||||
(tile) => tile > WATER
|
.every((done) => done);
|
||||||
);
|
|
||||||
const lowlandTiles2 = this.floodSearch(
|
|
||||||
this.lobePos2,
|
|
||||||
(tile) => tile > WATER
|
|
||||||
);
|
|
||||||
|
|
||||||
// grow shore
|
|
||||||
const shoreTiles1 = lowlandTiles1.filter((pos) => this.data[pos] == WATER);
|
|
||||||
this.dropWithin(shoreTiles1);
|
|
||||||
const shoreTiles2 = lowlandTiles2.filter((pos) => this.data[pos] == WATER);
|
|
||||||
this.dropWithin(shoreTiles2);
|
|
||||||
|
|
||||||
// seed beach
|
|
||||||
const beachTiles = lowlandTiles1.filter((pos) => this.data[pos] == BEACH);
|
|
||||||
this.dropWithin(beachTiles);
|
|
||||||
|
|
||||||
// expand forest
|
|
||||||
const forestLobe = this.floodSearch(this.lobePos1, (tile) => tile > BEACH);
|
|
||||||
const forestTiles = forestLobe.filter(
|
|
||||||
(pos) => this.data[pos] == LIGHT_FOREST
|
|
||||||
);
|
|
||||||
this.dropWithin(forestTiles);
|
|
||||||
this.dropWithin(forestTiles);
|
|
||||||
this.dropWithin(forestTiles);
|
|
||||||
|
|
||||||
// form mountain
|
|
||||||
const mountainTiles = this.floodSearch(
|
|
||||||
this.basePos,
|
|
||||||
(tile) => tile > MOUNTAIN
|
|
||||||
);
|
|
||||||
this.dropWithin(mountainTiles); // GENERATOR
|
|
||||||
|
|
||||||
if (lowlandTiles2.length > 1) {
|
|
||||||
const erodePos = lowlandTiles2[this.rng() % lowlandTiles2.length];
|
|
||||||
this.data[erodePos] = Math.max(this.data[erodePos] - 1, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue