Fantasy-Map-Generator/procedural/docs/MAP_GENERATION_TRACE.md
2025-08-05 13:12:07 -04:00

21 KiB

Exhaustive Step-by-Step Trace of Fantasy Map Generator Execution Flow

Starting Point: "Generate Map" Button Click

File: /home/user/Fantasy-Map-Generator/procedural/index.html

  • Line 262: <button id="newMapButton" class="primary">🗺️ Generate Map</button>
  • Line 263: <button id="generateButton" class="primary">Generate (Alt)</button>

Phase 1: Event Handler Registration and Initialization

File: /home/user/Fantasy-Map-Generator/procedural/src/viewer/main.js

Step 1: DOM Content Loaded

  • Line 210: window.addEventListener('DOMContentLoaded', () => { ... })
  • Data Created: DOM content loaded event listener
  • Function Called: Anonymous function for initialization

Step 2: Button Event Handler Registration

  • Lines 222-225: Button event handler registration
const generateBtn = byId("newMapButton") || byId("generateButton");
if (generateBtn) {
    generateBtn.addEventListener("click", handleGenerateClick);
}
  • Data Created: Event listener for click event
  • Function Called: handleGenerateClick when clicked

Phase 2: Configuration Building and Validation

File: /home/user/Fantasy-Map-Generator/procedural/src/viewer/main.js

Step 3: Generate Click Handler Starts

  • Line 32: async function handleGenerateClick() starts execution
  • Function Called: handleGenerateClick()

Step 4: Build Configuration from UI

  • Line 36: const config = buildConfigFromUI();
  • File: /home/user/Fantasy-Map-Generator/procedural/src/viewer/config-builder.js
  • Function Called: buildConfigFromUI() (Line 8)
  • Data Created: Complete configuration object with sections:

Step 5: Configuration Object Structure Created

  • Lines 9-31 in config-builder.js: Configuration object structure created
const config = {
  seed: getSeed(),                      // Line 61: Gets seed from UI or generates new one
  graph: buildGraphConfig(),            // Line 67: { width, height, cellsDesired }
  map: buildMapConfig(),               // Line 79: { coordinatesSize, latitude }
  heightmap: buildHeightmapConfig(),   // Line 86: { templateId }
  temperature: buildTemperatureConfig(), // Line 93: { heightExponent, temperatureScale, temperatureBase }
  precipitation: buildPrecipitationConfig(), // Line 101: { winds, moisture }
  features: {},
  biomes: {},
  lakes: buildLakesConfig(),           // Line 110: { lakeElevationLimit, heightExponent }
  rivers: buildRiversConfig(),         // Line 119: { resolveDepressionsSteps, cellsCount }
  oceanLayers: buildOceanLayersConfig(), // Line 129: { outline }
  cultures: buildCulturesConfig(),     // Line 137: { culturesInput, culturesSet, emblemShape, etc. }
  burgs: buildBurgsConfig(),          // Line 162: { statesNumber, manorsInput, growthRate, etc. }
  religions: buildReligionsConfig(),   // Line 178: { religionsNumber, growthRate }
  provinces: buildProvincesConfig(),   // Line 185: { provincesRatio }
  military: buildMilitaryConfig(),     // Line 192: { year, eraShort, era }
  markers: buildMarkersConfig(),       // Line 196: { culturesSet }
  zones: buildZonesConfig(),          // Line 202: { globalModifier }
  debug: buildDebugConfig()           // Line 208: { TIME, WARN, INFO, ERROR }
};

Step 6: Configuration Validation

  • Line 39 in main.js: const { fixed, originalValidation, fixedValidation, wasFixed } = validateAndFix(config);
  • File: /home/user/Fantasy-Map-Generator/procedural/src/viewer/config-validator.js
  • Function Called: validateAndFix(config)
  • Data Created: Validation results and fixed configuration

Step 7: Validation Logging

  • Lines 42-60 in main.js: Validation logging and error handling
  • Objects Received: originalValidation, fixedValidation, wasFixed boolean
  • Expected: Validation objects with errors, warnings, valid properties

