131 lines
9.7 KiB
Python
131 lines
9.7 KiB
Python
"""Execute production finite-courier policies and native-operation observation.
|
|
API doubles do not establish engine inventory, navigation, radio or MP behavior.
|
|
"""
|
|
from policy_harness import ROOT, body, run
|
|
import re
|
|
r=ROOT/'addons/ai/Scripts/Game/ERR'
|
|
p=r/'ERR_MortarLogistics.c'; t=r/'ERR_MortarCourierTransfer.c'
|
|
# C++ would accept an Enforce ownership annotation as an identifier.
|
|
# Reject that native compile regression before executing the source body.
|
|
assert not re.search(r'\b(?:bool|int|float|string)\s+(?:owned|event|autoptr|typename|proto|modded|notnull)\b', p.read_text())
|
|
policies='\n'.join(body(p,s) for s in ('static bool Fresh(', 'static bool Need(', 'static bool NewRequest(', 'static bool Near(', 'static bool ActiveTrip('))
|
|
run('''#include <cassert>
|
|
'''+policies+'''
|
|
int main(){
|
|
assert(Fresh(100,100)&&Fresh(100,180100));
|
|
assert(Fresh(0,0)&&Fresh(0,180000)&&!Fresh(0,180001));
|
|
assert(!Fresh(-1,-1)&&!Fresh(-1,0)&&!Fresh(-1,100)&&!Fresh(-0.001f,0));
|
|
assert(!Fresh(100,99)&&!Fresh(100,180101));
|
|
assert(Need(0)&&Need(6)&&!Need(-1)&&!Need(7));
|
|
assert(NewRequest(4,3,true)&&!NewRequest(4,4,true)&&!NewRequest(3,4,true));
|
|
assert(!NewRequest(1,0,false)&&!NewRequest(0,0,true));
|
|
assert(Near(0)&&Near(12)&&!Near(12.001)&&!Near(-1));
|
|
assert(ActiveTrip(true,false,1,1,true,true));
|
|
assert(!ActiveTrip(false,false,1,1,true,true));
|
|
assert(!ActiveTrip(true,true,1,1,true,true));
|
|
assert(!ActiveTrip(true,false,0,0,true,true));
|
|
assert(!ActiveTrip(true,false,1,2,true,true));
|
|
assert(!ActiveTrip(true,false,1,1,false,true));
|
|
assert(!ActiveTrip(true,false,1,1,true,false));
|
|
}
|
|
''')
|
|
poll=body(t,'int Poll(')
|
|
poll=poll.replace('bool exact;','bool exact=false;').replace('InventoryItemComponent item;','InventoryItemComponent* item=nullptr;')
|
|
poll=poll.replace('if (m_Shell) item = InventoryItemComponent.Cast(m_Shell.FindComponent(InventoryItemComponent));','if (m_Shell) item = m_Shell;')
|
|
poll=poll.replace('item.GetParentSlot().GetStorage()','item->GetParentSlot()->GetStorage()').replace('item.GetParentSlot()','item->GetParentSlot()')
|
|
poll=poll.replace('m_Service.TransferAllowed','m_Service->TransferAllowed')
|
|
run('''#include <cassert>
|
|
struct Slot {void* value;void* GetStorage(){return value;}};
|
|
struct InventoryItemComponent {Slot* slot;Slot* GetParentSlot(){return slot;}};
|
|
struct Service {bool valid=true;int token=1;bool TransferAllowed(int captured,InventoryItemComponent*,int,int,float){return valid&&token==captured;}};
|
|
'''+body(t,'static bool Proven(')+'''
|
|
struct Move {
|
|
Service service; Service* m_Service=&service;
|
|
bool source=true,destination=false,m_Accepted=true,m_Invalidated=false,m_Resolved=false;
|
|
int m_Acknowledgement=0,m_Trip=1,m_From=1,m_To=2,m_Source=1,m_Destination=2;
|
|
float m_Deadline=8000;void* m_Storage=this;
|
|
Slot slot{this};InventoryItemComponent item{&slot};InventoryItemComponent* m_Shell=&item;
|
|
bool Contains(int owner){return m_Shell&&(owner==1?source:destination);}
|
|
'''+body(t,'void Acknowledge(')+body(t,'void Invalidate(')+body(t,'bool Unresolved(')+poll+'''
|
|
};
|
|
int main(){
|
|
for(int bits=0;bits<16;bits++)assert(Proven(bits&1,bits&2,bits&4,bits&8)==(bits==13));
|
|
Move pending;assert(pending.Poll(0)==0&&pending.Unresolved());
|
|
pending.Acknowledge(true);pending.Acknowledge(false);assert(pending.m_Acknowledgement==1);
|
|
assert(pending.Poll(1)==0);pending.destination=true;assert(pending.Poll(2)==0);
|
|
pending.source=false;pending.slot.value=nullptr;assert(pending.Poll(3)==0);
|
|
pending.slot.value=pending.m_Storage;assert(pending.Poll(4)==1&&!pending.Unresolved());
|
|
Move canceled;canceled.Invalidate();assert(canceled.Poll(1)==-1&&canceled.Unresolved());
|
|
canceled.source=false;canceled.destination=true;canceled.Acknowledge(true);
|
|
assert(canceled.Poll(2)==-1&&!canceled.Unresolved()); // late physical success releases reservation, never authority
|
|
Move expired;assert(expired.Poll(8000)==-1&&expired.Unresolved());
|
|
expired.source=false;expired.destination=true;expired.Acknowledge(true);
|
|
assert(expired.Poll(9000)==-1&&!expired.Unresolved());
|
|
Move replaced;replaced.service.token=2;replaced.source=false;replaced.destination=true;replaced.Acknowledge(true);
|
|
assert(replaced.Poll(1)==-1); // callback from previous trip cannot supply new trip
|
|
Move captured;captured.service.valid=false;assert(captured.Poll(1)==-1&&captured.Unresolved());
|
|
Move rejected;rejected.Acknowledge(false);assert(rejected.Poll(1)==-1&&!rejected.Unresolved());
|
|
Move lost;lost.m_Shell=nullptr;lost.Acknowledge(true);assert(lost.Poll(1)==-1&&!lost.Unresolved());assert(lost.Poll(8000)==-1&&!lost.Unresolved());
|
|
}
|
|
''')
|
|
accept=body(p,'bool AcceptsStatus(').replace('ERR_MortarSupplyStatus report','ERR_MortarSupplyStatus* report').replace('m_Battery.','m_Battery->').replace('report.','report->').replace('ERR_MortarLogisticsRules.','Rules::')
|
|
run('''#include <cassert>
|
|
struct Rules {'''+policies+'''};
|
|
struct ERR_MortarSupplyStatus {void* Group;void* Gun;float ObservedAt;int MessageId;int Shells;};
|
|
struct Battery {void* Group;void* Gun;};
|
|
struct Service {bool m_Stopped=false;int m_State=1,m_ConsumedMessage=0;Battery* m_Battery=nullptr;
|
|
'''+accept+'''};
|
|
int main(){int group,gun,other;Battery battery{&group,&gun};Service service;service.m_Battery=&battery;
|
|
ERR_MortarSupplyStatus report{&group,&gun,100,1,0};assert(service.AcceptsStatus(&report,101));
|
|
assert(!service.AcceptsStatus(nullptr,101));
|
|
report.Gun=&other;assert(!service.AcceptsStatus(&report,101));report.Gun=&gun;
|
|
report.Group=&other;assert(!service.AcceptsStatus(&report,101));report.Group=&group;
|
|
report.Shells=7;assert(!service.AcceptsStatus(&report,101));report.Shells=0;
|
|
assert(!service.AcceptsStatus(&report,180101));assert(!service.AcceptsStatus(&report,99));
|
|
report.ObservedAt=-1;assert(!service.AcceptsStatus(&report,100));report.ObservedAt=100;
|
|
service.m_ConsumedMessage=1;assert(!service.AcceptsStatus(&report,101));report.MessageId=2;assert(service.AcceptsStatus(&report,101));
|
|
service.m_State=3;assert(!service.AcceptsStatus(&report,101));service.m_State=1;
|
|
service.m_Stopped=true;assert(!service.AcceptsStatus(&report,101));
|
|
}
|
|
''')
|
|
print('PASS: actual finite-courier age, token, exact ownership/callback and delivered-status admission reject stale, replayed, captured, canceled and ambiguous work')
|
|
# Run the actual gun-capture gate with narrow native identity/compartment doubles.
|
|
target=body(p,'bool TargetAvailable(')
|
|
target=target.replace('m_Battery.','m_Battery->').replace('m_HQ.Mortars().FindGun','m_HQ->Mortars()->FindGun').replace('m_Mode.EnemyFaction()','m_Mode->EnemyFaction()')
|
|
target=target.replace('SCR_FactionManager.SGetFaction','SCR_FactionManager::SGetFaction').replace('ERR_Actors.','ERR_Actors::')
|
|
target=target.replace('SCR_AIVehicleUsageComponent usage = SCR_AIVehicleUsageComponent.Cast(m_OriginalGun.FindComponent(SCR_AIVehicleUsageComponent));','Usage* usage = m_OriginalGun->usage;')
|
|
target=target.replace('IEntity occupant','Actor* occupant').replace('usage.GetTurretCompartmentSlot().GetOccupant()','usage->GetTurretCompartmentSlot()->GetOccupant()').replace('usage.GetTurretCompartmentSlot()','usage->GetTurretCompartmentSlot()')
|
|
run('''#include <cassert>
|
|
struct Usage;
|
|
struct Actor {void* faction;void* group;bool alive=true;bool player=false;Usage* usage=nullptr;};
|
|
struct Slot {Actor* occupant=nullptr;Actor* GetOccupant(){return occupant;}};
|
|
struct Usage {Slot slot;bool present=true;Slot* GetTurretCompartmentSlot(){return present?&slot:nullptr;}};
|
|
struct Battery {Actor* Gun;void* Group;bool StartupActivated=true;bool operational=true;bool stopped=false;bool Stopped(){return stopped;}bool Operational(){return operational;}};
|
|
struct Registry {Battery* battery;Battery* FindGun(Actor* gun){return battery&&battery->Gun==gun?battery:nullptr;}};
|
|
struct HQ {Registry registry;Registry* Mortars(){return ®istry;}};
|
|
struct Mode {void* faction;void* EnemyFaction(){return faction;}};
|
|
struct SCR_FactionManager {static void* SGetFaction(Actor* actor){return actor->faction;}};
|
|
struct ERR_Actors {static bool CanFight(Actor* a){return a->alive;}static bool Player(Actor* a){return a->player;}static void* Group(Actor* a){return a->group;}};
|
|
struct Members {Actor* member;bool IsEmpty(){return !member;}bool Contains(Actor* a){return a==member;}};
|
|
struct Service {Battery* m_Battery;Actor* m_OriginalGun;void* m_OriginalBatteryGroup;HQ* m_HQ;Mode* m_Mode;Members m_BatteryMembers;
|
|
'''+target+'''
|
|
};
|
|
int main(){int faction,group,foreign;Usage usage;Actor gun{&faction,&group};gun.usage=&usage;Actor original{&faction,&group};
|
|
Battery battery{&gun,&group};HQ hq{{&battery}};Mode mode{&faction};Service service{&battery,&gun,&group,&hq,&mode,{&original}};
|
|
assert(service.TargetAvailable());usage.slot.occupant=&original;assert(service.TargetAvailable());
|
|
original.player=true;assert(!service.TargetAvailable());original.player=false;
|
|
original.alive=false;assert(!service.TargetAvailable());original.alive=true;
|
|
original.group=&foreign;assert(!service.TargetAvailable());original.group=&group;
|
|
original.faction=&foreign;assert(!service.TargetAvailable());original.faction=&faction;
|
|
Actor stranger{&faction,&group};usage.slot.occupant=&stranger;assert(!service.TargetAvailable());usage.slot.occupant=&original;
|
|
gun.faction=&foreign;assert(!service.TargetAvailable());gun.faction=&faction;
|
|
usage.present=false;assert(!service.TargetAvailable());usage.present=true;
|
|
battery.operational=false;assert(!service.TargetAvailable());battery.operational=true;
|
|
battery.stopped=true;assert(!service.TargetAvailable());battery.stopped=false;
|
|
battery.Gun=&stranger;assert(!service.TargetAvailable());battery.Gun=&gun;
|
|
hq.registry.battery=nullptr;assert(!service.TargetAvailable());hq.registry.battery=&battery;
|
|
service.m_BatteryMembers.member=nullptr;assert(!service.TargetAvailable());
|
|
}
|
|
''')
|
|
print('PASS: actual native-gun ownership gate rejects player/foreign/replaced/dead occupant, faction change, missing seat and missing registry')
|