wip(L25, side branch): FI helix enclosed in a 13 m rock root; support never created in open air

Fixes the L24 ribbon (owner request). NOT merged: the open-air support gate leaves ~4,000 unsupported
samples on every SurfaceWorld-recipe passage style (TN -> SW), a walkability regression. L26 fixes that
on this branch. See Linux25/REPORT.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-21 00:38:57 +02:00
1 parent cb9236c265
commit ef789aaa00
14 files changed
+662 -110

No files matched your search

+42 -9
View File
@@ -550,6 +550,14 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
const auto routeAnchor=[](const ResolvedLayoutStratumV2& s,bool departure,
std::array<std::int64_t,3>& out)
{
if(departure)
for(const auto& a:s.anchors)
if(a.kind=="passage_anchor"&&a.values.size()>=10)
{out={a.values[7],a.values[8],a.values[9]};return true;}
if(!departure)
for(const auto& a:s.anchors)
if(a.kind=="passage_arrival"&&a.values.size()>=3)
{out={a.values[0],a.values[1],a.values[2]};return true;}
const ResolvedLayoutAnchorV2* selected=nullptr;
for(const auto& a:s.anchors)
if(a.kind=="route_point"&&a.values.size()>=3)
@@ -597,8 +605,9 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
// Leave room for the capsule and bounded wall relief at the floor/wall seam.
const std::int64_t mouthRadius=std::max<std::int64_t>(static_cast<std::int64_t>(std::llround(1.5*qPerMetre)),
cfg?cfg->mouthRadiusSubvoxels:0);
const std::int64_t midRadius=std::max<std::int64_t>(mouthRadius,
cfg?cfg->midRadiusSubvoxels:0);
const std::int64_t midRadius=std::max<std::int64_t>(
static_cast<std::int64_t>(std::llround(1.5*qPerMetre)),
cfg?cfg->midRadiusSubvoxels:mouthRadius);
const std::int64_t reachMinimum=cfg?std::max<std::int64_t>(0,cfg->reachMinimumSubvoxels):8*qPerMetre;
const std::int64_t reachMaximum=cfg?std::max<std::int64_t>(reachMinimum,cfg->reachMaximumSubvoxels):24*qPerMetre;
const std::uint32_t style=cfg?std::min<std::uint32_t>(cfg->style,3u):1u;
@@ -624,7 +633,9 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
for(const auto& anchor:upper.anchors)
if(anchor.kind=="passage_anchor"&&anchor.values.size()>=7)
{passageAnchor=&anchor;break;}
const bool anchoredSpiral=style==2&&passageAnchor!=nullptr;
const bool anchoredIslandPassage=passageAnchor!=nullptr
&&upper.generatorKind=="FloatingIslands";
const bool anchoredSpiral=style==2&&anchoredIslandPassage;
if(!hasUpperRoute||!hasLowerRoute)
{
const auto xy=PassageRandomXY(PassageSeed(seed,upper.strateIndex,lower.strateIndex,
@@ -652,7 +663,10 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
std::array<std::int64_t,2> upperTangent{},lowerTangent{};
const bool hasUpperTangent=hasUpperRoute
&&routeTangent(upper,true,upperTangent);
const bool hasLowerTangent=hasLowerRoute
const bool hasPassageArrival=std::any_of(lower.anchors.begin(),lower.anchors.end(),
[](const auto& anchor){return anchor.kind=="passage_arrival"
&&anchor.values.size()>=3;});
const bool hasLowerTangent=hasLowerRoute&&!hasPassageArrival
&&routeTangent(lower,false,lowerTangent);
const std::int64_t outerRingRadius=std::max<std::int64_t>(1,
@@ -671,6 +685,8 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
std::max<std::int64_t>(0,cfg?cfg->cascadeLedgeSubvoxels:0)
*static_cast<std::int64_t>(cfg?cfg->cascadeSteps:4)),
mouthRadius+2*qPerMetre,outerRingRadius);
if(anchoredIslandPassage)
ringRadius=std::min(ringRadius,mouthRadius+qPerMetre/2);
std::uint32_t phase=static_cast<std::uint32_t>(PassageSeed(seed,
upper.strateIndex,lower.strateIndex,connection,0x50484153u)%16);
if(hasUpperRoute)
@@ -700,7 +716,7 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
+clockwiseTangentY*upperTangent[1]>=0.0;
}
const int direction=clockwise?1:-1;
constexpr std::int64_t TargetGradeQ16=12500; // leave margin below the 15-degree contract.
constexpr std::int64_t TargetGradeQ16=12500; // leave margin below the 15-degree helix contract.
const std::int64_t wormRadialWobble=std::min<std::int64_t>(
std::max<std::int64_t>(0,wander/3),2*qPerMetre);
const std::int64_t wormCenterWobble=std::min<std::int64_t>(
@@ -716,10 +732,14 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
const double loop=static_cast<double>(loopIndex);
const double phaseA=loop*0.6180339887498948+0.37;
const double phaseB=loop*0.4142135623730950+1.11;
const double jitterX=static_cast<double>(wormCenterWobble)*std::sin(phaseB);
const double jitterY=static_cast<double>(wormCenterWobble)*std::cos(phaseB);
radius+=static_cast<double>(wormRadialWobble)
*std::sin(angle+phaseA);
centerX=static_cast<double>(wormCenterWobble)*std::sin(phaseB);
centerY=static_cast<double>(wormCenterWobble)*std::cos(phaseB);
centerX=jitterX+(anchoredIslandPassage&&passageAnchor
?static_cast<double>(passageAnchor->values[0]):0.0);
centerY=jitterY+(anchoredIslandPassage&&passageAnchor
?static_cast<double>(passageAnchor->values[1]):0.0);
}
else if(pathStyle==3u)
{
@@ -730,6 +750,11 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
cfg->cascadeLedgeSubvoxels):0));
radius-=ledge*(0.5-0.5*std::cos(angle*steps));
}
if(pathStyle!=1u&&anchoredIslandPassage&&passageAnchor)
{
centerX=static_cast<double>(passageAnchor->values[0]);
centerY=static_cast<double>(passageAnchor->values[1]);
}
return std::array<std::int64_t,2>{
static_cast<std::int64_t>(std::llround(centerX+radius*directions[directionIndex][0]/65536.0)),
static_cast<std::int64_t>(std::llround(centerY+radius*directions[directionIndex][1]/65536.0))};
@@ -748,7 +773,11 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
const std::int64_t anchorY=passageAnchor->values[1];
const std::int64_t rootRadius=passageAnchor->values[2];
const std::int64_t rootBottom=passageAnchor->values[5];
helixBedrockZ=rootBottom!=0?rootBottom:contentZQ(upper.bedrock.topMicrometres);
const std::int64_t bedrockTop=rootBottom!=0?rootBottom
:contentZQ(upper.bedrock.topMicrometres);
// Passage route heights are player-center positions. End one capsule
// half-height above the bedrock top so the final ramp step is walkable.
helixBedrockZ=bedrockTop+qPerMetre;
const std::int64_t helixRadius=spiralRadius;
if(rootRadius<helixRadius+midRadius+qPerMetre/4
||std::hypot(static_cast<double>(upperMouth[0]-anchorX),
@@ -796,6 +825,8 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
helixEndIndex=xy.size()-1;
hasAnchorHelix=helixEndIndex>0;
}
const std::int64_t routeGradeQ16=hasAnchorHelix
&&lower.generatorKind=="SurfaceWorld"?8000:TargetGradeQ16;
const std::array<std::int64_t,2> firstRing=ringPoint(phase);
if(hasAnchorHelix&&pathStyle==1u)
{
@@ -843,12 +874,14 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
const std::size_t start=hasAnchorHelix?helixEndIndex:0;
for(std::size_t i=start+1;i<xy.size();++i)
total+=distanceQ(xy[i][0]-xy[i-1][0],xy[i][1]-xy[i-1][1]);
if(!hasLowerTangent&&!xy.empty())
total+=distanceQ(lowerMouth[0]-xy.back()[0],lowerMouth[1]-xy.back()[1]);
return total;
};
while(loops<256)
{
totalHorizontal=measurePath();
if(totalHorizontal*static_cast<std::uint64_t>(TargetGradeQ16)
if(totalHorizontal*static_cast<std::uint64_t>(routeGradeQ16)
>=static_cast<std::uint64_t>(verticalDistance)*65536ull)break;
for(int step=1;step<=16;++step)
{