From d954e357b2339e515a937110342036278522cbeb Mon Sep 17 00:00:00 2001 From: FloPinguin <25036848+FloPinguin@users.noreply.github.com> Date: Thu, 18 Jun 2026 21:23:25 +0200 Subject: [PATCH] Fix water nukes water depth gradient --- map-generator/map_generator.go | 43 ++++++++++++++++++++++++++++++---- src/core/game/WaterManager.ts | 5 +++- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/map-generator/map_generator.go b/map-generator/map_generator.go index db7dd8bae..3b2dca9d0 100644 --- a/map-generator/map_generator.go +++ b/map-generator/map_generator.go @@ -167,13 +167,19 @@ func GenerateMap(ctx context.Context, args GeneratorArgs) (MapResult, error) { removeSmallIslands(ctx, terrain, minIslandSize, args.RemoveSmall) processWater(ctx, terrain, args.RemoveSmall) + // Water adjacent to impassable terrain should be deep (no depth gradient), + // just like water at the map edge. Override the BFS-calculated magnitude + // so these tiles render as the deepest shade. + setImpassableNeighborWaterDepth(ctx, terrain) terrain4x := createMiniMap(terrain) removeSmallIslands(ctx, terrain4x, minIslandSize/2, args.RemoveSmall) processWater(ctx, terrain4x, false) + setImpassableNeighborWaterDepth(ctx, terrain4x) terrain16x := createMiniMap(terrain4x) processWater(ctx, terrain16x, false) + setImpassableNeighborWaterDepth(ctx, terrain16x) thumb := createMapThumbnail(ctx, terrain4x, 0.5) webp, err := convertToWebP(ThumbData{ @@ -322,11 +328,11 @@ func processShore(ctx context.Context, terrain [][]Terrain) []Coord { } } else if tile.Type == Water { // Water tile adjacent to land is shoreline - for _, c := range buf[:n] { - if terrain[c.X][c.Y].Type == Land { - tile.Shoreline = true - shorelineWaters = append(shorelineWaters, Coord{X: x, Y: y}) - break + for _, c := range buf[:n] { + if terrain[c.X][c.Y].Type == Land { + tile.Shoreline = true + shorelineWaters = append(shorelineWaters, Coord{X: x, Y: y}) + break } } } @@ -386,6 +392,33 @@ func processDistToLand(ctx context.Context, shorelineWaters []Coord, terrain [][ } } +// setImpassableNeighborWaterDepth forces water tiles adjacent to impassable +// terrain to deep-water magnitude. Without this, the processDistToLand BFS +// assigns them a shallow magnitude (close to "land"), producing a visible +// depth gradient next to impassable terrain. Impassable terrain is void โ€” +// like the map edge โ€” so the water beside it should be uniformly deep. +func setImpassableNeighborWaterDepth(ctx context.Context, terrain [][]Terrain) { + width := len(terrain) + height := len(terrain[0]) + const deepMagnitude = 20 // packed as 10 (รท2), matches max render depth + + var buf [4]Coord + for x := 0; x < width; x++ { + for y := 0; y < height; y++ { + if terrain[x][y].Type != Water { + continue + } + n := neighborCoords(x, y, width, height, &buf) + for _, c := range buf[:n] { + if terrain[c.X][c.Y].Type == Impassable { + terrain[x][y].Magnitude = deepMagnitude + break + } + } + } + } +} + // neighborCoords fills out with the valid orthogonal neighbours of (x, y) and // returns the count. out must be a caller-allocated [4]Coord buffer; by // reusing the same buffer across calls the caller avoids any heap allocation. diff --git a/src/core/game/WaterManager.ts b/src/core/game/WaterManager.ts index 09478c597..f72cc685e 100644 --- a/src/core/game/WaterManager.ts +++ b/src/core/game/WaterManager.ts @@ -299,6 +299,9 @@ export class WaterManager { const sMaxY = Math.min(h - 1, cMaxY + MAX_MAG_DIST * 2); // Seed from coastline water tiles inside the seed box. + // Impassable terrain is void (like the map edge), so water tiles + // adjacent only to impassable terrain are NOT coastline โ€” they should + // be uniformly deep with no depth gradient. for (let by = sMinY; by <= sMaxY; by++) { const rowStart = by * w; for (let bx = sMinX; bx <= sMaxX; bx++) { @@ -306,7 +309,7 @@ export class WaterManager { if (!map.isWater(tile) || stampArr[tile] === stamp) continue; const end = pushNeighbors(tile, nb, 0); for (let i = 0; i < end; i++) { - if (map.isLand(nb[i])) { + if (map.isLand(nb[i]) && !map.isImpassable(nb[i])) { stampArr[tile] = stamp; distArr[tile] = 0; magQueue.push(tile);