Fix convoy coordination, AI combat and spectator recovery
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
"""Execute fixes for the 26 September log failures against boundary doubles."""
|
||||
from policy_harness import ROOT, body, run
|
||||
r=ROOT/'addons/core/Scripts/Game/ERR/10_AI'
|
||||
cleanup=body(r/'ERR_HunterCrewRecovery.c','static void Complete(')
|
||||
cleanup=cleanup.replace('SCR_AIVehicleBehavior behavior','Behavior* behavior').replace('IEntity actor','Actor* actor')
|
||||
cleanup=cleanup.replace('SCR_ChimeraAIAgent agent = SCR_ChimeraAIAgent.Cast(SCR_AIUtils.GetAIAgent(actor));','Agent* agent = actor->agent;')
|
||||
cleanup=cleanup.replace('array<ref AIActionBase> actions = {};','Actions actions;').replace('agent.','agent->').replace('m_UtilityComponent.','m_UtilityComponent->').replace('behavior.Complete()','behavior->Complete()')
|
||||
run('''#include <cassert>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
struct Behavior {int completions=0;void Complete(){completions++;}};
|
||||
struct Actions:std::vector<Behavior*>{bool Contains(Behavior* b){return std::find(begin(),end(),b)!=end();}};
|
||||
struct Utility {void* m_AIInfo=this;Actions queued;void GetActions(Actions& out){out=queued;}};
|
||||
struct Agent {Utility* m_UtilityComponent=nullptr;};struct Actor{Agent* agent=nullptr;};
|
||||
'''+cleanup+'''
|
||||
int main(){Behavior b;Actor actor;Complete(&b,nullptr);Complete(&b,&actor);assert(!b.completions);
|
||||
Agent agent;actor.agent=&agent;Complete(&b,&actor);assert(!b.completions);
|
||||
Utility utility;agent.m_UtilityComponent=&utility;Complete(&b,&actor);assert(!b.completions);
|
||||
utility.queued.push_back(&b);utility.m_AIInfo=nullptr;Complete(&b,&actor);assert(!b.completions);
|
||||
utility.m_AIInfo=&utility;Complete(&b,&actor);assert(b.completions==1);
|
||||
utility.queued.clear();Complete(&b,&actor);assert(b.completions==1);}
|
||||
''')
|
||||
# Execute the actual HQ eligibility branch. Its success permits the existing
|
||||
# radio request path, never directly a shot; per-shot checks remain separate.
|
||||
tick=body(r/'ERR_MortarSystem.c','void Tick(')
|
||||
a=tick.index(' vector predicted;');b=tick.index(' selected = battery;',a)
|
||||
preflight=tick[a:b].replace('vector predicted;','Vec predicted;').replace('ERR_MortarPrediction.Predict','Predict').replace('battery.Trace','battery->Trace').replace('predicted.ToString()','std::string("reported")')
|
||||
run('''#include <cassert>
|
||||
#include <string>
|
||||
struct Vec{};struct Battery{int holds=0;void Trace(std::string,std::string,std::string){holds++;}};
|
||||
struct Test{bool prediction=true,safe=true;int predictions=0,safetyChecks=0,orders=0;std::string SafetyReason="friendly";
|
||||
bool Predict(void*,float,float,Vec&){predictions++;return prediction;}
|
||||
bool Safe(Battery*,Vec,float){safetyChecks++;return safe;}
|
||||
void Tick(Battery* battery){void* report=nullptr;float now=100;for(int i=0;i<1;i++){
|
||||
'''+preflight+'''orders++;}}};
|
||||
int main(){Test t;Battery battery;t.prediction=false;t.Tick(&battery);assert(!t.orders&&!t.safetyChecks);
|
||||
t.prediction=true;t.safe=false;t.Tick(&battery);assert(!t.orders&&battery.holds==1);
|
||||
t.safe=true;t.Tick(&battery);assert(t.orders==1&&t.safetyChecks==2);}
|
||||
''')
|
||||
# Prevent the exact mounted Defend regression from returning: mounted escorts
|
||||
# keep Move-to-cover/native vehicle combat, while infantry retain flank/search.
|
||||
tactics=r/'ERR_SupplyConvoyTactics.c'
|
||||
assert 'DefendWaypoint()' not in body(tactics,'protected void Support(')
|
||||
assert 'orders.Add(Move(support))' in body(tactics,'protected void Support(')
|
||||
assert 'SearchWaypoint()' in body(tactics,'protected void Flank(')
|
||||
print('PASS: stale/deleted AI utility cannot receive Complete; mortar HQ preflight withholds unsafe orders; mounted convoy cover never creates infantry Defend')
|
||||
|
||||
# The native RHS fixture reproduces this boundary: the convenience API boards
|
||||
# before applying a group faction. Keep production affiliation ahead of entry.
|
||||
flight=r/'ERR_ReconFlightComponent.c'
|
||||
prepare=body(flight,'protected bool PrepareCrew(')
|
||||
assert 'SpawnCharacterInCompartment(' not in prepare
|
||||
assert prepare.index('ERR_Actors.SetFaction(initialCrew,') < prepare.index('access.GetInVehicle(')
|
||||
assert prepare.index('m_Crew.AddAgent(') < prepare.index('access.GetInVehicle(')
|
||||
assert 'SpawnCharacterInCompartment(' not in body(flight,'void Initialize(')
|
||||
finish=body(flight,'protected bool FinishCrew(')
|
||||
assert finish.index('now - m_Started > 45000') < finish.index('m_Assault.Preparing()')
|
||||
print('PASS: flight crew affiliation and group precede native boarding; preparation remains bounded even while passengers wait')
|
||||
Reference in New Issue
Block a user