1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
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 件家具。
[<TestClass>]
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
[<TestMethod>]
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)
[<TestMethod>]
member _.BridgeAbutmentsFlankTheSingleSampleBridge () =
let plan = samplePlan ()
let abutments = VillageArt.sampleBridgeAbutmentTiles plan
Assert.AreEqual<int>(4, abutments.Length)
Assert.AreEqual<int>(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, "护岸石不得压在桥面上")
[<TestMethod>]
member _.InteriorLowerBandGainsFurniture () =
let plan = samplePlan ()
let kinds = plan.Interior.Elements |> List.map (fun element -> element.Kind)
Assert.AreEqual<int>(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 门。
[<TestMethod>]
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)
|