wip: Tunnel Network cave planner on Core caves (L134, route support still failing)

Seed + 21/47 legacy fields -> 30 compound rooms (72 primitives), 3 branches, destination chamber; mouths fixed;
8.67 deg max grade. Passage composer no longer skips native cave layers (incoming passage 21,425/21,425 open).
Open: route-support audit has 380 unsupported samples near the arrival mouth. Not for merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-31 11:42:04 +01:00
1 parent 0065ee68e6
commit 75c6ad251d
9 files changed
+1008 -47

No files matched your search

+265 -26
View File
@@ -1595,6 +1595,205 @@ namespace StandaloneStreamBenchmark
return passed;
}
inline bool AuditNativeTunnelNetworkField(const VoxelForgeCore::World& shape,
const VoxelForgeCore::ResolvedLayoutSnapshotV3& layout,
std::uint32_t voxelMicrometres)
{
using namespace VoxelForgeCore;
constexpr double Pi=3.14159265358979323846;
const double vm=std::max<std::uint32_t>(1,voxelMicrometres)/1.0e6;
const auto density=[&](double x,double y,double z)
{return static_cast<double>(shape.densityAt({x/vm,y/vm,z/vm}))*vm;};
const auto cave=std::find_if(layout.strates.begin(),layout.strates.end(),
[](const auto& s){return s.generatorKind=="TunnelNetwork"
&&IsNativeCaveFieldStratum(s)&&s.passageCapabilities.hasNativeCaveField;});
if(cave==layout.strates.end()||layout.cavernGraphVocabularyVersion!=1)
{std::printf("[TunnelNetworkCavernAudit] recipe=%s graph=%u status=FAIL\n",
cave==layout.strates.end()?"missing":"present",
layout.cavernGraphVocabularyVersion);return false;}
const ResolvedLayoutPassageV1* arrival=nullptr;
const ResolvedLayoutPassageV1* departure=nullptr;
for(const auto& passage:layout.passages)
{
if(passage.lowerStrateIndex==cave->strateIndex
&&passage.upperStrateIndex<cave->strateIndex)arrival=&passage;
if(passage.upperStrateIndex==cave->strateIndex
&&passage.lowerStrateIndex>cave->strateIndex)departure=&passage;
}
std::vector<const ResolvedCavernRoomV1*> rooms;
std::vector<const ResolvedCavernEdgeV1*> routeEdges;
for(const auto& room:layout.cavernRooms)
if(room.strateIndex==cave->strateIndex)rooms.push_back(&room);
for(const auto& edge:layout.cavernEdges)
if(edge.strateIndex==cave->strateIndex
&&edge.stableId.find("/route-edge-")!=std::string::npos)
routeEdges.push_back(&edge);
const auto routeIndex=[](const ResolvedCavernEdgeV1* edge)
{
const auto marker=edge->stableId.rfind("/route-edge-");
return marker==std::string::npos?std::uint64_t{0}
:static_cast<std::uint64_t>(std::stoull(edge->stableId.substr(marker+12)));
};
std::sort(routeEdges.begin(),routeEdges.end(),[&](const auto* a,const auto* b)
{return routeIndex(a)<routeIndex(b);});
std::unordered_map<std::string,std::size_t> compoundCounts;
std::unordered_map<std::string,double> compoundRadii;
double largestRoomRadius=0.0,largestOtherRoomRadius=0.0;
std::string largestRoomGroup;
for(const auto* room:rooms)
{
const auto marker=room->stableId.rfind("/primitive-");
const std::string group=marker==std::string::npos
?room->stableId:room->stableId.substr(0,marker);
++compoundCounts[group];
const double radius=std::max(room->halfExtentsMicrometres[0],
room->halfExtentsMicrometres[1])/1.0e6;
compoundRadii[group]=std::max(compoundRadii[group],radius);
if(radius>largestRoomRadius)
{largestRoomRadius=radius;largestRoomGroup=group;}
}
for(const auto& [group,radius]:compoundRadii)
if(group!=largestRoomGroup)
largestOtherRoomRadius=std::max(largestOtherRoomRadius,radius);
const bool compoundRooms=!compoundCounts.empty()
&&std::all_of(compoundCounts.begin(),compoundCounts.end(),
[](const auto& row){return row.second>=2&&row.second<=4;});
const bool destination=largestOtherRoomRadius>0.0
&&largestRoomRadius>largestOtherRoomRadius*1.10;
std::vector<const ResolvedLayoutAnchorV2*> routeAnchors;
for(const auto& anchor:cave->anchors)
if(anchor.kind=="route_point"&&anchor.values.size()>=3)
routeAnchors.push_back(&anchor);
double maximumGrade=0.0;
bool gradeOk=routeAnchors.size()>=2;
for(std::size_t i=1;i<routeAnchors.size();++i)
{
const auto& a=routeAnchors[i-1]->values;
const auto& b=routeAnchors[i]->values;
const double run=std::hypot(static_cast<double>(b[0]-a[0]),
static_cast<double>(b[1]-a[1]));
const double rise=std::abs(static_cast<double>(b[2]-a[2]));
if(run<=0.0){gradeOk=false;continue;}
const double grade=std::atan2(rise,run)*180.0/Pi;
maximumGrade=std::max(maximumGrade,grade);
gradeOk=gradeOk&&grade<=15.0+1.0e-6;
}
bool mouthBinding=arrival&&departure&&routeAnchors.size()>=2;
if(mouthBinding)
{
const auto qOffset=static_cast<std::int64_t>(std::llround(
250000.0*WorldAssemblySubvoxelsPerVoxel/layout.coreVoxelSizeMicrometres));
const auto& start=routeAnchors.front()->values;
const auto& end=routeAnchors.back()->values;
mouthBinding=start[0]==arrival->lowerMouthSubvoxels[0]
&&start[1]==arrival->lowerMouthSubvoxels[1]
&&start[2]==arrival->lowerMouthSubvoxels[2]+qOffset
&&end[0]==departure->upperMouthSubvoxels[0]
&&end[1]==departure->upperMouthSubvoxels[1]
&&end[2]==departure->upperMouthSubvoxels[2]+qOffset;
}
std::uint64_t airSamples=0,floorSamples=0,shellSamples=0;
bool centerAir=true,floorSolid=true,shellSolid=true;
for(const auto* edge:routeEdges)
{
const auto& p=edge->controlPointsMicrometres;
const double x=(p[0][0]+3.0*p[1][0]+3.0*p[2][0]+p[3][0])/8.0e6;
const double y=(p[0][1]+3.0*p[1][1]+3.0*p[2][1]+p[3][1])/8.0e6;
const double floor=(p[0][2]+3.0*p[1][2]+3.0*p[2][2]+p[3][2])/8.0e6;
const double bore=edge->boreRadiusMicrometres/1.0e6;
if(density(x,y,floor+1.0)<=0.0)centerAir=false;
++airSamples;
if(density(x,y,floor-0.10)>=0.0)floorSolid=false;
++floorSamples;
const double dx=(p[3][0]-p[0][0])/1.0e6;
const double dy=(p[3][1]-p[0][1])/1.0e6;
const double length=std::hypot(dx,dy);
if(length<=1.0e-6){shellSolid=false;continue;}
const double nx=-dy/length,ny=dx/length;
if(density(x+nx*(bore+0.90),y+ny*(bore+0.90),floor+2.0)>=0.0
||density(x-nx*(bore+0.90),y-ny*(bore+0.90),floor+2.0)>=0.0)
shellSolid=false;
shellSamples+=2;
}
const ResolvedCavernEdgeV1* rippleEdge=nullptr;
double longest=0.0;
for(const auto* edge:routeEdges)
{
const auto& p=edge->controlPointsMicrometres;
const double length=std::hypot(static_cast<double>(p[3][0]-p[0][0]),
static_cast<double>(p[3][1]-p[0][1]));
if(length>longest){longest=length;rippleEdge=edge;}
}
std::vector<double> rippleRadii;
if(rippleEdge)
{
const auto& p=rippleEdge->controlPointsMicrometres;
const double radius=rippleEdge->boreRadiusMicrometres/1.0e6;
constexpr std::array<double,7> stations{{0.18,0.29,0.40,0.51,0.62,0.73,0.84}};
for(double t:stations)
{
const auto bezier=[&](double u,std::size_t axis)
{
const double one=1.0-u;
return (one*one*one*p[0][axis]+3.0*one*one*u*p[1][axis]
+3.0*one*u*u*p[2][axis]+u*u*u*p[3][axis])/1.0e6;
};
const double x=bezier(t,0),y=bezier(t,1),floor=bezier(t,2);
const double tx=bezier(std::min(1.0,t+0.01),0)
-bezier(std::max(0.0,t-0.01),0);
const double ty=bezier(std::min(1.0,t+0.01),1)
-bezier(std::max(0.0,t-0.01),1);
const double tangent=std::hypot(tx,ty);
if(tangent<=1.0e-6)continue;
for(const double side:{-1.0,1.0})
{
double prior=0.20;
double priorDensity=density(x,y,floor+2.0);
bool found=false;
for(double radial=0.25;radial<=radius+1.8;radial+=0.05)
{
const double sampleX=x-side*ty/tangent*radial;
const double sampleY=y+side*tx/tangent*radial;
const double value=density(sampleX,sampleY,floor+2.0);
if(priorDensity>=0.0&&value<0.0)
{
const double fraction=priorDensity/(priorDensity-value);
rippleRadii.push_back(prior+(radial-prior)*fraction);
found=true;break;
}
prior=radial;priorDensity=value;
}
if(!found)continue;
}
}
}
double ripplePeakToPeak=0.0;
if(!rippleRadii.empty())
{
const auto limits=std::minmax_element(rippleRadii.begin(),rippleRadii.end());
ripplePeakToPeak=*limits.second-*limits.first;
}
const bool ripple=rippleRadii.size()>=8&&ripplePeakToPeak>=0.02
&&ripplePeakToPeak<=1.25;
std::printf("[TunnelNetworkCavernAudit] strate=%d recipe=%s rooms=%zu compound_groups=%zu destination_radius_m=%.3f route_edges=%zu route_points=%zu mouth_binding=%s max_grade_deg=%.3f grade_ok=%s center_air=%llu/%llu floor_solid=%llu/%llu shell_solid=%llu/%llu ripple_samples=%zu ripple_peak_to_peak_m=%.4f status=%s\n",
cave->strateIndex,cave->recipeId.c_str(),rooms.size(),compoundCounts.size(),
largestRoomRadius,routeEdges.size(),routeAnchors.size(),mouthBinding?"PASS":"FAIL",
maximumGrade,gradeOk?"PASS":"FAIL",
static_cast<unsigned long long>(airSamples),static_cast<unsigned long long>(airSamples),
static_cast<unsigned long long>(floorSamples),static_cast<unsigned long long>(floorSamples),
static_cast<unsigned long long>(shellSamples),static_cast<unsigned long long>(shellSamples),
rippleRadii.size(),ripplePeakToPeak,
arrival&&departure&&routeEdges.size()>=2&&!rooms.empty()&&compoundRooms
&&destination&&mouthBinding&&gradeOk&&centerAir&&floorSolid&&shellSolid
&&ripple?"PASS":"FAIL");
return arrival&&departure&&routeEdges.size()>=2&&!rooms.empty()&&compoundRooms
&&destination&&mouthBinding&&gradeOk&&centerAir&&floorSolid&&shellSolid&&ripple;
}
inline bool AuditNativeCavesField(const VoxelForgeCore::World& shape,
const VoxelForgeCore::ResolvedLayoutSnapshotV3& layout,std::uint32_t voxelMicrometres)
{
@@ -1605,9 +1804,13 @@ namespace StandaloneStreamBenchmark
const auto density=[&](double x,double y,double z)
{return static_cast<double>(shape.densityAt({x/vm,y/vm,z/vm}))*vm;};
const auto cave=std::find_if(layout.strates.begin(),layout.strates.end(),
[](const auto& s){return s.generatorKind=="Caves"
&&s.recipeId=="Core.Caves.PrimitiveField"&&s.recipeVersion==1
[](const auto& s){return IsNativeCaveFieldStratum(s)
&&s.passageCapabilities.hasNativeCaveField;});
if(cave!=layout.strates.end()&&cave->generatorKind=="TunnelNetwork")
return AuditNativeTunnelNetworkField(shape,layout,voxelMicrometres);
if(cave==layout.strates.end()||cave->generatorKind!="Caves")
{std::printf("[CavesAudit] recipe=missing rooms=%zu edges=%zu status=FAIL\n",
layout.cavernRooms.size(),layout.cavernEdges.size());return false;}
if(cave==layout.strates.end()||layout.cavernRooms.size()!=1||layout.cavernEdges.size()!=2)
{std::printf("[CavesAudit] recipe=%s rooms=%zu edges=%zu status=FAIL\n",
cave==layout.strates.end()?"missing":"present",layout.cavernRooms.size(),layout.cavernEdges.size());return false;}
@@ -4796,6 +4999,7 @@ namespace StandaloneStreamBenchmark
}
}
std::uint64_t routePoints=0,routePasses=0,routeWalkPasses=0,routeBindings=0,routeBindingFailures=0;
std::uint64_t tunnelNetworkRoutes=0,tunnelNetworkBlockedControls=0;
for(const auto& stratum:ResolvedLayout->strates)
{
std::vector<const VoxelForgeCore::ResolvedLayoutAnchorV2*> anchors;
@@ -4859,36 +5063,56 @@ namespace StandaloneStreamBenchmark
supportStepMetres,supportMaximumMetres,minimumSupportProbes,
supportProbeRadiusMetres);
bool binding=true;
const auto equalPosition=[](const auto& a,const auto& b)
{return a[0]==b[0]&&a[1]==b[1]&&a[2]==b[2];};
const auto boundMouthMatches=[&](const auto& authored,const auto& mouth)
{
if(stratum.generatorKind!="TunnelNetwork")
return equalPosition(authored,mouth);
auto expected=mouth;
expected[2]+=static_cast<std::int64_t>(std::llround(
250000.0*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel
/World.CoreVoxelSizeMicrons));
return equalPosition(authored,expected);
};
for(const auto& passage:ResolvedLayout->passages)
{
const auto equalPosition=[](const auto& a,const auto& b)
{return a[0]==b[0]&&a[1]==b[1]&&a[2]==b[2];};
if(passage.upperStrateIndex==stratum.strateIndex)
{
const auto rootedMouth=std::find_if(stratum.anchors.begin(),
stratum.anchors.end(),[](const auto& anchor)
{return anchor.kind=="passage_anchor"&&anchor.values.size()>=10;});
const std::array<std::int64_t,3> departure=
rootedMouth!=stratum.anchors.end()
?std::array<std::int64_t,3>{{rootedMouth->values[7],
rootedMouth->values[8],rootedMouth->values[9]}}
:std::array<std::int64_t,3>{{anchors.back()->values[0],
anchors.back()->values[1],anchors.back()->values[2]}};
binding&=equalPosition(passage.upperMouthSubvoxels,
departure);
if(stratum.generatorKind=="TunnelNetwork")
binding&=boundMouthMatches(anchors.back()->values,
passage.upperMouthSubvoxels);
else
{
const auto rootedMouth=std::find_if(stratum.anchors.begin(),
stratum.anchors.end(),[](const auto& anchor)
{return anchor.kind=="passage_anchor"&&anchor.values.size()>=10;});
const std::array<std::int64_t,3> departure=
rootedMouth!=stratum.anchors.end()
?std::array<std::int64_t,3>{{rootedMouth->values[7],
rootedMouth->values[8],rootedMouth->values[9]}}
:std::array<std::int64_t,3>{{anchors.back()->values[0],
anchors.back()->values[1],anchors.back()->values[2]}};
binding&=equalPosition(passage.upperMouthSubvoxels,departure);
}
}
if(passage.lowerStrateIndex==stratum.strateIndex)
{
const auto passageArrival=std::find_if(stratum.anchors.begin(),
stratum.anchors.end(),[](const auto& anchor)
{return anchor.kind=="passage_arrival"&&anchor.values.size()>=3;});
const std::array<std::int64_t,3> arrival=passageArrival!=stratum.anchors.end()
?std::array<std::int64_t,3>{{passageArrival->values[0],
passageArrival->values[1],passageArrival->values[2]}}
:std::array<std::int64_t,3>{{anchors.front()->values[0],
anchors.front()->values[1],anchors.front()->values[2]}};
binding&=equalPosition(passage.lowerMouthSubvoxels,
arrival);
if(stratum.generatorKind=="TunnelNetwork")
binding&=boundMouthMatches(anchors.front()->values,
passage.lowerMouthSubvoxels);
else
{
const auto passageArrival=std::find_if(stratum.anchors.begin(),
stratum.anchors.end(),[](const auto& anchor)
{return anchor.kind=="passage_arrival"&&anchor.values.size()>=3;});
const std::array<std::int64_t,3> arrival=passageArrival!=stratum.anchors.end()
?std::array<std::int64_t,3>{{passageArrival->values[0],
passageArrival->values[1],passageArrival->values[2]}}
:std::array<std::int64_t,3>{{anchors.front()->values[0],
anchors.front()->values[1],anchors.front()->values[2]}};
binding&=equalPosition(passage.lowerMouthSubvoxels,arrival);
}
}
}
++routePasses;routeWalkPasses+=routeAudit.passed;
@@ -4918,6 +5142,18 @@ namespace StandaloneStreamBenchmark
stratum.strateIndex,routeAudit.firstUnsupported[i][0],
routeAudit.firstUnsupported[i][1],routeAudit.firstUnsupported[i][2],
routeAudit.firstUnsupported[i][3]);
if(stratum.generatorKind=="TunnelNetwork")
{
++tunnelNetworkRoutes;
const FWalkAudit control=auditPlayerPath(blockedWorld,route,
supportStartMetres,supportStepMetres,supportMaximumMetres,
minimumSupportProbes,supportProbeRadiusMetres);
const bool detected=control.blocked>0&&!control.passed;
tunnelNetworkBlockedControls+=detected;
std::printf("[TunnelNetworkBlockedRouteControl] strate=%d arrival_to_departure=true blocked_capsule_samples=%llu result=%s expected=FAIL status=%s\n",
stratum.strateIndex,static_cast<unsigned long long>(control.blocked),
control.passed?"PASS":"FAIL",detected?"PASS":"FAIL");
}
}
for(std::size_t passageIndex=0;
passageIndex<ResolvedLayout->passages.size();++passageIndex)
@@ -4984,13 +5220,16 @@ namespace StandaloneStreamBenchmark
&&shellAuditPassed
&&routePasses>0&&routePasses==routeWalkPasses&&routePasses==routeBindings
&&routeBindingFailures==0
&&tunnelNetworkRoutes==tunnelNetworkBlockedControls
&&blockedCompiled&&blockedControls==passageCount;
std::printf("[ResolvedPassageAuditSummary] interfaces=%llu passed=%llu natural=%llu/%llu strate_routes=%llu route_walkable=%llu route_points=%llu route_bindings=%llu route_binding_failures=%llu blocked_controls=%llu/%llu status=%s\n",
std::printf("[ResolvedPassageAuditSummary] interfaces=%llu passed=%llu natural=%llu/%llu strate_routes=%llu route_walkable=%llu route_points=%llu route_bindings=%llu route_binding_failures=%llu tunnel_network_block_controls=%llu/%llu blocked_controls=%llu/%llu status=%s\n",
static_cast<unsigned long long>(passageCount),static_cast<unsigned long long>(passagePasses),
static_cast<unsigned long long>(naturalPasses),static_cast<unsigned long long>(passageCount),
static_cast<unsigned long long>(routePasses),static_cast<unsigned long long>(routeWalkPasses),
static_cast<unsigned long long>(routePoints),
static_cast<unsigned long long>(routeBindings),static_cast<unsigned long long>(routeBindingFailures),
static_cast<unsigned long long>(tunnelNetworkBlockedControls),
static_cast<unsigned long long>(tunnelNetworkRoutes),
static_cast<unsigned long long>(blockedControls),static_cast<unsigned long long>(passageCount),
auditPassed?"PASS":"FAIL");
if(!auditPassed)