impl sinkholes

This commit is contained in:
Tangent Wantwight 2024-01-13 14:54:25 -05:00
parent d44076b32c
commit dc8fc5ef87
3 changed files with 85 additions and 7 deletions

View File

@ -168,6 +168,50 @@ export const NO_ISLAND: LobeGeneratorConstructor =
return true;
};
const SINKHOLE_BURNOUT = 1500;
/** carve out elevation */
export const SINKHOLE: LobeGeneratorConstructor = (
islands: IslandGrid,
basePos: number
) => {
// emergency cutoff in case sinkhole ends up fighting a generator that terminates at a given elevation
let ticks = 0;
return () => {
if (ticks++ < SINKHOLE_BURNOUT) {
const sunk = islands.floodSearch(basePos, (tile) => tile < 0);
islands.sinkhole(islands.choose(sunk));
}
return true;
};
};
/** carve out elevation more aggressively */
export const WIDE_SINKHOLE: LobeGeneratorConstructor = (
islands: IslandGrid,
basePos: number
) => {
// emergency cutoff in case sinkhole ends up fighting a generator that terminates at a given elevation
let ticks = 0;
return () => {
if (ticks++ < SINKHOLE_BURNOUT) {
const sunk = islands.floodSearch(basePos, (tile) => tile < 0);
const sunkEdge = sunk.filter((pos) => islands.data[pos] >= WATER);
if (sunkEdge.length > 0) {
islands.sinkhole(islands.choose(sunkEdge));
} else {
islands.sinkhole(islands.choose(sunk));
}
}
return true;
};
};
export const BIG_ISLANDS = [BIG_MOUNTAIN, BIG_BEACH, HILLY_FOREST];
export const ROCKY_ISLANDS = [SMALL_MOUNTAIN, BIG_MOUNTAIN, HILLY_FOREST];
export const GREEN_ISLANDS = [
@ -186,3 +230,4 @@ export const ALL_ISLANDS = [
HILLY_FOREST,
ERODED_BEACH,
];
export const VOIDS = [NO_ISLAND, SINKHOLE, WIDE_SINKHOLE];

View File

@ -7,7 +7,9 @@ import {
LobeGenerator,
NO_ISLAND,
ROCKY_ISLANDS,
SINKHOLE,
SMALL_ISLANDS,
VOIDS,
} from "./generators";
export class IslandGrid {
@ -30,10 +32,10 @@ export class IslandGrid {
this.choose(SMALL_ISLANDS),
this.choose(ALL_ISLANDS),
this.choose(ALL_ISLANDS),
NO_ISLAND,
NO_ISLAND,
NO_ISLAND,
NO_ISLAND,
this.choose(VOIDS),
this.choose(VOIDS),
this.choose(VOIDS),
this.choose(VOIDS),
NO_ISLAND,
NO_ISLAND,
]);
@ -126,10 +128,36 @@ export class IslandGrid {
}
// flat, increase elevation
const newValue = ++this.data[pos];
if (newValue == ICECAP) {
this.done = true;
++this.data[pos];
}
public sinkhole(pos: number): void {
const higherNeighbors: number[] = [];
const check = (adjPos: number) => {
if (this.data[adjPos] > this.data[pos]) {
higherNeighbors.push(adjPos);
}
};
// try to pull from neighbors
check((pos - this.width - 1) % this.data.length);
check((pos - this.width) % this.data.length);
check((pos - this.width + 1) % this.data.length);
check((pos - 1) % this.data.length);
check((pos + 1) % this.data.length);
check((pos + this.width - 1) % this.data.length);
check((pos + this.width) % this.data.length);
check((pos + this.width + 1) % this.data.length);
if (higherNeighbors.length > 0) {
const uphill = higherNeighbors[this.rng() % higherNeighbors.length];
return this.sinkhole(uphill);
}
// flat, decrease elevation
this.data[pos] = Math.max(this.data[pos] - 1, -3);
}
public choose<T>(list: T[]) {

View File

@ -9,6 +9,11 @@ export function renderIslands(
for (let x = 0; x < islands.width; x++) {
const tile = islands.data[islands.xy(x, y)];
switch (tile) {
case -3:
case -2:
case -1:
cx.fillStyle = "#000088";
break;
case WATER:
cx.fillStyle = "blue";
break;