Merge owned systems into one addon while preserving resource identities. Gate player admission on the replicated prison scene, restore the original framed door, and hold enemy AI until escape. Correct scenario branding and author metadata, include publishing assets, and retain regression and native verification evidence.
131 lines
8.9 KiB
Python
131 lines
8.9 KiB
Python
"""Actual Enforce policies and transaction observation body under narrow API fakes."""
|
|
from policy_harness import ROOT, body, run
|
|
r=ROOT/'addons/core/Scripts/Game/ERR/10_AI'
|
|
readiness=r/'ERR_MortarReadiness.c'; transfer=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 <cassert>
|
|
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 <cassert>
|
|
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+poll+'''
|
|
};
|
|
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);
|
|
Transfer gone;gone.m_Shell=nullptr;gone.Acknowledge(true);
|
|
assert(gone.Poll(1)==S::PENDING && !gone.m_Resolved); // ambiguous until deadline, never another move
|
|
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 <cassert>
|
|
#include <string>
|
|
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<ResourceName>()' 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')
|