"""Execute radio-site reinforcement selection, quotas and defence geometry from production.""" import re from policy_harness import ROOT, body, run P=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c' HQ=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c' def cpp(s): s=s.replace('protected ', '').replace('foreach (', 'for (').replace('null', 'nullptr') s=s.replace('array sites', 'Array sites').replace('array reserved', 'Array reserved') s=s.replace('array locations = {};', 'Array locations;') s=s.replace('array candidates = {};', 'Array candidates;') s=s.replace('out vector position', 'Vec& position').replace('vector ', 'Vec ') for typ in ('ERR_HQUnit','ERR_HQTask','ERR_HQWatchEntry','ERR_LocationComponent','ERR_HQRoute','ERR_HQReport'): s=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',s) for name in ('unit','target','location','planned','best','candidate','status','task','lineage','m_Mode'): s=s.replace(name+'.',name+'->') s=s.replace('PendingTask.', 'PendingTask->').replace('Task.', 'Task->') for typ in ('ERR_BodyRecoveryRules','ERR_InfantryResupplyRules','ERR_LocationKind','ERR_HQPursuitRole','ERR_Actors','ERR_HQRoadIntercept','Math','vector'): s=s.replace(typ+'.',('Geometry' if typ=='vector' else typ)+'::') s=s.replace('ERR_HQ.Event','Event').replace('string.Format','Format').replace('GetGame().GetWorld().GetWorldTime()', 'clock') s=s.replace('int committed;', 'int committed=0;').replace('int queued;', 'int queued=0;').replace('int count;', 'int count=0;').replace('int total;', 'int total=0;') s=s.replace('bool occupied;', 'bool occupied=false;').replace('ERR_HQUnit* best;', 'ERR_HQUnit* best=nullptr;').replace('ERR_LocationComponent* target;', 'ERR_LocationComponent* target=nullptr;') return s rules=cpp(body(P,'class ERR_BodyRecoveryRules')).replace('class ERR_BodyRecoveryRules','struct ERR_BodyRecoveryRules')+';' methods='\n'.join(cpp(body(P,s)) for s in ('protected bool SecurityCandidate(', 'protected bool SecurityPosition(', 'protected void TrySecureSites(')) budgets='\n'.join(cpp(body(HQ,s)) for s in ('protected bool SecurityAssigned(', 'protected int ResponseAssigned(', 'protected int HuntingAssigned(')) run(r''' #include #include #include #include #include #include struct string:std::string{using std::string::string;string(std::string s):std::string(s){}bool IsEmpty(){return empty();}}; template string Format(string s,T...){return s;}void Event(string,string){} struct Vec{float x=0,y=0,z=0;Vec operator+(Vec b){return {x+b.x,y+b.y,z+b.z};}Vec operator*(float f){return {x*f,y*f,z*f};}}; Vec Vector(float x,float y,float z){return {x,y,z};} namespace Geometry{float DistanceXZ(Vec a,Vec b){return std::hypot(a.x-b.x,a.z-b.z);}} namespace Math{const float DEG2RAD=3.14159265359f/180;float Sin(float x){return std::sin(x);}float Cos(float x){return std::cos(x);}float Min(float a,float b){return std::min(a,b);}} templatestruct Array:std::vector{using std::vector::vector;void Insert(T t){this->push_back(t);}int Count(){return this->size();}bool IsEmpty(){return this->empty();}void RemoveItem(T t){this->erase(std::find(this->begin(),this->end(),t));}}; namespace ERR_LocationKind{enum{RADIO=1,DEPOT=2};} namespace ERR_HQPursuitRole{enum{SEARCH};} namespace ERR_Actors{Vec Ground(Vec p){p.y=10;return p;}} namespace ERR_HQRoadIntercept{bool standable=true;int calls=0;bool Standable(Vec){calls++;return standable;}} struct ERR_HQTask{string SecuritySite;float ExpiresAt=0,QueuedAt=0;int Role=0;Vec Destination;bool ReleaseOnly=false,investigation=false;ERR_HQTask* ReplacesTask=nullptr;bool Investigation(){return investigation;}}; struct ERR_HQReport{Vec Position;float ObservedAt=0;bool Distress=false;}; struct ERR_HQRoute{}; struct ERR_HQWatchEntry{Vec Position;bool fresh=true,blocked=false;}; namespace ERR_InfantryResupplyRules{bool Fresh(ERR_HQWatchEntry*s,float){return s&&s->fresh;}} struct Group{bool connected=true;}; struct ERR_HQUnit{int Id=0,ForceSourceId=0;bool HomeGuard=false,eligible=true,fighting=false,Radio=true,PendingCheckin=false,PendingConvoyOrder=false; struct Group group;struct Group* Group=&group;ERR_HQTask* Task=nullptr;ERR_HQTask* PendingTask=nullptr;ERR_HQReport* Assignment=nullptr;ERR_HQReport* PendingOrder=nullptr;ERR_HQRoute* Downlink=nullptr; bool Eligible(void*){return eligible;}ERR_HQTask* PlannedTask(){return PendingTask?PendingTask:Task;}}; struct Watch{std::map entries;ERR_HQWatchEntry* Find(int id){return &entries[id];}bool ArmedSearchBlocked(int id,float){return entries[id].blocked;}}; struct Network{bool connected=true;bool Route(bool,bool){return connected;}}; struct Compromised{std::map times;float Get(string s){return times[s];}}; struct ERR_LocationComponent{string id="radio";int kind=ERR_LocationKind::RADIO;Vec position;string Id(){return id;}int Kind(){return kind;}Vec Position(){return position;}}; struct Mode{Array sites;void Locations(Array& out){out=sites;}}; '''+rules+r''' struct HQ{float clock=1000;int queued=0,mounted=0;Mode mode;Mode* m_Mode=&mode;Watch m_Watch;Network m_Network;Compromised m_Compromised;Array m_Units; bool Fighting(ERR_HQUnit*u){return u->fighting;} ERR_HQRoute* Downlink(Group*g,string,string,int){if(!g->connected)return nullptr;queued++;return new ERR_HQRoute();} int Assigned(){int total=mounted;for(auto* u:m_Units)if(u->Assignment||u->PendingOrder)total++;return total;} '''+methods+budgets+r''' }; struct Fixture{HQ h;ERR_LocationComponent radio;ERR_HQUnit units[6];Fixture(){h.mode.sites={&radio};h.m_Compromised.times["radio"]=1800000; for(int i=0;i<6;i++){units[i].Id=i+1;units[i].ForceSourceId=i;h.m_Units.Insert(&units[i]);h.m_Watch.entries[i].Position={float((i+1)*100),0,0};}} void dispatch(){h.TrySecureSites({"radio"});} int count(){int n=0;for(auto&u:units)if(u.PendingTask)n++;return n;}}; int main(){ for(int n=0;n<10;n++)assert(ERR_BodyRecoveryRules::TeamSlot(n)==(n<4)); assert(ERR_BodyRecoveryRules::SpawnBudget(11,47,253)); assert(!ERR_BodyRecoveryRules::SpawnBudget(12,0,0)&&!ERR_BodyRecoveryRules::SpawnBudget(0,48,0)&&!ERR_BodyRecoveryRules::SpawnBudget(0,0,254)); assert(ERR_BodyRecoveryRules::SecurityTarget(true,0)==0); for(int n=1;n<=128;n++){int k=ERR_BodyRecoveryRules::SecurityTarget(true,n);assert(k==(2*n+2)/3&&k<=n);assert(ERR_BodyRecoveryRules::SecurityTarget(false,n)==1);} {Fixture f;f.dispatch();assert(f.count()==4&&f.h.queued==4); // two thirds, nearest first for(int i=0;i<4;i++){auto*t=f.units[i].PendingTask;assert(t&&t->SecuritySite=="radio"&&t->ExpiresAt==601000&&!f.units[i].Task); auto d=Geometry::DistanceXZ(t->Destination,{});assert(d>=119.9&&d<=220.1); for(int j=0;jDestination,f.units[j].PendingTask->Destination)>=60);} f.dispatch();assert(f.count()==4&&f.h.queued==4); // pending orders count: no growth toward 100% or duplication f.h.mounted=2;assert(f.h.Assigned()==6&&f.h.ResponseAssigned()==2&&f.h.HuntingAssigned()==0); // preserve separately counted mounted dispatches ERR_HQTask pursuit;ERR_HQReport report;f.units[4].Task=&pursuit;f.units[4].Assignment=&report; assert(f.h.ResponseAssigned()==3&&f.h.HuntingAssigned()==1); } {Fixture f;f.radio.kind=ERR_LocationKind::DEPOT;f.dispatch();assert(f.count()==1&&f.units[0].PendingTask->Destination.x==0);} {Fixture f;f.units[0].group.connected=false;f.dispatch();assert(f.count()==4&&!f.units[0].PendingTask&&f.units[4].PendingTask);} {Fixture f;f.h.m_Network.connected=false;f.dispatch();assert(f.count()==0);} {Fixture f;ERR_HQRoadIntercept::standable=false;int calls=ERR_HQRoadIntercept::calls;f.dispatch();assert(f.count()==0&&ERR_HQRoadIntercept::calls==calls+6*24);ERR_HQRoadIntercept::standable=true;} {Fixture f;f.h.m_Compromised.times.clear();f.dispatch();assert(f.count()==0); // no delivered compromise record f.h.m_Compromised.times["radio"]=1000;f.dispatch();assert(f.count()==0); f.h.m_Compromised.times["radio"]=1500;f.dispatch();assert(f.units[0].PendingTask->ExpiresAt==1500);} {Fixture f;f.h.m_Watch.entries[0].Position.x=2500;assert(f.h.SecurityCandidate(&f.units[0],{},1000)); f.h.m_Watch.entries[0].Position.x=2501;assert(!f.h.SecurityCandidate(&f.units[0],{},1000));} for(int fault=0;fault<14;fault++){Fixture f;auto&u=f.units[0];ERR_HQTask task;ERR_HQReport report;ERR_HQRoute route; if(fault==0)u.eligible=false; if(fault==1)u.HomeGuard=true; if(fault==2)u.fighting=true; if(fault==3)u.Radio=false; if(fault==4)u.Task=&task; if(fault==5)u.PendingTask=&task; if(fault==6)u.Assignment=&report; if(fault==7)u.PendingOrder=&report; if(fault==8)u.Downlink=&route; if(fault==9)u.PendingConvoyOrder=true; if(fault==10)u.PendingCheckin=true; if(fault==11)f.h.m_Watch.entries[0].fresh=false; if(fault==12)f.h.m_Watch.entries[0].blocked=true; if(fault==13)f.h.m_Network.connected=false; assert(!f.h.SecurityCandidate(&u,{},1000));} {Fixture f;ERR_LocationComponent other;other.id="other";f.h.mode.sites.Insert(&other);f.h.m_Compromised.times["other"]=1800000; f.h.TrySecureSites({"radio","other"});int first=0,second=0;for(auto&u:f.units){if(u.PendingTask->SecuritySite=="radio")first++;else second++;} assert(first==4&&second==2); // a pending group cannot be taken by another compromised site } } ''') print('PASS: four-team/twelve-wave bounds; two-thirds nearby radio defence; nearest selection, radio failures, expiry, perimeter separation, protected duties and independent response budgets')