Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
"""Execute the hunter fleet and actual seat allocation for UAZs and troop trucks."""
|
||||
import re
|
||||
from policy_harness import ROOT,body,run
|
||||
p=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c'
|
||||
bike_rules=body(p.parent/'ERR_OptionalMotorbikes.c','static bool Seats(')
|
||||
rules=body(p,'static bool Transport(')+body(p,'static bool Seats(')
|
||||
s=body(p,'override protected bool FillCrew(').replace('override protected ','')
|
||||
s=s.replace('array<BaseCompartmentSlot> all = {}, cargo = {}, turrets = {}, drivers = {};','Array<BaseCompartmentSlot*> all,cargo,turrets,drivers;')
|
||||
s=s.replace('ERR_HunterVehicle.Cast(unit)','unit')
|
||||
s=s.replace('foreach (','for (').replace('null','nullptr')
|
||||
for typ in ['ERR_ConvoyVehicle','ERR_HunterVehicle','BaseCompartmentSlot','AIGroup','IEntity']:
|
||||
s=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',s)
|
||||
for obj in ['unit','seat','hunter','m_Mode']:
|
||||
s=s.replace(obj+'.',obj+'->')
|
||||
s=s.replace('unit->Seats[i].','unit->Seats[i]->')
|
||||
for cls in ['ERR_EnemyMedicalCatalog','ERR_EnemyLoadoutCatalog','ERR_ConvoyRules','ERR_HunterFleetRules','ERR_MotorbikeRules','ERR_ConvoyResources','ERR_HQ','ECompartmentType','string']:
|
||||
s=s.replace(cls+'.',cls+'::')
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
using ResourceName=int;
|
||||
struct string{template<class...T>static int Format(T...){return 0;}};
|
||||
template<class T>struct Array:std::vector<T>{using std::vector<T>::operator=;void Insert(T x){this->push_back(x);}int Count(){return this->size();}};
|
||||
struct ERR_HunterFleetRules{
|
||||
'''+rules+r'''
|
||||
};
|
||||
struct ERR_MotorbikeRules{
|
||||
'''+bike_rules+r'''
|
||||
};
|
||||
namespace ECompartmentType{enum{PILOT,TURRET,CARGO};}
|
||||
struct IEntity{int prefab;};struct AIGroup{};
|
||||
struct BaseCompartmentSlot{int type;bool available=true,fail=false;IEntity*occupant=nullptr;bool IsCompartmentAccessible(){return available;}IEntity*GetOccupant(){return occupant;}int GetType(){return type;}
|
||||
IEntity*SpawnCharacterInCompartment(int prefab,AIGroup*&,int){if(fail)return nullptr;occupant=new IEntity{prefab};return occupant;}};
|
||||
struct Vehicle{Array<BaseCompartmentSlot*> seats;};
|
||||
struct ERR_ConvoyVehicle{Vehicle*Entity;AIGroup*Group;bool TroopTransport=false;bool Motorbike=false;Array<BaseCompartmentSlot*>Seats;Array<IEntity*>Members;IEntity*Driver=nullptr;};using ERR_HunterVehicle=ERR_ConvoyVehicle;
|
||||
struct Mode{int owned=0;void Own(IEntity*){owned++;}};
|
||||
namespace ERR_EnemyMedicalCatalog{int Crew(Mode*,bool medic){return medic?2:1;}}
|
||||
namespace ERR_EnemyLoadoutCatalog{bool Available(int p){return p>0;}}
|
||||
namespace ERR_ConvoyRules{bool CollectSeats(Vehicle*v,Array<BaseCompartmentSlot*>&out){out=v->seats;return true;}}
|
||||
namespace ERR_ConvoyResources{int GroupPrefab(){return 1;}}
|
||||
namespace ERR_HQ{void Event(const char*,int){}void Event(const char*,const char*){}}
|
||||
struct Service{Mode*m_Mode;
|
||||
'''+s+r'''
|
||||
};
|
||||
int main(){
|
||||
int trucks=0;for(int i=0;i<15;i++){if(ERR_HunterFleetRules::Transport(i))trucks++;assert(ERR_HunterFleetRules::Transport(i)==(i%3==2));}assert(trucks==5);
|
||||
assert(!ERR_HunterFleetRules::Transport(-1)&&!ERR_HunterFleetRules::Transport(15));
|
||||
for(int transport=0;transport<2;transport++){
|
||||
Mode mode;Service service{&mode};Vehicle vehicle;AIGroup group;ERR_HunterVehicle unit{&vehicle,&group};unit.TroopTransport=transport;
|
||||
BaseCompartmentSlot driver{ECompartmentType::PILOT},gunner{ECompartmentType::TURRET};vehicle.seats.Insert(&driver);
|
||||
if(!transport)vehicle.seats.Insert(&gunner);
|
||||
BaseCompartmentSlot cargo[14];for(int i=0;i<(transport?14:3);i++){cargo[i].type=ECompartmentType::CARGO;vehicle.seats.Insert(&cargo[i]);}
|
||||
assert(service.FillCrew(&unit));assert(unit.Members.Count()==(transport?15:5)&&unit.Driver==driver.occupant&&mode.owned==unit.Members.Count());
|
||||
int medics=0;for(auto member:unit.Members)if(member->prefab==2)medics++;assert(medics==1&&cargo[0].occupant->prefab==2);
|
||||
}
|
||||
{Mode mode;Service service{&mode};Vehicle vehicle;AIGroup group;ERR_HunterVehicle bike{&vehicle,&group};bike.Motorbike=true;
|
||||
BaseCompartmentSlot driver{ECompartmentType::PILOT},passenger{ECompartmentType::CARGO};vehicle.seats={};vehicle.seats.Insert(&driver);vehicle.seats.Insert(&passenger);
|
||||
assert(service.FillCrew(&bike)&&bike.Members.Count()==2&&bike.Driver==driver.occupant);
|
||||
assert(driver.occupant->prefab==1&&passenger.occupant->prefab==2);}
|
||||
assert(!ERR_HunterFleetRules::Seats(true,1,0,13,14)); // no silent population shrink
|
||||
assert(!ERR_HunterFleetRules::Seats(false,1,0,14,15)); // transport cannot pass as armed UAZ
|
||||
assert(!ERR_HunterFleetRules::Seats(true,2,0,14,16));
|
||||
}
|
||||
''')
|
||||
print('PASS: finite 2-UAZ/1-truck rotation, exact physical crew seats, one medic, and no smaller/armed substitute for transport')
|
||||
Reference in New Issue
Block a user