78 lines
4.1 KiB
Python
78 lines
4.1 KiB
Python
"""Execute the fixture's deterministic pad survey geometry; no terrain claims."""
|
|
from policy_harness import ROOT, body, run
|
|
p=ROOT/'addons/core/Scripts/Game/ERR/ERR_NativePoweredFlightProbe.c'
|
|
source=body(p,'static vector PadOffset(')
|
|
source+='\n'+body(p,'static vector RefineOffset(')
|
|
source+='\n'+body(p,'static vector AirportOffset(')
|
|
# C++ accepts %, but Enforce does not. Fail before the C++ harness can hide
|
|
# that native compilation error; only namespace spelling is translated.
|
|
assert '%' not in source, 'Enforce remainder requires Math.Mod, not the C++ % operator'
|
|
s=source.replace('Math.','Math::').replace('vector.Zero','vector::Zero')
|
|
run('''#include <cassert>
|
|
#include <cmath>
|
|
#include <vector>
|
|
struct vector {float x,y,z;static const vector Zero;};const vector vector::Zero{0,0,0};
|
|
vector Vector(float x,float y,float z){return {x,y,z};}
|
|
namespace Math {constexpr float PI=3.14159265358979323846f;float Cos(float a){return std::cos(a);}float Sin(float a){return std::sin(a);}float Mod(float value,float divisor){return std::fmod(value,divisor);}}
|
|
constexpr int PAD_CANDIDATES=128;
|
|
constexpr int PAD_REFINEMENTS=80;
|
|
constexpr int AIRPORT_CANDIDATES=169;
|
|
'''+s+'''
|
|
int main(){
|
|
std::vector<vector> seen;
|
|
for(int i=0;i<PAD_CANDIDATES;i++){
|
|
auto p=PadOffset(i);float radius=std::hypot(p.x,p.z);assert(p.y==0&&radius>=119.99f&&radius<=500.01f);
|
|
for(auto old:seen)assert(std::hypot(p.x-old.x,p.z-old.z)>1);
|
|
seen.push_back(p);
|
|
if(i<12){float angle=i*Math::PI/6;assert(std::hypot(p.x-std::cos(angle)*120,p.z-std::sin(angle)*120)<.001f);}
|
|
if(i>=12&&i<108){
|
|
int ring=(i-12)/24;int sample=(i-12)-24*ring;
|
|
float phase=(ring==1||ring==3)?0.5f:0.f;
|
|
float expectedRadius=200+80*ring;float angle=(sample+phase)*2*Math::PI/24;
|
|
assert(std::fabs(radius-expectedRadius)<.001f);
|
|
assert(std::hypot(p.x-std::cos(angle)*expectedRadius,p.z-std::sin(angle)*expectedRadius)<.001f);
|
|
}
|
|
if(i>=108)assert(std::fabs(radius-500)<.001f);
|
|
}
|
|
assert(seen.size()==128);
|
|
for(int invalid:{-1,128,999}){auto p=PadOffset(invalid);assert(p.x==0&&p.y==0&&p.z==0);}
|
|
seen.clear();
|
|
for(int i=0;i<PAD_REFINEMENTS;i++){
|
|
auto p=RefineOffset(i);assert(p.y==0&&std::hypot(p.x,p.z)>9.99f&&std::hypot(p.x,p.z)<56.57f);
|
|
assert(std::fabs(p.x)<=40&&std::fabs(p.z)<=40);
|
|
for(auto old:seen)assert(std::hypot(p.x-old.x,p.z-old.z)>9.99f);
|
|
seen.push_back(p);
|
|
}
|
|
assert(seen.size()==80);
|
|
for(int x=-40;x<=40;x+=10)for(int z=-40;z<=40;z+=10){
|
|
if(x==0&&z==0)continue;
|
|
int matches=0;for(auto p:seen)if(p.x==x&&p.z==z)matches++;assert(matches==1);
|
|
}
|
|
for(int invalid:{-1,80,999}){auto p=RefineOffset(invalid);assert(p.x==0&&p.y==0&&p.z==0);}
|
|
seen.clear();
|
|
for(int i=0;i<AIRPORT_CANDIDATES;i++){
|
|
auto p=AirportOffset(i);assert(p.y==0&&std::fabs(p.x)<=300&&std::fabs(p.z)<=300);
|
|
for(auto old:seen)assert(std::hypot(p.x-old.x,p.z-old.z)>49.99f);
|
|
seen.push_back(p);
|
|
}
|
|
assert(seen.size()==169);
|
|
for(int x=-300;x<=300;x+=50)for(int z=-300;z<=300;z+=50){
|
|
int matches=0;for(auto p:seen)if(p.x==x&&p.z==z)matches++;assert(matches==1);
|
|
}
|
|
for(int invalid:{-1,169,999}){auto p=AirportOffset(invalid);assert(p.x==0&&p.y==0&&p.z==0);}
|
|
}
|
|
''')
|
|
# The native safety queries remain boundaries, not fake geometry measurements.
|
|
find=body(p,'protected bool FindPad(')
|
|
assert 'maximumDelta > 0.8' in find and 'Math.Cos(side) * 14' in find
|
|
assert 'TraceCilinderUtil(candidate + "0 2.5 0", 40, 4, TraceFlags.ENTS)' in find
|
|
assert 'clearance.Start = candidate + "0 3 0"; clearance.End = candidate + "0 60 0"' in find
|
|
assert 'clearance.Mins = "-40 -1 -40"; clearance.Maxs = "40 1 40"' in find
|
|
assert find.index('TraceMove(clearance, null) < 1') < find.index('result = candidate; return true;')
|
|
assert 'result = bestCandidate' not in find
|
|
assert find.count('refinementAnchor = bestCandidate') == 1
|
|
assert 'index == ERR_PoweredFlightRules.PAD_CANDIDATES' in find
|
|
assert 'ERR_PoweredFlightRules.PAD_CANDIDATES + ERR_PoweredFlightRules.PAD_REFINEMENTS' in find
|
|
assert 'localCandidates + ERR_PoweredFlightRules.AIRPORT_CANDIDATES' in find
|
|
print('PASS: 128 coarse+80 local refinement+169 airport grid candidates retain all native clearance gates; real terrain untested')
|