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:
@@ -36,13 +36,13 @@ assert 'if (m_ERRTestHQBody) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 24
|
||||
start=smoke.index('m_ERRTestLostHelicopter = System.GetCLIParam(')
|
||||
end=smoke.index('OnStop().Insert(ERR_StopHQPatrol);',start)
|
||||
selector=smoke[start:end].replace('System.GetCLIParam("errSmokeOutcome", outcome) && ', '')
|
||||
selector=selector.replace('GetWorld().GetWorldTime()', 'now').replace('ERR_NativeConvoyCoverProbe.Enabled()', 'cover')
|
||||
selector=selector.replace('GetWorld().GetWorldTime()', 'now').replace('ERR_NativeConvoyCoverProbe.Enabled()', 'cover').replace('ERR_NativeMountedCourierProbe.Enabled()', 'courier').replace('ERR_NativeMaintenanceProbe.Enabled()', 'maintenance').replace('ERR_NativeMountedInterceptProbe.Enabled()', 'intercept')
|
||||
flags=sorted(set(re.findall(r'\bm_ERRTest\w+',selector)))
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
using string = std::string;
|
||||
float deadline(string outcome,float now,bool cover=false){
|
||||
float deadline(string outcome,float now,bool cover=false,bool courier=false,bool maintenance=false,bool intercept=false){
|
||||
[[maybe_unused]] bool DECLARATIONS;
|
||||
float m_ERRSmokeDeadline=0;
|
||||
SELECTOR
|
||||
@@ -51,12 +51,17 @@ float deadline(string outcome,float now,bool cover=false){
|
||||
int main(){
|
||||
for(float now : {0.0f, 42000.0f}) {
|
||||
for(string outcome : {"", "victory", "lost-helicopter"}) assert(deadline(outcome,now)==now+300000);
|
||||
for(string outcome : {"escape-route", "player-death", "radio-network", "hq-response", "map-ownership"}) assert(deadline(outcome,now)==now+150000);
|
||||
for(string outcome : {"escape-route", "normal-escape-route", "player-death", "radio-network", "hq-response", "map-ownership"}) assert(deadline(outcome,now)==now+150000);
|
||||
assert(deadline("patrol-hq",now)==now+420000);
|
||||
assert(deadline("hq-memory",now)==now+360000);
|
||||
assert(deadline("hq-body",now)==now+240000);
|
||||
assert(deadline("convoy",now)==now+540000);
|
||||
assert(deadline("convoy",now,false,false,false,true)==now+840000);
|
||||
assert(deadline("supply-convoys",now)==now+840000);
|
||||
assert(deadline("convoy",now,true)==now+840000);
|
||||
assert(deadline("mounted-ammo",now)==now+330000);
|
||||
assert(deadline("mounted-ammo",now,false,true)==now+750000);
|
||||
assert(deadline("normal-escape-route",now,false,false,true)==now+330000);
|
||||
}
|
||||
}
|
||||
'''.replace('DECLARATIONS', ','.join(flag+'=false' for flag in flags)).replace('SELECTOR',selector))
|
||||
@@ -64,12 +69,13 @@ print('PASS: bounded HQ startup/memory windows and outcome-specific full-route d
|
||||
|
||||
# The new route diagnostic must leave the original administrator/reroll stress
|
||||
# intact and may skip only those extras, never clue or radio progression gates.
|
||||
route=body(Path(os.environ.get('ERR_SMOKE_SOURCE',REPO/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c')), 'bool ERR_CheckRouteExtras(float now)')
|
||||
route=body(Path(os.environ.get('ERR_SMOKE_SOURCE',REPO/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c')), 'bool ERR_CheckRouteExtras(float now)').replace('ERR_NativeMaintenanceProbe.Enabled()', 'maintenance')
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
struct Probe {
|
||||
bool m_ERRTestEscapeRoute=false,rerollReady=false;
|
||||
bool m_ERRTestEscapeRoute=false,rerollReady=false,maintenance=false,maintenanceReady=false;
|
||||
int maintenanceCalls=0; bool ERR_RunMaintenance(float){maintenanceCalls++;return maintenanceReady;}
|
||||
int adminResult=0,adminCalls=0,rerollCalls=0,failures=0;
|
||||
int ERR_ProbeAdminMenu(float){adminCalls++;return adminResult;}
|
||||
bool ERR_Check(bool result,std::string){if(!result)failures++;return result;}
|
||||
@@ -79,6 +85,8 @@ struct Probe {
|
||||
int main(){
|
||||
Probe route;route.m_ERRTestEscapeRoute=true;assert(route.ERR_CheckRouteExtras(100));
|
||||
assert(route.adminCalls==0&&route.rerollCalls==0&&route.failures==0);
|
||||
route.maintenance=true;assert(!route.ERR_CheckRouteExtras(101)&&route.maintenanceCalls==1);
|
||||
route.maintenanceReady=true;assert(route.ERR_CheckRouteExtras(102)&&route.maintenanceCalls==2&&route.adminCalls==0&&route.rerollCalls==0);
|
||||
Probe full;assert(!full.ERR_CheckRouteExtras(100)&&full.adminCalls==1&&full.rerollCalls==0);
|
||||
full.adminResult=-1;assert(!full.ERR_CheckRouteExtras(200)&&full.failures==1&&full.rerollCalls==0);
|
||||
full.adminResult=1;assert(!full.ERR_CheckRouteExtras(300)&&full.rerollCalls==1);
|
||||
@@ -89,3 +97,115 @@ assert 'if (!ERR_CheckRouteExtras(now)) return;' in smoke
|
||||
assert 'if (!ERR_Check(m_ERRSmokeRadio.Knowledge() == 2,' in smoke
|
||||
assert 'if (!ERR_Check(Phase() == ERR_Phase.EXTRACTION,' in smoke
|
||||
print('PASS: explicit escape-route skips only administrator stress, preserving original full-fixture wait/failure paths')
|
||||
|
||||
# Execute the actual scenario-selection expressions: normal route must retain
|
||||
# the ordinary catalog AND random placement, while historical probes stay fixed.
|
||||
scenario=Path(os.environ.get('ERR_SCENARIO_SOURCE',REPO/'addons/core/Scripts/Game/ERR/00_Core/ERR_ScenarioComponent.c')).read_text()
|
||||
conditions=[]
|
||||
for variable in ('historicalFixture','fixture'):
|
||||
line=next(line.strip() for line in scenario.splitlines() if line.strip().startswith('if (') and 'System.GetCLIParam("errSmokeOutcome", '+variable+')' in line)
|
||||
expression=line[4:-1].replace('System.GetCLIParam("errSmokeOutcome", '+variable+')','supplied').replace(variable,'outcome')
|
||||
conditions.append(expression)
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
using string=std::string;
|
||||
bool legacy(bool supplied,string outcome,bool m_TerrainIndependent=false){return LEGACY;}
|
||||
bool fixed(bool supplied,string outcome,bool m_TerrainIndependent=false){return FIXED;}
|
||||
int main(){
|
||||
for(string route : {"normal-escape-route","generated-sites","optional-site-skip"}) {assert(!legacy(true,route));assert(!fixed(true,route));}
|
||||
for(string route : {"escape-route","victory","transport-survey"}) {assert(legacy(true,route));assert(fixed(true,route));}
|
||||
assert(!legacy(false,"escape-route")&&!fixed(false,"escape-route"));
|
||||
}
|
||||
'''.replace('LEGACY',conditions[0]).replace('FIXED',conditions[1]))
|
||||
print('PASS: normal escape route keeps ordinary catalog and generated placement; historical selectors remain unchanged')
|
||||
|
||||
# Execute the actual patrol-hq admission branch. The existing production
|
||||
# prison-AI/progression tests cover canonical UnlockPrison and phase callbacks;
|
||||
# here native damage, allocation and unlock boundaries are explicit doubles.
|
||||
smoke_path=Path(os.environ.get('ERR_SMOKE_SOURCE',REPO/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c'))
|
||||
smoke_tick=body(smoke_path,'protected void ERR_SmokeTick(')
|
||||
a=smoke_tick.index('if (m_ERRTestPatrolHQ)'); b=smoke_tick.index('{',a); i=b+1; depth=1
|
||||
while depth:
|
||||
depth+=(smoke_tick[i]=='{')-(smoke_tick[i]=='}');i+=1
|
||||
patrol_branch=smoke_tick[a:i]
|
||||
patrol_branch=patrol_branch.replace('DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);','ProtectOriginal(m_ERRSmokePlayer);').replace('ERR_Phase.RADIO_SEARCH','2')
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
struct Fixture;
|
||||
struct ERR_NativePatrolHQProbe {explicit ERR_NativePatrolHQProbe(Fixture* owner);};
|
||||
struct ERR_NativePatrolProbe {explicit ERR_NativePatrolProbe(Fixture*){assert(false && "permanent patrol must follow responder HQ proof");}};
|
||||
struct Fixture {
|
||||
bool m_ERRTestPatrolHQ=true,allowed=true,wrongPhase=false,active=false;
|
||||
int m_ERRSmokePlayer=7,phase=1,unlocks=0,failures=0,allocations=0,protections=0,m_ERRSmokeStep=0;
|
||||
ERR_NativePatrolHQProbe* m_ERRHQPatrolOrder=nullptr;
|
||||
ERR_NativePatrolProbe* m_ERRHQPatrolMovement=nullptr;
|
||||
~Fixture(){delete m_ERRHQPatrolOrder;delete m_ERRHQPatrolMovement;}
|
||||
void ProtectOriginal(int actor){assert(actor==7);protections++;}
|
||||
bool UnlockPrison(int actor){assert(actor==7);unlocks++;if(!allowed)return false;if(!wrongPhase){phase=2;active=true;}return true;}
|
||||
int Phase(){return phase;}
|
||||
bool ERR_Check(bool ok,std::string){if(!ok)failures++;return ok;}
|
||||
void Start(){BRANCH}
|
||||
};
|
||||
ERR_NativePatrolHQProbe::ERR_NativePatrolHQProbe(Fixture* owner){assert(owner->phase==2&&owner->active&&owner->unlocks==1);owner->allocations++;}
|
||||
int main(){
|
||||
Fixture healthy;healthy.Start();assert(healthy.m_ERRSmokeStep==131&&healthy.allocations==1&&healthy.failures==0&&healthy.protections==1);
|
||||
Fixture refused;refused.allowed=false;refused.Start();assert(refused.unlocks==1&&refused.failures==1&&refused.allocations==0&&refused.m_ERRSmokeStep==0&&!refused.active);
|
||||
Fixture wrong;wrong.wrongPhase=true;wrong.Start();assert(wrong.unlocks==1&&wrong.failures==1&&wrong.allocations==0&&wrong.m_ERRSmokeStep==0);
|
||||
Fixture other;other.m_ERRTestPatrolHQ=false;other.Start();assert(other.unlocks==0&&other.allocations==0&&other.protections==0&&other.m_ERRSmokeStep==0);
|
||||
}
|
||||
'''.replace('BRANCH',patrol_branch))
|
||||
assert 'if (result == 1) { m_ERRHQPatrolMovement = new ERR_NativePatrolProbe(this); m_ERRSmokeStep = 132; }' in body(smoke_path,'protected void ERR_SmokeTick(')
|
||||
print('PASS: actual patrol fixture leaves prison before responder HQ proof, followed by separate permanent-patrol observation')
|
||||
|
||||
# Execute the isolated definition mutation on the actual legacy outpost fields.
|
||||
# Definition.Valid is a boundary double here; full production authoring policy
|
||||
# remains enforced by the normal preparation path and repository checks.
|
||||
scenario_path=Path(os.environ.get('ERR_SCENARIO_SOURCE',REPO/'addons/core/Scripts/Game/ERR/00_Core/ERR_ScenarioComponent.c'))
|
||||
legacy=(REPO/'addons/core/Configs/ERR/Tests/LegacySites.conf').read_text()
|
||||
start=legacy.index('Id "everon-outpost-1"');end=legacy.index('\n }',start);outpost=legacy[start:end]
|
||||
assert 'ResponseCount' not in outpost and 'Guarded 1' in outpost and 'GuardOffset 16 0 0' in outpost
|
||||
assert outpost.count('ERR_SitePatrolPoint')==4
|
||||
if 'protected bool ERR_ConfigurePatrolHQFixture(' in scenario:
|
||||
configure=body(scenario_path,'protected bool ERR_ConfigurePatrolHQFixture(').replace('protected ','').replace('ERR_SiteDefinition site =','Site* site =').replace('m_RuntimeDefinition.','m_RuntimeDefinition->').replace('site.','site->').replace('ERR_LocationKind.OUTPOST','3').replace('"-20 0 -20"','Vec{-20,0,-20}')
|
||||
assert scenario.index('ERR_ConfigurePatrolHQFixture(fixture)') < scenario.index('m_Generated.Begin(m_RuntimeDefinition)') < scenario.index('m_Sites.Begin(m_RuntimeDefinition')
|
||||
else:
|
||||
# Baseline has no prepopulation mutation; executing its unchanged definition
|
||||
# must fail the required two-mobile-originals assertion below.
|
||||
configure='bool ERR_ConfigurePatrolHQFixture(string){return true;}'
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
using string=std::string;
|
||||
struct Vec{float x,y,z;};
|
||||
struct Site {int Kind=3,ResponseCount=0,GuardCount=0,patrolPoints=4,stock=4;bool Guarded=true;Vec ResponseOffset{-12,0,0},GuardOffset{16,0,0};};
|
||||
struct Definition{Site site;bool present=true,valid=true;int validations=0;Site*Find(string id){assert(id=="everon-outpost-1");return present?&site:nullptr;}bool Valid(){validations++;return valid;}};
|
||||
struct Fixture {bool m_TerrainIndependent=false;Definition* m_RuntimeDefinition=nullptr;METHOD};
|
||||
int main(){
|
||||
Definition d;Fixture f;f.m_RuntimeDefinition=&d;assert(f.ERR_ConfigurePatrolHQFixture("patrol-hq"));
|
||||
assert(d.site.ResponseCount==2&&d.site.ResponseOffset.x==-20&&d.site.ResponseOffset.z==-20&&d.site.ResponseOffset.y==0&&d.validations==1);
|
||||
assert(d.site.Guarded&&d.site.GuardCount==0&&d.site.GuardOffset.x==16&&d.site.patrolPoints==4&&d.site.stock==4);
|
||||
for(string outcome:{"","normal-escape-route","patrol","victory","hq-memory"}){Definition other;Fixture g;g.m_RuntimeDefinition=&other;assert(g.ERR_ConfigurePatrolHQFixture(outcome)&&other.site.ResponseCount==0&&other.validations==0);}
|
||||
Definition terrain;Fixture t;t.m_TerrainIndependent=true;t.m_RuntimeDefinition=&terrain;assert(t.ERR_ConfigurePatrolHQFixture("patrol-hq")&&terrain.site.ResponseCount==0);
|
||||
for(int fault=0;fault<6;fault++){Definition bad;Fixture x;x.m_RuntimeDefinition=&bad;if(fault==0)x.m_RuntimeDefinition=nullptr;if(fault==1)bad.present=false;if(fault==2)bad.site.Kind=0;if(fault==3)bad.site.Guarded=false;if(fault==4)bad.site.ResponseCount=1;if(fault==5)bad.valid=false;assert(!x.ERR_ConfigurePatrolHQFixture("patrol-hq"));}
|
||||
}
|
||||
'''.replace('METHOD',configure))
|
||||
# Test actual final receipt decision. Delivery/native allocation are covered by
|
||||
# their own methods and the real opt-in run; this checks the native getter is
|
||||
# required instead of accepting an assignment with the untouched prefab radius.
|
||||
patrol_path=Path(os.environ.get('ERR_PATROL_HQ_SOURCE',REPO/'addons/core/Scripts/Game/ERR/10_AI/ERR_NativePatrolHQProbe.c'))
|
||||
patrol=body(patrol_path,'bool ERR_TestPatrolSearch(')
|
||||
assert 'float queuedRadius = task.SearchRadiusMetres;' in patrol
|
||||
assert patrol.index('float queuedRadius =') < patrol.index('DeliverOrder(unit,')
|
||||
tail=patrol[patrol.index(' search = unit.Waypoint;'):patrol.index('\n }',patrol.index(' search = unit.Waypoint;'))].replace('unit.','unit->').replace('search.','search->')
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
struct Waypoint{float radius=30;float GetCompletionRadius(){return radius;}};
|
||||
struct Unit{Waypoint*WaypointValue=nullptr;int Assignment=1;};
|
||||
int logs=0;void PrintFormat(std::string,float,float){logs++;}
|
||||
bool Delivered(Unit* unit,int order,float queuedRadius){Waypoint*search=nullptr;TAIL}
|
||||
int main(){Waypoint wp;Unit unit;unit.WaypointValue=℘assert(!Delivered(&unit,1,45));wp.radius=45;assert(Delivered(&unit,1,45));wp.radius=110;assert(Delivered(&unit,1,110));assert(!Delivered(&unit,1,45));unit.Assignment=2;assert(!Delivered(&unit,1,110));unit.WaypointValue=nullptr;int before=logs;assert(!Delivered(&unit,1,110)&&logs==before);}
|
||||
'''.replace('TAIL',tail.replace('unit->Waypoint','unit->WaypointValue')))
|
||||
print('PASS: exact patrol-hq finite responder preparation and native search-radius receipt verification')
|
||||
|
||||
Reference in New Issue
Block a user