Files
EscapistsReintroduced/tests/test_gameplay_review_fixes.py
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

60 lines
4.3 KiB
Python

"""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 'AIWaypoint movement = Move(support)' in body(tactics,'protected void Support(')
assert 'orders.Add(movement)' in body(tactics,'protected void Support(')
assert 'SearchWaypoint()' in body(tactics,'protected bool PlanFlank(')
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')