62 lines
4.0 KiB
Python
62 lines
4.0 KiB
Python
"""Execute production adaptive planning and explicit recorded rescue search."""
|
|
from pathlib import Path
|
|
import runpy,subprocess,tempfile
|
|
root=Path(__file__).resolve().parents[2]
|
|
e=runpy.run_path(str(root/'tests/clientless/test_free_flight_planner.py'))
|
|
s=e['s']
|
|
def method(sig):
|
|
a=s.index(sig);b=s.index('{',a);n=1;c=b+1
|
|
while n:n+=(s[c]=='{')-(s[c]=='}');c+=1
|
|
return s[a:c]
|
|
preamble=e['preamble'].replace('uint32 GetMapId()const{return 0;}','uint32 map=369; uint32 GetMapId()const{return map;} float GetExactDist(float a,float b,float c)const{return std::sqrt((x-a)*(x-a)+(y-b)*(y-b)+(z-c)*(z-c));}')
|
|
cls=e['cls'].replace('\n};','''
|
|
std::vector<ClientlessTravelEdgePoint>const*GetEdgePoints(uint32 id)const{auto i=_edgePoints.find(id);return i==_edgePoints.end()?nullptr:&i->second;}
|
|
bool PlanRescueRoute(Player*,std::vector<ClientlessTravelRouteStep>&,std::string&,bool=false,std::unordered_set<uint32>const* =nullptr);
|
|
bool FindNearestNodeToPosition(uint32,float,float,float,std::string&,float&)const;
|
|
};''')
|
|
code=preamble+e['structs']+cls+e['method']+method('bool ClientlessTravelGraphMgr::FindNearestNodeToPosition(')+method('bool ClientlessTravelGraphMgr::PlanRescueRoute(')+r'''
|
|
void node(ClientlessTravelGraphMgr&g,std::string k,float x,std::string type="ground"){
|
|
ClientlessTravelNode n;n.Key=k;n.Type=type;n.X=x;n.MapId=369;g._nodes[k]=n;
|
|
}
|
|
void edge(ClientlessTravelGraphMgr&g,std::string a,std::string b,unsigned id){
|
|
g._edges[a].push_back({id,a,b,"ground",10,false});
|
|
ClientlessTravelEdgePoint p;p.X=g._nodes.at(a).X;p.MapId=369;g._edgePoints[id].push_back(p);
|
|
p.X=g._nodes.at(b).X;g._edgePoints[id].push_back(p);
|
|
}
|
|
int main(){
|
|
ClientlessTravelGraphMgr g;Player p;p.x=5000;
|
|
node(g,"sw",0,"rescue");node(g,"if",2500,"rescue");node(g,"exit_sw",10);node(g,"exit_if",2490);
|
|
edge(g,"sw","exit_sw",1);edge(g,"if","exit_if",2);edge(g,"sw","if",3);
|
|
std::vector<ClientlessTravelRouteStep>r;std::string transfer,error,reached;bool complete=false;
|
|
// Rescue roots are excluded from ordinary nearest anchors and destinations.
|
|
float distance;assert(g.FindNearestNodeToPosition(369,0,0,0,reached,distance)&&reached=="exit_sw");
|
|
assert(!g.PlanAdaptiveRoute(&p,"sw",4000,200,r,complete,reached,error));
|
|
// A recorded rescue corridor cannot be borrowed as a normal shortcut,
|
|
// including virtual entries into the interior of its ground edges.
|
|
p.x=0;g.PlanAdaptiveRoute(&p,"exit_if",1,200,r,complete,reached,error);assert(!complete);p.x=5000;
|
|
// No traversable local start: only map369 may transfer to the nearest
|
|
// permitted authored rescue node with a recorded escape edge.
|
|
travel.complete=false;
|
|
assert(g.PlanRescueRoute(&p,r,transfer)&&transfer=="if"&&r.size()==2&&r.back().EdgeDatabaseId==2);
|
|
assert(!g._rescuePlanning); // scoped privilege cannot leak into later plans
|
|
p.map=0;assert(!g.PlanRescueRoute(&p,r,transfer));p.map=369;
|
|
// A reachable MMAP approach walks; it must not transfer a healthy bot.
|
|
travel.complete=true;p.x=2497;
|
|
assert(g.PlanRescueRoute(&p,r,transfer)&&transfer.empty()&&r.back().NodeKey=="exit_if");
|
|
assert(g.PlanRescueRoute(&p,r,transfer,true)&&transfer=="if");
|
|
// Blocked recording and faction/area denial select another legal escape;
|
|
// no bypass of a denied rescue root or native edge is allowed.
|
|
std::unordered_set<uint32>blocked{2};travel.complete=false;
|
|
assert(g.PlanRescueRoute(&p,r,transfer,true,&blocked)&&transfer=="sw");
|
|
access.blocked.insert("sw");assert(!g.PlanRescueRoute(&p,r,transfer,true,&blocked));access.blocked.clear();
|
|
blocked={1,2,3};assert(!g.PlanRescueRoute(&p,r,transfer,true,&blocked));
|
|
// A node without a recorded edge cannot become a teleport destination.
|
|
g._edgePoints.clear();assert(!g.PlanRescueRoute(&p,r,transfer,true));
|
|
}
|
|
'''
|
|
with tempfile.TemporaryDirectory()as d:
|
|
p=Path(d);(p/'test.cpp').write_text(code)
|
|
subprocess.run(['c++','-std=c++17','-I'+str(root/'src/server/game/World'),str(p/'test.cpp'),'-o',str(p/'test')],check=True)
|
|
subprocess.run([str(p/'test')],check=True)
|
|
print('Rescue graph: normal exclusion, walking first, recorded-only escapes, bounded tram transfer, access/blocked-edge checks and scoped planning passed')
|