Step 8: Save Configuration to LocalStorage

  • Line 64: localStorage.setItem('fmg-last-config', saveConfigToJSON(fixed));
  • Function Called: saveConfigToJSON(fixed) from config-builder.js
  • Data Created: JSON string representation of configuration stored in localStorage

Phase 3: Engine Generation Call

File: /home/user/Fantasy-Map-Generator/procedural/src/viewer/main.js

Step 9: Call Engine Generate Function

  • Line 70: const mapData = await generateMapEngine(fixed);
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/main.js
  • Function Called: generate(config) (imported as generateMapEngine, Line 33)
  • Data Passed: Validated and fixed configuration object

Phase 4: Engine Initialization

File: /home/user/Fantasy-Map-Generator/procedural/src/engine/main.js

Step 10: Start Performance Timer

  • Line 34: const timeStart = performance.now();
  • Data Created: Timestamp for performance measurement

Step 11: Extract Debug Flags

  • Line 37: const { TIME, WARN, INFO } = config.debug;
  • Data Extracted: Debug flags from configuration

Step 12: Seed Initialization

  • Line 40: const seed = config.seed || Utils.generateSeed();
  • Function Called: Utils.generateSeed() if no seed provided
  • Data Created: Final seed value for generation

Step 13: Initialize Seeded Random Number Generator

  • Line 41: Math.random = Utils.aleaPRNG(seed);
  • Function Called: Utils.aleaPRNG(seed) from /home/user/Fantasy-Map-Generator/procedural/src/engine/utils/alea.js
  • Data Modified: Global Math.random function replaced with seeded PRNG

Step 14: Console Group Start

  • Line 44: INFO && console.group("Generating Map with Seed: " + seed);
  • Action: Console group started if INFO debug flag is true

Phase 5: Grid Generation

File: /home/user/Fantasy-Map-Generator/procedural/src/engine/main.js

Step 15: Generate Initial Grid

  • Line 48: let grid = Graph.generateGrid(config.graph);
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/utils/graph.js
  • Function Called: generateGrid(config) (Line 13)
  • Data Passed: config.graph object containing { width, height, cellsDesired }
  • Data Created: Initial grid object

Step 16: Grid Generation Process

  • Lines 15-17 in graph.js: Grid generation process
const { spacing, cellsDesired, boundary, points, cellsX, cellsY } = placePoints(config);
const { cells, vertices } = calculateVoronoi(points, boundary);
return { spacing, cellsDesired, boundary, points, cellsX, cellsY, cells, vertices };
  • Functions Called: placePoints(config) (Line 21), calculateVoronoi(points, boundary) (Line 34)
  • Data Created: Voronoi diagram with cells and vertices

Step 17: Point Placement

  • Lines 21-31 in graph.js: Point placement
  • Function Called: getBoundaryPoints(), getJitteredGrid()
  • Data Created: Array of points for Voronoi calculation
  • Objects Created: { spacing, cellsDesired, boundary, points, cellsX, cellsY }

Step 18: Voronoi Calculation

  • Lines 34-50 in graph.js: Voronoi calculation
  • External Library: Delaunator for Delaunay triangulation
  • Function Called: new Voronoi(delaunay, allPoints, points.length)
  • Data Created: cells and vertices objects with neighbor relationships

Phase 6: Heightmap Generation

File: /home/user/Fantasy-Map-Generator/procedural/src/engine/main.js

Step 19: Generate Heightmap

  • Line 51: grid.cells.h = await Heightmap.generate(grid, config, Utils);
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/modules/heightmap-generator.js
  • Function Called: generate(graph, config, utils) (Line 3)
  • Data Passed: grid object, config object, Utils module
  • Data Created: Height values array assigned to grid.cells.h

Step 20: Heightmap Processing

  • Lines 3-18 in heightmap-generator.js: Heightmap generation
  • Data Extracted: templateId from config.heightmap
  • Function Called: fromTemplate(graph, templateId, config, utils) (Line 32)
  • Data Created: Heights array for all grid cells

Step 21: Template Processing

  • Lines 32-48 in heightmap-generator.js: Template processing
  • Data Accessed: heightmapTemplates[id].template string
  • Function Called: setGraph(graph, utils), addStep() for each template step
  • Data Created: Final heights array with template-based terrain

