diff --git a/src/index.html b/src/index.html
index b6a4a603..5d9cf35a 100644
--- a/src/index.html
+++ b/src/index.html
@@ -8470,7 +8470,6 @@
-
diff --git a/public/modules/biomes.js b/src/modules/biomes.ts
similarity index 62%
rename from public/modules/biomes.js
rename to src/modules/biomes.ts
index 06280fad..49bc24b8 100644
--- a/public/modules/biomes.js
+++ b/src/modules/biomes.ts
@@ -1,10 +1,30 @@
-"use strict";
+import { range, mean } from "d3";
+import { rn } from "../utils";
-window.Biomes = (function () {
- const MIN_LAND_HEIGHT = 20;
+declare global {
+ var Biomes: BiomesModule;
- const getDefault = () => {
- const name = [
+ var pack: any;
+ var grid: any;
+ var TIME: boolean;
+
+ var biomesData: {
+ i: number[];
+ name: string[];
+ color: string[];
+ biomesMartix: Uint8Array[];
+ habitability: number[];
+ iconsDensity: number[];
+ icons: string[][];
+ cost: number[];
+ };
+}
+
+class BiomesModule {
+ private MIN_LAND_HEIGHT = 20;
+
+ getDefault() {
+ const name: string[] = [
"Marine",
"Hot desert",
"Cold desert",
@@ -20,7 +40,7 @@ window.Biomes = (function () {
"Wetland"
];
- const color = [
+ const color: string[] = [
"#466eab",
"#fbe79f",
"#b5b887",
@@ -35,9 +55,9 @@ window.Biomes = (function () {
"#d5e7eb",
"#0b9131"
];
- const habitability = [0, 4, 10, 22, 30, 50, 100, 80, 90, 12, 4, 0, 12];
- const iconsDensity = [0, 3, 2, 120, 120, 120, 120, 150, 150, 100, 5, 0, 250];
- const icons = [
+ const habitability: number[] = [0, 4, 10, 22, 30, 50, 100, 80, 90, 12, 4, 0, 12];
+ const iconsDensity: number[] = [0, 3, 2, 120, 120, 120, 120, 150, 150, 100, 5, 0, 250];
+ const icons: Array<{[key: string]: number}> = [
{},
{dune: 3, cactus: 6, deadTree: 1},
{dune: 9, deadTree: 1},
@@ -52,8 +72,8 @@ window.Biomes = (function () {
{},
{swamp: 1}
];
- const cost = [10, 200, 150, 60, 50, 70, 70, 80, 90, 200, 1000, 5000, 150]; // biome movement cost
- const biomesMartix = [
+ const cost: number[] = [10, 200, 150, 60, 50, 70, 70, 80, 90, 200, 1000, 5000, 150]; // biome movement cost
+ const biomesMartix: Uint8Array[] = [
// hot ↔ cold [>19°C; <-4°C]; dry ↕ wet
new Uint8Array([1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10]),
new Uint8Array([3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 10, 10, 10]),
@@ -63,53 +83,53 @@ window.Biomes = (function () {
];
// parse icons weighted array into a simple array
+ const parsedIcons: string[][] = [];
for (let i = 0; i < icons.length; i++) {
- const parsed = [];
+ const parsed: string[] = [];
for (const icon in icons[i]) {
for (let j = 0; j < icons[i][icon]; j++) {
parsed.push(icon);
}
}
- icons[i] = parsed;
+ parsedIcons[i] = parsed;
}
- return {i: d3.range(0, name.length), name, color, biomesMartix, habitability, iconsDensity, icons, cost};
+ return {i: range(0, name.length), name, color, biomesMartix, habitability, iconsDensity, icons: parsedIcons, cost};
};
- // assign biome id for each cell
- function define() {
+ define() {
TIME && console.time("defineBiomes");
const {fl: flux, r: riverIds, h: heights, c: neighbors, g: gridReference} = pack.cells;
const {temp, prec} = grid.cells;
pack.cells.biome = new Uint8Array(pack.cells.i.length); // biomes array
- for (let cellId = 0; cellId < heights.length; cellId++) {
- const height = heights[cellId];
- const moisture = height < MIN_LAND_HEIGHT ? 0 : calculateMoisture(cellId);
- const temperature = temp[gridReference[cellId]];
- pack.cells.biome[cellId] = getId(moisture, temperature, height, Boolean(riverIds[cellId]));
- }
-
- function calculateMoisture(cellId) {
+ const calculateMoisture = (cellId: number) => {
let moisture = prec[gridReference[cellId]];
if (riverIds[cellId]) moisture += Math.max(flux[cellId] / 10, 2);
const moistAround = neighbors[cellId]
- .filter(neibCellId => heights[neibCellId] >= MIN_LAND_HEIGHT)
- .map(c => prec[gridReference[c]])
+ .filter((neibCellId: number) => heights[neibCellId] >= this.MIN_LAND_HEIGHT)
+ .map((c: number) => prec[gridReference[c]])
.concat([moisture]);
- return rn(4 + d3.mean(moistAround));
+ return rn(4 + (mean(moistAround) as number));
+ }
+
+ for (let cellId = 0; cellId < heights.length; cellId++) {
+ const height = heights[cellId];
+ const moisture = height < this.MIN_LAND_HEIGHT ? 0 : calculateMoisture(cellId);
+ const temperature = temp[gridReference[cellId]];
+ pack.cells.biome[cellId] = this.getId(moisture, temperature, height, Boolean(riverIds[cellId]));
}
TIME && console.timeEnd("defineBiomes");
}
- function getId(moisture, temperature, height, hasRiver) {
+ getId(moisture: number, temperature: number, height: number, hasRiver: boolean) {
if (height < 20) return 0; // all water cells: marine biome
if (temperature < -5) return 11; // too cold: permafrost biome
if (temperature >= 25 && !hasRiver && moisture < 8) return 1; // too hot and dry: hot desert biome
- if (isWetland(moisture, temperature, height)) return 12; // too wet: wetland biome
+ if (this.isWetland(moisture, temperature, height)) return 12; // too wet: wetland biome
// in other cases use biome matrix
const moistureBand = Math.min((moisture / 5) | 0, 4); // [0-4]
@@ -117,12 +137,12 @@ window.Biomes = (function () {
return biomesData.biomesMartix[moistureBand][temperatureBand];
}
- function isWetland(moisture, temperature, height) {
+ private isWetland(moisture: number, temperature: number, height: number) {
if (temperature <= -2) return false; // too cold
if (moisture > 40 && height < 25) return true; // near coast
if (moisture > 24 && height > 24 && height < 60) return true; // off coast
return false;
}
+}
- return {getDefault, define, getId};
-})();
+window.Biomes = new BiomesModule();
diff --git a/src/modules/index.ts b/src/modules/index.ts
index 09b6be21..21836080 100644
--- a/src/modules/index.ts
+++ b/src/modules/index.ts
@@ -2,4 +2,5 @@ import "./voronoi";
import "./heightmap-generator";
import "./features";
import "./ocean-layers";
-import "./river-generator";
\ No newline at end of file
+import "./river-generator";
+import "./biomes"
\ No newline at end of file