"""Execute production hill/road geometry and finite admission state machine.""" import re from policy_harness import ROOT, body, run p=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_ScoutSystem.c' hill=body(p,'static bool Hill(') road=body(p,'static bool OnSegment(') prepare=body(p,'ERR_PrepareResult Prepare(') for name in ('Math','vector','ERR_PrepareResult','Replication'): hill=hill.replace(name+'.',name+'::');road=road.replace(name+'.',name+'::');prepare=prepare.replace(name+'.',name+'::') prepare=prepare.replace('ERR_ScenarioDefinition definition','ERR_ScenarioDefinition* definition').replace('foreach (ERR_ScoutPost post : m_Posts)','for (ERR_ScoutPost* post : m_Posts)').replace('post.','post->').replace('bool pending;','bool pending=false;').replace('GetGame().GetWorld().','clock.').replace('GetGame().GetWorldEntity().','world.').replace('System.GetTickCount()','0') motion=body(p,'static void Estimate(').replace('ERR_HQReport report','ERR_HQReport* report').replace('ERR_HQReport previous','ERR_HQReport* previous') for name in ('report','previous'): motion=motion.replace(name+'.',name+'->') for name in ('vector','ERR_HQMemoryRules'): motion=motion.replace(name+'.',name+'::') memory=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQMemory.c' credible=body(memory,'static float SpeedLimit(')+'\n'+body(memory,'static bool MotionCredible(') credible=credible.replace('string ', 'std::string ') run(r''' #include #include #include #include #include struct Math{static float Max(float a,float b){return std::max(a,b);}static float Clamp(float n,float a,float b){return std::clamp(n,a,b);}static float AbsFloat(float n){return std::abs(n);}}; struct vector{float v[3]={};vector()=default;vector(float x,float y,float z):v{x,y,z}{}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/(float f)const{return{v[0]/f,v[1]/f,v[2]/f};}static const vector Zero;static float Dot(vector a,vector b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];}static vector Lerp(vector a,vector b,float f){return{a[0]+(b[0]-a[0])*f,a[1]+(b[1]-a[1])*f,a[2]+(b[2]-a[2])*f};}static float DistanceXZ(vector a,vector b){return std::hypot(a[0]-b[0],a[2]-b[2]);}}; const vector vector::Zero{}; '''+hill+'\n'+road+r''' struct ERR_HQReport{void* Target=nullptr;void* Source=nullptr;bool Distress=false,HasVelocity=false;vector Position,Velocity;float ObservedAt=0;std::string TravelMode="on foot";}; struct ERR_HQMemoryRules{static bool Finite(float n){return std::isfinite(n);} '''+credible+r'''}; '''+motion+r''' enum class ERR_PrepareResult{PENDING,READY,FAILED}; struct Replication{static bool server;static bool IsServer(){return server;}};bool Replication::server=true; struct ERR_ScenarioDefinition{};struct ERR_ScoutPost{bool Ready=false,Group=false;}; struct Clock{float now=0;float GetWorldTime(){return now;}}; struct World{void GetWorldBounds(vector&,vector&) {}}; struct Population{ bool m_Stopped=false,m_Ready=false,m_Begun=false,m_Surveyed=false;ERR_ScenarioDefinition*m_Definition=nullptr;int m_Started=0,spawns=0,stocks=0,surveys=0;float m_Deadline=10;vector m_Low,m_High;Clock clock;World world; std::vectorm_Posts; ERR_PrepareResult survey=ERR_PrepareResult::READY,stock=ERR_PrepareResult::READY; ERR_PrepareResult Survey(){surveys++;m_Surveyed=survey==ERR_PrepareResult::READY;return survey;} ERR_PrepareResult Fail(const char*){m_Stopped=true;return ERR_PrepareResult::FAILED;} bool Spawn(ERR_ScoutPost*p){spawns++;p->Group=true;return true;} ERR_PrepareResult Stock(ERR_ScoutPost*p){stocks++;p->Ready=stock==ERR_PrepareResult::READY;return stock;} '''+prepare+r''' }; int main(){ assert(Hill(90,200,6,4));assert(!Hill(34,100,30,8));assert(!Hill(35,200,30,8));assert(!Hill(100,200,5.9,8));assert(!Hill(100,200,30,3)); vector a{0,10,0},b{100,20,0}; assert(OnSegment({50,15,2},a,b,4));assert(!OnSegment({50,15,2.01},a,b,4)); assert(!OnSegment({50,25,0},a,b,4)); // aircraft/overpass != ground road assert(!OnSegment({105,20,0},a,b,4)); // no infinite extension past end assert(!OnSegment({50,15,0},a,a,4));assert(!OnSegment({50,15,0},a,b,0)); // A bend is tested as its real segments, not a diagonal shortcut. assert(!OnSegment({50,10,50},{0,10,0},{100,10,0},4));assert(!OnSegment({50,10,50},{100,10,0},{100,10,100},4)); ERR_HQReport previous,current;previous.Target=&previous;current.Target=&previous;previous.Source=¤t;current.Source=¤t; previous.ObservedAt=1000;previous.Position={0,0,0};current.ObservedAt=11000;current.Position={20,5,30}; Estimate(¤t,&previous);assert(current.HasVelocity&¤t.Velocity[0]==2&¤t.Velocity[1]==0&¤t.Velocity[2]==3); current.Target=¤t;Estimate(¤t,&previous);assert(!current.HasVelocity);current.Target=&previous; current.Source=nullptr;Estimate(¤t,&previous);assert(!current.HasVelocity);current.Source=¤t; current.ObservedAt=1000;Estimate(¤t,&previous);assert(!current.HasVelocity); current.ObservedAt=33000;Estimate(¤t,&previous);assert(!current.HasVelocity); current.ObservedAt=11000;current.Position={500,0,0};Estimate(¤t,&previous);assert(!current.HasVelocity); current.TravelMode="in vehicle";Estimate(¤t,&previous);assert(!current.HasVelocity); previous.TravelMode="in vehicle";Estimate(¤t,&previous);assert(current.HasVelocity&¤t.Velocity[0]==50); previous.Distress=true;Estimate(¤t,&previous);assert(!current.HasVelocity); ERR_ScenarioDefinition def;Population pop;ERR_ScoutPost first,second;pop.m_Posts={&first,&second}; pop.survey=ERR_PrepareResult::PENDING;assert(pop.Prepare(&def)==ERR_PrepareResult::PENDING&&pop.spawns==0); pop.survey=ERR_PrepareResult::READY;assert(pop.Prepare(&def)==ERR_PrepareResult::PENDING&&pop.spawns==1); pop.stock=ERR_PrepareResult::PENDING;assert(pop.Prepare(&def)==ERR_PrepareResult::PENDING&&pop.spawns==2); assert(pop.Prepare(&def)==ERR_PrepareResult::PENDING&&pop.spawns==2); pop.stock=ERR_PrepareResult::READY;assert(pop.Prepare(&def)==ERR_PrepareResult::READY); int stocks=pop.stocks;first.Group=false;first.Ready=false; assert(pop.Prepare(&def)==ERR_PrepareResult::READY&&pop.spawns==2&&pop.stocks==stocks); // dead original never replaced/refilled Population timeout;timeout.m_Begun=true;timeout.m_Surveyed=true;timeout.clock.now=11;assert(timeout.Prepare(&def)==ERR_PrepareResult::FAILED&&timeout.spawns==0); Population stopped;stopped.m_Stopped=true;assert(stopped.Prepare(&def)==ERR_PrepareResult::FAILED&&stopped.surveys==0); Replication::server=false;Population client;assert(client.Prepare(&def)==ERR_PrepareResult::FAILED&&client.surveys==0); } ''') print('PASS: hill prominence/elevation, actual road edges/heights/bends and server-only finite scout admission, pending stock, timeout and no replacements/refills')