Phase 7: Features Markup

File: /home/user/Fantasy-Map-Generator/procedural/src/engine/main.js

Step 22: Markup Grid Features

  • Line 52: grid = Features.markupGrid(grid, config, Utils);
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/modules/features.js
  • Function Called: markupGrid(grid, config, utils) (Line 28)
  • Data Passed: Grid with heights, config, utils
  • Data Modified: Grid object enhanced with feature information

Step 23: Grid Markup Process

  • Lines 28-50 in features.js: Grid markup process
  • Data Created: distanceField (Int8Array), featureIds (Uint16Array), features array
  • Algorithm: Flood-fill to identify connected land/water regions
  • Data Added to Grid: Distance fields and feature classifications

Phase 8: Geography and Climate

File: /home/user/Fantasy-Map-Generator/procedural/src/engine/main.js

Step 24: Define Map Size

  • Line 55: const { mapCoordinates } = Geography.defineMapSize(grid, config, Utils);
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/utils/geography.js
  • Function Called: defineMapSize(grid, config, Utils)
  • Data Created: mapCoordinates object with geographic bounds

Step 25: Add Lakes in Deep Depressions

  • Line 56: grid = Geography.addLakesInDeepDepressions(grid, config.lakes, Utils);
  • Function Called: addLakesInDeepDepressions(grid, config.lakes, Utils)
  • Data Modified: Grid enhanced with lake information

Step 26: Open Near-Sea Lakes

  • Line 57: grid = Geography.openNearSeaLakes(grid, config.lakes, Utils);
  • Function Called: openNearSeaLakes(grid, config.lakes, Utils)
  • Data Modified: Lake connectivity to ocean processed

Step 27: Calculate Temperatures

  • Line 60: const { temp } = Geography.calculateTemperatures(grid, mapCoordinates, config.temperature, Utils);
  • Function Called: calculateTemperatures()
  • Data Created: Temperature array for all cells
  • Line 61: grid.cells.temp = temp; - Temperature data assigned to grid

Step 28: Generate Precipitation

  • Line 62: const { prec } = Geography.generatePrecipitation(grid, mapCoordinates, config.precipitation, Utils);
  • Function Called: generatePrecipitation()
  • Data Created: Precipitation array for all cells
  • Line 63: grid.cells.prec = prec; - Precipitation data assigned to grid

Phase 9: Pack Generation (Refined Mesh)

File: /home/user/Fantasy-Map-Generator/procedural/src/engine/main.js

Step 29: Generate Refined Mesh (Pack)

  • Line 66: let pack = Graph.reGraph(grid, Utils);
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/utils/graph.js
  • Function Called: reGraph(grid, Utils)
  • Data Created: Refined mesh (pack) with higher resolution than grid
  • Purpose: Creates detailed mesh for final map features

Step 30: Markup Pack Features

  • Line 67: pack = Features.markupPack(pack, grid, config, Utils, { Lakes });
  • Function Called: Features.markupPack()
  • Data Passed: Pack mesh, original grid, config, utils, Lakes module
  • Data Modified: Pack enhanced with feature information

Phase 10: River Generation

File: /home/user/Fantasy-Map-Generator/procedural/src/engine/main.js

Step 31: Generate Rivers

  • Line 70: const riverResult = Rivers.generate(pack, grid, config.rivers, Utils, { Lakes, Names });
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/modules/river-generator.js
  • Function Called: generate(pack, grid, config.rivers, Utils, { Lakes, Names })
  • Data Passed: Pack mesh, grid, river config, utilities, Lakes and Names modules
  • Data Created: River system data

Step 32: Update Pack with Rivers

  • Line 71: pack = riverResult.pack;
  • Data Modified: Pack object updated with river information

Phase 11: Biome Assignment

File: /home/user/Fantasy-Map-Generator/procedural/src/engine/main.js

Step 33: Define Biomes

  • Line 74: const { biome } = Biomes.define(pack, grid, config.biomes, Utils);
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/modules/biomes.js
  • Function Called: define(pack, grid, config.biomes, Utils)
  • Data Created: Biome classifications for each cell

