"""Actual bounded target/start/stage policy, with native boundaries substituted.""" from policy_harness import ROOT, body, run SOURCE=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFlight.c' def cpp(s): return s.replace('protected ','').replace('ERR_AircraftFlightState.','State::').replace('ERR_AircraftFlightRules.','FlightRules::').replace('ERR_AircraftTranslationRules.','Rules::').replace('Math.','Math::').replace('vector.','vector::').replace('SignalsManagerComponent signals','SignalsManagerComponent* signals').replace('signals.FindSignal','signals->FindSignal') rules='\n'.join(cpp(body(SOURCE,key)) for key in ('static bool Target(', 'static bool Reachable(', 'static vector Demand(', 'static bool Held(')) methods='\n'.join(cpp(body(SOURCE,key)) for key in ('bool StartTranslation(', 'protected bool BeginTranslation(', 'protected void CheckTranslation(')) run(r'''#include #include #include #include #include #define PrintFormat(...) ((void)0) using string=std::string; using ERR_GameMode=int;using Vehicle=int;using SCR_AIGroup=int;using IEntity=int;using PilotCompartmentSlot=int; namespace State {enum {IDLE,HOOKS,STARTING,POSITIVE,NEGATIVE,CLIMB,LANDING,SHUTDOWN,COMPLETE,CANCELLED,FAILED,RELINQUISHED,TRANSLATING};} struct Math {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 float AbsFloat(float a){return std::abs(a);}}; struct vector {float x=0,y=0,z=0; float& operator[](int i){return i==0?x:(i==1?y:z);}float operator[](int i)const{return i==0?x:(i==1?y:z);} vector operator-(vector b)const{return {x-b.x,y-b.y,z-b.z};}vector operator*(float n)const{return {x*n,y*n,z*n};} float Length()const{return std::sqrt(x*x+y*y+z*z);}static float DistanceXZ(vector a,vector b){return std::hypot(a.x-b.x,a.z-b.z);} }; struct FlightRules { '''+cpp(body(SOURCE,'static bool Hover('))+r''' }; struct Rules { '''+rules+r''' }; struct ERR_AircraftFlightEnvelope {bool valid=true;vector home;explicit operator bool()const{return valid;}vector Home(){return home;}}; struct SignalsManagerComponent {bool present=true;int FindSignal(const char*){return present?0:-1;}}; struct Controller {bool hover=true;SignalsManagerComponent signals;SignalsManagerComponent* GetSignalsManager(){return &signals;}bool GetAutohoverEnabled(){return hover;}}; struct Simulation {vector velocity;bool contact=false;vector GetVelocity(){return velocity;}bool HasAnyGroundContact(){return contact;}}; struct Probe { bool m_StartAttempted=false,m_TranslationRequested=false,m_TranslationStarted=false,m_TranslationProven=false; vector m_TranslationTarget,m_TranslationOrigin,m_Home; float m_TranslationDistance=0,m_Stable=-1,m_Deadline=240000,m_StageDeadline=0; int m_State=State::CLIMB,m_Token=123,m_TranslationUpdates=10,cancelled=0,landings=0,starts=0; Controller m_Controller;Simulation m_Simulation;string reason; bool Start(ERR_GameMode,Vehicle,SCR_AIGroup,IEntity,PilotCompartmentSlot,ERR_AircraftFlightEnvelope,int,float){m_StartAttempted=true;starts++;return true;} void Cancel(string detail){reason=detail;cancelled++;m_State=State::LANDING;} bool Landing(float){landings++;m_State=State::LANDING;return true;} '''+methods+r''' }; int main(){ assert(Rules::Target({0,0,0},{3,999,4})); // API is explicitly horizontal assert(!Rules::Target({0,0,0},{3.01f,0,4})); assert(!Rules::Target({0,0,0},{NAN,0,0})); assert(Rules::Reachable(4)&&Rules::Reachable(4.04f)&&!Rules::Reachable(4.06f)); assert(!Rules::Reachable(-.01f)&&!Rules::Reachable(NAN)); for(float error:{-100.f,-4.f,-.5f,0.f,.5f,4.f,100.f})for(float velocity:{-100.f,-1.f,0.f,1.f,100.f}){ vector demand=Rules::Demand({error,9,error},{0,1,0},{velocity,100,velocity}); assert(demand.Length()<=.030001f&&demand.y==0); } vector brake=Rules::Demand({0,0,0},{0,8,0},{1,0,0});assert(brake.x<0&&brake.z==0); assert(Rules::Held(false,8,.2f,.1f,1,.1f,.5f,3.5f,4)); assert(!Rules::Held(true,8,.2f,.1f,1,.1f,.5f,3.5f,4)); assert(!Rules::Held(false,8,.2f,.1f,1,.3f,.5f,3.5f,4)); assert(!Rules::Held(false,8,.2f,.1f,1,.1f,.76f,3.5f,4)); assert(!Rules::Held(false,8,.2f,.1f,1,.1f,.5f,3.24f,4)); assert(!Rules::Held(false,10,.2f,.1f,1,.1f,.5f,3.5f,4)); // Invalid absolute targets cannot reach native Start; valid target copies once. Probe invalid;ERR_AircraftFlightEnvelope q; assert(!invalid.StartTranslation(1,1,1,1,1,q,123,10000,{6,0,0})&&invalid.starts==0&&!invalid.m_TranslationRequested); Probe stale;q.valid=false;assert(!stale.StartTranslation(1,1,1,1,1,q,123,10000,{0,0,0})&&stale.starts==0);q.valid=true; Probe immutable;vector target={3,100,0};assert(immutable.StartTranslation(1,1,1,1,1,q,123,10000,target)); target.x=0;assert(immutable.m_TranslationTarget.x==3&&immutable.m_TranslationTarget.y==8&&immutable.starts==1); assert(!immutable.StartTranslation(1,1,1,1,1,q,123,10000,{0,0,0})&&immutable.starts==1); // Natural hover drift may make an accepted preflight target unreachable. Land, // never shift its target/home or extend the original deadline to force success. Probe drift;drift.m_TranslationRequested=true;drift.m_TranslationTarget={0,8,0}; assert(!drift.BeginTranslation(1000,{4.1f,8,0})&&drift.cancelled==1&&!drift.m_TranslationStarted); assert(drift.m_State==State::LANDING&&drift.m_TranslationTarget.x==0&&drift.m_Home.x==0&&drift.m_Deadline==240000); Probe noSignals;noSignals.m_TranslationRequested=true;noSignals.m_Controller.signals.present=false; assert(!noSignals.BeginTranslation(1000,{3,8,0})&&noSignals.cancelled==1&&!noSignals.m_TranslationStarted); Probe move;move.m_TranslationRequested=true;move.m_TranslationTarget={0,8,0};move.m_Deadline=42000; assert(move.BeginTranslation(1000,{3.3f,8,0}));assert(move.m_State==State::TRANSLATING&&move.m_StageDeadline==42000&&move.m_Deadline==42000); assert(move.m_TranslationOrigin.x==3.3f&&move.m_TranslationTarget.x==0); for(int i=0;i<5;i++)move.CheckTranslation(2000+i*1000,{.5f,8,0},8,0,1); assert(!move.m_TranslationProven&&move.landings==0); move.CheckTranslation(7000,{.5f,8,0},8,0,1);assert(move.m_TranslationProven&&move.landings==1); Probe interrupted;interrupted.m_TranslationRequested=true;assert(interrupted.BeginTranslation(1000,{3.3f,8,0})); interrupted.CheckTranslation(2000,{.5f,8,0},8,0,1);interrupted.CheckTranslation(5000,{2,8,0},8,0,1); assert(interrupted.m_Stable==-1);interrupted.CheckTranslation(6000,{.5f,8,0},8,0,1); interrupted.CheckTranslation(10000,{.5f,8,0},8,0,1);assert(!interrupted.m_TranslationProven); Probe insufficient;insufficient.m_TranslationRequested=true;assert(insufficient.BeginTranslation(1000,{3.3f,8,0})); insufficient.m_TranslationUpdates=2;insufficient.CheckTranslation(9000,{.5f,8,0},8,0,1);assert(insufficient.m_Stable==-1); } ''') source=SOURCE.read_text(); prepare=body(SOURCE,'void PrepareActions('); tick=body(SOURCE,'void Tick(') assert 'Math.Clamp(vector.Dot(demand, transform[2]), -0.03, 0.03)' in prepare assert 'Math.Clamp(vector.Dot(demand, transform[0]), -0.03, 0.03)' in prepare assert prepare.index('!ControlLease()') < prepare.index('ERR_AircraftTranslationRules.Demand(') assert 'm_State == ERR_AircraftFlightState.TRANSLATING' in prepare assert tick.index('ERR_AircraftFlightRules.Envelope(') < tick.index('CheckTranslation(') assert 'if (m_TranslationRequested) BeginTranslation(now, transform[3]);' in tick assert 'else Landing(now);' in tick assert source.count('m_TranslationTarget = target')==1 for method in (body(SOURCE,'protected bool BeginTranslation('),body(SOURCE,'protected void CheckTranslation(')): assert 'm_Home =' not in method and 'm_Deadline =' not in method assert 'm_TranslationTarget =' not in method assert 'SetVelocity' not in method and 'SetWorldTransform' not in method print('PASS: actual immutable target, bounded autohover demand, drift refusal, five-second hold and unchanged qualification/deadline')