69 lines
5.2 KiB
Python
69 lines
5.2 KiB
Python
"""Actual immutable corridor geometry and native-survey orchestration with fake traces."""
|
|
from policy_harness import ROOT, body, run
|
|
P=ROOT/'addons/ai/Scripts/Game/ERR/ERR_AircraftRouteEnvelope.c'
|
|
BASE=ROOT/'addons/ai/Scripts/Game/ERR/ERR_AircraftFlight.c'
|
|
def cpp(s):
|
|
for name in ('Math','vector','ERR_AircraftRouteRules','ERR_AircraftFlightRules','SCR_TerrainHelper','TraceFlags'):
|
|
s=s.replace(name+'.',name+'::')
|
|
s=s.replace('array<IEntity> excluded = null','void* excluded = nullptr')
|
|
s=s.replace('TraceBox corridor','TraceBox* corridor').replace('TraceBox low','TraceBox* low')
|
|
for name in ('corridor','low'):s=s.replace(name+'.',name+'->')
|
|
return s.replace('GetGame().','GetGame()->').replace('GetWorld().','GetWorld()->').replace(', null)', ', nullptr)')
|
|
rules='\n'.join(cpp(body(P,key)) for key in ('static bool Length(', 'static vector Nearest(', 'static bool Contains(', 'static bool Held('))
|
|
run(r'''#include <cassert>
|
|
#include <cmath>
|
|
#include <algorithm>
|
|
#include <vector>
|
|
#include <cstdio>
|
|
struct Math {static float Clamp(float v,float lo,float hi){return std::clamp(v,lo,hi);}static float Min(float a,float b){return std::min(a,b);}static float Max(float a,float b){return std::max(a,b);}static int Ceil(float x){return std::ceil(x);}static float AbsFloat(float x){return std::abs(x);}};
|
|
struct vector {float v[3]={};vector(){}vector(float x,float y,float z){v[0]=x;v[1]=y;v[2]=z;}vector(const char*s){sscanf(s,"%f %f %f",v,v+1,v+2);}float&operator[](int i){return v[i];}float operator[](int i)const{return v[i];}vector operator+(vector b)const{return {v[0]+b[0],v[1]+b[1],v[2]+b[2]};}vector operator-(vector b)const{return {v[0]-b[0],v[1]-b[1],v[2]-b[2]};}vector operator*(float n)const{return {v[0]*n,v[1]*n,v[2]*n};}static float Dot(vector a,vector b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];}static float DistanceXZ(vector a,vector b){return std::hypot(a[0]-b[0],a[2]-b[2]);}};
|
|
vector Vector(float x,float y,float z){return {x,y,z};}
|
|
struct ERR_AircraftFlightRules {
|
|
'''+cpp(body(BASE,'static bool Hover('))+r'''
|
|
};
|
|
struct ERR_AircraftRouteRules {
|
|
'''+rules+r'''
|
|
};
|
|
namespace TraceFlags {enum {ENTS=1,WORLD=2};}
|
|
struct TraceBox {vector Start,End,Mins,Maxs;int Flags=0;void* ExcludeArray=nullptr;};
|
|
struct World {int calls=0;int refuseAt=0;std::vector<TraceBox> seen;float TraceMove(TraceBox* t,void*){calls++;seen.push_back(*t);delete t;return calls==refuseAt?0.5:1;}} world;
|
|
struct Game {World* GetWorld(){return &world;}} game;
|
|
Game* GetGame(){return &game;}
|
|
struct SCR_TerrainHelper {static int samples,kind;static float GetTerrainY(vector){samples++;if(kind==1)return 10.31f;if(kind==2&&samples==60)return 9.69f;if(kind==3)return NAN;return 10;}};
|
|
int SCR_TerrainHelper::samples=0;int SCR_TerrainHelper::kind=0;
|
|
'''+cpp(body(P,'static bool Survey('))+r'''
|
|
int main(){
|
|
assert(ERR_AircraftRouteRules::Length(18)&&ERR_AircraftRouteRules::Length(20)&&!ERR_AircraftRouteRules::Length(17.99f)&&!ERR_AircraftRouteRules::Length(20.06f)&&!ERR_AircraftRouteRules::Length(NAN));
|
|
vector a={0,10,0},b={20,10,0};
|
|
assert(ERR_AircraftRouteRules::Contains(a,b,{10,18,7.99f},1));
|
|
assert(!ERR_AircraftRouteRules::Contains(a,b,{10,18,8},1));
|
|
assert(ERR_AircraftRouteRules::Contains(a,b,{-7.99f,18,0},1));
|
|
assert(!ERR_AircraftRouteRules::Contains(a,b,{-8,18,0},1));
|
|
assert(!ERR_AircraftRouteRules::Contains(a,b,{28,18,0},1));
|
|
assert(!ERR_AircraftRouteRules::Contains(a,b,{10,28.01f,0},1));
|
|
assert(!ERR_AircraftRouteRules::Contains(a,b,{10,18,0},.84f));
|
|
assert(!ERR_AircraftRouteRules::Contains(a,b,{NAN,18,0},1));
|
|
assert(ERR_AircraftRouteRules::Contains(a,{12,10,16},{6,18,8},1));
|
|
assert(ERR_AircraftRouteRules::Held(false,8,0,0,1,0,.75f));
|
|
assert(!ERR_AircraftRouteRules::Held(true,8,0,0,1,0,0));
|
|
assert(!ERR_AircraftRouteRules::Held(false,8,0,0,1,.25f,0));
|
|
int exclusion=1;assert(Survey(a,b,&exclusion));assert(world.calls==2&&SCR_TerrainHelper::samples==33*23);
|
|
auto high=world.seen[0],low=world.seen[1];assert(high.Flags==(TraceFlags::ENTS|TraceFlags::WORLD)&&low.Flags==TraceFlags::ENTS);
|
|
assert(high.Start[0]==10&&high.Mins[0]==-50&&high.Maxs[0]==50&&high.Mins[2]==-40&&high.Maxs[2]==40);
|
|
assert(high.Start[1]+high.Mins[1]==12&&high.End[1]+high.Maxs[1]==71);
|
|
assert(high.ExcludeArray==&exclusion&&low.ExcludeArray==&exclusion);
|
|
for(int fault=1;fault<=3;fault++){world=World();SCR_TerrainHelper::samples=0;SCR_TerrainHelper::kind=fault;assert(!Survey(a,b));assert(world.calls==0&&SCR_TerrainHelper::samples<=33*23);}
|
|
SCR_TerrainHelper::kind=0;
|
|
for(int trace=1;trace<=2;trace++){world=World();world.refuseAt=trace;assert(!Survey(a,b));assert(world.calls==trace);}
|
|
world=World();assert(!Survey(a,{100,10,0}));assert(world.calls==0);
|
|
}
|
|
''')
|
|
s=P.read_text();qualify=body(P,'static ERR_AircraftRouteEnvelope QualifyRoute(')
|
|
assert 'ERR_AircraftFlightEnvelope.Qualify(mode, aircraft, pilot)' in qualify
|
|
assert qualify.index('ClearColumn(')<qualify.index('new ERR_AircraftRouteEnvelope')
|
|
assert qualify.index('Survey(')<qualify.index('new ERR_AircraftRouteEnvelope')
|
|
assert 'm_Home = point.Home()' in qualify and 'm_Radius = point.Radius()' in qualify
|
|
assert 'bool Claim(' not in s and 'bool ClaimedBy(' not in s
|
|
assert s.count('m_Destination = end')==1
|
|
print('PASS: actual corridor caps/height/hold and whole-rectangle survey bounds, terrain refusal, native trace refusal and exact certificate lineage; native route unqualified')
|