47 lines
3.5 KiB
Python
47 lines
3.5 KiB
Python
"""Production hunter release and objective-role policy, without native spawning."""
|
|
from policy_harness import ROOT, body, run
|
|
source=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c'
|
|
s=body(source,'override void Release(ERR_GameMode mode)')
|
|
s=s.replace('override ','').replace('super.','Native::').replace('null','nullptr')
|
|
s=s.replace('ERR_GameMode mode','ERR_GameMode* mode').replace('ERR_ForceRecord record','ERR_ForceRecord* record')
|
|
s=s.replace('ERR_HQ hq = ERR_HQ.Cast(mode.Command())', 'ERR_HQ* hq = mode->Command()')
|
|
s=s.replace('array<AIAgent> agents = {};','Array<AIAgent*> agents;').replace('foreach (AIAgent agent : agents)','for (AIAgent* agent : agents)')
|
|
for name in ('mode','record','Group','agent','hq','Recovery'):s=s.replace(name+'.',name+'->')
|
|
s=s.replace('Forces().','Forces()->').replace('ERR_ConvoyRules.','ERR_ConvoyRules::')
|
|
objective=body(ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_ObjectiveDefence.c','static bool Objective(').replace('ERR_LocationKind.','ERR_LocationKind::')
|
|
run(r'''
|
|
#include <cassert>
|
|
#include <vector>
|
|
template<class T>using Array=std::vector<T>;
|
|
struct AIAgent{int lod=0,writes=0;void SetPermanentLOD(int x){lod=x;writes++;}};
|
|
struct GroupType{int lod=0;AIAgent agent;void SetPermanentLOD(int x){lod=x;}void GetAgents(Array<AIAgent*>& a){a={&agent};}};
|
|
struct ERR_ForceRecord{bool Pinned=true;};
|
|
struct Ledger{ERR_ForceRecord record;ERR_ForceRecord* FindGroup(GroupType*){return &record;}};
|
|
struct ERR_HQ{int releases=0;void ReleaseRecovery(GroupType*){releases++;}};
|
|
struct ERR_GameMode{bool active=true;Ledger ledger;ERR_HQ hq;bool Active(){return active;}Ledger* Forces(){return &ledger;}ERR_HQ* Command(){return &hq;}};
|
|
namespace ERR_ConvoyRules{bool captured=false;bool Captured(void*,GroupType*){return captured;}}
|
|
struct RecoveryTask{int stops=0;void Stop(){stops++;}};
|
|
struct Native{RecoveryTask* Recovery=nullptr;bool Released=false;int delegated=0,clears=0;GroupType* Group=nullptr;void* Entity=nullptr;void* Downlink=nullptr;
|
|
void Release(ERR_GameMode*){delegated++;Released=true;}void ClearOrder(){clears++;}
|
|
};
|
|
struct Hunter:Native{
|
|
'''+s+r'''
|
|
};
|
|
namespace ERR_LocationKind{enum{PRISON,RADIO,EXTRACTION,PATROL,DEPOT,OUTPOST,MORTAR,HOSPITAL};}
|
|
'''+objective+r'''
|
|
int main(){
|
|
ERR_GameMode mode;GroupType group;Hunter unit;unit.Group=&group;unit.Entity=&group;unit.Downlink=&mode;RecoveryTask recovery;unit.Recovery=&recovery;
|
|
unit.Release(&mode);assert(unit.Released&&!unit.Downlink&&unit.clears==1&&unit.delegated==0);
|
|
assert(recovery.stops==1);
|
|
assert(!mode.ledger.record.Pinned&&mode.hq.releases==1&&group.lod==-1&&group.agent.writes==1);
|
|
assert(unit.Entity==&group&&unit.Group==&group); // living and dead actors/vehicle are preserved
|
|
unit.Release(&mode);assert(unit.clears==1&&mode.hq.releases==1&&group.agent.writes==1);
|
|
Hunter captured;ERR_ConvoyRules::captured=true;captured.Release(&mode);assert(captured.delegated==1&&mode.hq.releases==1);
|
|
ERR_ConvoyRules::captured=false;Hunter stopped;mode.active=false;stopped.Release(&mode);assert(stopped.delegated==1);
|
|
Hunter missing;missing.Release(nullptr);assert(missing.delegated==1);
|
|
assert(Objective(ERR_LocationKind::RADIO)&&Objective(ERR_LocationKind::DEPOT)&&Objective(ERR_LocationKind::OUTPOST)&&Objective(ERR_LocationKind::EXTRACTION));
|
|
assert(!Objective(ERR_LocationKind::PRISON)&&!Objective(ERR_LocationKind::PATROL)&&!Objective(ERR_LocationKind::MORTAR));
|
|
}
|
|
''')
|
|
print('PASS: actual hunter release preserves survivors/HQ, releases driving ownership once, delegates capture/teardown, and excludes prison/patrol/mortar from generic objective defence')
|