mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-18 02:01:22 +01:00
226 lines
No EOL
10 KiB
Markdown
226 lines
No EOL
10 KiB
Markdown
# Heightmap Generator Assessment
|
|
|
|
## Executive Summary
|
|
|
|
The heightmap generator module has undergone significant refactoring during the port from the browser-based version to the headless engine. While the core logic remains intact, several critical deviations have been introduced that impact functionality, architecture consistency, and maintainability. Most critically, the naming convention has become inconsistent and the state management pattern has been fundamentally altered.
|
|
|
|
## Key Deviations Identified
|
|
|
|
### 1. **Critical Naming Convention Violations**
|
|
|
|
**Original Pattern (../modules/heightmap-generator.js):**
|
|
- **Input parameter:** `graph` (lines 9, 24, 40, 64, 70) - represents the incoming data structure
|
|
- **Internal variable:** `grid` (line 4, 14, 21) - closure variable storing the graph after `setGraph(graph)` call
|
|
- **Usage pattern:** Functions receive `graph`, call `setGraph(graph)` to store as `grid`, then use `grid` throughout
|
|
|
|
**Current Broken Pattern (src/engine/modules/heightmap-generator.js):**
|
|
- **Inconsistent parameter naming:** Mix of `grid` and `graph` parameters
|
|
- **Line 178:** `addPit(heights, graph, ...)` - should be `grid` like other functions
|
|
- **Line 254, 255:** `findGridCell(startX, startY, graph)` - uses undefined `graph` variable
|
|
- **Line 347:** `findGridCell(startX, startY, graph)` - uses undefined `graph` variable
|
|
- **Line 444, 445:** `findGridCell(startX, startY, graph)` - uses undefined `graph` variable
|
|
|
|
**CRITICAL BUG:** These functions will fail at runtime because `graph` is undefined in their scope.
|
|
|
|
### 2. **setGraph/setGrid State Management Deviation**
|
|
|
|
**Original setGraph Pattern:**
|
|
```javascript
|
|
const setGraph = graph => {
|
|
const {cellsDesired, cells, points} = graph;
|
|
heights = cells.h ? Uint8Array.from(cells.h) : createTypedArray({maxValue: 100, length: points.length});
|
|
blobPower = getBlobPower(cellsDesired);
|
|
linePower = getLinePower(cellsDesired);
|
|
grid = graph; // Store graph as grid for internal use
|
|
};
|
|
```
|
|
|
|
**Current setGrid Pattern:**
|
|
```javascript
|
|
function setGrid(grid, utils) {
|
|
const { createTypedArray } = utils;
|
|
const { cellsDesired, cells, points } = grid;
|
|
const heights = cells.h ? Uint8Array.from(cells.h) : createTypedArray({ maxValue: 100, length: points.length });
|
|
const blobPower = getBlobPower(cellsDesired);
|
|
const linePower = getLinePower(cellsDesired);
|
|
return { heights, blobPower, linePower }; // Returns computed values instead of storing state
|
|
}
|
|
```
|
|
|
|
**Critical Differences:**
|
|
1. **State Storage:** Original stores state in closure, current returns computed values
|
|
2. **Naming:** Original uses `graph` parameter name, current uses `grid`
|
|
3. **Function Name:** `setGraph` vs `setGrid` - breaks the original naming logic
|
|
4. **Return Pattern:** Original modifies closure state, current returns data for functional approach
|
|
|
|
### 3. **Architectural Pattern Shift Analysis**
|
|
|
|
**Original Closure-Based State Management:**
|
|
- State variables (`grid`, `heights`, `blobPower`, `linePower`) live in module closure
|
|
- `setGraph(graph)` initializes state once per generation cycle
|
|
- Helper functions access closure state directly (no parameters needed)
|
|
- `clearData()` cleans up state after generation
|
|
|
|
**Current Pure Functional Approach:**
|
|
- No persistent state - everything passed as parameters
|
|
- Each function receives `(heights, grid, blobPower, config, utils, ...args)`
|
|
- `setGrid(grid, utils)` computes values and returns them (no state storage)
|
|
- Each helper function creates new arrays and returns modified results
|
|
|
|
**Impact Analysis:**
|
|
- **Positive:** True functional purity enables better testing and no side effects
|
|
- **Negative:** Massive parameter bloat (8+ parameters per function vs 0 in original)
|
|
- **Performance:** Multiple array allocations vs single state initialization
|
|
|
|
### 4. **Parameter Propagation Problems**
|
|
|
|
**Missing Parameters:**
|
|
- Line 90-92: `modify()` function call missing `power` parameter that's used in implementation
|
|
- Line 92: `modify(heights, a3, +a2, 1, utils)` - missing `power` but function expects it
|
|
|
|
**Wrong Parameter Order:**
|
|
- Functions expect `(heights, grid, ...)` but some calls pass different structures
|
|
- Type mismatches between expected `grid` object and passed `graph` references
|
|
|
|
### 5. **Return Value Handling Issues**
|
|
|
|
**Critical Deviation:**
|
|
- Original functions modified global `heights` array in place
|
|
- Current functions create new `Uint8Array(heights)` copies but don't always maintain referential consistency
|
|
- This could lead to performance issues and memory overhead
|
|
|
|
### 6. **Utility Dependencies**
|
|
|
|
**Incomplete Migration:**
|
|
- Line 51: `fromPrecreated` function is completely stubbed out
|
|
- Missing critical browser-to-headless migration for image processing
|
|
- DOM dependencies (`document.createElement`, `canvas`, `Image`) not replaced
|
|
|
|
## Specific Runtime Failures
|
|
|
|
### Bug 1: Undefined Variable References (CRITICAL)
|
|
```javascript
|
|
// Line 178 - Function parameter name
|
|
export function addPit(heights, graph, blobPower, config, utils, count, height, rangeX, rangeY) {
|
|
// Line 199 - Internal usage tries to access 'grid' (UNDEFINED)
|
|
start = findGridCell(x, y, grid); // ReferenceError: grid is not defined
|
|
```
|
|
|
|
### Bug 2: Parameter/Variable Mismatch Pattern
|
|
**Broken Functions:**
|
|
- `addPit` (line 178): parameter `graph`, usage `grid` (line 199, 209)
|
|
- `addRange` (line 221): parameter `grid`, but calls `findGridCell(x, y, graph)` (lines 254-255)
|
|
- `addTrough` (line 320): parameter `grid`, but calls `findGridCell(x, y, graph)` (lines 347, 359)
|
|
- `addStrait` (line 425): parameter `grid`, but calls `findGridCell(x, y, graph)` (lines 444-445)
|
|
|
|
### Bug 3: Missing Parameter in Function Calls
|
|
```javascript
|
|
// Line 90 - Call site
|
|
if (tool === "Add") return modify(heights, a3, +a2, 1, utils);
|
|
|
|
// Line 490 - Function signature expects 6 parameters, gets 5
|
|
export function modify(heights, range, add, mult, power, utils) {
|
|
// ^^^^^ undefined
|
|
```
|
|
|
|
### Bug 4: Inconsistent Array Handling
|
|
```javascript
|
|
// Every helper function does:
|
|
heights = new Uint8Array(heights); // Unnecessary copying if already Uint8Array
|
|
// Original pattern: direct mutation of closure variable
|
|
```
|
|
|
|
## Performance Impact Assessment
|
|
|
|
1. **Memory Overhead:** Each helper function creates new Uint8Array copies
|
|
2. **Parameter Bloat:** Functions now take 6-8 parameters instead of accessing closure variables
|
|
3. **Reduced Efficiency:** Multiple array allocations per generation step
|
|
|
|
## Recommendations
|
|
|
|
### Critical Fixes (Must Fix Immediately)
|
|
|
|
#### 1. **Restore Original Naming Convention**
|
|
**All functions must use the original pattern:**
|
|
- **Parameter name:** `graph` (not `grid`)
|
|
- **Internal usage:** `grid` (converted from `graph` parameter)
|
|
- **Function name:** `setGraph` (not `setGrid`)
|
|
|
|
```javascript
|
|
// CORRECT pattern matching original:
|
|
export function addPit(heights, graph, blobPower, config, utils, count, height, rangeX, rangeY) {
|
|
const grid = graph; // Convert parameter to internal variable name
|
|
// ... use grid throughout function body
|
|
}
|
|
```
|
|
|
|
#### 2. **Fix Parameter/Variable Mismatches**
|
|
**Every function with graph/grid issues:**
|
|
- Line 178: `addPit` - change parameter from `graph` to `grid` OR add `const grid = graph;`
|
|
- Lines 254-255, 347, 359, 444-445: Change `graph` to `grid` in `findGridCell` calls
|
|
- Line 92: Add missing `power` parameter to `modify()` call
|
|
|
|
#### 3. **Standardize Function Signatures**
|
|
**All helper functions should follow this pattern:**
|
|
```javascript
|
|
export function addHill(heights, graph, blobPower, config, utils, ...specificArgs) {
|
|
const grid = graph; // Mirror original internal conversion
|
|
// ... implementation using grid
|
|
}
|
|
```
|
|
|
|
### Architecture Decision Points
|
|
|
|
#### Option A: Pure Functional (Current Broken Approach)
|
|
**Pros:** No side effects, better testability
|
|
**Cons:** 8+ parameters per function, performance overhead, complexity
|
|
**Fix Required:** Complete parameter standardization
|
|
|
|
#### Option B: Hybrid Closure Pattern (Recommended)
|
|
**Restore original naming but keep functional returns:**
|
|
```javascript
|
|
function setGraph(graph, utils) { // Restore original name
|
|
const grid = graph; // Original internal conversion
|
|
const { cellsDesired, cells, points } = grid;
|
|
// ... compute values
|
|
return { heights, blobPower, linePower, grid }; // Include grid in return
|
|
}
|
|
```
|
|
|
|
#### Option C: Context Object Pattern
|
|
**Bundle related parameters:**
|
|
```javascript
|
|
export function addHill(context, count, height, rangeX, rangeY) {
|
|
const { heights, graph, blobPower, config, utils } = context;
|
|
const grid = graph; // Maintain original pattern
|
|
// ... implementation
|
|
}
|
|
```
|
|
|
|
## Conclusion
|
|
|
|
The heightmap generator refactoring represents an **incomplete and broken migration** from the original closure-based pattern. While the functional approach has merit, the implementation violates the original naming convention and introduces multiple runtime failures. The core issue is that the refactoring was performed without understanding the original `graph` → `grid` naming logic.
|
|
|
|
**Root Cause:** The original code used `graph` as the input parameter name and `grid` as the internal variable name after calling `setGraph(graph)`. The current version inconsistently mixes these names, creating undefined variable references.
|
|
|
|
**Severity:** HIGH - Multiple functions will fail at runtime due to undefined variable access.
|
|
|
|
## Priority Actions (In Order)
|
|
|
|
### Immediate (Blocking)
|
|
1. **Fix undefined variable references** - All `findGridCell(x, y, graph)` calls where `graph` is undefined
|
|
2. **Standardize parameter names** - Either all `graph` or all `grid`, but consistently applied
|
|
3. **Restore setGraph naming** - Change `setGrid` back to `setGraph` to match original pattern
|
|
4. **Fix missing parameters** - Add `power` parameter to `modify()` function calls
|
|
|
|
### Short Term
|
|
1. **Choose architectural pattern** - Pure functional vs hybrid vs context object
|
|
2. **Optimize array handling** - Eliminate unnecessary Uint8Array copying
|
|
3. **Complete parameter standardization** - Ensure all functions follow chosen pattern
|
|
|
|
### Long Term
|
|
1. **Complete fromPrecreated migration** - Implement headless image processing
|
|
2. **Performance benchmarking** - Compare against original implementation
|
|
3. **Add comprehensive testing** - Prevent regression of these naming issues
|
|
|
|
**Recommendation:** Restore the original `graph` parameter → `grid` internal variable pattern throughout the entire module to maintain consistency with the original design intent. |