diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-22 04:37:59 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-22 04:37:59 +0800 |
| commit | 1724ce6b659850907d3bf5dc4daff70137804cf2 (patch) | |
| tree | 3aa3b59515151121e69bebc176e0e6f21f38bad9 /src/LivingVillage.Desktop | |
| parent | 8654557d9ba1c98208b67f5909f7dd7917e10d50 (diff) | |
| download | living-village-1724ce6b659850907d3bf5dc4daff70137804cf2.tar.gz | |
feat(mapgen): 512x384 尺寸自适应参数与扩程回归(P23)
- paramsForSize:河道数量随高度约每 96 行一条(64x48/256x192 仍 2 条,512x384 得 4 条),
第 3 条起在核心上/下方逐层外扩,互不重叠且不压核心。
- 噪声特征尺度封顶 4x,避免 512x384 退化成过度平滑的放大图。
- 64x48/256x192 生成结果逐字节不变(新增 checksum 锁定用例)。
- 新增 512x384 同 seed 逐字节一致/异 seed 分化/四河道连续/30 spawn 与桥两岸可达用例。
- Desktop 测试 124 -> 130。
Diffstat (limited to 'src/LivingVillage.Desktop')
| -rw-r--r-- | src/LivingVillage.Desktop/MapGen.fs | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/src/LivingVillage.Desktop/MapGen.fs b/src/LivingVillage.Desktop/MapGen.fs index 7c7059a..ce9bccf 100644 --- a/src/LivingVillage.Desktop/MapGen.fs +++ b/src/LivingVillage.Desktop/MapGen.fs @@ -72,6 +72,15 @@ module MapGen = SpawnColumns = 5 SpawnRows = 6 } + /// P23 尺寸自适应参数:河道数量随高度增长(约每 96 行一条),其余沿用默认。 + /// 64x48 / 256x192 仍得到 2 条河道,与既有输出逐字节一致;512x384 得到 4 条。 + let paramsForSize (width: int) (height: int) (seed: uint64) : Params = + let base_ = defaultParams seed + { base_ with + Width = width + Height = height + RiverCount = max base_.RiverCount (max 1 (height / 96)) } + // ---- splitmix64 与 value noise(无外部依赖、无时钟) ---- let private splitmix (state: uint64) : uint64 * uint64 = @@ -104,6 +113,10 @@ module MapGen = (v00 * (1.0f - sx) + v10 * sx) * (1.0f - sy) + (v01 * (1.0f - sx) + v11 * sx) * sy /// 2-3 octave 叠加;特征尺度随地图宽度等比缩放,保证小图/大图观感一致。 + /// P23:特征尺度封顶(<=4x),避免 512x384 退化成过于平滑的「放大图」。 + let private noiseWidthScale (width: int) : float32 = + min 4.0f (float32 width / 64.0f) + let private multiOctave (widthScale: float32) (x: int) (y: int) (seed: uint64) : float32 = let xf = float32 x let yf = float32 y @@ -138,7 +151,7 @@ module MapGen = x >= core.MinX && x <= core.MaxX && y >= core.MinY && y <= core.MaxY // 1) 多八度噪声:低洼草地转泥炭(跳过核心区)。 - let widthScale = float32 w / 64.0f + let widthScale = noiseWidthScale w for y in 0 .. h - 1 do for x in 0 .. w - 1 do if multiOctave widthScale x y p.Seed < 0.18f && not (inCore x y) then @@ -148,14 +161,26 @@ module MapGen = let riverWidth = max 3 p.RiverWidth let riverBands = [ for i in 0 .. max 0 p.RiverCount - 1 do - if i % 2 = 0 then + if i = 0 then let centerY = max 1 (min (h - 1 - riverWidth) (min (core.MinY - riverWidth - 2) (h / 4))) if centerY + riverWidth - 1 < core.MinY then yield { CenterY = centerY; Width = riverWidth } - else + elif i = 1 then let centerY = max 1 (min (h - 1 - riverWidth) (max (core.MaxY + 2) (3 * h / 4))) if centerY > core.MaxY then - yield { CenterY = centerY; Width = riverWidth } ] + yield { CenterY = centerY; Width = riverWidth } + else + // P23:第 3 条起在核心上/下方逐层外扩堆叠,互不重叠、不压核心。 + let layer = (i - 1) / 2 + let offset = if i % 2 = 1 then layer - 1 else layer + if i % 2 = 0 then + let centerY = core.MinY - riverWidth - 2 - offset * (riverWidth + 3) + if centerY >= 1 then + yield { CenterY = centerY; Width = riverWidth } + else + let centerY = core.MaxY + 2 + offset * (riverWidth + 3) + if centerY + riverWidth - 1 <= h - 2 then + yield { CenterY = centerY; Width = riverWidth } ] for river in riverBands do for x in 1 .. w - 2 do for dy in 0 .. river.Width - 1 do @@ -310,7 +335,7 @@ module MapGen = BridgeCrossingsOk = crossingsOk } let generateWithSize (width: int) (height: int) (seed: uint64) : Result = - generate { defaultParams seed with Width = width; Height = height } + generate (paramsForSize width height seed) /// 生成结果的确定性序列化(同 seed 逐字节一致),供回归测试与跨机核对。 let serialize (map: Result) : string = |
