core: Tunnel Network cave planner with a continuous backbone floor (L134, evaluator v230)
Backbone rooms and edges share one floor profile h(s); side branches keep flat floors; overlap backing capped at the lower floor. Default seed: route audit 0 blocked / 0 unsupported / 0 grade over 51,975 capsule samples; passages open; fast tier, seams, Clang/GCC W1/W8/W12 green. Open: seed 1 (24 blocked at the 2-3 arrival mouth) and seed 2 (22 unsupported at passage 1-2) fail composed audits; near-ready +6..+14% on layers 1-3. 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:
1 parent
4a97023b24
commit
a3c8e3687d
23 files changed
+338
-53
No files matched your search
@@ -1607,7 +1607,10 @@ namespace StandaloneStreamBenchmark
|
||||
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)
|
||||
const bool supportedGraphVocabulary=
|
||||
layout.cavernGraphVocabularyVersion==ResolvedLayoutCavernGraphVocabularyVersionV1
|
||||
||layout.cavernGraphVocabularyVersion==ResolvedLayoutCavernGraphVocabularyVersionV2;
|
||||
if(cave==layout.strates.end()||!supportedGraphVocabulary)
|
||||
{std::printf("[TunnelNetworkCavernAudit] recipe=%s graph=%u status=FAIL\n",
|
||||
cave==layout.strates.end()?"missing":"present",
|
||||
layout.cavernGraphVocabularyVersion);return false;}
|
||||
@@ -2128,7 +2131,10 @@ namespace StandaloneStreamBenchmark
|
||||
const auto lattice=std::find_if(layout.strates.begin(),layout.strates.end(),
|
||||
[](const auto& s){return IsNativeLatticeFieldStratum(s)
|
||||
&&s.passageCapabilities.hasNativeLatticeField;});
|
||||
if(lattice==layout.strates.end()||layout.cavernGraphVocabularyVersion!=1)
|
||||
const bool supportedGraphVocabulary=
|
||||
layout.cavernGraphVocabularyVersion==ResolvedLayoutCavernGraphVocabularyVersionV1
|
||||
||layout.cavernGraphVocabularyVersion==ResolvedLayoutCavernGraphVocabularyVersionV2;
|
||||
if(lattice==layout.strates.end()||!supportedGraphVocabulary)
|
||||
{std::printf("[LatticeAudit] recipe=%s graph=%u status=FAIL\n",
|
||||
lattice==layout.strates.end()?"missing":"present",
|
||||
layout.cavernGraphVocabularyVersion);return false;}
|
||||
@@ -3178,13 +3184,16 @@ namespace StandaloneStreamBenchmark
|
||||
ResolvedLayout->strates.end(),[&](const auto& stratum)
|
||||
{return stratum.strateIndex==passage.upperStrateIndex;});
|
||||
if(upperStratum==ResolvedLayout->strates.end()
|
||||
||upperStratum->generatorKind!="FloatingIslands")
|
||||
||(upperStratum->generatorKind!="FloatingIslands"
|
||||
&&upperStratum->generatorKind!="TunnelNetwork"))
|
||||
return authoredMouthDepth;
|
||||
std::vector<std::array<double,3>> route;
|
||||
for(const auto& anchor:upperStratum->anchors)
|
||||
if(anchor.kind=="route_point"&&anchor.values.size()>=3)
|
||||
route.push_back({qToMetres(anchor.values[0]),
|
||||
qToMetres(anchor.values[1]),qToMetres(anchor.values[2])});
|
||||
if(upperStratum->generatorKind=="TunnelNetwork"&&route.size()>2)
|
||||
route.erase(route.begin(),route.end()-2);
|
||||
double routeHeight=0.0,distanceSquared=0.0;
|
||||
const double mouthX=qToMetres(passage.controlPoints.front().positionSubvoxels[0]);
|
||||
const double mouthY=qToMetres(passage.controlPoints.front().positionSubvoxels[1]);
|
||||
@@ -3219,6 +3228,55 @@ namespace StandaloneStreamBenchmark
|
||||
for(const auto& point:passage.controlPoints)
|
||||
profile.push_back(qToMetres(point.positionSubvoxels[2]
|
||||
-point.radiusSubvoxels));
|
||||
const auto controls=passageSplineControls(passage);
|
||||
const auto routeForStrate=[&](std::int32_t strateIndex)
|
||||
{
|
||||
std::vector<std::array<double,3>> route;
|
||||
const auto stratum=std::find_if(ResolvedLayout->strates.begin(),
|
||||
ResolvedLayout->strates.end(),[&](const auto& candidate)
|
||||
{return candidate.strateIndex==strateIndex;});
|
||||
if(stratum!=ResolvedLayout->strates.end()
|
||||
&&(stratum->generatorKind=="TunnelNetwork"
|
||||
||stratum->generatorKind=="FloatingIslands"))
|
||||
for(const auto& anchor:stratum->anchors)
|
||||
if(anchor.kind=="route_point"&&anchor.values.size()>=3)
|
||||
route.push_back({qToMetres(anchor.values[0]),
|
||||
qToMetres(anchor.values[1]),qToMetres(anchor.values[2])});
|
||||
return route;
|
||||
};
|
||||
const auto upper=std::find_if(ResolvedLayout->strates.begin(),
|
||||
ResolvedLayout->strates.end(),[&](const auto& stratum)
|
||||
{return stratum.strateIndex==passage.upperStrateIndex;});
|
||||
if(upper!=ResolvedLayout->strates.end()
|
||||
&&upper->generatorKind=="TunnelNetwork"&&!controls.empty())
|
||||
{
|
||||
auto route=routeForStrate(passage.upperStrateIndex);
|
||||
if(route.size()>2)route.erase(route.begin(),route.end()-2);
|
||||
double routeHeight=0.0,distanceSquared=0.0;
|
||||
if(VoxelForgeCore::PassageSpline::ClosestRouteHeightAtXY(route,
|
||||
controls.front()[0],controls.front()[1],routeHeight,distanceSquared)
|
||||
&&distanceSquared<=std::pow(controls.front()[3]+2.0,2.0))
|
||||
VoxelForgeCore::PassageSpline::BlendEndpointFloorToRoute(
|
||||
controls,profile,0,route,1.0);
|
||||
}
|
||||
const auto lower=std::find_if(ResolvedLayout->strates.begin(),
|
||||
ResolvedLayout->strates.end(),[&](const auto& stratum)
|
||||
{return stratum.strateIndex==passage.lowerStrateIndex;});
|
||||
const std::size_t routeEnd=std::clamp<std::size_t>(
|
||||
passage.lowerMouthControlIndex,1,passage.controlPoints.size()-1);
|
||||
if(lower!=ResolvedLayout->strates.end()
|
||||
&&lower->generatorKind=="TunnelNetwork"&&routeEnd<controls.size())
|
||||
{
|
||||
auto route=routeForStrate(passage.lowerStrateIndex);
|
||||
if(route.size()>2)route.resize(2);
|
||||
double routeHeight=0.0,distanceSquared=0.0;
|
||||
if(VoxelForgeCore::PassageSpline::ClosestRouteHeightAtXY(route,
|
||||
controls[routeEnd][0],controls[routeEnd][1],
|
||||
routeHeight,distanceSquared)
|
||||
&&distanceSquared<=std::pow(controls[routeEnd][3]+2.0,2.0))
|
||||
VoxelForgeCore::PassageSpline::BlendEndpointFloorToRoute(
|
||||
controls,profile,routeEnd,route,1.0);
|
||||
}
|
||||
return profile;
|
||||
};
|
||||
const auto passageBodyFloorDepth=[&](
|
||||
@@ -5059,6 +5117,16 @@ namespace StandaloneStreamBenchmark
|
||||
supportMaximumMetres=routeConstraints->supportSearchDepthSubvoxels*qMetres;
|
||||
}
|
||||
}
|
||||
if(stratum.generatorKind=="TunnelNetwork")
|
||||
{
|
||||
std::int64_t floorSupportDepth=0;
|
||||
for(const auto& edge:ResolvedLayout->cavernEdges)
|
||||
if(edge.strateIndex==stratum.strateIndex)
|
||||
floorSupportDepth=std::max(floorSupportDepth,
|
||||
edge.floorSupportDepthMicrometres);
|
||||
supportMaximumMetres=std::max(supportMaximumMetres,
|
||||
floorSupportDepth/1000000.0+0.25);
|
||||
}
|
||||
const FWalkAudit routeAudit=auditPlayerPath(Shape,route,supportStartMetres,
|
||||
supportStepMetres,supportMaximumMetres,minimumSupportProbes,
|
||||
supportProbeRadiusMetres);
|
||||
@@ -5071,7 +5139,7 @@ namespace StandaloneStreamBenchmark
|
||||
return equalPosition(authored,mouth);
|
||||
auto expected=mouth;
|
||||
expected[2]+=static_cast<std::int64_t>(std::llround(
|
||||
1000000.0*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel
|
||||
1130000.0*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel
|
||||
/World.CoreVoxelSizeMicrons));
|
||||
return equalPosition(authored,expected);
|
||||
};
|
||||
@@ -5145,13 +5213,29 @@ namespace StandaloneStreamBenchmark
|
||||
if(stratum.generatorKind=="TunnelNetwork")
|
||||
{
|
||||
++tunnelNetworkRoutes;
|
||||
const FWalkAudit control=auditPlayerPath(blockedWorld,route,
|
||||
auto controlRoute=route;
|
||||
constexpr double OffBoreControlOffsetMetres=12.0;
|
||||
const std::size_t controlIndex=controlRoute.size()/2;
|
||||
const double tangentX=route[controlIndex+1][0]
|
||||
-route[controlIndex-1][0];
|
||||
const double tangentY=route[controlIndex+1][1]
|
||||
-route[controlIndex-1][1];
|
||||
const double tangentLength=std::hypot(tangentX,tangentY);
|
||||
if(tangentLength>1.0e-9)
|
||||
{
|
||||
controlRoute[controlIndex][0]+=-tangentY/tangentLength
|
||||
*OffBoreControlOffsetMetres/coreMetres;
|
||||
controlRoute[controlIndex][1]+=tangentX/tangentLength
|
||||
*OffBoreControlOffsetMetres/coreMetres;
|
||||
}
|
||||
const FWalkAudit control=auditPlayerPath(blockedWorld,controlRoute,
|
||||
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),
|
||||
std::printf("[TunnelNetworkBlockedRouteControl] strate=%d mode=off_bore_lateral_deviation_m=%.1f blocked_capsule_samples=%llu result=%s expected=FAIL status=%s\n",
|
||||
stratum.strateIndex,OffBoreControlOffsetMetres,
|
||||
static_cast<unsigned long long>(control.blocked),
|
||||
control.passed?"PASS":"FAIL",detected?"PASS":"FAIL");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1081,6 +1081,17 @@ namespace StandaloneWorldAssemblyPrototype
|
||||
if(!slot.Definition
|
||||
||owner.Manager->GetGeneratorTypeForChunk(FIntVector(0,0,slot.TopChunkZ))
|
||||
!=ECaveGeneratorType::TunnelNetwork)continue;
|
||||
const bool hasIncomingMouth=std::any_of(layout.passages.begin(),
|
||||
layout.passages.end(),[&](const auto& passage)
|
||||
{return passage.lowerStrateIndex==slot.StrateIndex
|
||||
&&passage.upperStrateIndex<slot.StrateIndex;});
|
||||
const bool hasOutgoingMouth=std::any_of(layout.passages.begin(),
|
||||
layout.passages.end(),[&](const auto& passage)
|
||||
{return passage.upperStrateIndex==slot.StrateIndex
|
||||
&&passage.lowerStrateIndex>slot.StrateIndex;});
|
||||
// A native planner route requires two mouths. Boundary Tunnel Network
|
||||
// strates keep their legacy field until they have both connections.
|
||||
if(!hasIncomingMouth||!hasOutgoingMouth)continue;
|
||||
auto stratum=std::find_if(layout.strates.begin(),layout.strates.end(),
|
||||
[&](const auto& item){return item.strateIndex==slot.StrateIndex;});
|
||||
if(stratum==layout.strates.end())
|
||||
@@ -1179,7 +1190,8 @@ namespace StandaloneWorldAssemblyPrototype
|
||||
!=ECaveGeneratorType::TunnelNetwork)continue;
|
||||
auto stratum=std::find_if(layout.strates.begin(),layout.strates.end(),
|
||||
[&](const auto& item){return item.strateIndex==slot.StrateIndex;});
|
||||
if(stratum==layout.strates.end())continue;
|
||||
if(stratum==layout.strates.end()
|
||||
||!IsNativeCaveFieldStratum(*stratum))continue;
|
||||
const bool hasRoutePoints=std::count_if(stratum->anchors.begin(),
|
||||
stratum->anchors.end(),[](const auto& anchor)
|
||||
{return anchor.kind=="route_point"&&anchor.values.size()>=3;})>=2;
|
||||
@@ -1204,7 +1216,13 @@ namespace StandaloneWorldAssemblyPrototype
|
||||
anchor.values={point[0],point[1],point[2]};
|
||||
stratum->anchors.push_back(std::move(anchor));
|
||||
};
|
||||
constexpr std::int64_t PlayerCenterAboveFloorMicrometres=1000000;
|
||||
const auto sameRoutePoint=[](const auto& a,const auto& b)
|
||||
{
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
if(std::abs(a[axis]-b[axis])>2)return false;
|
||||
return true;
|
||||
};
|
||||
constexpr std::int64_t PlayerCenterAboveFloorMicrometres=1130000;
|
||||
auto start=arrival->lowerMouthSubvoxels;
|
||||
start[2]+=toCoreSubvoxels(PlayerCenterAboveFloorMicrometres);
|
||||
appendRoutePoint("000-arrival",start);
|
||||
@@ -1222,9 +1240,11 @@ namespace StandaloneWorldAssemblyPrototype
|
||||
{
|
||||
auto inner=edge->controlPointsMicrometres.front();
|
||||
inner[2]+=PlayerCenterAboveFloorMicrometres;
|
||||
appendRoutePoint("000-edge-start",
|
||||
{toCoreSubvoxels(inner[0]),toCoreSubvoxels(inner[1]),
|
||||
toCoreSubvoxels(inner[2])});
|
||||
const std::array<std::int64_t,3> point={
|
||||
toCoreSubvoxels(inner[0]),toCoreSubvoxels(inner[1]),
|
||||
toCoreSubvoxels(inner[2])};
|
||||
if(!sameRoutePoint(point,start))
|
||||
appendRoutePoint("000-edge-start",point);
|
||||
}
|
||||
auto point=edge->controlPointsMicrometres.back();
|
||||
point[2]+=PlayerCenterAboveFloorMicrometres;
|
||||
@@ -1242,9 +1262,13 @@ namespace StandaloneWorldAssemblyPrototype
|
||||
{
|
||||
auto inner=departureEdge->controlPointsMicrometres.front();
|
||||
inner[2]+=PlayerCenterAboveFloorMicrometres;
|
||||
appendRoutePoint("998-departure-inner",
|
||||
{toCoreSubvoxels(inner[0]),toCoreSubvoxels(inner[1]),
|
||||
toCoreSubvoxels(inner[2])});
|
||||
const std::array<std::int64_t,3> innerPoint={
|
||||
toCoreSubvoxels(inner[0]),toCoreSubvoxels(inner[1]),
|
||||
toCoreSubvoxels(inner[2])};
|
||||
auto end=departure->upperMouthSubvoxels;
|
||||
end[2]+=toCoreSubvoxels(PlayerCenterAboveFloorMicrometres);
|
||||
if(!sameRoutePoint(innerPoint,end))
|
||||
appendRoutePoint("998-departure-inner",innerPoint);
|
||||
}
|
||||
auto end=departure->upperMouthSubvoxels;
|
||||
end[2]+=toCoreSubvoxels(PlayerCenterAboveFloorMicrometres);
|
||||
@@ -1370,8 +1394,15 @@ namespace StandaloneWorldAssemblyPrototype
|
||||
const auto authored=sealAndDensity(*slot.Definition,type);
|
||||
const bool nativeSurfaceCaves=recipeVariant=="caves"
|
||||
&&type==ECaveGeneratorType::SurfaceWorld;
|
||||
const bool hasLowerStrate=std::any_of(owner.Manager->GetLayout().begin(),
|
||||
owner.Manager->GetLayout().end(),[&](const FStrateSlot& candidate)
|
||||
{return candidate.StrateIndex<slot.StrateIndex;});
|
||||
const bool hasUpperStrate=std::any_of(owner.Manager->GetLayout().begin(),
|
||||
owner.Manager->GetLayout().end(),[&](const FStrateSlot& candidate)
|
||||
{return candidate.StrateIndex>slot.StrateIndex;});
|
||||
const bool nativeTunnelCaves=type==ECaveGeneratorType::TunnelNetwork
|
||||
&&recipeVariant!="legacy-tunnel-network"&&recipeVariant!="caves";
|
||||
&&recipeVariant!="legacy-tunnel-network"&&recipeVariant!="caves"
|
||||
&&hasLowerStrate&&hasUpperStrate;
|
||||
const bool nativeCaves=nativeSurfaceCaves||nativeTunnelCaves;
|
||||
const bool nativeLattice=recipeVariant==("lattice/"+std::to_string(slot.StrateIndex))
|
||||
&&(type==ECaveGeneratorType::Maze||type==ECaveGeneratorType::VerticalShafts);
|
||||
|
||||
Reference in new issue
Block a user