Files
EscapistsReintroduced/tests/test_powered_flight_pad.py
T
jakub cab998fb64 Combine Workshop addon and fix prison startup
Merge owned systems into one addon while preserving resource identities. Gate player admission on the replicated prison scene, restore the original framed door, and hold enemy AI until escape. Correct scenario branding and author metadata, include publishing assets, and retain regression and native verification evidence.
2026-09-20 16:42:52 +02:00

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/00_Core/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')