"""Execute actual HQ encounter allocation with physical/radio boundary doubles.""" import re from policy_harness import ROOT, body, run p=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HunterTactics.c' code='\n'.join(body(p,x) for x in ['bool Covered(', 'protected bool PlanningPosition(', 'protected void RefreshApproaches(', 'void Tick(ERR_HQ hq, array']) code=code.replace('protected ','').replace('foreach (','for (').replace('vector position','Vec position').replace('vector desired','Vec desired') for typ in ['ERR_HunterVehicle','ERR_HunterAttack','ERR_HunterTactics','ERR_HQReport']: code=code.replace('array','Array<'+typ+'*>').replace('array<'+typ+'>','Array<'+typ+'*>') code=code.replace('array','Array') code=code.replace('out vector ', 'Vec& ').replace('out Vec ', 'Vec& ') code=re.sub(r'\bvector (?=\w)', 'Vec ',code) for typ in ['ERR_HQ','ERR_HQBelief','ERR_HQReport','ERR_HunterVehicle','ERR_HunterAttack','ERR_HunterTactics']: code=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',code) for name in ['hq','attack','old','report','belief','candidate','best','unit','selected','team','incomplete']: code=code.replace(name+'.',name+'->') code=code.replace('m_Attacks[i].','m_Attacks[i]->').replace('available[index].','available[index]->') code=code.replace('Memory().Get','Memory()->Get').replace('Tactics.Stopped','Tactics->Stopped').replace('Entity.GetOrigin','Entity->GetOrigin') code=code.replace('ERR_HunterTactics.CoverCrew','ERR_HunterTactics::CoverCrew') code=code.replace('ERR_HQ.Event','Event').replace('string.Format','Format').replace('ERR_HunterAttackRules.Fresh','Fresh').replace('ERR_HunterAttackRules.Offset','Offset').replace('vector.DistanceXZ','Distance') code=code.replace('"0 0 1"','Vec(0,0,1)').replace('bool running;','bool running=false;').replace('int nearby;','int nearby=0;').replace('bool travelling = true;', 'bool travelling = true;').replace('int active;','int active=0;').replace('int nearest;','int nearest=0;').replace('ERR_HQBelief* best;','ERR_HQBelief* best=nullptr;') run(r''' #include #include #include #include #include using string=std::string; struct Vec{float x=0,y=0,z=0;Vec(){}Vec(float a,float b,float c):x(a),y(b),z(c){}float&operator[](int i){return i==0?x:i==1?y:z;}Vec operator-(Vec b){return{x-b.x,y-b.y,z-b.z};}float Length(){return std::hypot(x,z);}void Normalize(){float l=Length();x/=l;z/=l;}}; float Distance(Vec a,Vec b){return (a-b).Length();} templatestruct Array:std::vector{using std::vector::vector;int Count(){return this->size();}bool IsEmpty(){return this->empty();}void Insert(T t){this->push_back(t);}void Remove(int i){this->erase(this->begin()+i);}void RemoveItem(T t){this->erase(std::remove(this->begin(),this->end(),t),this->end());}}; bool Fresh(float a,float n){return a>=0&&n>=a&&n-a<=60000;}Vec Offset(Vec c,Vec,int r,int){return{c.x+(r==1?-155.f:155.f),0,c.z-240};} string Format(string,int,Vec){return "";}void Event(string,string,int){} struct ERR_GameMode{};struct Entity{Vec pos;Vec GetOrigin(){return pos;}}; struct ERR_HunterTactics; struct ERR_HunterVehicle{void*Downlink=nullptr;string Source="hunter";bool CloseContactHeld=false,Registered=true,Released=false,valid=true,plan=true,radio=true,armed=true;struct Entity entity;struct Entity*Entity=&entity;ERR_HunterTactics*Tactics=nullptr;bool CrewValid(ERR_GameMode*){return valid;}}; struct ERR_HQBelief{Vec PredictedPosition;float ObservedAt=0;int BeliefId=1,MessageId=1;bool actionable=true;bool Actionable(){return actionable;}}; struct ERR_HQReport{int Target=0;};struct Memory{Array beliefs;ERR_HQBelief*Get(int i){return &beliefs[i];}}; struct ERR_HQ{bool CoordinatedDoctrine(){return false;}bool CoordinatedHunterCandidate(string,ERR_HQBelief*,float,Vec&){return false;}struct Memory memory;Arrayreports;struct Memory*Memory(){return &memory;}void SupportContacts(Array&out,float){for(auto&r:reports)out.Insert(&r);}void Contact(Vec p,float age){ERR_HQBelief b;b.PredictedPosition=p;b.ObservedAt=age;b.BeliefId=memory.beliefs.Count()+1;reports.Insert({memory.beliefs.Count()});memory.beliefs.Insert(b);}}; struct ERR_HunterAttack{int BeliefId=0;Vec ReportPosition,Forward;float Observed=0,Started=0;int Message=0;ArrayTeams;}; struct ERR_HunterTactics{static bool CoverCrew(ERR_HunterVehicle*u,ERR_GameMode*){return u->armed;}ERR_HunterVehicle*Unit;ERR_HunterAttack*Attack;int Role,State=0;bool visual=false;bool Covering(){return visual;}bool Stopped=false;Vec Stage;ERR_HunterTactics(ERR_GameMode*,ERR_HunterVehicle*u,ERR_HunterAttack*a,int r):Unit(u),Attack(a),Role(r){}bool Plan(Array){Stage=Unit->Entity->GetOrigin();return Unit->plan;}bool Queue(ERR_HQ*){return Unit->radio;}bool Living(){return !Unit->Released;}void Stop(){Stopped=true;}}; struct Coordination{ERR_GameMode mode;ERR_GameMode*m_Mode=&mode;Arraym_Attacks;float m_NextPlan=0; '''+code+r''' }; int main(){ {ERR_HQ local;local.Contact({0,0,0},0);ERR_HunterVehicle busy,other;busy.CloseContactHeld=true; Array pair={&busy,&other};Coordination c;c.Tick(&local,pair,1000);assert(c.m_Attacks.empty());} // Only newer delivered knowledge for this belief redirects traveling crews. {Coordination c;ERR_HunterVehicle u,v;ERR_HunterAttack a;a.BeliefId=3;a.Observed=10; ERR_HunterTactics t(&c.mode,&u,&a,0),f(&c.mode,&v,&a,1);a.Teams={&t,&f};c.m_Attacks={&a}; ERR_HQBelief b;b.BeliefId=4;b.ObservedAt=20;b.PredictedPosition={500,0,0}; c.RefreshApproaches(&b,100);assert(!t.Stopped&&!f.Stopped); b.BeliefId=3;f.State=2;c.RefreshApproaches(&b,100);assert(!t.Stopped&&!f.Stopped); f.State=1;b.ObservedAt=9;c.RefreshApproaches(&b,100);assert(!t.Stopped); b.ObservedAt=20;b.PredictedPosition={249,0,0};c.RefreshApproaches(&b,100);assert(!t.Stopped); b.PredictedPosition={250,0,0};t.State=3;t.visual=true;c.RefreshApproaches(&b,100);assert(!t.Stopped&&!f.Stopped); // active gun retains fight t.visual=false;c.RefreshApproaches(&b,100);assert(t.Stopped&&f.Stopped); // blind idle gun cannot trap the travelling truck on old report } ERR_HQ hq;hq.Contact({0,0,0},0);hq.Contact({6000,0,0},1); // Newer but unreachable report must not starve local fight. ERR_HunterVehicle a,b,c;a.entity.pos={0,0,-210};b.entity.pos={-155,0,-240};c.entity.pos={155,0,-240}; Arrayunits={&a,&b,&c};Coordination co;co.Tick(&hq,units,1000); assert(co.m_Attacks.Count()==1&&co.m_Attacks[0]->Teams.Count()==3); assert(a.Tactics->Role==0&&b.Tactics->Role==1&&c.Tactics->Role==2); a.Tactics->Stopped=true;b.Tactics->Stopped=true;assert(!co.Covered({200,0,0}));a.Tactics->Stopped=false;b.Tactics->Stopped=false; a.Released=true;b.Released=true;assert(!co.Covered({200,0,0}));a.Released=false;b.Released=false; assert(co.Covered({200,0,0})&&!co.Covered({6000,0,0})); ERR_HunterVehicle d,e;d.entity.pos={6000,0,-210};e.entity.pos={5845,0,-240};units.Insert(&d);units.Insert(&e); co.Tick(&hq,units,5000);assert(!d.Tactics); // Five-second planning throttle. co.Tick(&hq,units,11000);assert(co.m_Attacks.Count()==2&&d.Tactics&&e.Tactics); // Independent front. co.Tick(&hq,units,21000);assert(co.m_Attacks.Count()==2); // No duplicate crews/encounter. for(auto*t:co.m_Attacks[0]->Teams)t->Stop(); co.Tick(&hq,units,70000);assert(co.m_Attacks.Count()==1&&!co.Covered({0,0,0})); // Expired report not reused. {ERR_HQ h;h.Contact({},0);ERR_HunterVehicle u,v;u.entity.pos={0,0,-150};v.entity.pos={-150,0,-240};u.armed=false;Coordination x;x.Tick(&h,{&u,&v},1000);assert(x.m_Attacks.Count()==1&&v.Tactics->Role==0&&u.Tactics->Role==1);} {ERR_HQ h;h.Contact({},0);ERR_HunterVehicle u,v;u.armed=false;v.armed=false;Coordination x;x.Tick(&h,{&u,&v},1000);assert(x.m_Attacks.empty()&&!u.Tactics&&!v.Tactics);} {ERR_HQ h;h.Contact({},0);ERR_HunterVehicle u,v;u.entity.pos={0,0,-200};v.entity.pos={-150,0,-240};v.radio=false;Coordination x;x.Tick(&h,{&u,&v},1000);assert(x.m_Attacks.empty()&&u.Tactics&&u.Tactics->Stopped);} {ERR_HQ h;h.Contact({},0);ERR_HunterVehicle u,v;u.entity.pos={0,0,-200};v.entity.pos={-150,0,-240};u.plan=false;Coordination x;x.Tick(&h,{&u,&v},1000);assert(x.m_Attacks.empty()&&!u.Tactics&&!v.Tactics);} {ERR_HQ h;h.Contact({},0);ERR_HunterVehicle u,v;u.entity.pos={0,0,-200};v.Released=true;Coordination x;x.Tick(&h,{&u,&v},1000);assert(x.m_Attacks.empty());v.Released=false;v.valid=false;x.Tick(&h,{&u,&v},11000);assert(x.m_Attacks.empty());} {ERR_HQ h;h.Contact({},0);ERR_HunterVehicle u,v;Coordination x;for(int i=0;i<5;i++){auto*a=new ERR_HunterAttack();a->Teams.Insert(new ERR_HunterTactics(&x.mode,&u,a,0));x.m_Attacks.Insert(a);}x.Tick(&h,{&u,&v},1000);assert(x.m_Attacks.Count()==5&&!u.Tactics);} } ''') print('PASS: actual HQ allocator selects reachable reports, distinct cover/flanks, simultaneous fronts, bounded reservations and failed-radio/placement rollback')