"""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' sarka_rules=body(p.parent/'ERR_HunterSarkaRules.c','static bool Seats(') 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 all = {}, cargo = {}, turrets = {}, drivers = {};','Array 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_SarkaRules','ERR_ConvoyResources','ERR_HQ','ECompartmentType','string']: s=s.replace(cls+'.',cls+'::') run(r''' #include #include #include using ResourceName=int; struct string{templatestatic int Format(T...){return 0;}}; templatestruct Array:std::vector{using std::vector::operator=;void Insert(T x){this->push_back(x);}int Count(){return this->size();}}; struct ERR_HunterFleetRules{ '''+rules+r''' }; struct ERR_SarkaRules{ '''+sarka_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 seats;}; struct ERR_ConvoyVehicle{Vehicle*Entity;AIGroup*Group;bool TroopTransport=false;bool Motorbike=false;bool Sarka=false;ArraySeats;ArrayMembers;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&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);} for(int passengers=2;passengers<=4;passengers++){ Mode mode;Service service{&mode};Vehicle vehicle;AIGroup group;ERR_HunterVehicle car{&vehicle,&group};car.Sarka=true;car.TroopTransport=true; BaseCompartmentSlot driver{ECompartmentType::PILOT},cargo[4];vehicle.seats.Insert(&driver); for(int i=0;iprefab==2)medics++;assert(medics==1);} else assert(mode.owned==0); } 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')