feat(descent): landing ROOMS and a walkable tunnel -- per Jahni's correction
Jahni corrected the design: "the connection between level is a tiny tunnel
connecting both strate, not vertical, it needs to be walkable" and "'the
spine' shouldn't be carved except optionally from the top first strate,
then it's used to have a landing room".
COMPOSER-NOTES §6.8 had said the spine "provides a clean landing space, not
a continuous open shaft" -- and the implementation carved a vertical
cylinder anyway. A vertical cylinder has no walkable floor except at its
bottom, so a carve guaranteeing open AIR guaranteed nothing STANDABLE.
That one omission is behind five of my dead hypotheses this week.
Now:
origin spine a finite rounded ROOM per strate, no vertical bore.
radius 14 -> 8 m wide, 7.5 m tall
descent a walkable tunnel, single-file by design: 3 m mouth,
2.5 m waist, gradient capped at a NAMED 15 deg
exotic styles VerticalShaft / SpiralDescent / CascadingDrops /
CrackCrevice preserved, no longer the default
⚠️ THE GEOMETRY BITES, and it is worth Jahni's eye: at 15 deg a 32 m drop
needs 119.4 m of horizontal run -- about 59.7 m per switchback leg. That is
a long walk between strates. It is the honest consequence of "walkable",
not a tuning artifact, and the alternative is a steeper number.
⭐ AND THE ROOT CAUSE GOT NAMED A THIRD TIME, by Codex mid-run: "the round
tube was hollow air but had no authored support strip, so 'open' still did
not mean 'standable'." Tunnels now carry a floor band, and the root join
terminates in the finite origin room rather than an annular shaft hub.
Measured, commandlet sweep, 8 archetypes x 8 seeds, 64/64 valid:
origin column has player-fit cells 17/64 -> 63/64
origin column reachable 0/64 -> 7/64
arrival landing probes 315/320 fit AND in the arrival component
tunnel audit 5,916/5,916 floor and capsule samples pass; zero gradient,
floor, capsule, geometry or seal failures
narrow-gap events 0 box verdicts 14 checked, 0 violations
⚠️ arrival->departure is 6/64. The landings and tunnels are now provably
walkable; what remains is the INTRA-STRATE vertical connectivity problem
found in 6b91669 -- floors at different levels inside a strate with nothing
joining them. Separate and larger. Not tuned toward.
⚠️ PROCESS: this took 5.7 hours, of which Codex used 4 SECONDS of CPU. The
rest was polling the 73-minute automation suite at ~10% machine load. The
commandlet exists to avoid exactly that. New rule recorded: iterate with the
commandlet, full suite ONCE at the end.
Editor + Shipping builds clean. Automation 32/32, 0 failed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aheo2crrZmHuYtPpdY2Cb
This commit is contained in:
1 parent
6b916699af
commit
55bf807f60
19 files changed
+1996
-334
No files matched your search
@@ -1677,23 +1677,18 @@ namespace
|
||||
VF_ApplyOriginSpine(InOut.Density, X, Y, Z, TopZ, BotZ, Seal, Base, Radius);
|
||||
}
|
||||
|
||||
// Ne fait QUE de l'air ⇒ tue AllSolid, jamais AllAir. Identity quand le cercle XY rate la
|
||||
// boîte, ou quand la boîte est entièrement hors de l'intérieur de la strate.
|
||||
// ≡ le test cercle/boîte écrit à la main dans ClassifyTile aujourd'hui.
|
||||
// The room kills AllSolid; its support slab also kills AllAir. Identity when the room
|
||||
// misses the box or the box is wholly outside this strate's safe interior.
|
||||
EVoxelOpEffect EffectOverBox(const FBox& VoxelBox, const FVoxelOpContext&) const override
|
||||
{
|
||||
if (Radius <= 0.0f) { return EVoxelOpEffect::Identity; }
|
||||
|
||||
const float InnerTop = TopZ - Seal;
|
||||
const float InnerBot = BotZ + Seal;
|
||||
if (VoxelBox.Max.Z <= InnerBot || VoxelBox.Min.Z >= InnerTop) { return EVoxelOpEffect::Identity; }
|
||||
|
||||
const float Reach = Radius + VoxelDensityReach::SpineBlend;
|
||||
const float CX = FMath::Clamp(0.0f, (float)VoxelBox.Min.X, (float)VoxelBox.Max.X);
|
||||
const float CY = FMath::Clamp(0.0f, (float)VoxelBox.Min.Y, (float)VoxelBox.Max.Y);
|
||||
if (CX * CX + CY * CY > Reach * Reach) { return EVoxelOpEffect::Identity; }
|
||||
|
||||
return EVoxelOpEffect::CarveOnly;
|
||||
if (!VoxelPassageGeometry::OriginLandingRoomTouchesBox(
|
||||
VoxelBox, TopZ, BotZ, Seal, Radius))
|
||||
{
|
||||
return EVoxelOpEffect::Identity;
|
||||
}
|
||||
return VoxelPassageGeometry::OriginLandingFloorTouchesBox(
|
||||
VoxelBox, TopZ, BotZ, Seal, Radius)
|
||||
? EVoxelOpEffect::Both : EVoxelOpEffect::CarveOnly;
|
||||
}
|
||||
|
||||
const TCHAR* DebugName() const override { return TEXT("OriginSpineOp"); }
|
||||
@@ -1842,8 +1837,10 @@ namespace
|
||||
class FPassageCarveOp final : public IVoxelDensityOp
|
||||
{
|
||||
public:
|
||||
FPassageCarveOp(const UVoxelStrateManager* InManager, float InBase, float InSeal)
|
||||
: Manager(InManager), Base(InBase), Seal(InSeal) {}
|
||||
FPassageCarveOp(const UVoxelStrateManager* InManager, float InBase, float InSeal,
|
||||
float InTopZ, float InBotZ, float InSpineRadius)
|
||||
: Manager(InManager), Base(InBase), Seal(InSeal),
|
||||
TopZ(InTopZ), BotZ(InBotZ), SpineRadius(InSpineRadius) {}
|
||||
|
||||
EVoxelOpRole GetRole() const override { return EVoxelOpRole::StructuralPost; }
|
||||
EVoxelOpChannelMask ChannelReads() const override { return VoxelOpChannels::Density; }
|
||||
@@ -1853,8 +1850,15 @@ namespace
|
||||
|
||||
void Eval(float X, float Y, float Z, FVoxelOpSample& InOut) const override
|
||||
{
|
||||
if (!Manager) { return; }
|
||||
Manager->ApplyPassageModifier(InOut.Density, X, Y, Z, Base, Seal);
|
||||
if (Manager)
|
||||
{
|
||||
Manager->ApplyPassageModifier(InOut.Density, X, Y, Z, Base, Seal);
|
||||
}
|
||||
// Keep the source and op-stack operation order identical: the origin room is carved
|
||||
// before the boundary seal, then its support floor is reasserted after the passage
|
||||
// post so no connector can remove the standing surface.
|
||||
VF_ApplyOriginLandingFloor(
|
||||
InOut.Density, X, Y, Z, TopZ, BotZ, Seal, Base, SpineRadius);
|
||||
}
|
||||
|
||||
// ≡ la garde `AnyPassageNearBox` écrite à la main dans ClassifyTile — déjà écrite, ici
|
||||
@@ -1862,7 +1866,9 @@ namespace
|
||||
EVoxelOpEffect EffectOverBox(const FBox& VoxelBox, const FVoxelOpContext&) const override
|
||||
{
|
||||
if (!Manager) { return EVoxelOpEffect::Identity; }
|
||||
if (Manager->AnyPassageLandingFloorNearBox(VoxelBox.Min, VoxelBox.Max))
|
||||
if (VoxelPassageGeometry::OriginLandingFloorTouchesBox(
|
||||
VoxelBox, TopZ, BotZ, Seal, SpineRadius)
|
||||
|| Manager->AnyPassageLandingFloorNearBox(VoxelBox.Min, VoxelBox.Max))
|
||||
{
|
||||
// The room carves air, while its support slab force-writes solid. Both
|
||||
// hypotheses must therefore be killed for a box touching that slab.
|
||||
@@ -1876,7 +1882,7 @@ namespace
|
||||
|
||||
private:
|
||||
const UVoxelStrateManager* Manager;
|
||||
float Base, Seal;
|
||||
float Base, Seal, TopZ, BotZ, SpineRadius;
|
||||
};
|
||||
|
||||
//=========================================================================
|
||||
@@ -5218,7 +5224,8 @@ void FVoxelOpStack::AppendStructuralPost(float StrateTopWorldZ, float StrateBott
|
||||
// restent le dernier post de GetDensityAt, hors de cette pile, comme avant.
|
||||
Add(MakeUnique<FOriginSpineOp>(StrateTopWorldZ, StrateBottomWorldZ, SealThickness, BaseDensity, SpineRadius));
|
||||
Add(MakeUnique<FBoundarySealOp>(StrateTopWorldZ, StrateBottomWorldZ, SealThickness, BaseDensity));
|
||||
Add(MakeUnique<FPassageCarveOp>(StrateManager, BaseDensity, SealThickness));
|
||||
Add(MakeUnique<FPassageCarveOp>(StrateManager, BaseDensity, SealThickness,
|
||||
StrateTopWorldZ, StrateBottomWorldZ, SpineRadius));
|
||||
Add(MakeUnique<FXYEdgeSealOp>(BaseDensity));
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user