fix(content): lay the Vigilant hull along la Saignee within the distance budget

The target hull now lies along the groove axis (yaw derived from the
groove constants), set back 22 m from the groove end so both hull ends
rest on the flat groove floor. The mooring, spawn and first route
waypoints move to z = -210 and the decoy yacht to (-30, -150) so no
wreck is farther than 320 m from the mooring and no two wrecks are
farther than 260 m apart (spec 4.1). The spawn faces south toward the
site. Four contract assertions pin the budget, the spawn heading and
the hull orientation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
OlivierandClaude Opus 5.5 committed 2026-10-06 20:49:28 +02:00
1 parent 5344b045d9
commit be16d2ee07
4 files changed
+63 -19

No files matched your search

+36 -1
View File
@@ -15,7 +15,11 @@ const DiveRulesResolver = preload("res://game/domain/rules/dive_rules_resolver.g
const SITE_PATH := "res://content/sites/zone1_vigilant.tres"
const ROUTE_CLEARANCE_M := 3.0
const MINIMUM_LANDMARK_SPACING_M := 60.0
const TEST_COUNT := 30
const MAXIMUM_ANCHOR_TO_WRECK_M := 320.0
const MAXIMUM_WRECK_SPACING_M := 260.0
const HULL_HALF_LENGTH_M := 14.0
const HULL_SEABED_TOLERANCE_M := 2.0
const TEST_COUNT := 34
var _failures: Array[String] = []
@@ -107,6 +111,26 @@ func _test_zone1_content() -> void:
spaced = false
_expect(spaced, "landmarks are at least 60 m apart")
var wrecks := targets + decoys
if anchors.size() == 1:
var anchor := anchors[0].position_m
var farthest := 0.0
for wreck: SitePlacement in wrecks:
farthest = maxf(farthest, _xz_distance(anchor, wreck.position_m))
_expect(farthest <= MAXIMUM_ANCHOR_TO_WRECK_M, "every wreck lies within 320 m of the mooring (farthest %.0f m)" % farthest)
var widest := 0.0
for i in wrecks.size():
for j in range(i + 1, wrecks.size()):
widest = maxf(widest, _xz_distance(wrecks[i].position_m, wrecks[j].position_m))
_expect(widest <= MAXIMUM_WRECK_SPACING_M, "every pair of wrecks lies within 260 m (widest %.0f m)" % widest)
if targets.size() == 1:
var target_xz := Vector2(targets[0].position_m.x, targets[0].position_m.z)
var spawn_xz := Vector2(spawn.x, spawn.z)
var yaw := definition.spawn_yaw_radians
var spawn_forward := Vector2(-sin(yaw), -cos(yaw))
_expect(spawn_forward.dot(target_xz - spawn_xz) > 0.0, "the spawn faces the target wreck")
_expect(_hull_lies_along_seabed(field, targets[0]), "the target hull lies along the groove floor")
func _rests_on_terrain(field: TerrainHeightField, placement: SitePlacement) -> bool:
var seabed := field.elevation_at(placement.position_m.x, placement.position_m.z)
@@ -114,6 +138,17 @@ func _rests_on_terrain(field: TerrainHeightField, placement: SitePlacement) -> b
return bottom >= seabed - placement.footprint_m.y and bottom <= seabed + 1.0
func _hull_lies_along_seabed(field: TerrainHeightField, hull: SitePlacement) -> bool:
var centre := Vector2(hull.position_m.x, hull.position_m.z)
var long_axis := Vector2(cos(hull.yaw_radians), -sin(hull.yaw_radians))
var centre_seabed := field.elevation_at(centre.x, centre.y)
for side: float in [-1.0, 1.0]:
var end := centre + long_axis * HULL_HALF_LENGTH_M * side
if absf(field.elevation_at(end.x, end.y) - centre_seabed) > HULL_SEABED_TOLERANCE_M:
return false
return true
func _route_clears_terrain(field: TerrainHeightField, route: SiteRoute) -> bool:
for i in range(route.waypoints_m.size() - 1):
var a := route.waypoints_m[i]