"""Execute the complete read-only supply travel probe with native boundary doubles.""" import os,re from pathlib import Path from policy_harness import ROOT,run p=Path(os.environ.get('ERR_NATIVE_SUPPLY_TRAVEL_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyTravelProbe.c')) s=p.read_text() assert s.startswith('#ifdef WORKBENCH') and s.rstrip().endswith('#endif') for forbidden in ('SetOrigin(', 'SetAngles(', 'Spawn(', 'TrySpawn', 'SetHealth(', 'SetAmmo', '.Dispatch(', '.Reserve(', '.Tick(', '.Advance(', '.AddWaypoint(', '.RemoveWaypoint(', '.Ingest('): assert forbidden not in s,forbidden code=s.replace('#ifdef WORKBENCH','').replace('#endif','').replace('protected ','').replace('class ERR_Native','struct ERR_Native') code=code.replace('void ERR_NativeSupplyTravelProbe(', 'ERR_NativeSupplyTravelProbe(') code=re.sub(r'array]+)>',r'array<\1*>',code).replace('ref ','') code=re.sub(r'array<([^>]+)>',r'Arr<\1>',code).replace('vector','Vec') code=code.replace('ERR_SupplyConvoyService.Cast(hq.Convoys())','dynamic_cast(hq->Convoys())') code=code.replace('ERR_SupplyConvoyTask.Cast(m_Service.At(index))','dynamic_cast(m_Service->At(index))') code=re.sub(r'\bERR_NativeSupplyTravelFormation (?=\w)', 'ERR_NativeSupplyTravelFormation* ',code) code=code.replace('foreach (','for (').replace('null','nullptr').replace('slot.ToString()','std::to_string(slot)') for typ in ('ERR_ForceRules','ERR_Actors','ERR_GameMode','ERR_ConvoyRules','CompartmentAccessComponent','Replication','Vec'): code=code.replace(typ+'.',typ+'::') code=code.replace('LogLevel.ERROR','LogLevel::ERROR').replace('ERR_ForceKind.CONVOY','ERR_ForceKind::CONVOY') for var in ('m_Mode','m_HQ','m_Service','m_Task','m_Receipt','saved','task','service','hq','record','original','agent','escort','team'): code=re.sub(r'\b'+var+r'\.',var+'->',code) for field in ('Escort','Team','Root','Group','Record'): code=code.replace(field+'.',field+'->') code=code.replace('Tactics.','Tactics->').replace('Forces().','Forces()->').replace('].GetOccupant()',']->GetOccupant()') code=re.sub(r'^(\s*)(?!return\b)([\w<>*]+) (\w+);$',r'\1\2 \3{};',code,flags=re.M) code=code.replace('\n}\n','\n};\n') prelude=r''' #include #include #include #include #include using string=std::string; templatestruct Arr:std::vector{using std::vector::vector;int Count()const{return this->size();}bool IsEmpty()const{return this->empty();}void Insert(T v){this->push_back(v);}void Clear(){this->clear();}bool Contains(T v)const{return std::find(this->begin(),this->end(),v)!=this->end();}void Copy(const Arr&a){*this=a;}int Find(T v)const{auto i=std::find(this->begin(),this->end(),v);return i==this->end()?-1:i-this->begin();}}; struct Vec{float v[3]={0,0,0};Vec()=default;Vec(float x,float y,float z){v[0]=x;v[1]=y;v[2]=z;}float&operator[](int i){return v[i];}float operator[](int i)const{return v[i];}static float DistanceXZ(Vec a,Vec b){return std::hypot(a[0]-b[0],a[2]-b[2]);}}; struct Entity;struct SCR_AIGroup; using IEntity=Entity*;using Vehicle=Entity*; struct Entity{Vec position;bool alive=true,fight=true,player=false;SCR_AIGroup*group=nullptr;IEntity vehicle=nullptr;Vec GetOrigin(){return position;}}; struct AIAgent{IEntity actor=nullptr;IEntity GetControlledEntity(){return actor;}}; struct SCR_AIGroup{int faction=2,players=0;Arr agents;int GetFaction(){return faction;}int GetPlayerCount(bool){return players;}void GetAgents(Arr&out){out=agents;}}; struct BaseCompartmentSlot{IEntity occupant=nullptr;int type=0;IEntity GetOccupant(){return occupant;}int GetType(){return type;}}; struct ECompartmentType{static const int PILOT=0,CARGO=1;}; struct ERR_Actors{static bool Alive(IEntity a){return a&&a->alive;}static bool CanFight(IEntity a){return Alive(a)&&a->fight;}static bool Player(IEntity a){return a&&a->player;}static SCR_AIGroup*Group(IEntity a){return a?a->group:nullptr;}}; struct ERR_ForceRules{static bool Finite(float v){return std::isfinite(v);}static bool FiniteVector(Vec v){return Finite(v[0])&&Finite(v[1])&&Finite(v[2]);}}; struct CompartmentAccessComponent{static IEntity GetVehicleIn(IEntity a){return a?a->vehicle:nullptr;}}; struct LogLevel{static const int ERROR=1;}; int printed=0;void Print(const string&,int=0){printed++;}templatevoid PrintFormat(T...){printed++;} ''' prelude+=r''' struct ERR_ForceKind{static const int CONVOY=4;}; struct ForceRecord{int Id=0,Kind=ERR_ForceKind::CONVOY;bool Physical=true,Eliminated=false;SCR_AIGroup*Group=nullptr;string SourceId;};using ERR_ForceRecord=ForceRecord*; struct Ledger{Arr records;ForceRecord*FindGroup(SCR_AIGroup*g){for(auto*r:records)if(r&&r->Group==g)return r;return nullptr;}}; struct ConvoyVehicle{int Index=0;IEntity Entity=nullptr,Driver=nullptr;SCR_AIGroup*Group=nullptr;ArrMembers;ArrSeats;bool Released=false,Registered=true;};using ERR_ConvoyVehicle=ConvoyVehicle*; struct SupplyTeam{SCR_AIGroup*Group=nullptr;ArrMembers;ArrSeats;bool Released=false,Registered=true;};using ERR_SupplyTeam=SupplyTeam*; struct ConvoyReceipt{int Id=1,OutstandingBodies=0,OutstandingGroups=0;bool Consumed=true;string SourceId="supply-1";ArrRecords;};using ERR_ConvoyReceipt=ConvoyReceipt*; struct ConvoyTask{virtual ~ConvoyTask()=default;}; struct Tactics{int State(){return 0;}}; struct SupplyTask:ConvoyTask{struct Tactics*Tactics=nullptr;bool Ready=true,Stopped=false;string Reason;ERR_ConvoyReceipt Receipt=nullptr;ArrVehicles;ArrTeams;ArrStarts;};using ERR_SupplyConvoyTask=SupplyTask*; struct ConvoyService{virtual ~ConvoyService()=default;}; struct SupplyService:ConvoyService{Arrtasks;int overrideCount=-1,reads=0;int Count(){return overrideCount==-1?tasks.Count():overrideCount;}ConvoyTask*At(int i){reads++;return tasks[i];}};using ERR_SupplyConvoyService=SupplyService*; struct ERR_HQ{ConvoyService*service=nullptr;bool supply=true;ConvoyService*Convoys(){return service;}bool SupplyConvoys(){return supply;}string ConvoyStatus(){return "status";}}; struct ERR_GameMode{static inline ERR_GameMode*current=nullptr;bool active=true;ERR_HQ*hq=nullptr;Ledger ledger;bool ledgerPresent=true;static ERR_GameMode*Get(){return current;}bool Active(){return active;}Ledger*Forces(){return ledgerPresent?&ledger:nullptr;}ERR_HQ*Command(){return hq;}int EnemyFaction(){return 2;}}; struct Replication{static inline bool server=true;static bool IsServer(){return server;}}; struct ERR_ConvoyRules{static bool PartOf(IEntity a,IEntity b){return a&&a==b;}static bool Captured(IEntity r,SCR_AIGroup*g){return (r&&r->player)||(g&&g->players>0);}}; ''' # These native managed types are pointer references in Enforce. Arrays and vectors # remain values here; production Copy/identity checks are executed unchanged. code=re.sub(r'\b(ERR_GameMode|ERR_HQ|SCR_AIGroup|BaseCompartmentSlot|AIAgent)(?=[ >]|\*)',lambda m:m.group(1)+'*',code) run(prelude+code+r''' struct Setup{ ERR_GameMode mode;ERR_HQ hq;SupplyService service;SupplyTask task;ConvoyReceipt receipt;Entity roots[6],actors[25];SCR_AIGroup groups[8];ForceRecord records[8];AIAgent agents[25];BaseCompartmentSlot seats[25];ConvoyVehicle vehicles[6];SupplyTeam teams[2]; Setup(){ERR_GameMode::current=&mode;Replication::server=true;mode.hq=&hq;hq.service=&service;service.tasks.Insert(&task);task.Receipt=&receipt;int actor=0; for(int slot=0;slot<8;slot++){ auto&g=groups[slot];auto&r=records[slot];r.Id=100+slot;r.Group=&g;r.SourceId=receipt.SourceId+"-vehicle-"+std::to_string(slot);receipt.Records.Insert(r.Id);mode.ledger.records.Insert(&r); int count=slot>=6?7:slot==1||slot==2?1:slot==4?3:2; if(slot<6){auto&v=vehicles[slot];v.Index=slot;v.Entity=&roots[slot];v.Group=&g;v.Driver=&actors[actor];task.Vehicles.Insert(&v);roots[slot].position=Vec(100+slot*40,10,200);task.Starts.Insert(Vec(-1000,0,-1000));} else{teams[slot-6].Group=&g;task.Teams.Insert(&teams[slot-6]);} for(int j=0;jvehicle=nullptr;s.move();assert(p.Tick(&s.hq,2)==1);} // Permanent failure/Stop cannot re-adopt a now-valid task or pass late motion. {Setup s;ERR_NativeSupplyTravelProbe p(&s.mode,0);assert(p.Tick(&s.hq,1)==0);p.Stop();p.Stop();s.move();assert(p.Tick(&s.hq,2)==-1&&p.m_Formations.IsEmpty()&&!p.m_Task&&!p.m_Mode);} // Original task, receipt, exact record, body, group, seat and service identities // remain necessary even after every vehicle has physically moved. for(int fault=0;fault<36;fault++){ Setup s;ERR_NativeSupplyTravelProbe p(&s.mode,0);assert(p.Tick(&s.hq,1)==0);s.move(); Entity replacement;ConvoyReceipt receipt=s.receipt;ForceRecord record=s.records[0];ConvoyVehicle vehicle=s.vehicles[0];SupplyTeam team=s.teams[0];BaseCompartmentSlot seat;SCR_AIGroup group;SupplyService service=s.service;ERR_HQ hq=s.hq; if(fault==0)s.task.Ready=false; if(fault==1)s.task.Stopped=true; if(fault==2)s.task.Receipt=&receipt; if(fault==3)s.receipt.Consumed=false; if(fault==4)s.receipt.Id++; if(fault==5)s.receipt.SourceId="replacement"; if(fault==6)s.receipt.Records[0]++; if(fault==7)s.receipt.OutstandingBodies=1; if(fault==8)s.receipt.OutstandingGroups=1; if(fault==9)s.task.Vehicles[0]=&vehicle; if(fault==10)s.vehicles[0].Entity=&replacement; if(fault==11)s.vehicles[0].Group=&group; if(fault==12)s.vehicles[0].Driver=&replacement; if(fault==13)s.vehicles[0].Released=true; if(fault==14)s.vehicles[0].Registered=false; if(fault==15)s.roots[0].alive=false; if(fault==16)s.roots[0].player=true; if(fault==17)s.roots[0].position[0]=NAN; if(fault==18)s.vehicles[0].Members[1]=&replacement; if(fault==19)s.vehicles[0].Seats[0]=&seat; if(fault==20)s.vehicles[0].Driver->alive=false; if(fault==21)s.vehicles[0].Driver->fight=false; if(fault==22)s.vehicles[0].Driver->vehicle=nullptr; if(fault==23)s.vehicles[0].Seats[0]->occupant=nullptr; if(fault==24)s.task.Teams[0]=&team; if(fault==25)s.teams[0].Released=true; if(fault==26)s.teams[0].Members[0]->alive=false; if(fault==27)s.mode.ledger.records[0]=&record; if(fault==28)s.records[0].Physical=false; if(fault==29)s.records[0].Eliminated=true; if(fault==30)s.records[0].SourceId="alien"; if(fault==31)s.groups[0].agents[1]=s.groups[0].agents[0]; if(fault==32)s.hq.service=&service; if(fault==33)s.mode.hq=&hq; if(fault==34)s.service.tasks.Clear(); if(fault==35)s.groups[0].players=1; assert(p.Tick(&s.hq,2)==-1); } // Malformed admission cannot turn a smaller or duplicate formation into proof. for(int fault=0;fault<12;fault++){ Setup s;ERR_NativeSupplyTravelProbe p(&s.mode,0); if(fault==0)s.task.Vehicles.pop_back(); if(fault==1)s.task.Teams.pop_back(); if(fault==2)s.receipt.Records.pop_back(); if(fault==3)s.vehicles[1].Entity=s.vehicles[0].Entity; if(fault==4)s.teams[1].Group=s.teams[0].Group; if(fault==5)s.teams[0].Members[1]=s.teams[0].Members[0]; if(fault==6)s.teams[0].Seats[1]=s.teams[0].Seats[0]; if(fault==7)s.vehicles[0].Members.pop_back(); if(fault==8)s.teams[0].Members.pop_back(); if(fault==9)s.vehicles[0].Seats.pop_back(); if(fault==10)s.groups[0].agents.pop_back(); if(fault==11)s.mode.ledger.records[0]=nullptr; assert(p.Tick(&s.hq,1)==-1); } for(int fault=0;fault<10;fault++){ Setup s;ERR_NativeSupplyTravelProbe p(&s.mode,0);ERR_GameMode other;ConvoyService legacy; if(fault==0)Replication::server=false; if(fault==1)ERR_GameMode::current=&other; if(fault==2)s.mode.active=false; if(fault==3)s.mode.ledgerPresent=false; if(fault==4)s.hq.supply=false; if(fault==5)s.hq.service=&legacy; if(fault==6)s.service.overrideCount=21; if(fault==7){assert(p.Tick(&s.hq,10)==0);assert(p.Tick(&s.hq,9)==-1);continue;} if(fault==8){assert(p.Tick(&s.hq,NAN)==-1);continue;} if(fault==9){assert(p.Tick(&s.hq,INFINITY)==-1);continue;} assert(p.Tick(&s.hq,1)==-1); } {Setup s;ERR_NativeSupplyTravelProbe p(&s.mode,-1);assert(p.Tick(&s.hq,1)==-1);} {Setup s;ERR_NativeSupplyTravelProbe p(&s.mode,NAN);assert(p.Tick(&s.hq,1)==-1);} } ''') print('PASS: complete actual supply-travel probe, immutable 6+2 formations and 25 actors, admission/travel deadlines, six observed native-boundary moves, stop/ownership/partial-substitution refusals')