"""Actual finite post ledger; engine identity/vector boundaries are doubles.""" import os,re from pathlib import Path from policy_harness import ROOT,run P=Path(os.environ.get('ERR_ENGINEER_MINE_POSTS_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMinePosts.c')) BOUNDARY=r''' #include #include #include #include #include struct string:std::string{using std::string::string;using std::string::operator=;string(std::string s):std::string(s){} bool IsEmpty(){return empty();}}; struct vector{float x=0,y=0,z=0;static float DistanceXZ(vector a,vector b){return std::hypot(a.x-b.x,a.z-b.z);}}; templatestruct Array:std::vector{using std::vector::vector;int Count(){return this->size();}void Insert(T p){this->push_back(p);}void Clear(){this->clear();}}; struct SCR_AIGroup{vector position;vector GetOrigin(){return position;}}; struct ERR_ForceRecord{SCR_AIGroup* Group=nullptr;bool Physical=true,Eliminated=false;string SourceId="s";int InitialStrength=2;}; struct ERR_HQTask{bool RoadIntercept=true,ReleaseOnly=false,investigation=false;string SecuritySite;int BeliefId=1,BeliefRevision=1;vector Destination;float QueuedAt=10,ExpiresAt=100000;bool Investigation(){return investigation;}}; struct ERR_HQReport{int MessageId=1;float ObservedAt=5;vector Position;}; namespace ERR_ForceRules{bool Finite(float f){return std::isfinite(f);}bool FiniteVector(vector p){return Finite(p.x)&&Finite(p.y)&&Finite(p.z);}} struct ERR_EngineerMineSite{static inline bool valid=true;static inline int calls=0;static bool InBand(vector a,vector b){float d=vector::DistanceXZ(a,b);return d>=25&&d<=60;}static bool Select(vector post,vector&site){calls++;site={post.x+30,post.y,post.z};return valid;}}; ''' def ledger_cpp(path=P): s=path.read_text().replace('class ','struct ').replace('protected ','').replace('ref ','').replace('out array sites','Array& sites').replace('array<','Array<').replace(' = {};',';') for typ in ['ERR_EngineerMinePost','ERR_ForceRecord','SCR_AIGroup','ERR_HQTask','ERR_HQReport']: s=re.sub(r'\b'+typ+r'(?=\s+\w)',typ+'*',s);s=s.replace('Array<'+typ+'>','Array<'+typ+'*>') for ns in ['ERR_ForceRules','vector','ERR_EngineerMineSite']:s=s.replace(ns+'.',ns+'::') for obj in ['record','task','assignment','previous','entry']:s=re.sub(r'\b'+obj+r'\.',obj+'->',s) s=s.replace('foreach (','for (').replace('int used;','int used=0;') # Enforce initializes scalar fields to zero; C++ aggregate members must match. s=re.sub(r'^( (?:bool|int|float|ERR_ForceRecord\*|SCR_AIGroup\*|ERR_HQTask\*|ERR_HQReport\*) \w+);$',r'\1{};',s,flags=re.M) s=s.replace('\n}\n','\n};\n') return s TEST=r''' struct Fixture{SCR_AIGroup group;ERR_ForceRecord record;ERR_HQTask tasks[40];ERR_HQReport reports[40];ERR_EngineerMinePosts posts; Fixture(){record.Group=&group;for(int i=0;i<40;i++){tasks[i].Destination={float(i*200),0,0};tasks[i].QueuedAt=10+i*10;tasks[i].BeliefRevision=1+i;reports[i].ObservedAt=5+i*10;reports[i].MessageId=i+1;}} int Take(int i){return posts.Consume(&record,"s",&tasks[i],&reports[i],1000);}}; int main(){ {Fixture f;assert(f.Take(0)==0);assert(f.Take(1)==1);assert(f.Take(2)==2);assert(f.Take(3)==3);assert(f.Take(4)==-1&&f.posts.Count()==4);} {Fixture f;assert(f.Take(0)==0);assert(f.Take(0)==-1);f.tasks[0].Destination={900,0,0};f.tasks[0].QueuedAt=900;f.reports[0].ObservedAt=800;f.reports[0].MessageId=999;f.tasks[0].BeliefRevision=999; assert(f.Take(1)==1);assert(f.posts.RecordSite(0,{30,0,0}));assert(!f.posts.RecordSite(0,{31,0,0}));Array sites;f.posts.PriorSites(sites);assert(sites.size()==1&&sites[0].x==30);sites[0].x=900;f.posts.PriorSites(sites);assert(sites[0].x==30);} for(int fault=0;fault<8;fault++){Fixture f;f.Take(0);if(fault==0)f.tasks[1].Destination={160,0,0};if(fault==1)f.tasks[1].QueuedAt=10;if(fault==2)f.reports[1].ObservedAt=5;if(fault==3)f.reports[1].MessageId=1;if(fault==4)f.tasks[1].BeliefRevision=1;if(fault==5)f.tasks[1].BeliefRevision=0;if(fault==6)f.tasks[1].ExpiresAt=1000;if(fault==7)f.tasks[1].Destination.x=NAN;assert(f.Take(1)==-1&&f.posts.Count()==1);} {Fixture f;f.Take(0);f.tasks[1].Destination.x=160.001f;assert(f.Take(1)==1);} {Fixture f;f.Take(0);f.tasks[1].BeliefId=2;f.tasks[1].BeliefRevision=1;assert(f.Take(1)==1);} {Fixture f;f.Take(0);ERR_ForceRecord alias=f.record;assert(f.posts.Consume(&alias,"s",&f.tasks[1],&f.reports[1],1000)==-1);alias.SourceId="alias";assert(f.posts.Consume(&alias,"alias",&f.tasks[1],&f.reports[1],1000)==-1);f.record.SourceId="changed";assert(f.posts.Consume(&f.record,"changed",&f.tasks[1],&f.reports[1],1000)==-1);} {Fixture f;f.Take(0);SCR_AIGroup replacement;f.record.Group=&replacement;assert(f.Take(1)==-1);f.record.Group=&f.group;f.record.InitialStrength=3;assert(f.Take(1)==-1);} {Fixture f;assert(!f.posts.RecordSite(-1,{30,0,0}));assert(f.Take(0)==0);assert(!f.posts.RecordSite(0,{24,0,0}));assert(!f.posts.RecordSite(0,{61,0,0}));assert(!f.posts.RecordSite(0,{30,NAN,0}));Array empty;f.posts.PriorSites(empty);assert(empty.empty());assert(f.posts.RecordSite(0,{25,0,0}));} {Fixture f;ERR_ForceRecord records[33];SCR_AIGroup groups[33];for(int i=0;i<33;i++){records[i].Group=&groups[i];records[i].SourceId=std::to_string(i);int result=f.posts.Consume(&records[i],records[i].SourceId,&f.tasks[i],&f.reports[i],1000);assert(result==(i<32?i:-1));}assert(f.posts.Count()==32);} for(int fault=0;fault<10;fault++){Fixture f;if(fault==0)f.record.Physical=false;if(fault==1)f.record.Eliminated=true;if(fault==2)f.record.InitialStrength=33;if(fault==3)f.record.Group=nullptr;if(fault==4)f.tasks[0].ReleaseOnly=true;if(fault==5)f.tasks[0].investigation=true;if(fault==6)f.tasks[0].SecuritySite="site";if(fault==7)f.tasks[0].QueuedAt=1001;if(fault==8)f.reports[0].ObservedAt=11;if(fault==9)f.reports[0].Position.x=NAN;assert(f.Take(0)==-1&&f.posts.Count()==0);} } ''' if __name__=='__main__': run(BOUNDARY+ledger_cpp()+TEST) print('PASS: actual mine post ledger immutable history, strict chronology/evidence, aliases, >160m separation, detached sites and finite4/32 consumed attempts')