Files
EscapistsReintroduced/docs/evidence/mounted-native-2026-10-02/deadline-adapter/before.py
T
jakub 6a667d8deb Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
2026-10-13 22:52:53 +02:00

120 lines
7.8 KiB
Python

"""Actual native-fixture startup/deadline gate, engine boundaries doubled."""
import os,sys,re
from pathlib import Path
REPO=Path(os.environ.get('ERR_REPO', Path(__file__).resolve().parents[1]))
sys.path.insert(0,str(REPO/'tests'))
from policy_harness import body,run
p=Path(os.environ.get('ERR_MEMORY_PROBE_SOURCE',REPO/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQMemoryProbe.c'))
s=body(p,'int Tick(ERR_HQ hq, float now)')
# Execute the unchanged deadline/startup prefix; payload/native radio assertions
# after this gate remain the full fixture's responsibility.
s=s[:s.index(' if (!m_ValueChecked)')]+ ' }\n return 1;\n }'
s=s.replace('ERR_HQ hq','ERR_HQ* hq').replace('hq.','hq->')
run(r'''
#include <cassert>
#include <string>
using string = std::string;
struct CLI {string outcome="hq-memory"; void GetCLIParam(string,string& value){value=outcome;}} System;
struct ERR_HQ{bool ready=true;bool ERR_ProbeSquadsReady(){return ready;}};
struct Probe{bool enabled=true,m_Mode=true,m_Failed=false,m_AutoChecked=false;int m_Step=0,automatic=0,checks=0;float m_Deadline=0;bool Enabled(){return enabled;}void Check(bool,std::string){checks++;m_Failed=true;}int AutomaticConvoy(ERR_HQ*){if(automatic==1)m_AutoChecked=true;return automatic;}
METHOD
};
int main(){ERR_HQ hq;
Probe p;assert(p.Tick(&hq,1000)==0&&p.m_Deadline==151000);assert(p.Tick(&hq,130000)==0&&p.m_Deadline==151000);p.automatic=1;assert(p.Tick(&hq,145000)==1&&p.m_Deadline==265000);assert(p.Tick(&hq,200000)==1&&p.m_Deadline==265000);assert(p.Tick(&hq,265000)==1);assert(p.Tick(&hq,265001)==-1&&p.checks==1);
Probe missing;assert(missing.Tick(&hq,0)==0);assert(missing.Tick(&hq,150001)==-1&&missing.checks==1);
Probe refused;refused.Tick(&hq,0);refused.automatic=-1;assert(refused.Tick(&hq,40000)==-1&&refused.m_Deadline==150000&&!refused.m_AutoChecked);
Probe unavailable;hq.ready=false;assert(unavailable.Tick(&hq,0)==0);assert(unavailable.Tick(&hq,150001)==-1);hq.ready=true;
System.outcome="hq-awareness"; hq.ready=false; Probe awareness; assert(awareness.Tick(&hq,1000)==1 && !awareness.m_AutoChecked && awareness.m_Deadline==151000); assert(awareness.Tick(&hq,151001)==-1);
Probe invalid;invalid.enabled=false;assert(invalid.Tick(&hq,0)==-1&&invalid.m_Deadline==0);
}
'''.replace('METHOD',s))
smoke=Path(os.environ.get('ERR_SMOKE_SOURCE',REPO/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c')).read_text()
assert 'if (m_ERRTestHQMemory) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 360000;' in smoke
assert 'if (m_ERRTestHQBody) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 240000;' in smoke
# Execute the actual startup selector, so enlarged full-route budgets cannot
# accidentally extend a death/radio test or shorten an existing specialized run.
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').replace('ERR_NativeMountedCourierProbe.Enabled()', 'courier').replace('ERR_NativeMaintenanceProbe.Enabled()', 'maintenance')
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,bool courier=false,bool maintenance=false){
[[maybe_unused]] bool DECLARATIONS;
float m_ERRSmokeDeadline=0;
SELECTOR
return m_ERRSmokeDeadline;
}
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", "normal-escape-route", "player-death", "radio-network", "hq-response", "map-ownership"}) assert(deadline(outcome,now)==now+150000);
assert(deadline("hq-memory",now)==now+360000);
assert(deadline("hq-body",now)==now+240000);
assert(deadline("convoy",now)==now+540000);
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))
print('PASS: bounded HQ startup/memory windows and outcome-specific full-route deadlines')
# 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)').replace('ERR_NativeMaintenanceProbe.Enabled()', 'maintenance')
run(r'''
#include <cassert>
#include <string>
struct Probe {
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;}
bool ERR_CheckIntelReroll(float){rerollCalls++;return rerollReady;}
METHOD
};
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);
full.rerollReady=true;assert(full.ERR_CheckRouteExtras(400)&&full.rerollCalls==2);
}
'''.replace('METHOD',route))
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=(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')