"""Actual WORKBENCH refresh-fixture observation/acceptance policy, not native proof.""" import re from policy_harness import ROOT, body, run p=ROOT/'addons/ai/Scripts/Game/ERR/ERR_NativeMortarSalvoProbe.c' base=ROOT/'addons/ai/Scripts/Game/ERR/ERR_NativeMortarFiringProbe.c' def adapt(s): s=s.replace('protected ','').replace('null','nullptr').replace('string kind','std::string kind').replace('string reason, string failure','std::string reason, std::string failure') for typ in ['ERR_HQReport','ERR_MortarBattery','ERR_NativeMortarRefreshRecord','ERR_MortarRefresh']: s=re.sub(r'\b'+typ+r' (\w+)',typ+r'* \1',s) for name in ['battery','report','observation','record','initial','update','m_Battery']: s=s.replace(name+'.',name+'->') for name in ['Report','Route','Delivered']: s=s.replace('.'+name+'.','.'+name+'->').replace('->'+name+'.','->'+name+'->') s=s.replace('ERR_MortarSalvo.','ERR_MortarSalvo::').replace('ERR_MortarPrediction.','ERR_MortarPrediction::').replace('ERR_NativeMortarEvidenceRules.','ERR_NativeMortarEvidenceRules::').replace('vector.Distance','vector::Distance') s=re.sub(r'foreach \(ERR_NativeMortarRefreshRecord\* (\w+) : m_Observations\)',r'for (ERR_NativeMortarRefreshRecord* \1 : m_Observations.values)',s) s=s.replace('].ObservedAt',']->ObservedAt') return s rules=adapt(body(p,'static bool QueueUpdate(')) evidence='\n'.join(adapt(body(base,s)) for s in ['static bool CommitFresh(', 'static bool AimFresh(']) matching=adapt(body(p,'bool Matches(')) methods='\n'.join(adapt(body(p,s)) for s in ['protected ERR_NativeMortarRefreshRecord FindObservation(', 'protected bool AddObservation(', 'protected bool ReportKnown(', 'protected bool AllAccepted(', 'protected bool NoReportReplay(', 'void NativeAudit(', 'void NativeCommit(', 'void NativeClosing(']) # A return type is a reference in Enforce, a pointer in this policy adapter. methods=methods.replace('ERR_NativeMortarRefreshRecord FindObservation(', 'ERR_NativeMortarRefreshRecord* FindObservation(') run(r''' #include #include #include #include #include using IEntity=void*;using SCR_AIGroup=void*; struct vector {float x=0,y=0,z=0;float Length(){return std::sqrt(x*x+y*y+z*z);}static float Distance(vector a,vector b){return vector{a.x-b.x,a.y-b.y,a.z-b.z}.Length();}}; struct ERR_MortarSalvo {static constexpr int ROUNDS=8;}; struct ERR_MortarPrediction {static constexpr float MAX_REPORT_AGE_MS=60000;}; struct Rules {'''+rules+r'''}; struct ERR_NativeMortarEvidenceRules {'''+evidence+r'''}; templatestruct Items {std::vector values;int Count(){return values.size();}bool IsEmpty(){return values.empty();}void Insert(T t){values.push_back(t);}T operator[](int n){return values[n];}}; struct ERR_HQReport {int MessageId=1;float ObservedAt=0;IEntity Target=nullptr;SCR_AIGroup Source=nullptr;vector Position{},Velocity{};bool HasVelocity=true,Distress=false;ERR_HQReport* Snapshot(){return new ERR_HQReport(*this);}}; struct Route {bool Downlink=true;int MessageId=3;Items Nodes;Route(){Nodes.Insert(1);}}; struct ERR_MortarBattery; struct ERR_MortarRefresh {IEntity Gun=nullptr,Group=nullptr;int OrderId=1,RadioId=3;ERR_HQReport* Report=nullptr;struct Route* Route=nullptr;bool Owns(ERR_MortarBattery*);}; struct ERR_MortarBattery {IEntity Gun=this,Group=this,Activity=this;int SourceId=1,OrderId=1,OrderShots=0;bool Released=false,CommandOpen=true,RefreshRejected=false,stopped=false;float AimedAt=1000,AimValidatedAt=24000,FlightTime=20;ERR_HQReport* Report=nullptr;ERR_MortarRefresh* Refresh=nullptr;std::set claimed;bool Stopped(){return stopped;}bool CanRequest(ERR_HQReport* r,float){return !claimed.count(r->MessageId);}}; bool ERR_MortarRefresh::Owns(ERR_MortarBattery* b){return b&&Gun==b->Gun&&Group==b->Group&&OrderId==b->OrderId;} struct ERR_NativeMortarRefreshRecord {int MessageId=0;float ObservedAt=0;int DownlinkId=0;bool Accepted=false;ERR_HQReport* Delivered=nullptr; '''+matching+r'''}; templatevoid PrintFormat(Args... args){} struct Probe { bool m_RefreshCase=true,m_Stopped=false,m_SawDownlink=true,m_SawActivity=false,m_BadProjectile=false,m_CommitPending=false,m_ClosureSeen=false,m_ClosureComplete=false; ERR_MortarBattery* m_Battery=nullptr;IEntity m_Target=this,m_Group=this,m_OriginalActivity=nullptr,m_OriginalRTO=this;vector m_Impact{}; int m_Source=1,m_Order=1,m_UpdatesAccepted=0,m_UpdatedCommits=0,m_Commits=0,m_Step=1,m_CommitOrder=0,m_CommitShot=0,m_CommitSource=0,m_Events=0;float m_ObservedAt=0,m_CommittedAt=0,m_CommitObservedAt=0;std::string m_BadReason;ERR_HQReport* m_Delivered=nullptr; Items m_Observations; '''+methods+r'''}; struct F { Probe p;ERR_MortarBattery b;ERR_HQReport first,next;ERR_MortarRefresh update;Route route; F(){p.m_Battery=&b;first.Target=p.m_Target;first.Source=p.m_Group;next=first;next.MessageId=2;next.ObservedAt=20000;b.Report=&first;b.claimed.insert(1);update.Gun=b.Gun;update.Group=b.Group;update.Report=&next;update.Route=&route;} void initial(){assert(p.AddObservation(1,0));p.FindObservation(1)->DownlinkId=2;p.NativeAudit(&b,"AIM");assert(!p.m_BadProjectile);} void queued(){assert(p.AddObservation(2,20000));b.Refresh=&update;b.claimed.insert(2);p.NativeAudit(&b,"UPDATE QUEUED");} void accepted(){update.Route=nullptr;b.Report=&next;p.NativeAudit(&b,"UPDATE RECEIVED");b.Refresh=nullptr;} }; int main(){ assert(Rules::QueueUpdate(true,false,0,0,1000,20000));assert(!Rules::QueueUpdate(true,false,0,0,1000,19999)); assert(!Rules::QueueUpdate(false,false,0,0,1000,20000));assert(!Rules::QueueUpdate(true,true,0,0,1000,20000)); assert(!Rules::QueueUpdate(true,false,4,0,1000,20000));assert(!Rules::QueueUpdate(true,false,0,0,1000,91000)); assert(!Rules::QueueUpdate(true,false,0,0,22000,20000)); F f;f.initial();assert(f.p.ReportKnown(&f.first));assert(!f.p.ReportKnown(&f.next));assert(!f.p.AllAccepted()); assert(!f.p.AddObservation(1,1));assert(!f.p.AddObservation(2,0));assert(!f.p.AddObservation(0,100)); f.queued();assert(!f.p.ReportKnown(&f.next)&&f.p.ReportKnown(&f.next,false));assert(!f.p.AllAccepted()); f.accepted();assert(!f.p.m_BadProjectile&&f.p.ReportKnown(&f.next)&&f.p.m_UpdatesAccepted==1); f.b.Released=true;f.p.NativeCommit(&f.b,25000);assert(!f.p.m_BadProjectile&&f.p.m_UpdatedCommits==1&&f.p.m_CommitSource==2&&f.p.m_CommitObservedAt==20000); assert(f.p.AllAccepted()&&f.p.NoReportReplay(26000));f.b.claimed.erase(2);assert(!f.p.NoReportReplay(26000));f.b.claimed.insert(2); f.b.OrderShots=8;f.p.m_Events=8;f.p.m_Commits=8;f.p.m_CommitPending=false;f.b.Released=false; f.p.NativeClosing(&f.b,"native artillery activity COMPLETED (shot count is separate)","");assert(f.p.m_ClosureComplete&&!f.p.m_BadProjectile); for(int fault=0;fault<7;fault++){ F a;a.initial();a.queued(); if(fault==0)a.update.OrderId=2; if(fault==1)a.b.Activity=&a.next; if(fault==2)a.next.ObservedAt=20001; if(fault==3)a.next.Position.x=.02f; if(fault==4)a.next.Target=&a.next; if(fault==5)a.next.Source=&a.next; if(fault==6)a.next.Velocity.x=1; a.accepted();assert(a.p.m_BadProjectile&&!a.p.FindObservation(2)->Accepted); } F beforeRoute;beforeRoute.initial();beforeRoute.queued();beforeRoute.b.Report=&beforeRoute.next;beforeRoute.p.NativeAudit(&beforeRoute.b,"UPDATE RECEIVED");assert(beforeRoute.p.m_BadProjectile); F committed;committed.initial();committed.queued();committed.b.Released=true;committed.accepted();assert(committed.p.m_BadProjectile); F duplicate;duplicate.initial();duplicate.queued();duplicate.accepted();duplicate.b.Refresh=&duplicate.update;duplicate.p.NativeAudit(&duplicate.b,"UPDATE RECEIVED");assert(duplicate.p.m_BadProjectile&&duplicate.p.m_UpdatesAccepted==1); F recreated;recreated.initial();recreated.p.NativeAudit(&recreated.b,"AIM");assert(recreated.p.m_BadProjectile); F unaccepted;unaccepted.initial();unaccepted.queued();unaccepted.b.Report=&unaccepted.next;unaccepted.b.Released=true;unaccepted.p.NativeCommit(&unaccepted.b,25000);assert(unaccepted.p.m_BadProjectile&&unaccepted.p.m_Commits==0); F extra;extra.initial();extra.queued();extra.accepted();extra.p.m_UpdatedCommits=1;assert(extra.p.AddObservation(3,40000));assert(!extra.p.AllAccepted()); F ignored;ignored.p.m_RefreshCase=false;ignored.p.NativeAudit(&ignored.b,"AIM");assert(!ignored.p.m_BadProjectile);assert(ignored.p.ReportKnown(&ignored.first)); } ''') source=p.read_text();queue=body(p,'int ERR_QueueMortarRefreshReport(') assert 'observedAt = GetGame().GetWorld().GetWorldTime()' in queue assert 'm_Network.Route(radio)' in queue and 'unit.Radio != radio' in queue assert 'unit.PendingReport = report; unit.Uplink = route;' in queue assert 'm_Contacts.' not in queue and '.Order(' not in queue and 'BeginRefresh(' not in queue assert 'report.ObservedAt = observedAt' in queue assert 'outcome == "mortar-salvo" || outcome == "mortar-refresh"' in source assert 'm_Battery.RadioOperator != m_OriginalRTO' in source assert 'm_Battery.Report.MessageId != m_CommitSource' in body(p,'void NativeProjectile(') assert 'ERR_NativeMortarSalvoRules.QueueUpdate(' in body(p,'int Tick(') assert 'm_Battery.Report =' not in body(p,'int Tick(') print('PASS: actual refresh-fixture gates pin immutable observations/actual downlinks/original activity, reject unaccepted or relabelled commits, stop queueing early and require all queued contacts claimed before replay')