namespace LivingVillage.Desktop.Tests open Microsoft.VisualStudio.TestTools.UnitTesting open LivingVillage.Kernel open LivingVillage.Kernel.Sim open LivingVillage.Desktop open LivingVillage.Desktop.VillagePresentation /// P64(A3 成熟度):样板区三处视觉缺口的可复现约束。 /// 1. 俯瞰上半部(local y 0..6)不再是空场:足量中密度补种且种类多样。 /// 2. 桥在既有位置加可读性细节:4 块护岸石分列桥两侧水线。 /// 3. 内景下半部补入椅/凳/床尾凳/壶 4 件家具。 [] type P64EvidenceTests () = let samplePlan () = VillageArt.sampleRenderPlan () let rectsOverlap (a: Microsoft.Xna.Framework.Rectangle) (b: Microsoft.Xna.Framework.Rectangle) = a.X < b.X + b.Width && b.X < a.X + a.Width && a.Y < b.Y + b.Height && b.Y < a.Y + a.Height [] member _.OverviewUpperBandIsDenselyPopulated () = let plan = samplePlan () let upper = plan.Props |> List.filter (fun prop -> prop.Kind <> VillageArt.House && prop.Position.Y >= 0 && prop.Position.Y <= 6) let kinds = upper |> List.map (fun prop -> prop.Kind) |> List.distinct Assert.IsTrue(upper.Length >= 8, sprintf "上半部补种不足:%d" upper.Length) Assert.IsTrue(kinds.Length >= 4, sprintf "上半部地物种类不足:%A" kinds) for kind in [ VillageArt.VegetablePatch; VillageArt.BambooGrove; VillageArt.ShrubPatch; VillageArt.FlowerBush ] do Assert.IsTrue(kinds |> List.contains kind, sprintf "上半部缺少 %A" kind) // 北侧田埂小径贯通 x0..19。 for x in 0 .. 19 do Assert.IsTrue( plan.Grounds |> List.contains ({ X = x; Y = 0 }, VillageArt.StonePath), sprintf "北侧小径缺格 (%d,0)" x) [] member _.BridgeAbutmentsFlankTheSingleSampleBridge () = let plan = samplePlan () let abutments = VillageArt.sampleBridgeAbutmentTiles plan Assert.AreEqual(4, abutments.Length) Assert.AreEqual(4, (abutments |> List.distinct |> List.length)) let bridgeTiles = plan.Props |> List.filter (fun prop -> prop.Kind = VillageArt.Bridge) |> List.collect (fun prop -> [ for dy in 0 .. 2 -> ({ X = prop.Position.X; Y = prop.Position.Y + dy } : TilePosition) ]) |> List.map (VillageArt.worldTile plan) for tile in abutments do Assert.IsFalse(bridgeTiles |> List.contains tile, "护岸石不得压在桥面上") [] member _.InteriorLowerBandGainsFurniture () = let plan = samplePlan () let kinds = plan.Interior.Elements |> List.map (fun element -> element.Kind) Assert.AreEqual(8, plan.Interior.Elements.Length) for kind in [ VillageArt.Chair; VillageArt.Stool; VillageArt.BedFoot; VillageArt.Teapot ] do Assert.IsTrue(kinds |> List.contains kind, sprintf "内景缺少 %A" kind) /// P64 整改:家具分布全屋四角、两两不重叠、不压中央通道。red→green 门。 [] member _.InteriorFurnitureIsSpreadAcrossRoomAndNonOverlapping () = let plan = samplePlan () let layout = VillageArt.interiorLayout 1280 720 let placed = plan.Interior.Elements |> List.map (fun element -> element.Kind, VillageArt.interiorElementScreenRect layout element) for i in 0 .. placed.Length - 2 do for j in i + 1 .. placed.Length - 1 do let (kindA, a) = placed.[i] let (kindB, b) = placed.[j] Assert.IsFalse(rectsOverlap a b, sprintf "内景家具 %A 与 %A 重叠" kindA kindB) let midX = layout.RoomX + layout.RoomWidth / 2 let midY = layout.RoomY + layout.RoomHeight / 2 let quadrant (r: Microsoft.Xna.Framework.Rectangle) = (r.X + r.Width / 2 < midX, r.Y + r.Height / 2 < midY) let quads = placed |> List.map (fun (_, r) -> quadrant r) |> List.distinct Assert.IsTrue(quads.Length >= 4, "家具须分布在四个象限(四角/沿墙)") // 中央通道(房间中心点)不得被家具矩形覆盖。 for kind, r in placed do let coversCenter = r.X <= midX && midX < r.X + r.Width && r.Y <= midY && midY < r.Y + r.Height Assert.IsFalse(coversCenter, sprintf "%A 压住中央通道" kind)