39 lines
2.6 KiB
Python
39 lines
2.6 KiB
Python
"""Delivered ammo gates new tasks without becoming active-order cancellation."""
|
|
from policy_harness import ROOT, body, run
|
|
H=ROOT/'addons/ai/Scripts/Game/ERR/ERR_HQ.c'
|
|
for method in ('protected void Investigate(', 'protected void Retask(', 'protected void Assign('):
|
|
s=body(H,method)
|
|
assert 'if (m_Watch.ArmedSearchBlocked(unit.ForceSourceId, now)) continue;' in s
|
|
# Execute the production delivery admission before unrelated native waypoint creation.
|
|
s=body(H,'protected void DeliverOrder(')
|
|
s=s[:s.index(' if (task.Investigation())')]+' admitted++;\n }'
|
|
s=s.replace('protected ','').replace('null','nullptr').replace('ERR_HQUnit unit','ERR_HQUnit* unit')
|
|
s=s.replace('ERR_HQReport order','ERR_HQReport* order').replace('ERR_HQTask task','ERR_HQTask* task')
|
|
for name in ('unit','task','order'):s=s.replace(name+'.',name+'->')
|
|
run(r'''
|
|
#include <cassert>
|
|
#include <string>
|
|
struct ERR_HQReport{};
|
|
struct ERR_HQTask{float ExpiresAt=100000;bool ReleaseOnly=false;ERR_HQTask* ReplacesTask=nullptr;};
|
|
struct ERR_HQUnit{ERR_HQReport* PendingOrder=nullptr;ERR_HQTask* PendingTask=nullptr;ERR_HQTask* Task=nullptr;
|
|
std::string ForceSourceId="original-1";bool eligible=true;int cancellations=0;
|
|
bool Eligible(void*){return eligible;}void CancelPending(){cancellations++;PendingOrder=nullptr;PendingTask=nullptr;}};
|
|
struct Watch {bool empty=false;int calls=0;bool ArmedSearchBlocked(std::string s,float){assert(s=="original-1");calls++;return empty;}};
|
|
struct Journal {void Write(std::string,std::string){}};
|
|
struct HQ{Watch m_Watch;Journal m_Journal;void* m_Mode=nullptr;int admitted=0,lost=0,released=0;
|
|
void LostOrder(ERR_HQUnit* u,float){lost++;u->CancelPending();}void ReleaseUnit(ERR_HQUnit* u,float){released++;u->Task=nullptr;u->CancelPending();}
|
|
'''+s+r'''
|
|
};
|
|
int main(){HQ h;ERR_HQUnit u;ERR_HQReport report;ERR_HQTask active,next;u.Task=&active;
|
|
auto queue=[&](){u.PendingOrder=&report;u.PendingTask=&next;};
|
|
queue();h.m_Watch.empty=true;h.DeliverOrder(&u,1000);assert(h.lost==1&&h.admitted==0&&u.Task==&active&&!u.PendingTask);
|
|
queue();h.m_Watch.empty=false;h.DeliverOrder(&u,1000);assert(h.admitted==1&&u.Task==&active);
|
|
// Delivered release commands still work for empty squads and do not consult ammo.
|
|
next.ReleaseOnly=true;next.ReplacesTask=&active;queue();h.m_Watch.empty=true;int calls=h.m_Watch.calls;
|
|
h.DeliverOrder(&u,1000);assert(h.released==1&&!u.Task&&h.m_Watch.calls==calls);
|
|
// Stale orders fail before inventory knowledge is consulted.
|
|
next.ReleaseOnly=false;next.ExpiresAt=500;queue();h.DeliverOrder(&u,1000);assert(h.lost==2&&h.m_Watch.calls==calls);
|
|
}
|
|
''')
|
|
print('PASS: new/retasked search and radio delivery ammo gates; active tasks and delivered release preserved')
|