Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
"""Production shared attack-space leases and confirmed-contact manoeuvre gate."""
|
||||
import re
|
||||
from policy_harness import ROOT,body,run
|
||||
p=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_AttackSpace.c'
|
||||
s='\n'.join(body(p,x) for x in ['protected void Prune(', 'bool Free(', 'void Claim(', 'void Release(', 'void Clear('])
|
||||
s=s.replace('protected ','').replace('foreach (','for (').replace('vector position','Vec position')
|
||||
for typ in ['SCR_AIGroup','ERR_AttackSlot']:s=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',s)
|
||||
s=s.replace('slot.','slot->').replace('added.','added->').replace('m_Slots[i].','m_Slots[i]->').replace('vector.DistanceXZ','Distance').replace('ERR_ForceRules.','ERR_ForceRules::')
|
||||
r=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQPursuit.c'
|
||||
gate='\n'.join(body(r,x) for x in ['static bool Finite(', 'static bool Actionable(', 'static bool Maneuver('])
|
||||
gate=gate.replace('0.65', '0.65f').replace('0.15','0.15f')
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
struct Vec{float x=0,z=0;};float Distance(Vec a,Vec b){return std::hypot(a.x-b.x,a.z-b.z);}
|
||||
struct ERR_ForceRules{static bool Finite(float x){return std::isfinite(x);}static bool FiniteVector(Vec p){return Finite(p.x)&&Finite(p.z);}};
|
||||
struct SCR_AIGroup{};struct ERR_AttackSlot{SCR_AIGroup*Group=nullptr;Vec Position;float Until=0;};
|
||||
template<class T>struct Array:std::vector<T>{int Count(){return this->size();}void Insert(T p){this->push_back(p);}void Remove(int i){delete this->at(i);this->erase(this->begin()+i);}void Clear(){while(!this->empty())Remove(0);}};
|
||||
struct Space{Array<ERR_AttackSlot*>m_Slots;
|
||||
'''+s+r'''
|
||||
};struct Rules{
|
||||
'''+gate+r'''
|
||||
};int main(){
|
||||
Space s;SCR_AIGroup cover,left,right;assert(s.Free(&cover,{},0));s.Claim(&cover,{},0);
|
||||
assert(s.Free(&cover,{},1)&&!s.Free(&left,{59,0},1)&&s.Free(&left,{60,0},1));
|
||||
s.Claim(&left,{120,0},1000);assert(!s.Free(&right,{100,0},1001));
|
||||
s.Claim(&left,{240,0},2000);assert(s.Free(&right,{120,0},2001)&&!s.Free(&right,{240,0},2001));
|
||||
s.Release(&cover);assert(s.Free(&right,{},2001)&&!s.Free(&right,{240,0},2001));
|
||||
assert(!s.Free(nullptr,{240,0},21999)&&s.Free(nullptr,{240,0},22000));
|
||||
s.Claim(nullptr,{},22001);assert(s.m_Slots.empty());
|
||||
s.Claim(&cover,{std::numeric_limits<float>::quiet_NaN(),0},22001);assert(s.m_Slots.empty());
|
||||
assert(!s.Free(&cover,{},-1));
|
||||
s.Claim(&left,{120,0},22002);s.m_Slots[0]->Group=nullptr;assert(s.Free(&right,{120,0},22003));
|
||||
SCR_AIGroup groups[129];for(int i=0;i<129;i++)s.Claim(&groups[i],{float(i*100),0},30000);assert(s.m_Slots.Count()==128);
|
||||
s.Clear();assert(s.m_Slots.empty());
|
||||
assert(Rules::Maneuver(true,.65,60,150,1)&&Rules::Maneuver(true,1,0,1,2));
|
||||
assert(!Rules::Maneuver(false,1,0,1,1)&&!Rules::Maneuver(true,.64,0,1,1));
|
||||
assert(!Rules::Maneuver(true,1,61,1,1)&&!Rules::Maneuver(true,1,0,151,1));
|
||||
assert(!Rules::Maneuver(true,1,0,1,0)&&!Rules::Maneuver(true,1,0,1,3));
|
||||
}
|
||||
''')
|
||||
print('PASS: shared own-force attack spacing, own-group refresh, exact release, expiry/deletion, finite capacity and fresh confirmed sighting-only flank permission')
|
||||
|
||||
# Execute the native vehicle-usage boundary: foot teams cannot choose their
|
||||
# troop truck as transport until regroup, and a captured truck is never restored.
|
||||
p=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyTactics.c'
|
||||
s=body(p,'void VehicleUse(').replace('null','nullptr')
|
||||
s=s.replace('SCR_AIVehicleUsageComponent.Cast(truck.FindComponent(SCR_AIVehicleUsageComponent))','truck->usage')
|
||||
for typ in ['ERR_GameMode','Vehicle','SCR_AIGroupUtilityComponent','SCR_AIVehicleUsageComponent']:
|
||||
s=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',s)
|
||||
for name in ['Group','utility','mode']:s=s.replace(name+'.',name+'->')
|
||||
s=s.replace('ERR_ConvoyRules.','ERR_ConvoyRules::')
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
struct SCR_AIVehicleUsageComponent{};
|
||||
struct Vehicle{SCR_AIVehicleUsageComponent*usage=nullptr;};
|
||||
struct SCR_AIGroupUtilityComponent{int removed=0,added=0;void RemoveUsableVehicle(SCR_AIVehicleUsageComponent*){removed++;}void AddUsableVehicle(SCR_AIVehicleUsageComponent*){added++;}};
|
||||
struct GroupType{int faction=1;SCR_AIGroupUtilityComponent*utility=nullptr;auto GetGroupUtilityComponent(){return utility;}int GetFaction(){return faction;}};
|
||||
struct ERR_GameMode{bool active=true;bool Active(){return active;}int EnemyFaction(){return 1;}};
|
||||
struct ERR_ConvoyRules{static inline bool captured=false;static bool Captured(Vehicle*,GroupType*){return captured;}};
|
||||
struct Team{GroupType*Group=nullptr;Vehicle*m_WalkVehicle=nullptr;bool alive=true;bool Living(){return alive;}
|
||||
'''+s+r'''
|
||||
};int main(){
|
||||
for(int invalid=0;invalid<6;invalid++){
|
||||
ERR_GameMode mode;Vehicle truck,other;SCR_AIVehicleUsageComponent usage;SCR_AIGroupUtilityComponent utility;GroupType group;Team team;
|
||||
truck.usage=other.usage=&usage;group.utility=&utility;team.Group=&group;ERR_ConvoyRules::captured=false;
|
||||
team.VehicleUse(&mode,&truck,false);team.VehicleUse(&mode,&truck,false);
|
||||
assert(utility.removed==1&&team.m_WalkVehicle==&truck);
|
||||
team.VehicleUse(&mode,&other,true);assert(!utility.added&&team.m_WalkVehicle==&truck);
|
||||
if(invalid==1)mode.active=false;
|
||||
if(invalid==2)team.alive=false;
|
||||
if(invalid==3)group.faction=2;
|
||||
if(invalid==4)ERR_ConvoyRules::captured=true;
|
||||
team.VehicleUse(invalid==5?nullptr:&mode,&truck,true);
|
||||
assert(utility.added==(invalid==0)&&!team.m_WalkVehicle);
|
||||
team.VehicleUse(&mode,&truck,true);assert(utility.added==(invalid==0));
|
||||
}
|
||||
}
|
||||
''')
|
||||
print('PASS: actual convoy foot transport detachment is idempotent; regroup restores only its live friendly uncaptured original truck')
|
||||
Reference in New Issue
Block a user