Step 34: Assign Biomes to Pack

  • Line 75: pack.cells.biome = biome;
  • Data Modified: Biome data assigned to pack cells

Phase 12: Cell Ranking and Population

File: /home/user/Fantasy-Map-Generator/procedural/src/engine/main.js

Step 35: Rank Cells

  • Line 78: const { s, pop } = Cell.rankCells(pack, Utils, { biomesData: Biomes.getDefault() });
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/utils/cell.js
  • Function Called: rankCells(pack, Utils, { biomesData })
  • Data Passed: Pack, utilities, default biomes data
  • Data Created: Cell suitability rankings (s) and population values (pop)

Step 36: Assign Cell Rankings

  • Lines 79-80: Cell data assignment
pack.cells.s = s;
pack.cells.pop = pop;

Phase 13: Culture Generation

File: /home/user/Fantasy-Map-Generator/procedural/src/engine/main.js

Step 37: Generate Cultures

  • Line 83: const culturesResult = Cultures.generate(pack, grid, config.cultures, Utils, { Names });
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/modules/cultures-generator.js
  • Function Called: generate(pack, grid, config.cultures, Utils, { Names })
  • Data Created: Cultures data and culture assignments

Step 38: Integrate Culture Data

  • Lines 84-85: Culture data integration
let packWithCultures = { ...pack, cultures: culturesResult.cultures };
packWithCultures.cells.culture = culturesResult.culture;

Step 39: Expand Cultures

  • Line 87: const expandedCulturesData = Cultures.expand(packWithCultures, config.cultures, Utils, { biomesData: Biomes.getDefault() });
  • Function Called: Cultures.expand()
  • Data Created: Expanded culture territories

Step 40: Update Pack with Expanded Cultures

  • Line 88: pack = { ...packWithCultures, ...expandedCulturesData };
  • Data Modified: Pack updated with expanded culture data

Phase 14: Burgs and States Generation

File: /home/user/Fantasy-Map-Generator/procedural/src/engine/main.js

Step 41: Generate Burgs and States

  • Line 90: const burgsAndStatesResult = BurgsAndStates.generate(pack, grid, config.burgs, Utils);
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/modules/burgs-and-states.js
  • Function Called: generate(pack, grid, config.burgs, Utils)
  • Data Created: Settlements (burgs) and political entities (states)

Step 42: Integrate Burgs and States Data

  • Lines 91-97: Burgs and states data integration
pack = {
  ...pack,
  burgs: burgsAndStatesResult.burgs,
  states: burgsAndStatesResult.states
};
pack.cells.burg = burgsAndStatesResult.burg;
pack.cells.state = burgsAndStatesResult.state;

Phase 15: Additional Features Generation

File: /home/user/Fantasy-Map-Generator/procedural/src/engine/main.js

Step 43: Generate Routes

  • Line 99: const routesResult = Routes.generate(pack, grid, Utils, []);
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/modules/routes-generator.js
  • Function Called: generate(pack, grid, Utils, [])
  • Data Created: Trade and travel routes

Step 44: Generate Religions

  • Line 102: const religionsResult = Religions.generate(pack, grid, config.religions, Utils);
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/modules/religions-generator.js
  • Function Called: generate(pack, grid, config.religions, Utils)
  • Data Created: Religious systems and distributions

Step 45: Define State Forms

  • Line 105: const stateFormsResult = BurgsAndStates.defineStateForms(undefined, pack, Utils);
  • Function Called: BurgsAndStates.defineStateForms()
  • Data Created: Government forms for states

Step 46: Generate Provinces

  • Line 108: const provincesResult = Provinces.generate(pack, config.provinces, Utils);
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/modules/provinces-generator.js
  • Function Called: generate(pack, config.provinces, Utils)
  • Data Created: Provincial subdivisions

Step 47: Define Burg Features

  • Line 111: const burgFeaturesResult = BurgsAndStates.defineBurgFeatures(undefined, pack, Utils);
  • Function Called: BurgsAndStates.defineBurgFeatures()
  • Data Created: Detailed settlement features

