summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop/MapGen.fs
diff options
context:
space:
mode:
Diffstat (limited to 'src/LivingVillage.Desktop/MapGen.fs')
-rw-r--r--src/LivingVillage.Desktop/MapGen.fs91
1 files changed, 88 insertions, 3 deletions
diff --git a/src/LivingVillage.Desktop/MapGen.fs b/src/LivingVillage.Desktop/MapGen.fs
index 63b14bc..ce9fb3a 100644
--- a/src/LivingVillage.Desktop/MapGen.fs
+++ b/src/LivingVillage.Desktop/MapGen.fs
@@ -34,7 +34,9 @@ module MapGen =
/// P24:大图额外沿河民居数量(沿现有路网泊松散布)。默认 0,64x48/256x192 不受影响。
ExtraRiversideHouses: int
/// P25:是否放置孤立装饰石块。默认 true;大图关闭,避免草地上出现游离石板 tile。
- DecorativeStones: bool }
+ DecorativeStones: bool
+ /// P26:是否沿海河岸放置河岸装饰(护岸石垒/芦苇/垂柳)。默认 false;仅大图开启。
+ RiverDecorations: bool }
/// P20 第二步:一条贯穿全图的东西向河道(每列恰好一段,宽度下限 RiverWidth)。
type River =
@@ -50,6 +52,18 @@ module MapGen =
DoorX: int
DoorY: int }
+ /// P26 河岸装饰种类:护岸石垒 / 芦苇 / 垂柳(垂柳占上下两格)。
+ type RiverDecorationKind =
+ | RevetmentStone
+ | Reeds
+ | Willow
+
+ /// P26 河岸装饰:纯视觉,不写入瓦片、不影响通行;仅大图沿海河岸生成。
+ type RiverDecoration =
+ { Kind: RiverDecorationKind
+ X: int
+ Y: int }
+
type Result =
{ Width: int
Height: int
@@ -61,6 +75,7 @@ module MapGen =
Bridges: (int * int) list
Paths: (int * int) list
Buildings: Building list
+ Decorations: RiverDecoration list
ReachableTiles: int
ReachabilityOk: bool
BridgeCrossingsOk: bool }
@@ -76,7 +91,8 @@ module MapGen =
SpawnColumns = 5
SpawnRows = 6
ExtraRiversideHouses = 0
- DecorativeStones = true }
+ DecorativeStones = true
+ RiverDecorations = false }
/// P23 尺寸自适应参数:河道数量随高度增长(约每 96 行一条),其余沿用默认。
/// 64x48 / 256x192 仍得到 2 条河道,与既有输出逐字节一致;512x384 得到 4 条。
@@ -89,7 +105,8 @@ module MapGen =
Height = height
RiverCount = max base_.RiverCount (max 1 (height / 96))
ExtraRiversideHouses = (if large then 10 else 0)
- DecorativeStones = not large }
+ DecorativeStones = not large
+ RiverDecorations = large }
// ---- splitmix64 与 value noise(无外部依赖、无时钟) ----
@@ -330,6 +347,63 @@ module MapGen =
addPath building.DoorX building.DoorY
extraPlaced <- extraPlaced + 1
+ // 5c) P26:河岸装饰(护岸石垒/芦苇/垂柳),仅大图启用。纯视觉层,不写入任何瓦片,
+ // 故 64x48/256x192 的 tiles checksum 与默认世界完全不受影响;装饰只落在紧邻水面的
+ // 岸格,且避开路网/桥面/民居/核心区,保证不遮挡通行。
+ let mutable decorations: RiverDecoration list = []
+ if p.RiverDecorations then
+ let mutable decorRng = p.Seed ^^^ 0xD3C0DEUL
+ let nextDecor () =
+ let nextState, raw = splitmix decorRng
+ decorRng <- nextState
+ raw
+ let bridgeLookup = System.Collections.Generic.HashSet<int>(bridges |> List.map (fun (x, y) -> idx x y))
+ let inBuildingFootprint x y =
+ buildings
+ |> List.exists (fun b ->
+ x >= b.Left - 1 && x <= b.Left + b.Width && y >= b.Top && y <= b.DoorY + 1)
+ let blocked x y =
+ not (inMap x y)
+ || tiles.[idx x y] = int GroundTile.Water
+ || pathSet.Contains(idx x y)
+ || bridgeLookup.Contains(idx x y)
+ || inCore x y
+ || inBuildingFootprint x y
+ let occupies (kind: RiverDecorationKind) (y: int) =
+ if kind = Willow then [ y; y + 1 ] else [ y ]
+ let tooClose (kind: RiverDecorationKind) x y =
+ decorations
+ |> List.exists (fun d ->
+ let dyList = occupies d.Kind d.Y
+ occupies kind y
+ |> List.exists (fun cy ->
+ dyList
+ |> List.exists (fun oy ->
+ let dx = d.X - x
+ let dy = oy - cy
+ dx * dx + dy * dy < 9)))
+ let tryPlace (kind: RiverDecorationKind) x y =
+ let tilesFree =
+ if kind = Willow then not (blocked x y) && not (blocked x (y + 1))
+ else not (blocked x y)
+ if tilesFree && not (tooClose kind x y) then
+ decorations <- { Kind = kind; X = x; Y = y } :: decorations
+ let kindOf (roll: uint64) =
+ match int (roll % 3UL) with
+ | 1 -> Reeds
+ | 2 -> Willow
+ | _ -> RevetmentStone
+ for river in riverBands do
+ for x in 2 .. w - 3 do
+ let lowerRoll = nextDecor ()
+ if lowerRoll % 3UL <> 0UL then
+ tryPlace (kindOf lowerRoll) x (river.CenterY + river.Width)
+ if nextDecor () % 4UL = 0UL then
+ let upperRoll = nextDecor ()
+ let kind = kindOf upperRoll
+ let anchorY = if kind = Willow then river.CenterY - 2 else river.CenterY - 1
+ tryPlace kind x anchorY
+
// 6) 30 个 spawn:核心区内的规则网格。
let sc = max 2 p.SpawnColumns
let sr = max 2 p.SpawnRows
@@ -385,6 +459,7 @@ module MapGen =
Bridges = bridges
Paths = paths
Buildings = buildings
+ Decorations = decorations
ReachableTiles = reachableTiles
ReachabilityOk = spawnsOk && doorsOk && bridgesOk
BridgeCrossingsOk = crossingsOk }
@@ -414,6 +489,16 @@ module MapGen =
.Append(building.Width).Append(':').Append(building.Height).Append(':')
.Append(building.DoorX).Append(':').Append(building.DoorY).Append(';')
|> ignore
+ builder.Append('|') |> ignore
+ let decorCode = function
+ | RevetmentStone -> 0
+ | Reeds -> 1
+ | Willow -> 2
+ for decoration in map.Decorations do
+ builder
+ .Append(decorCode decoration.Kind).Append(':')
+ .Append(decoration.X).Append(':').Append(decoration.Y).Append(';')
+ |> ignore
builder.ToString()
/// 可行走判定:非水,或位于桥面上(桥面仍标记为水但可通行)。