"""Actual bounded negative-search coverage rules; physical radio delivery is HQ's boundary.""" from policy_harness import ROOT, body, run P=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQCoverage.c' PURSUIT=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQPursuit.c' def cpp(s): return (s.replace('protected ', '').replace('Math.', 'Math::').replace('vector.', 'vector::') .replace('ERR_HQPursuitRules.', 'ERR_HQPursuitRules::').replace('ERR_HQCoverageRules.', 'ERR_HQCoverageRules::') .replace('out vector ', 'vector& ').replace('array reserved', 'Array* reserved') .replace('ERR_HQSearchReport report', 'ERR_HQSearchReport* report').replace('report.', 'report->') .replace('reserved.Count()', 'reserved->Count()').replace('= null', '= nullptr') .replace('foreach (vector position : reserved)', 'for (vector position : *reserved)') .replace('foreach (int known, float searched : m_Cells)', 'for (auto [known, searched] : m_Cells)') .replace('int oldestKey;', 'int oldestKey=0;').replace('bool found;', 'bool found=false;')) common='\n'.join(cpp(body(PURSUIT,s)) for s in ('static bool Finite(', 'static bool PositionValid(')) rules='\n'.join(cpp(body(P,s)) for s in ('static bool PositionValid(', 'static int Cell(', 'static int Key(', 'static bool Recent(', 'static bool ValidReport(', 'static bool Point(')) methods='\n'.join(cpp(body(P,s)) for s in ('int Count(', 'void Forget(', 'bool Recent(vector', 'bool Ingest(', 'protected bool Reserved(', 'bool Select(', 'void Clear(')) run(r''' #include #include #include #include #include #include struct vector{ float x=0,y=0,z=0; float& operator[](int i){return i==0?x:i==1?y:z;} float operator[](int i)const{return i==0?x:i==1?y:z;} static float DistanceXZ(vector a,vector b){return std::hypot(a.x-b.x,a.z-b.z);} }; vector Vector(float x,float y,float z){return {x,y,z};} struct Math{ static float Clamp(float n,float lo,float hi){return std::clamp(n,lo,hi);} static float Floor(float n){return std::floor(n);} static float AbsFloat(float n){return std::abs(n);} }; templatestruct Array:std::vector{int Count(){return this->size();}}; templatestruct Map:std::map{ bool Contains(K k){return this->count(k);}V Get(K k){return this->count(k)?this->at(k):V{};} int Count(){return this->size();}void Set(K k,V v){(*this)[k]=v;} void Remove(K k){this->erase(k);}void Clear(){this->clear();} }; struct ERR_HQPursuitRules{ '''+common+r''' }; struct ERR_HQCoverageRules{ '''+rules+r''' }; struct ERR_HQSearchReport{ int SourceId=1,MessageId=1,BeliefId=1,BeliefRevision=1; vector Position{250,12,250};float ObservedAt=0; bool SweepCompleted=true,ContactFound=false; }; struct Coverage{ Mapm_Cells;Mapm_Messages; '''+methods+r''' }; int main(){ using R=ERR_HQCoverageRules; assert(R::Cell(0)==0&&R::Cell(499.9)==0&&R::Cell(500)==1); assert(R::Cell(-.1)==-1&&R::Cell(-500)==-1&&R::Cell(-500.1)==-2); assert(R::Key({-1,0,0})!=R::Key({0,0,-1})); assert(R::Recent(0,900000)&&!R::Recent(0,900001)&&!R::Recent(1,0)); assert(R::ValidReport(1,1,1,1,true,false,0,120000)); assert(!R::ValidReport(1,1,1,1,true,false,0,120001)); assert(!R::ValidReport(1,1,1,1,false,false,0,1000)); assert(!R::ValidReport(1,1,1,1,true,true,0,1000)); assert(!R::ValidReport(1,1,0,1,true,false,0,1000)); assert(!R::ValidReport(1,1,1,0,true,false,0,1000)); float nan=std::numeric_limits::quiet_NaN(); assert(!R::ValidReport(1,1,1,1,true,false,nan,1000)); assert(!R::PositionValid({nan,0,0})&&!R::PositionValid({1000000,0,0})); vector point; assert(R::Point(0,0,{0,12,0},0,point)&&point.x==0&&point.z==0); assert(R::Point(0,0,{180,12,180},25,point)&&point.x==180&&point.z==180); assert(!R::Point(2,2,{180,12,180},25,point)); // Undelivered reports remain inert objects. Only Ingest applies the delivered snapshot. Coverage coverage;ERR_HQSearchReport report; assert(coverage.Count()==0&&!coverage.Recent(report.Position,1000)); assert(coverage.Ingest(&report,1000)&&coverage.Count()==1); assert(coverage.Recent(report.Position,900000)&&!coverage.Recent(report.Position,900001)); assert(!coverage.Ingest(&report,1000)); report.Position={750,12,250};report.BeliefRevision=2; assert(!coverage.Ingest(&report,1000)&&!coverage.Recent(report.Position,1000)); report.MessageId=2;report.ObservedAt=1000; assert(coverage.Ingest(&report,2000)&&coverage.Count()==2); report.MessageId=1;report.Position={1250,12,250}; assert(!coverage.Ingest(&report,2000)); // Invalid/future/old/incomplete/positive observations never advance replay guards. ERR_HQSearchReport invalid;invalid.SourceId=2; for(int field=0;field<8;field++){ invalid=ERR_HQSearchReport{};invalid.SourceId=2; if(field==0)invalid.ObservedAt=2001; if(field==1)invalid.SweepCompleted=false; if(field==2)invalid.ContactFound=true; if(field==3)invalid.BeliefId=0; if(field==4)invalid.BeliefRevision=0; if(field==5)invalid.Position.x=nan; if(field==6)invalid.MessageId=0; if(field==7)invalid.ObservedAt=-1; assert(!coverage.Ingest(&invalid,2000)&&!coverage.m_Messages.Contains(2)); } assert(!coverage.Ingest(nullptr,2000)); // A fresh positive sighting may reopen a coarse cell, without replaying an old negative. Coverage reopened;ERR_HQSearchReport searched; assert(reopened.Ingest(&searched,1000)); reopened.Forget({1,12,1});assert(reopened.Count()==0); assert(!reopened.Ingest(&searched,1000)); searched.MessageId=2;searched.ObservedAt=2000; assert(reopened.Ingest(&searched,2000)); reopened.Forget({nan,0,0});assert(reopened.Count()==1); // Delivery latency does not restart the 900-second coverage lifetime. Coverage delayed;ERR_HQSearchReport late; assert(delayed.Ingest(&late,120000)); assert(delayed.Recent(late.Position,900000)&&!delayed.Recent(late.Position,900001)); Coverage old;assert(!old.Ingest(&late,120001)&&old.Count()==0); // Bounded cell retention evicts the oldest only for genuinely newer coverage. Coverage bounded;ERR_HQSearchReport item; for(int i=0;i<128;i++){ item.MessageId=i+1;item.Position={float(i*500+250),12,250};item.ObservedAt=1000+i; assert(bounded.Ingest(&item,2000)); } assert(bounded.Count()==128); item.MessageId=129;item.Position={70000,12,250};item.ObservedAt=999; assert(!bounded.Ingest(&item,2000)&&bounded.Count()==128); item.MessageId=130;item.ObservedAt=1500; assert(bounded.Ingest(&item,2000)&&bounded.Count()==128); assert(!bounded.Recent({250,12,250},2000)&&bounded.Recent(item.Position,2000)); // Replay watermarks do not grow or evict an old source's identity under pressure. Coverage sources; for(int i=1;i<=128;i++){ item=ERR_HQSearchReport{};item.SourceId=i;item.ObservedAt=i; assert(sources.Ingest(&item,1000)); } item.SourceId=129;item.ObservedAt=129; assert(!sources.Ingest(&item,1000)&&sources.m_Messages.Count()==128); item.SourceId=1;item.MessageId=2;item.ObservedAt=130; assert(sources.Ingest(&item,1000)&&sources.m_Messages.Count()==128); // Nearest unswept candidates remain inside uncertainty, including a small circle. Coverage search;vector center{250,12,250},destination; assert(search.Select(center,25,{1000,0,250},1000,destination)); assert(R::Key(destination)==R::Key(center)&&vector::DistanceXZ(center,destination)<=25); item=ERR_HQSearchReport{};assert(search.Ingest(&item,1000)); assert(!search.Select(center,25,{1000,0,250},1000,destination)); assert(search.Select(center,25,{1000,0,250},900001,destination)); assert(search.Select(center,600,{1000,0,250},1000,destination)); assert(destination.x==750&&destination.z==250); Array reserved;reserved.push_back({501,0,1}); // different point, same reserved cell assert(search.Select(center,600,{1000,0,250},1000,destination,&reserved)); assert(R::Key(destination)!=R::Key(reserved[0])); assert(vector::DistanceXZ(center,destination)<=600); Coverage tiny;reserved.clear();reserved.push_back({1,0,1}); assert(!tiny.Select(center,25,center,1000,destination,&reserved)); for(int i=0;i<7;i++)reserved.push_back(center); assert(reserved.Count()==8&&tiny.Select(center,2000,center,1000,destination,&reserved)); reserved.push_back(center); assert(!tiny.Select(center,2000,center,1000,destination,&reserved)); assert(!tiny.Select(center,2001,center,1000,destination)); assert(!tiny.Select(center,-1,center,1000,destination)); assert(!tiny.Select(center,nan,center,1000,destination)); assert(!tiny.Select(center,100,center,-1,destination)); assert(!tiny.Select({nan,0,0},100,center,1000,destination)); assert(!tiny.Select(center,100,{nan,0,0},1000,destination)); sources.Clear();assert(sources.Count()==0&&sources.m_Messages.Count()==0); } ''') source=P.read_text() for forbidden in ('GetGame(', 'GetOrigin(', 'GetPlayers(', 'GetControlledEntity(', 'Spawn(', 'CallLater(', 'IEntity'): assert forbidden not in source assert all(len(line)<120 for line in source.splitlines()) print('PASS: actual bounded delivered-negative coverage, replay/freshness/expiry/invalid guards, oldest eviction, small-circle and nearest-unswept selection, reserved-cell exclusion and cleanup')