Step 48: Specify Rivers

  • Line 114: const specifiedRiversResult = Rivers.specify(pack, { Names }, Utils);
  • Function Called: Rivers.specify()
  • Data Created: Named and detailed river information

Step 49: Specify Features

  • Line 117: const specifiedFeaturesResult = Features.specify(pack, grid, { Lakes });
  • Function Called: Features.specify()
  • Data Created: Detailed geographic feature information

Step 50: Initialize Notes Array

  • Line 121: const notes = [];
  • Data Created: Notes array for modules requiring annotation

Step 51: Generate Military

  • Line 123: const militaryResult = Military.generate(pack, config.military, Utils, notes);
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/modules/military-generator.js
  • Function Called: generate(pack, config.military, Utils, notes)
  • Data Created: Military units and fortifications

Step 52: Generate Markers

  • Line 126: const markersResult = Markers.generateMarkers(pack, config.markers, Utils);
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/modules/markers-generator.js
  • Function Called: generateMarkers(pack, config.markers, Utils)
  • Data Created: Map markers and labels

Step 53: Generate Zones

  • Line 129: const zonesResult = Zones.generate(pack, notes, Utils, config.zones);
  • File: /home/user/Fantasy-Map-Generator/procedural/src/engine/modules/zones-generator.js
  • Function Called: generate(pack, notes, Utils, config.zones)
  • Data Created: Special zones and areas

Phase 16: Generation Completion

File: /home/user/Fantasy-Map-Generator/procedural/src/engine/main.js

Step 54: Log Performance Timing

  • Line 133: WARN && console.warn(\TOTAL GENERATION TIME: ${Utils.rn((performance.now() - timeStart) / 1000, 2)}s`);`
  • Action: Performance timing logged if WARN debug flag is true

Step 55: Close Console Group

  • Line 134: INFO && console.groupEnd("Generated Map " + seed);
  • Action: Console group ended if INFO debug flag is true

Step 56: Return Generated Map Data

  • Line 137: return { seed, grid, pack, mapCoordinates };
  • Data Returned: Complete map data object containing:
    • seed: Generation seed
    • grid: Coarse Voronoi mesh with basic geographic data
    • pack: Refined mesh with all generated features
    • mapCoordinates: Geographic coordinate system

Phase 17: Return to Viewer

File: /home/user/Fantasy-Map-Generator/procedural/src/viewer/main.js

Step 57: Log Map Generation Complete

  • Line 72: console.log("Engine finished. Map data generated:", mapData);
  • Data Received: Complete mapData object from engine
  • Objects Available: { seed, grid, pack, mapCoordinates }

Step 58: Render Map (Currently Commented Out)

  • Line 74: // renderMap(mapData); (commented out)
  • Expected Next Step: Rendering system would take the mapData and create visual representation
  • Current State: Generation complete, awaiting rendering implementation

Summary of Data Flow

Key Data Transformations:

  1. UI → Configuration: HTML form values → structured config object
  2. Configuration → Grid: Config parameters → Voronoi mesh
  3. Grid → Heightmap: Mesh structure → elevation data
  4. Grid → Features: Heights → land/water classification
  5. Grid → Pack: Coarse mesh → refined mesh
  6. Pack → Biomes: Climate data → biome assignments
  7. Pack → Cultures: Suitability → cultural territories
  8. Pack → Complete Map: Sequential module processing → final map data

Module Interaction Pattern:

  • Each module receives: (pack/grid, config_section, Utils, dependencies)
  • Each module returns: New data to merge into pack/grid
  • Modules are stateless and pure (no side effects beyond returned data)
  • Sequential processing builds up complexity from basic terrain to complete civilization

Common Data Mismatches:

  1. Modules expecting properties that don't exist yet (e.g., expecting cells.culture before Cultures module runs)
  2. Config sections missing expected fields (validation tries to fix this)
  3. Pack/Grid structure differences (pack is refined version of grid)
  4. Module dependencies (Rivers needs Lakes, Cultures needs Names)

This trace shows the complete execution flow from button click to final map data generation, with each step clearly identifying the files, functions, data transformations, and object relationships involved in the Fantasy Map Generator's procedural generation process.