"""Actual Enforce policies and transaction observation body under narrow API fakes.""" from policy_harness import ROOT, body, run from pathlib import Path import os r=ROOT/'addons/core/Scripts/Game/ERR/10_AI' readiness=r/'ERR_MortarReadiness.c'; transfer=Path(os.environ.get('ERR_MORTAR_SUPPLY_TRANSFER_SOURCE',r/'ERR_MortarSupplyTransfer.c')); battery=r/'ERR_MortarBattery.c' policy='\n'.join([body(readiness,'static ERR_MortarSupplyState Population('),body(readiness,'static bool AllocationValid('),body(readiness,'static int CycleGate('),body(transfer,'static bool Authority('),body(transfer,'static bool Proven(')]) policy=policy.replace('ERR_MortarSupplyState.','ERR_MortarSupplyState::') run('''#include enum class ERR_MortarSupplyState {FAILED=-1,PENDING,READY}; '''+policy+''' int main(){ using S=ERR_MortarSupplyState; assert(Population(0,0,0,false,false)==S::PENDING); assert(Population(3,3,0,true,false)==S::PENDING); assert(Population(4,3,1,false,false)==S::PENDING); assert(Population(4,3,1,true,false)==S::READY); assert(Population(4,3,1,true,true)==S::FAILED); assert(Population(0,0,0,false,true)==S::FAILED); assert(Population(5,3,2,true,false)==S::FAILED); assert(Population(4,4,0,true,false)==S::FAILED); assert(AllocationValid(0)&&AllocationValid(9)); assert(!AllocationValid(-1)&&!AllocationValid(10)); assert(Authority(true,false,1,1)); assert(!Authority(false,false,1,1)); assert(!Authority(true,true,1,1)); assert(!Authority(true,false,1,2)); for(int bits=0;bits<16;bits++) { bool callback=bits&1, source=bits&2, destination=bits&4, exact=bits&8; assert(Proven(callback,source,destination,exact)==(bits==13)); } int counter=0; assert(CycleGate(true,0,counter,8,1)==0); // no physical projectile, no count for(int i=0;i<1000;i++) if(CycleGate(true,1,counter,8,0)==1) counter++; assert(counter==0); // pending supply never invokes native super assert(CycleGate(true,1,counter,8,-1)==-1); if(CycleGate(true,1,counter,8,1)==1) counter++; assert(counter==1 && CycleGate(true,1,counter,8,1)==0); // same event not counted twice assert(CycleGate(false,2,counter,8,1)==-1); assert(CycleGate(true,8,7,8,-1)==1); // final confirmed round needs no ninth shell } ''') # Retain actual control flow; translate only native member/type syntax and the # component lookup into a directly supplied fake item component. poll=body(transfer,'ERR_MortarSupplyState Poll(') poll=poll.replace('ERR_MortarSupplyState.','ERR_MortarSupplyState::').replace('Replication.IsServer()','Replication::IsServer()').replace('InventoryItemComponent item;','InventoryItemComponent* item=nullptr;').replace('if (m_Shell) item = InventoryItemComponent.Cast(m_Shell.FindComponent(InventoryItemComponent));','if (m_Shell) item = m_Shell;').replace('item.GetParentSlot().GetStorage()','item->GetParentSlot()->GetStorage()').replace('item.GetParentSlot()','item->GetParentSlot()') ack=body(transfer,'void Acknowledge(') run('''#include #include enum class ERR_MortarSupplyState {FAILED=-1,PENDING,READY}; struct Replication { static bool IsServer(){return true;} }; struct Slot { void* storage; void* GetStorage(){return storage;} }; struct InventoryItemComponent { Slot* slot; Slot* GetParentSlot(){return slot;} }; '''+body(transfer,'static bool Proven(')+''' struct Transfer { bool valid=true,source=true,destination=false,m_Accepted=true,m_Invalidated=false,m_Resolved=false,m_Ready=false; int m_Source=1,m_Destination=2,m_Acknowledgement=0; float m_Deadline=8000; void* m_Storage=this; Slot slot{this}; InventoryItemComponent item{&slot}; InventoryItemComponent* m_Shell=&item; bool Valid(float){return valid&&!m_Invalidated;} bool Contains(int which){return m_Shell && (which==1 ? source : destination);} '''+ack+body(transfer,'bool Unresolved(')+poll+''' }; struct Battery {Transfer* m_Transfer=nullptr; '''+body(battery,'bool SupplyPending(').replace('m_Transfer.Unresolved()', 'm_Transfer->Unresolved()')+''' }; int main(){ using S=ERR_MortarSupplyState; Transfer t; assert(t.Poll(0)==S::PENDING && !t.m_Resolved); t.Acknowledge(true); t.Acknowledge(false); assert(t.m_Acknowledgement==1); assert(t.Poll(1)==S::PENDING && !t.m_Resolved); // callback alone cannot supply t.destination=true; assert(t.Poll(2)==S::PENDING); // source still claims ownership t.source=false; t.slot.storage=nullptr; assert(t.Poll(3)==S::PENDING); // wrong storage t.slot.storage=t.m_Storage; assert(t.Poll(4)==S::READY && t.m_Resolved); Transfer stopped; stopped.m_Invalidated=true; stopped.source=false; stopped.destination=true; stopped.Acknowledge(true); assert(stopped.Poll(5)==S::FAILED && !stopped.m_Ready && stopped.m_Resolved); Transfer timeout; assert(timeout.Poll(8000)==S::FAILED && !timeout.m_Resolved && timeout.m_Invalidated); timeout.source=false;timeout.destination=true;timeout.Acknowledge(true); assert(timeout.Poll(9000)==S::FAILED && timeout.m_Resolved && !timeout.m_Ready); // late success cannot authorize Transfer late;late.source=false;late.destination=true;late.Acknowledge(true); assert(late.Poll(8000)==S::FAILED); // no deadline-boundary success bypass Transfer failed;failed.Acknowledge(false);failed.Acknowledge(true); assert(failed.Poll(1)==S::FAILED && failed.m_Acknowledgement==-1 && failed.m_Resolved); // Exact deletion is permanent loss, not an operation that can still arrive. for(int ack=0;ack<3;ack++)for(bool invalidated:{false,true}){ Transfer gone;Battery battery;battery.m_Transfer=&gone;gone.m_Invalidated=invalidated;assert(gone.Unresolved()&&battery.SupplyPending());gone.m_Shell=nullptr; if(ack==1)gone.Acknowledge(true); if(ack==2)gone.Acknowledge(false); assert(gone.Poll(1)==S::FAILED&&gone.m_Resolved&&gone.m_Invalidated&&!gone.m_Ready&&!gone.Unresolved()); assert(!battery.SupplyPending()); gone.Acknowledge(true);assert(gone.Poll(90000)==S::FAILED&&!gone.Unresolved()&&!gone.m_Ready); } // A surviving detached shell, missing inventory or lost authority remains // uncertain; only exact identity deletion permits unconditional settlement. Transfer detached;detached.source=false;detached.destination=false;detached.Acknowledge(true); assert(detached.Poll(1)==S::PENDING&&detached.Unresolved());assert(detached.Poll(8000)==S::FAILED&&detached.Unresolved()); Transfer unauthorized;unauthorized.valid=false; assert(unauthorized.Poll(0)==S::FAILED && !unauthorized.m_Resolved); } ''') # Execute the production classification helper and its actual delivered-report # lookup. The freshness adapter supplies only the report/time boundary; no # inventory retry, reservation release or native firing is modeled here. system_path=r/'ERR_MortarSystem.c' classification='\n'.join(body(system_path,signature) for signature in ['ERR_HQReport Latest(', 'string ContactFailure(', 'string SupplyFailure(']) classification=classification.replace('ERR_HQReport Latest(', 'Report* Latest(').replace('ERR_MortarBattery battery','Battery* battery').replace('battery.Report','battery->Report').replace('ERR_MortarPrediction.Fresh','Prediction::Fresh').replace('return null;', 'return nullptr;').replace('string ', 'std::string ') run('''#include #include struct Report {float observed=1000;bool valid=true;}; struct Battery {struct Report* Report=nullptr;}; struct Prediction {static bool Fresh(Report* report,float now){return report&&report->valid&&now>=report->observed&&now-report->observed<=60000;}}; struct System { '''+classification+'''}; int main(){ System system;Battery battery; assert(system.SupplyFailure(&battery,20000)=="no delivered target report"); Report report;battery.Report=&report; assert(system.SupplyFailure(&battery,61000)=="next native load lacks confirmed physical gunner ammunition"); assert(system.SupplyFailure(&battery,61001)=="delivered target report expired or invalid"); assert(system.SupplyFailure(&battery,999)=="delivered target report expired or invalid"); report.valid=false;assert(system.SupplyFailure(&battery,20000)=="delivered target report expired or invalid"); report.valid=true;report.observed=20000; assert(system.SupplyFailure(&battery,30000)=="next native load lacks confirmed physical gunner ammunition"); assert(battery.Report==&report&&report.observed==20000); // classification cannot retimestamp or replace a report } ''') # Source contract checks constrain integration that cannot run without the engine. b=battery.read_text();sys=(r/'ERR_MortarSystem.c').read_text();f=(r/'ERR_MortarFiring.c').read_text();rd=readiness.read_text();tr=transfer.read_text() update=body(battery,'void Update(float now)') assert update.index('m_Readiness.Poll(now)') < update.index('if (!Operational())') assert 'm_Allocated = true;' in rd and rd.count('TrySpawnPrefabToStorage(ERR_MortarBattery.SHELL')==1 assert rd.index('m_Allocated = true;') < rd.index('TrySpawnPrefabToStorage(ERR_MortarBattery.SHELL') assert 'm_aUnitPrefabSlots = new array()' in rd and 'PurgeSpawnRequestsForGroup(group)' in rd assert 'DeleteSpawned' not in body(readiness,'void Stop(') assert 'battery.Stop();' in body(r/'ERR_MortarSystem.c','void Stop(') assert tr.count('TryMoveItemToStorage(')==1 and 'GetItem()' not in tr.replace('callback.GetItem()','') assert 'm_AttemptedShells.Insert(item)' in b and 'm_AttemptedShells.Contains(item)' in b assert 'm_Transfer.CapturedOrder() == OrderId' in b assert 'battery.PendingSupplyReport' in sys and 'supply == ERR_MortarSupplyState.PENDING) return;' in sys shoot=f[f.index('modded class SCR_AIStaticArtilleryBehavior_ShootingLogic'):] assert shoot.index('battery.SupplyState(') < shoot.index('supply == ERR_MortarSupplyState.PENDING') < shoot.index('supply == ERR_MortarSupplyState.FAILED') < shoot.index('system.SupplyFailure(battery, now)') < shoot.index('super.EOnTaskSimulate(') assert 'system.Withhold(battery, system.SupplyFailure(battery, now))' in shoot supply_state=body(battery,'ERR_MortarSupplyState SupplyState(') assert supply_state.index('m_Transfer.Poll(now)') < supply_state.index('if (!SupplyAuthorized(now))') assert shoot.count('super.EOnTaskSimulate(')==1 and 'battery.SupplyGunner()' not in shoot print('PASS: actual startup/generation/ownership/timeout/callback policies and native-counter wait; integration preserves one-shot allocation and pending-crew cancellation') # Execute the production post-shot node, including the superclass completion # callback. A fast repeater must not start a ninth aim while HQ is still waiting # to observe native completion; pending ammunition and duplicate ticks stay safe. from types import SimpleNamespace section=(r/'ERR_MortarFiring.c').read_text().split('modded class SCR_AIStaticArtilleryBehavior_ShootingLogic',1)[1] cycle=body(SimpleNamespace(read_text=lambda:section),'override ENodeResult EOnTaskSimulate(') cycle=cycle.replace('override ', '').replace('AIAgent owner','void* owner') cycle=cycle.replace('ERR_MortarBattery battery;', 'ERR_MortarBattery* battery=nullptr;').replace('SCR_AIStaticArtilleryBehavior behavior;', 'SCR_AIStaticArtilleryBehavior* behavior=nullptr;') cycle=cycle.replace('SCR_AIStaticArtilleryBehavior.Cast(m_Utility.GetExecutedAction())','m_Utility->GetExecutedAction()') cycle=cycle.replace('ERR_MortarSystem system = ERR_MortarSystem.Get();','ERR_MortarSystem* system = &systemInstance;') for name in ['battery','behavior','system']:cycle=cycle.replace(name+'.',name+'->') for name in ['ERR_MortarSupplyRules','ERR_MortarSalvo','ERR_MortarSupplyState','ENodeResult']:cycle=cycle.replace(name+'.',name+'::') cycle=cycle.replace('GetGame().GetWorld().GetWorldTime()', '1000.f').replace('super.EOnTaskSimulate(owner, dt)', 'Base::EOnTaskSimulate(owner, dt)') gate=body(readiness,'static int CycleGate(') run('''#include enum class ENodeResult {FAIL,RUNNING,SUCCESS}; enum ERR_MortarSupplyState {FAILED=-1,PENDING,READY}; struct ERR_MortarSalvo {static constexpr int ROUNDS=8;}; struct ERR_MortarSupplyRules {'''+gate+'''}; struct ERR_MortarBattery { bool CommandOpen=true;int OrderShots=0,checks=0;ERR_MortarSupplyState supply=ERR_MortarSupplyState::READY; ERR_MortarSupplyState SupplyState(float){checks++;return supply;} }; struct SCR_AIStaticArtilleryBehavior { ERR_MortarBattery* battery=nullptr;int count=0,completions=0; int GetShotCount(){return count;}ERR_MortarBattery* ERR_GetMortarBattery(){return battery;} }; struct Utility {SCR_AIStaticArtilleryBehavior* behavior;auto GetExecutedAction(){return behavior;}}; struct ERR_MortarSystem {int refusals=0;void Withhold(ERR_MortarBattery*,int){refusals++;}int SupplyFailure(ERR_MortarBattery*,float){return 0;}} systemInstance; struct Base { Utility* m_Utility=nullptr;int calls=0;bool aiming=false;static constexpr int PORT_AIMING_NEEDED=1; ENodeResult EOnTaskSimulate(void*,float){calls++;auto b=m_Utility->behavior;if(++b->count==8)b->completions++;return ENodeResult::SUCCESS;} void SetVariableOut(int,bool value){aiming=value;} }; struct Node:Base {'''+cycle+'''}; int main(){ ERR_MortarBattery battery;SCR_AIStaticArtilleryBehavior behavior;behavior.battery=&battery;Utility utility{&behavior};Node n;n.m_Utility=&utility; assert(n.EOnTaskSimulate(nullptr,0)==ENodeResult::RUNNING&&n.calls==0); battery.OrderShots=1;battery.supply=ERR_MortarSupplyState::PENDING; assert(n.EOnTaskSimulate(nullptr,0)==ENodeResult::RUNNING&&n.calls==0); battery.supply=ERR_MortarSupplyState::READY; for(int shot=1;shot<=8;shot++){ battery.OrderShots=shot;n.aiming=false; if(shot==8)battery.supply=ERR_MortarSupplyState::FAILED; // final shot needs no ninth shell auto result=n.EOnTaskSimulate(nullptr,0); assert(n.calls==shot&&behavior.count==shot); assert(result==(shot<8?ENodeResult::SUCCESS:ENodeResult::RUNNING)); assert(n.aiming==(shot<8)); } assert(behavior.completions==1&&systemInstance.refusals==0); for(int tick=0;tick<100;tick++)assert(n.EOnTaskSimulate(nullptr,0)==ENodeResult::RUNNING); assert(n.calls==8&&behavior.completions==1); // no duplicate count or ninth aim battery.CommandOpen=false;assert(n.EOnTaskSimulate(nullptr,0)==ENodeResult::FAIL); behavior.battery=nullptr;assert(n.EOnTaskSimulate(nullptr,0)==ENodeResult::SUCCESS); // unrelated native artillery unchanged } ''') print('PASS: rapid mortar cycle counts eight physical rounds once and waits for native completion without a ninth aim or shell')