"""Execute actual HQ multi-convoy planning with delivered-report boundaries doubled.""" import os, re, sys from pathlib import Path ROOT=Path(os.environ.get('ERR_REPO','/home/jakub/devel/escapistsrereintroduced')) sys.path.insert(0,str(ROOT/'tests')) from policy_harness import body,run p=Path(os.environ.get('ERR_HQ_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c')) methods='\n'.join(body(p,s) for s in ('void PlanResupply(float now)','bool PlanResupplyTask(ERR_InfantryResupply supply, float now)')) methods=methods.replace('null','nullptr').replace('foreach (','for (') methods=methods.replace('ERR_HQUnit donor;','ERR_HQUnit donor=nullptr;') for name in ('m_Resupply','supply','task','unit','donor','recipient','mounted','mineRecipient','launcherRecipient','m_Watch'): methods=methods.replace(name+'.',name+'->') methods=methods.replace('task->Vehicles[1].','task->Vehicles[1]->') run(r''' #include #include #include #include using string=std::string; templatestruct Array:std::vector{using std::vector::vector;int Count(){return this->size();}}; struct Unit {int Group=0;string ForceSourceId;bool fighting=false;};using ERR_HQUnit=Unit*; struct Entry {int value=0;};using ERR_HQWatchEntry=Entry*; struct Watch {std::map delivered;Entry* Find(string id){return delivered.count(id)?delivered[id]:nullptr;}}; struct Vehicle{int Group=0;}; struct Task{bool Stopped=false,Ready=true;Array Vehicles;};using ERR_ConvoyTask=Task*; struct Supply{ int state=1,calls=0,accepted=0,mountedCalls=0,mountedAccepted=0;int launcherCalls=0,launcherAccepted=0;bool launcher=false;bool infantry=true,mounted=false,mines=false;int mineCalls=0,mineAccepted=0;Task*task=nullptr;Unit* recipient=nullptr;Entry* demand=nullptr;Entry* donorReport=nullptr; int State(){return state;}Task*Task(){return task;} bool TryPlan(Unit*r,Unit*,Entry*d,Entry*s,float){calls++;if(!infantry||r!=recipient||!d||!s||d!=demand||s!=donorReport)return false;accepted++;state=2;return true;} bool TryPlanMounted(Unit*r,Unit*,Entry*d,Entry*s,float){mountedCalls++;if(!mounted||r!=recipient||d!=demand||s!=donorReport||!d||!s)return false;mountedAccepted++;state=6;return true;} bool TryPlanLauncher(Unit*r,Unit*,Entry*d,Entry*s,float){launcherCalls++;if(!launcher||r!=recipient||d!=demand||s!=donorReport||!d||!s)return false;launcherAccepted++;state=2;return true;} bool TryPlanMines(Unit*r,Unit*,Entry*d,Entry*s,float){mineCalls++;if(!mines||r!=recipient||d!=demand||s!=donorReport||!d||!s)return false;mineAccepted++;state=2;return true;} };using ERR_InfantryResupply=Supply*; struct Pool{Array services;int Count(){return services.Count();}Supply*At(int i){return services[i];}}; struct HQ{ Pool*m_Resupply=nullptr;int m_NextResupply=0;Arraym_Units;Watch*m_Watch=nullptr; bool ConvoyContact(Unit*u,float){return u->fighting;} METHODS }; struct Fixture{ Pool pool;Watch watch;HQ hq;Supply first,second;Task a,b;Vehicle va{1},vb{2};Unit da{1,"a"},db{2,"b"},recipient{3,"recipient"};Entry aStatus,bStatus,demand; Fixture(){a.Vehicles={&va,&va,&va,&va,&va,&va};b.Vehicles={&vb,&vb,&vb,&vb,&vb,&vb}; first.task=&a;second.task=&b;first.recipient=second.recipient=&recipient;first.demand=second.demand=&demand;first.donorReport=&aStatus;second.donorReport=&bStatus; watch.delivered={{"a",&aStatus},{"b",&bStatus},{"recipient",&demand}};pool.services={&first,&second};hq.m_Resupply=&pool;hq.m_Watch=&watch;hq.m_Units={&da,&db,&recipient};} }; int main(){ {Fixture f;f.first.infantry=false;f.first.launcher=true;f.first.mines=true;f.hq.PlanResupply(100);assert(f.first.launcherAccepted==1&&f.first.mineCalls==0&&f.second.calls==0);} {Fixture f;f.first.launcher=true;f.hq.PlanResupply(100);assert(f.first.accepted==1&&f.first.launcherCalls==0);} {Fixture f;f.first.infantry=false;f.first.mounted=true;f.first.launcher=true;f.hq.PlanResupply(100);assert(f.first.mountedAccepted==1&&f.first.launcherCalls==0);} {Fixture f;f.first.infantry=false;f.first.mounted=false;f.first.mines=true;f.hq.PlanResupply(100);assert(f.first.mineAccepted==1&&f.first.mountedCalls>0&&f.second.calls==0);} {Fixture f;f.first.mines=true;f.hq.PlanResupply(100);assert(f.first.accepted==1&&f.first.mineCalls==0);} {Fixture f;f.first.infantry=false;f.first.mounted=true;f.first.mines=true;f.hq.PlanResupply(100);assert(f.first.mountedAccepted==1&&f.first.mineCalls==0);} {Fixture f;f.first.mounted=true;f.hq.PlanResupply(100);assert(f.first.accepted==1&&f.first.mountedCalls==0);} {Fixture f;f.first.infantry=false;f.first.mounted=true;f.hq.PlanResupply(100);assert(f.first.accepted==0&&f.first.mountedAccepted==1&&f.second.calls==0);} {Fixture f;f.first.infantry=false;f.first.mounted=true;f.recipient.fighting=true;f.hq.PlanResupply(100);assert(f.first.mountedAccepted==0);} {Fixture f;f.first.state=0;f.hq.PlanResupply(100);assert(f.first.calls==0&&f.second.accepted==1);} {Fixture f;f.hq.PlanResupply(100);assert(f.first.accepted==1&&f.second.calls==0);f.first.state=1; f.hq.PlanResupply(105);assert(f.second.accepted==1&&f.first.accepted==1);} {Fixture f;f.a.Stopped=true;f.hq.PlanResupply(100);assert(f.first.calls==0&&f.second.accepted==1);} {Fixture f;f.da.fighting=true;f.hq.PlanResupply(100);assert(f.first.calls==0&&f.second.accepted==1);} {Fixture f;f.watch.delivered.erase("a");f.hq.PlanResupply(100);assert(f.first.accepted==0&&f.second.accepted==1);} {Fixture f;f.watch.delivered.erase("recipient");f.hq.PlanResupply(100);assert(f.first.accepted==0&&f.second.accepted==0);} {Fixture f;f.pool.services={nullptr,&f.second};f.hq.m_NextResupply=17;f.hq.PlanResupply(100);assert(f.second.accepted==1);} {Fixture f;f.a.Vehicles[1]=nullptr;f.hq.PlanResupply(100);assert(f.first.calls==0&&f.second.accepted==1);} {Fixture f;f.pool.services.resize(21,&f.first);f.hq.PlanResupply(100);assert(f.first.calls==0);} {Fixture f;f.pool.services.clear();f.hq.PlanResupply(100);f.hq.m_Resupply=nullptr;f.hq.PlanResupply(100);assert(f.first.calls==0);} } '''.replace('METHODS',methods).replace('Task*Task()','struct Task*Task()').replace('Task*task=','struct Task*task=')) print('PASS: actual HQ rotates finite donors, skips unavailable/contacted trucks, uses delivered reports and dispatches at most one trip per planning cadence')