Files
EscapistsReintroduced/tests/test_site_map_visibility.py

106 lines
7.3 KiB
Python

"""Run production marker transitions and discovery with engine boundary doubles."""
from policy_harness import ROOT, body, run
base = ROOT/'addons/core/Scripts/Game/ERR/00_Core'
map_source = base/'ERR_DiscoveryMap.c'
rules = '\n'.join(body(map_source, s) for s in ('static int DisplayKnowledge(', 'static int Coordinate(')).replace('Math.Round','std::round').replace('Math.Floor','std::floor')
update = body(map_source, 'protected void ERR_UpdateMarker(').replace('protected ', '')
discover = body(base/'ERR_Location.c', 'bool Discover(')
icon = body(map_source, 'void SetLocationIcon(')
for name in ('ERR_GameMode', 'SCR_MapMarkerManagerComponent', 'ERR_DiscoveryMapRules', 'ERR_LocationKind', 'SCR_EMapMarkerType', 'Replication', 'ERR_MissionRules'):
update = update.replace(name+'.', name+'::')
discover = discover.replace(name+'.', name+'::')
for typename in ('ERR_GameMode', 'SCR_MapMarkerManagerComponent'):
update = update.replace(typename+' ', typename+'* ')
discover = discover.replace('ERR_GameMode mode', 'ERR_GameMode* mode')
for name in ('mode', 'manager', 'oldManager', 'm_ERRMarker'):
update = update.replace(name+'.',name+'->')
discover = discover.replace('mode.', 'mode->')
update = update.replace('GetGame().','GetGame()->').replace('null','nullptr')
mission = body(base/'ERR_MissionRules.c', 'static int Discovery(')
run(r'''
#include <cassert>
#include <cmath>
#include <string>
#include <memory>
struct string:std::string{using std::string::string;string(std::string s):std::string(s){}bool IsEmpty(){return empty();}};
namespace ERR_LocationKind {enum Kind{PRISON,RADIO,EXTRACTION,OUTPOST,DEPOT,MORTAR,HOSPITAL};}
namespace SCR_EMapMarkerType {constexpr int PLACED_CUSTOM=0;}
struct Game{bool controller=true;bool GetPlayerController(){return controller;}}game;
Game* GetGame(){return &game;}
struct Replication{static inline bool server=true;static bool IsServer(){return server;}static void BumpMe(){}};
struct ERR_GameMode{bool enabled=false;int events=0;static ERR_GameMode* Get();bool ShowAllSites(){return enabled;}void LocationDiscovered(void*,int,int){events++;}}mode;
ERR_GameMode* ERR_GameMode::Get(){return &mode;}
struct ERR_MissionRules {'''+mission+r'''};
struct ERR_DiscoveryMapRules {'''+rules+r'''};
struct ERR_DiscoveryMarker{
string label,m_Icon;int x=0,refreshes=0;bool removed=false;
static string Icon(int kind,string){return kind==ERR_LocationKind::RADIO?"radio":"supplies";}
void ApplyIcon(){}void SetType(int){}void SetMarkerConfigID(int){}
void SetCustomText(string v){label=v;}void RefreshPresentation(){refreshes++;}
void SetDiscoveryPosition(float p,int knowledge){x=ERR_DiscoveryMapRules::Coordinate(p,knowledge);}
void OnDelete(){removed=true;}
'''+icon.replace('ERR_LocationKind kind','int kind')+r'''
};
struct SCR_MapMarkerManagerComponent{
static inline bool ready=true;int inserts=0,removes=0;
static SCR_MapMarkerManagerComponent* GetInstance();
bool GetMarkerConfig(){return ready;}
void ERR_InsertDiscoveryMarker(ERR_DiscoveryMarker*){inserts++;}
void ERR_RemoveDiscoveryMarker(ERR_DiscoveryMarker* marker){removes++;delete marker;}
}manager;
SCR_MapMarkerManagerComponent* SCR_MapMarkerManagerComponent::GetInstance(){return &manager;}
struct Location{
ERR_DiscoveryMarker* m_ERRMarker=nullptr;int m_ERRShown=-1,m_Knowledge=0;string m_ERRShownLabel;
bool m_Prepared=true;int kind=ERR_LocationKind::RADIO;
int Knowledge(){return m_Knowledge;}bool Prepared(){return m_Prepared;}int Kind(){return kind;}
string Label(){return "Secret radio station";}string Id(){return "secret-radio-id";}float Position(){return 6123.25f;}
'''+update+'\n'+discover+r'''
~Location(){delete m_ERRMarker;}
};
int main(){
Location site;site.ERR_UpdateMarker();assert(!site.m_ERRMarker&&site.m_Knowledge==0);
mode.enabled=true;site.ERR_UpdateMarker();assert(site.m_ERRMarker);
assert(site.m_ERRMarker->label=="Unknown site"&&site.m_ERRMarker->m_Icon=="mark-question"&&site.m_ERRMarker->x==6123);
assert(site.m_Knowledge==0&&mode.events==0); // Visibility never grants discovery or objective progress.
auto* first=site.m_ERRMarker;site.ERR_UpdateMarker();assert(site.m_ERRMarker==first&&manager.inserts==1);
mode.enabled=false;site.ERR_UpdateMarker();assert(!site.m_ERRMarker&&manager.removes==1);
mode.enabled=true;site.ERR_UpdateMarker();assert(site.m_ERRMarker&&manager.inserts==2);
assert(site.Discover(99,0)); // An actual clue identifies even when normal exact chance is zero.
site.ERR_UpdateMarker();assert(site.Knowledge()==2&&mode.events==1);
assert(site.m_ERRMarker->label=="Secret radio station"&&site.m_ERRMarker->m_Icon=="radio");
mode.enabled=false;site.ERR_UpdateMarker();assert(site.m_ERRMarker&&site.m_ERRMarker->x==6123);
assert(!site.Discover(0,100)&&mode.events==1);
Location rough;assert(rough.Discover(99,0)&&rough.Knowledge()==1);rough.ERR_UpdateMarker();
assert(rough.m_ERRMarker->label=="Unknown location (500 m area)"&&rough.m_ERRMarker->x==6250);
mode.enabled=true;rough.ERR_UpdateMarker();assert(rough.Knowledge()==1&&rough.m_ERRMarker->x==6123&&rough.m_ERRMarker->m_Icon=="mark-question");
mode.enabled=false;rough.ERR_UpdateMarker();assert(rough.m_ERRMarker->x==6250);
mode.enabled=true;assert(rough.Discover(99,0)&&rough.Knowledge()==2);
Location pending;pending.m_Prepared=false;pending.ERR_UpdateMarker();assert(!pending.m_ERRMarker&&!pending.Discover(0,100));
pending.m_Prepared=true;pending.ERR_UpdateMarker();assert(pending.m_ERRMarker);
pending.m_Prepared=false;pending.ERR_UpdateMarker();assert(!pending.m_ERRMarker);
Location prison;prison.kind=ERR_LocationKind::PRISON;prison.ERR_UpdateMarker();assert(!prison.m_ERRMarker);
Location late;manager.ready=false;late.ERR_UpdateMarker();assert(!late.m_ERRMarker);
manager.ready=true;late.ERR_UpdateMarker();assert(late.m_ERRMarker&&late.m_ERRMarker->m_Icon=="mark-question");
Replication::server=false;assert(!late.Discover(0,100)&&late.Knowledge()==0);
for(int kind=ERR_LocationKind::RADIO;kind<=ERR_LocationKind::HOSPITAL;kind++){
Location other;other.kind=kind;other.ERR_UpdateMarker();assert(other.m_ERRMarker&&other.m_ERRMarker->label=="Unknown site"&&other.m_ERRMarker->m_Icon=="mark-question");
}
}
''')
# Persisted authority and runtime presentation wiring (including late-join replication).
settings=base/'ERR_Settings.c'
assert '"showAllSites"' in body(settings,'static array<string> Keys(')
assert 'if (key == "showAllSites") return 0;' in body(settings,'static int AddedDefault(')
assert 'showAllSites' not in body(settings,'static bool Randomizable(')
mode_source=(base/'ERR_GameMode.c').read_text()
assert '[RplProp()] protected bool m_ShowAllSites;' in mode_source
assert 'PublishSiteVisibility();' in body(base/'ERR_GameMode.c','protected override void EOnInit(')
publish=body(base/'ERR_GameMode.c','void PublishSiteVisibility(')
assert '!Replication.IsServer()' in publish and 'Replication.BumpMe()' in publish
admin=body(base/'ERR_AdminService.c','void Execute(')
assert admin.index('!authorized') < admin.index('mode.PublishSiteVisibility()')
assert admin.index('SettingCommand(mode.Settings(), key, parts, replies);') < admin.index('mode.PublishSiteVisibility()')
click=body(base/'ERR_AdminMenu.c','protected void OnButton(')
assert click.index('!m_Ready') < click.index('"intel sites set "')
print('PASS: hidden/anonymous/rough/identified markers, toggle transitions, prepared sites, no identity leakage, intel discovery and replicated authority wiring')