"""Run the actual bounded memory implementation with value-only native adapters. No fake world polling: identity stubs deliberately have no position/health API. """ import re from policy_harness import ROOT, run path = ROOT / 'addons/ai/Scripts/Game/ERR/ERR_HQMemory.c' source = path.read_text() for forbidden in ('GetOrigin(', 'GetControlledEntity(', 'GetPlayerManager(', 'GetDamageManager(', 'GetWorld('): assert forbidden not in source assert max(map(len, source.splitlines())) <= 120 code = source for kind in ('ERR_HQReport', 'ERR_HQMemoryTrack'): code = code.replace('ref array', 'Array<' + kind + '*>') for kind in ('int', 'float'): code = code.replace('ref array<' + kind + '>', 'Array<' + kind + '>') code = code.replace('protected ', '').replace('ref ERR_HQReport ', 'ERR_HQReport ') code = re.sub(r'\b(ERR_HQReport|ERR_HQBelief|ERR_HQMemoryTrack) ([A-Za-z_]\w*)', r'\1* \2', code) code = re.sub(r'class (\w+)\n\{', r'class \1\n{\npublic:', code) code = re.sub(r'^}', '};', code, flags=re.M) code = re.sub(r'\bvector\b', 'Vec', code) for cls in ('ERR_HQMemoryRules', 'ERR_HQMemoryKind', 'Math', 'Vec'): code = code.replace(cls + '.', cls + '::') for name in ('report', 'last', 'belief', 'previous', 'track'): code = re.sub(r'\b' + name + r'\.', name + '->', code) code = re.sub(r'm_Tracks\[([^\]]+)\]\.', r'm_Tracks[\1]->', code) code = code.replace('Latest().', 'Latest()->').replace('null', 'nullptr') code = re.sub(r'^(\s+(?:IEntity|Vec|bool|float|int|string|ERR_HQReport\*|ERR_HQMemoryTrack\*) \w+);$', r'\1{};', code, flags=re.M) run(r''' #include #include #include #include #include #include #include using string=std::string; struct Identity {int id;}; using IEntity=Identity*; struct Vec { float v[3]={0,0,0};Vec()=default;Vec(float x,float y,float z):v{x,y,z}{} float& operator[](int i){return v[i];}float operator[](int i)const{return v[i];} Vec operator+(Vec b)const{return {v[0]+b[0],v[1]+b[1],v[2]+b[2]};} Vec operator-(Vec b)const{return {v[0]-b[0],v[1]-b[1],v[2]-b[2]};} Vec operator*(float b)const{return {v[0]*b,v[1]*b,v[2]*b};} Vec operator/(float b)const{return {v[0]/b,v[1]/b,v[2]/b};} float Length()const{return std::sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);} Vec Normalized()const{return *this/Length();} static float DistanceXZ(Vec a,Vec b){return std::hypot(a[0]-b[0],a[2]-b[2]);} }; templatestruct Array:std::vector{ void Clear(){this->clear();}int Count(){return this->size();} void Insert(T v){this->push_back(v);}void Remove(int i){assert(i>=0&&ierase(this->begin()+i);} bool Contains(T v){return std::find(this->begin(),this->end(),v)!=this->end();} }; namespace Math { templateauto Max(A a,B b){using T=std::common_type_t;return std::max(T(a),T(b));} templateauto Clamp(A a,B b,C c){using T=std::common_type_t;return std::clamp(T(a),T(b),T(c));} float AbsFloat(float v){return std::abs(v);}float Pow(float a,float b){return std::pow(a,b);} float Atan2(float a,float b){return std::atan2(a,b);}constexpr float RAD2DEG=57.295779513f; } struct ERR_HQReport { int MessageId=0;IEntity Target=nullptr,Source=nullptr;Vec Position,Velocity; float ObservedAt=-1;bool Distress=false,HasVelocity=false;string TravelMode="unknown"; ERR_HQReport* Snapshot(){return new ERR_HQReport(*this);} }; ''' + code + r''' ERR_HQReport Report(int id,IEntity target,float when,Vec pos={0,0,0},string mode="on foot"){ ERR_HQReport r;r.MessageId=id;r.Target=target;r.Source=target;r.ObservedAt=when;r.Position=pos;r.TravelMode=mode;return r; } bool near(float a,float b,float tolerance=.001){return std::abs(a-b)::quiet_NaN(),inf=std::numeric_limits::infinity(); assert(near(Rules::Confidence(0),1)&&near(Rules::Confidence(600),.5)&&near(Rules::Confidence(1200),.25)); assert(Rules::Confidence(-1)==0&&Rules::Confidence(1,0)==0&&Rules::Confidence(nan)==0&&Rules::Confidence(inf)==0); assert(near(Rules::Radius(0,1.2,25),25)&&near(Rules::Radius(600,1.2,25),745)); assert(Rules::Radius(1,nan,25)>2000&&!Rules::Actionable(.5,2001)&&!Rules::Actionable(nan,20)); assert(Rules::RadiusGrowth(ERR_HQMemoryKind::SIGHTING,"vehicle")>Rules::RadiusGrowth(ERR_HQMemoryKind::SIGHTING,"on foot")); assert(!Rules::DeliveryFresh(10,9)&&!Rules::DeliveryFresh(-1,9)&&!Rules::DeliveryFresh(0,120001)); assert(Rules::DeliveryFresh(0,120000)&&!Rules::DeliveryFresh(nan,0)); assert(!Rules::PositionValid({nan,0,0})&&!Rules::PositionValid({0,inf,0})&&!Rules::PositionValid({1000001,0,0})); assert(Rules::MotionCredible(10,60,"on foot","on foot")); for(float gap:{0.f,1.f,121.f,nan})assert(!Rules::MotionCredible(gap,10,"on foot","on foot")); assert(!Rules::MotionCredible(10,130,"on foot","on foot")); assert(!Rules::MotionCredible(10,20,"unknown","unknown")&&!Rules::MotionCredible(10,20,"on foot","vehicle")); assert(near(Rules::Predict({0,40,0},{100,10,0},100)[0],300)); assert(near(Rules::Predict({0,40,0},{1,10,0},100)[0],30)&&near(Rules::Predict({0,40,0},{1,10,0},100)[1],40)); Identity a{1},b{2},friendly{3};ERR_HQMemory memory; auto first=Report(1,&a,1000,{10,40,10});first.HasVelocity=true;first.Velocity={100,0,100}; assert(memory.Ingest(&first,2000));auto belief=memory.Get(&a);int beliefId=belief->BeliefId; assert(belief->BeliefRevision==1&&belief->SampleCount==1&&!belief->HasVelocity&&belief->EvaluatedAt==2000); first.Position={999,999,999};first.TravelMode="aircraft";belief->Position={777,0,777};belief->Report->Position={888,0,888}; assert(near(memory.Get(&a)->Position[0],10)&&memory.Get(&a)->TravelMode=="on foot"); auto next=Report(2,&a,11000,{70,80,10});assert(memory.Ingest(&next,16000));belief=memory.GetById(beliefId); assert(belief->BeliefRevision==2&&belief->HasVelocity&&near(belief->Speed,6)&&near(belief->HeadingDegrees,90)); assert(near(belief->PredictedPosition[0],100)&&near(belief->PredictedPosition[1],80)); memory.Tick(611000);belief=memory.GetById(beliefId); assert(belief&&near(belief->Confidence,.5)&&near(belief->Radius,745)&&near(belief->PredictedPosition[0],250)); assert(belief->PredictionSeconds==30&&belief->Actionable()); memory.Tick(610000);assert(memory.Get(&a)->EvaluatedAt==611000);memory.Tick(nan);assert(memory.Get(&a)->EvaluatedAt==611000); assert(!memory.Ingest(&next,16000)&&!memory.Ingest(&next,611000)); assert(memory.NegativeSearch(beliefId,2,611000));belief=memory.Get(&a); assert(near(belief->Confidence,.325)&&belief->ObservedAt==11000&&belief->SampleCount==2&&belief->BeliefRevision==2); assert(!memory.NegativeSearch(beliefId,2,611000)&&!memory.NegativeSearch(beliefId,1,611000)); auto renewed=Report(3,&a,611000,{100,80,10});assert(memory.Ingest(&renewed,611000)); assert(near(memory.Get(&a)->Confidence,1)&&memory.Get(&a)->BeliefRevision==3&&!memory.Get(&a)->HasVelocity); assert(!memory.NegativeSearch(beliefId,2,611000)); // Per-kind identity protects a moving contact from uncertain friendly/body information. auto distress=Report(4,&a,611000,{500,0,500});distress.Distress=true;distress.Source=&friendly; assert(memory.Ingest(&distress,612000)&&memory.Count()==2&&memory.Get(&a)->Kind==ERR_HQMemoryKind::SIGHTING); auto distressBelief=memory.At(1);assert(distressBelief->Target==nullptr&&!distressBelief->HasVelocity&&!distressBelief->Actionable()); auto body=Report(5,&a,612000,{100,0,10},"body");assert(memory.Ingest(&body,612000)); assert(memory.At(2)->Kind==ERR_HQMemoryKind::BODY&&!memory.At(2)->HasVelocity&&memory.Get(&a)->BeliefRevision==3); assert(!memory.NegativeSearch(memory.At(2)->BeliefId,1,612000)); // A deleted engine identity cannot erase or rebind an already numbered belief. memory.m_Tracks[0]->Key=nullptr;memory.m_Tracks[0]->Latest()->Target=nullptr; assert(memory.GetById(beliefId)&&near(memory.GetById(beliefId)->Position[0],100)); memory.Tick(2300000);assert(memory.Count()==0&&!memory.GetById(beliefId)); memory.Clear();auto restart=Report(1,&a,0);assert(memory.Ingest(&restart,0));assert(memory.Get(&a)->BeliefId>beliefId); // Delayed legitimate deliveries for another track survive arbitrarily high fresh IDs. memory.Clear();auto high=Report(100000,&a,10000);assert(memory.Ingest(&high,11000)); auto delayed=Report(2,&b,9000);assert(memory.Ingest(&delayed,12000)); auto replay=delayed;replay.ObservedAt=12000;replay.Position={500,0,0};assert(!memory.Ingest(&replay,12000)); auto stale=Report(200000,&a,0);assert(!memory.Ingest(&stale,130001)); auto low=Report(3,&b,130001);assert(memory.Ingest(&low,130001)); auto future=Report(999999,&a,130003);assert(!memory.Ingest(&future,130002)); auto good=Report(4,&b,130002);assert(memory.Ingest(&good,130002)); // Strictly chronological samples, limited history and conservative discontinuities. memory.Clear();for(int i=1;i<=12;i++){auto r=Report(i,&a,i*2000,{float(i*2),0,0});assert(memory.Ingest(&r,i*2000));} assert(memory.Get(&a)->SampleCount==8&&memory.Get(&a)->BeliefRevision==12&&memory.Get(&a)->HasVelocity); auto old=Report(13,&a,23000);assert(!memory.Ingest(&old,25000)&&memory.Get(&a)->BeliefRevision==12); auto jump=Report(14,&a,26000,{10000,0,0});assert(memory.Ingest(&jump,26000)&&!memory.Get(&a)->HasVelocity); // No equal/weak burst can evict a stronger current sighting; later stronger reports can. memory.Clear();Identity people[70];for(int i=0;i<70;i++)people[i].id=i+10; for(int i=0;i<64;i++){auto r=Report(i+1,&people[i],0);assert(memory.Ingest(&r,0));} auto over=Report(65,&people[64],0);assert(!memory.Ingest(&over,0)&&memory.Count()==64); over.ObservedAt=10000;assert(memory.Ingest(&over,10000)&&memory.Count()==64); auto weak=Report(66,&people[65],10000);weak.Distress=true;assert(!memory.Ingest(&weak,10000)); assert(!memory.At(-1)&&!memory.At(64)&&!memory.Get(nullptr)); // The global replay table is bounded even when valid observation IDs arrive rapidly. memory.Clear();for(int i=1;i<=4096;i++){auto r=Report(i,&a,float(i));assert(memory.Ingest(&r,float(i)));} auto full=Report(4097,&a,4097);assert(!memory.Ingest(&full,4097)&&memory.m_Seen.Count()==4096); memory.Tick(124096);full.ObservedAt=124096;assert(memory.Ingest(&full,124096)&&memory.m_Seen.Count()==2); auto expired=Report(1,&b,1);assert(!memory.Ingest(&expired,124096)); } ''') print('PASS: actual HQ memory rules/service preserve delivered snapshots, chronology, replay bounds, decay, motion limits, identity and negative-search revisions')