"""Execute production rescue landing policy and routing; no native physics claim.""" from policy_harness import ROOT, body, run base = ROOT / 'addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c' rescue = ROOT / 'addons/core/Scripts/Game/ERR/10_AI/ERR_RescueFlightComponent.c' def native(method): return (method.replace('protected override ', '').replace('protected ', 'virtual ') .replace('Math.', 'Math::').replace('super.', 'Base::') .replace('ERR_RescueLandingRules.', 'ERR_RescueLandingRules::')) run(r''' #include #include #include #include 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 Clamp(float a,float low,float high){return std::clamp(a,low,high);} }; struct vector { float x=0,y=0,z=0; vector()=default;vector(float a,float b,float c):x(a),y(b),z(c){} float& operator[](int i){return i==0?x:i==1?y:z;} vector operator*(float f)const{return{x*f,y*f,z*f};} vector operator-(vector b)const{return{x-b.x,y-b.y,z-b.z};} float Length()const{return std::sqrt(x*x+y*y+z*z);} vector Normalized()const{float n=Length();return n>0?(*this)*(1/n):vector{};} }; float Horizontal(vector a){return std::hypot(a.x,a.z);} bool Near(float a,float b){return std::abs(a-b)<0.0001f;} bool Same(vector a,vector b){return Near(a.x,b.x)&&Near(a.y,b.y)&&Near(a.z,b.z);} struct Base { ''' + native(body(base, 'protected vector LandingVelocity(')) + r''' }; struct ERR_RescueLandingRules { ''' + native(body(rescue, 'static vector Velocity(')) + r''' }; struct Rescue : Base { bool m_Escort=false,m_Departing=false; ''' + native(body(rescue, 'protected override vector LandingVelocity(')) + r''' }; // Integrate only the velocity policy with the controller's unchanged 2-second // settling condition. Native collision, suspension and frame scheduling are not // modeled here and require the separate in-engine landing fixture. float IdealLandingSeconds(Base& flight,int hz){ vector offset{90,-150,0};float dt=1.0f/hz,settled=0; for(int frame=0;frame=2)return frame*dt; vector next=offset-velocity*dt; assert(next.y<=0); // Continuous taper must not command an overshoot through the pad. assert(Horizontal(next)<=Horizontal(offset)+0.0001f); offset=next; } assert(false&&"landing policy never settled");return -1; } int main(){ Base base;Rescue rescue;Base& dispatched=rescue; assert(Same(base.LandingVelocity({0,0,0}),{})); assert(Same(dispatched.LandingVelocity({0,0,0}),{})); assert(Same(base.LandingVelocity({0,-150,0}),{0,-3,0})); assert(Same(dispatched.LandingVelocity({0,-150,0}),{0,-9,0})); assert(Same(dispatched.LandingVelocity({0,-30,0}),{0,-9,0})); assert(Same(dispatched.LandingVelocity({0,-20,0}),{0,-6,0})); assert(Same(dispatched.LandingVelocity({0,-10,0}),{0,-3,0})); // The extra speed is downward only. Below-pad recovery remains the old // proportional climb with its original 3 m/s limit, even outside alignment. for(float below : {0.1f,1.0f,5.0f,10.0f,100.0f}){ assert(Same(base.LandingVelocity({0,below,0}),dispatched.LandingVelocity({0,below,0}))); assert(dispatched.LandingVelocity({100,below,0}).y>0); assert(dispatched.LandingVelocity({100,below,0}).y<=3); } // Exactly the original final approach vector within 16 m horizontally and // ten metres vertically, including the 15 m alignment boundary. for(float x : {-16.0f,-15.01f,-15.0f,-7.0f,0.0f,7.0f,15.0f,15.01f,16.0f}) for(float y : {-10.0f,-9.99f,-5.0f,-1.0f,0.0f,1.0f,5.0f,10.0f}) assert(Same(base.LandingVelocity({x,y,0}),dispatched.LandingVelocity({x,y,0}))); assert(dispatched.LandingVelocity({15,-100,0}).y==-9); assert(dispatched.LandingVelocity({15.001f,-100,0}).y==0); assert(dispatched.LandingVelocity({12,-100,9}).y==-9); // Radial gate, not an axis-only test. assert(dispatched.LandingVelocity({12,-100,9.001f}).y==0); // All approach directions remain aligned with the pad; the altitude must not // inflate the horizontal speed, and the horizontal cap cannot affect climb. for(float x : {-100.0f,-10.0f,0.0f,10.0f,100.0f}) for(float z : {-100.0f,-10.0f,0.0f,10.0f,100.0f}){ vector offset{x,-150,z};vector velocity=dispatched.LandingVelocity(offset); assert(Horizontal(velocity)<=14.0001f); assert(Horizontal(base.LandingVelocity(offset))<=8.0001f); assert(Near(velocity.x*z,velocity.z*x)); assert(velocity.x*x+velocity.z*z>=0); if(Horizontal(offset)>15)assert(velocity.y==0); if(Horizontal(offset)>28)assert(Near(Horizontal(velocity),14)); assert(Same({velocity.x,0,velocity.z},dispatched.LandingVelocity({x,0,z}))); } // No downward speed jump at 30 m or 10 m: braking is monotonic and bounded // by the original 0.3 gain all the way through touchdown. float previous=0; for(int centimetres=0;centimetres<=4000;centimetres++){ float height=centimetres/100.0f,speed=-dispatched.LandingVelocity({0,-height,0}).y; assert(speed>=previous-0.00001f&&speed-previous<0.00301f&&speed<=9); previous=speed; } // Exercise virtual dispatch with each flight role. Escorts and outbound // transport landings continue to use the default recon/logistics profile. for(bool escort : {false,true})for(bool departing : {false,true}){ rescue.m_Escort=escort;rescue.m_Departing=departing; for(vector offset : {vector{80,-150,0},vector{0,-100,0},vector{8,-5,4},vector{20,50,30}}){ vector expected=(escort||departing)?base.LandingVelocity(offset):ERR_RescueLandingRules::Velocity(offset); assert(Same(dispatched.LandingVelocity(offset),expected)); } } rescue.m_Escort=false;rescue.m_Departing=false; for(int hz : {15,30,60,120}){ float original=IdealLandingSeconds(base,hz),pickup=IdealLandingSeconds(dispatched,hz); assert(original>60&&original<70&&pickup>30&&pickup<36); assert(pickup