65 lines
4.6 KiB
Python
65 lines
4.6 KiB
Python
"""Exercise production discovery/availability for non-interacting exploration scenes."""
|
|
from pathlib import Path
|
|
import subprocess,tempfile
|
|
root=Path(__file__).resolve().parents[2]
|
|
source=(root/'src/server/game/World/AdventureSocialActions.cpp').read_text()
|
|
def function(sig):
|
|
a=source.index(sig);b=source.index('{',a);depth=1;e=b+1
|
|
while depth:depth+=(source[e]=='{')-(source[e]=='}');e+=1
|
|
return source[a:e]
|
|
code=r'''
|
|
#include "AdventureExplorationPolicy.h"
|
|
#include "AdventureProfessionPolicy.h"
|
|
#include <cassert>
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
#include <string>
|
|
#include <vector>
|
|
using uint32=unsigned;
|
|
constexpr int GAMEOBJECT_TYPE_GENERIC=5,GAMEOBJECT_TYPE_GOOBER=10,GAMEOBJECT_TYPE_TEXT=9,GAMEOBJECT_TYPE_CHAIR=7;
|
|
struct Guid{std::string ToString(){return "prop";}};
|
|
struct WorldObject{
|
|
bool world=true,phase=true;uint32 map=0;float x=0,z=0;
|
|
bool IsInWorld()const{return world;}uint32 GetMapId()const{return map;}float GetPositionZ()const{return z;}
|
|
};
|
|
struct GameObject:WorldObject{bool spawned=true,visible=true,los=true;int type=5;bool isSpawned(){return spawned;}int GetGoType(){return type;}Guid GetGUID(){return {};}};
|
|
struct Position{float GetExactDist(WorldObject const*p)const{return std::hypot(p->x,p->z);}float GetPositionZ()const{return 0;}};
|
|
struct Player{
|
|
std::vector<GameObject*> objects;bool outdoors=true;
|
|
void GetGameObjectListWithEntryInGrid(std::vector<GameObject*>&out,int,float radius){for(auto p:objects)if(std::hypot(p->x,p->z)<=radius)out.push_back(p);}
|
|
bool IsInPhase(WorldObject const*p){return p->phase;}bool CanSeeOrDetect(GameObject*p){return p->visible;}bool IsWithinLOSInMap(GameObject*p){return p->los;}bool IsOutdoors(){return outdoors;}bool IsInWater(){return false;}bool IsFalling(){return false;}
|
|
};
|
|
struct AdventureSocialContext{Position Anchor;uint32 MapId=0;std::string Intent="adventure",LocationCategory="ruins";bool Festival=false,AllowCreateFire=true;std::vector<std::string> TargetHistory;AdventureProfessionPolicy::Professions PrimaryProfessions;};
|
|
struct AdventureMicroAction{std::string Requirement;};
|
|
std::vector<GameObject*> Objects(Player*,int,AdventureSocialContext&){return {};}
|
|
std::vector<GameObject*> People(Player*,std::string const&,AdventureSocialContext&){return {};}
|
|
GameObject* Fire(Player*,AdventureSocialContext&){return nullptr;}bool CanMakeFire(Player*){return false;}
|
|
struct AdventureProfessionTargets{static std::vector<GameObject*> Find(Player*,std::string const&,AdventureSocialContext&){return {};}};
|
|
class AdventureSocialActions{public:static bool Available(Player*,AdventureMicroAction const&,AdventureSocialContext&);};
|
|
'''
|
|
for sig in ('bool InBounds(', 'std::vector<GameObject*> InspectionObjects(', 'bool AdventureSocialActions::Available('):code+=function(sig)+'\n'
|
|
code+=r'''
|
|
int main(){
|
|
Player p;AdventureSocialContext c;GameObject prop;p.objects={&prop};
|
|
for(int type:{5,9,10}){prop.type=type;assert(AdventureSocialActions::Available(&p,{"inspect"},c));}
|
|
for(int type:{0,1,3,6,7,11,15,21}){prop.type=type;assert(!AdventureSocialActions::Available(&p,{"inspect"},c));}
|
|
prop.type=5;prop.spawned=false;assert(InspectionObjects(&p,c).empty());prop.spawned=true;
|
|
prop.visible=false;assert(InspectionObjects(&p,c).empty());prop.visible=true;
|
|
prop.los=false;assert(InspectionObjects(&p,c).empty());prop.los=true;
|
|
prop.phase=false;assert(InspectionObjects(&p,c).empty());prop.phase=true;
|
|
prop.map=1;assert(InspectionObjects(&p,c).empty());prop.map=0;
|
|
prop.x=61;assert(InspectionObjects(&p,c).empty());prop.x=50;assert(!InspectionObjects(&p,c).empty());prop.x=0;
|
|
c.Intent="leisure";assert(!AdventureSocialActions::Available(&p,{"inspect"},c)&&!AdventureSocialActions::Available(&p,{"scout"},c));c.Intent="adventure";
|
|
assert(AdventureSocialActions::Available(&p,{"scout"},c));p.outdoors=false;
|
|
assert(!AdventureSocialActions::Available(&p,{"vista"},c)&&AdventureSocialActions::Available(&p,{"equipment"},c));p.outdoors=true;
|
|
for(auto category:{"ruins","dungeon","mine"}){c.LocationCategory=category;assert(AdventureSocialActions::Available(&p,{"entrance"},c));}
|
|
c.LocationCategory="tavern";assert(!AdventureSocialActions::Available(&p,{"entrance"},c));
|
|
// No gameobject use, loot, spellcast or inventory API is available in this adapter.
|
|
}
|
|
'''
|
|
with tempfile.TemporaryDirectory(prefix='vcore-exploration-') as folder:
|
|
cpp=Path(folder)/'test.cpp';binary=Path(folder)/'test';cpp.write_text(code)
|
|
subprocess.run(['c++','-std=c++17','-I',str(root/'src/server/game/World'),str(cpp),'-o',str(binary)],check=True)
|
|
subprocess.run([str(binary)],check=True)
|
|
print('Exploration: visible native props only, no chests/traps/furniture, phase/map/LOS/range gates and contextual preparation passed.')
|