"""Exercise concrete bounds, saved modes, calendar mapping and daylight edges.""" from datetime import date, timedelta from policy_harness import ROOT, body, run core = ROOT/'addons/core/Scripts/Game/ERR/00_Core' rules = '\n'.join(body(core/file, sig) for file, sig in ( ('ERR_Settings.c', 'static bool Valid('), ('ERR_Settings.c', 'static bool Randomizable('), ('ERR_Settings.c', 'static bool ValidSelection('), ('ERR_Settings.c', 'static bool RandomBounds('), ('ERR_EnvironmentService.c', 'static int DateFromOrdinal('), ('ERR_TimeService.c', 'static bool DaylightBounds('), )) rules = rules.replace('string ', 'std::string ').replace('out int ', 'int& ').replace('Math.Floor', 'std::floor').replace('Math.Ceil', 'std::ceil') calendar = [] for year in (1900, 1989, 2000, 2024, 2050): first = date(year, 1, 1) days = (date(year+1,1,1)-first).days for ordinal in range(days): day = first+timedelta(days=ordinal) code = (year-1900)*10000+day.month*100+day.day calendar.append(f'assert(DateFromOrdinal({year},{ordinal})=={code});') calendar.append(f'assert(DateFromOrdinal({year},{days})==-1);') run('#include \n#include \n#include \n' + rules + r""" int main() { int lo=-1,hi=-1; for (std::string key:{"reportIntervalSeconds","supportSquadLimit","responseRadiusMetres","aiIntelChancePercent","intelRevealChancePercent","radioDefenceSeconds","startTimeMinutes","timeMultiplier","startDateCode","weatherProfile","convoyCount","heliTimerMinutes","antiAirChancePercent","antiPersonnelMineChancePercent"}) { assert(ValidSelection(key,-1)); assert(!Valid(key,-1)); assert(ValidSelection(key,-2)==(key=="startTimeMinutes")); assert(!ValidSelection(key,-3)); if(key=="startDateCode")continue; assert(RandomBounds(key,lo,hi)); assert(lo<=hi); for(int value=lo;value<=hi;value++) assert(Valid(key,value)); } for(std::string key:{"unknown","","automaticConvoyEnabled"}) assert(!ValidSelection(key,-1)); assert(RandomBounds("convoyCount",lo,hi)&&lo==0&&hi==20); assert(RandomBounds("weatherProfile",lo,hi)&&lo==1&&hi==3); assert(RandomBounds("startTimeMinutes",lo,hi)&&lo==0&&hi==1439); assert(DaylightBounds(6.0,18.0,lo,hi)&&lo==361&&hi==1080); assert(DaylightBounds(6.125,18.125,lo,hi)&&lo==368&&hi==1088); for(int minute=lo;minute6.125&&minute/60.0<18.125); assert(!DaylightBounds(18,6,lo,hi)); assert(!DaylightBounds(12,12,lo,hi)); assert(!DaylightBounds(-1,18,lo,hi));assert(!DaylightBounds(6,25,lo,hi)); assert(!DaylightBounds(6.0,6.001,lo,hi)); assert(DaylightBounds(0,24,lo,hi)&&lo==1&&hi==1440); assert(DateFromOrdinal(1899,0)==-1&&DateFromOrdinal(2051,0)==-1&&DateFromOrdinal(2000,-1)==-1); """ + ''.join(calendar) + '}') print('PASS: random mode restrictions, full numeric ranges, independent calendar dates and strict daylight boundaries')