Files
EscapistsReintroduced/tests/test_convoy_startup.py
T
jakub 1b1a8b5173 Add mission customization, HQ support and aggression-driven AI
Integrate faction and random settings menus, generated objectives, scouts, convoys, air support, mortar stations and body-intel recovery. Add identified-body aggression, finite hunter UAZ deployment, dedicated objective defence and maximum AI skill with separate reduced aim accuracy. Include policy tests, native probes, evidence and documentation.
2026-09-23 15:07:14 +02:00

43 lines
4.3 KiB
Python

"""Execute one-shot startup timing and actual HQ dispatch boundary; no native claim."""
from policy_harness import ROOT, body, run
import re
p=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyStartup.c'
s=p.read_text().replace('protected ','').replace('ERR_ForceRules.','ERR_ForceRules::')
s=s[s.index('class ERR_ConvoyStartup'):].replace('void ERR_ConvoyStartup(bool enabled)','void Initialize(bool enabled)')
s=s.replace('bool m_Enabled;', 'bool m_Enabled=false;').replace('bool m_Finished;', 'bool m_Finished=false;').replace('float m_Next;', 'float m_Next=0;')
s=s.replace('class ERR_ConvoyStartup', 'struct ERR_ConvoyStartup').rstrip()+';'
h=body(ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c','protected void AutomaticConvoy(')
h=h.replace('protected ','').replace('null','nullptr').replace('Replication.','Replication::').replace('ERR_GameMode.','ERR_GameMode::')
for name in ('m_Mode','m_ConvoyStartup','m_SupplyConvoys','m_Convoys'):h=h.replace(name+'.',name+'->')
run(r'''
#include <cassert>
#include <cmath>
#include <limits>
#include <string>
using string=std::string;
struct ERR_ForceRules {static bool Finite(float n){return std::isfinite(n);}};
'''+s+r'''
struct Replication {inline static bool server=true;static bool IsServer(){return server;}};
struct ERR_GameMode {inline static ERR_GameMode* current;bool active=true;static ERR_GameMode* Get(){return current;}bool Active(){return active;}};
struct Journal {int count=0;void Write(string,string){count++;}};
struct Supply {void Tick(float,bool){}}; struct Service {int Count(){return 0;}void* At(int){return nullptr;}};
struct HQ {Supply* m_SupplyConvoys=nullptr; Service* m_Convoys=nullptr;ERR_GameMode* m_Mode;ERR_ConvoyStartup* m_ConvoyStartup;void* m_ConvoyTask=nullptr;string m_ConvoyFailure;Journal m_Journal;bool ready=true,accepted=true;int calls=0;bool ConvoyAdmissionReady(){return ready;}bool StartScenarioConvoy(){calls++;return accepted;}
'''+h+r'''
};
int main(){
ERR_ConvoyStartup off;off.Initialize(false);assert(!off.Enabled()&&off.Finished());assert(!off.Decide(0,false,true)&&!off.Decide(90000,false,true));
ERR_ConvoyStartup once;once.Initialize(true);assert(once.Enabled());assert(!once.Decide(1000,false,true));assert(!once.Decide(30999,false,true));assert(once.Decide(31000,false,true));assert(once.Finished());assert(!once.Decide(36000,false,true));once.Complete(false);assert(once.Status()=="dispatch refused; no automatic retry");assert(!once.Decide(1000000,false,true));
ERR_ConvoyStartup later;later.Initialize(true);later.Decide(0,false,false);assert(!later.Decide(30000,false,false));assert(!later.Decide(34000,false,true));assert(later.Decide(35000,false,true));later.Complete(true);assert(later.Status()=="canonical convoy dispatched");assert(!later.Decide(60000,false,true));
ERR_ConvoyStartup expire;expire.Initialize(true);expire.Decide(0,false,false);assert(!expire.Decide(120000,false,true)&&expire.Finished());assert(expire.Status()=="startup admission deadline expired");
ERR_ConvoyStartup manual;manual.Initialize(true);assert(!manual.Decide(0,true,true)&&manual.Finished());assert(!manual.Decide(60000,false,true));
ERR_ConvoyStartup invalid;invalid.Initialize(true);assert(!invalid.Decide(std::numeric_limits<float>::quiet_NaN(),false,true));assert(!invalid.Decide(-1,false,true));invalid.Decide(10000,false,false);assert(!invalid.Decide(0,false,true));assert(invalid.Decide(40000,false,true));
ERR_ConvoyStartup stopped;stopped.Initialize(true);stopped.Decide(0,false,false);stopped.Stop();assert(!stopped.Decide(30000,false,true));
ERR_GameMode mode;ERR_GameMode::current=&mode;ERR_ConvoyStartup startup;startup.Initialize(true);HQ hq;hq.m_Mode=&mode;hq.m_ConvoyStartup=&startup;
Replication::server=false;hq.AutomaticConvoy(0);assert(hq.calls==0&&hq.m_Journal.count==0);Replication::server=true;
ERR_GameMode::current=nullptr;hq.AutomaticConvoy(0);assert(hq.m_Journal.count==0);ERR_GameMode::current=&mode;
mode.active=false;hq.AutomaticConvoy(0);assert(hq.m_Journal.count==0);mode.active=true;
hq.AutomaticConvoy(0);hq.ready=false;hq.AutomaticConvoy(30000);assert(hq.calls==0);hq.ready=true;hq.accepted=false;hq.AutomaticConvoy(35000);assert(hq.calls==1&&startup.Finished());hq.AutomaticConvoy(100000);assert(hq.calls==1);
}
''')
print('PASS: actual automatic convoy timing/authority/admission/one-attempt/manual-task/stop policy; native deployment unproved')