Files
Viano-Core/tests/clientless/test_adventure_group_plan.py
T
Nico 649915e575
clang PCH / build (push) Waiting to run
GCC PCH / build (push) Waiting to run
Fix AdventureBot travel recovery, area eligibility and safe build logout
2026-10-30 12:43:22 +01:00

67 lines
4.9 KiB
Python

"""Execute production leader-plan inheritance without modifying members' own days."""
from pathlib import Path
import subprocess,tempfile
root=Path(__file__).resolve().parents[2]
s=(root/'src/server/game/World/AdventureBehaviorMgr.cpp').read_text()
sig='std::string AdventureBehaviorMgr::InteractionSchedule('
start=s.index(sig);begin=s.index('{',start);end=begin+1;depth=1
while depth:depth+=(s[end]=='{')-(s[end]=='}');end+=1
schedule=s[start:end]
a=s.index('AdventureGroupPlan AdventureBehaviorMgr::GroupPlan(')
code=r'''
#include "AdventureBehaviorPolicy.h"
#include "AdventureGroupPolicy.h"
#include "AdventureInstancePolicy.h"
#include <cassert>
#include <ctime>
#include <unordered_map>
using uint32=unsigned;
struct Guid{unsigned id;unsigned GetCounter(){return id;}};
struct Player{Guid guid;Guid GetGUID(){return guid;}};
struct AdventureGroupPlan{bool Enabled=false,Forming=false;std::string Intent,Location,NextIntent,NextLocation;time_t Deadline=0,NextDeadline=0;unsigned Capacity=0,Mode=0;bool EarlyDeparture=false;};
namespace GameTime{time_t GetGameTime(){return 100;}}
std::tm Local(time_t){std::tm tm{};tm.tm_hour=5;return tm;}unsigned DateOf(std::tm){return 1;}
struct Location{unsigned InstanceCapacity=5,InstanceDifficulty=1;};struct Locations{Location l;Location*Find(std::string const&){return &l;}}locations;auto sAdventureLocationMgr=&locations;
struct AdventureBehaviorMgr{
struct Record{bool Enabled=true,Schedule=true,GroupOverride=false,Dirty=false;int Hour=-1;unsigned Date=1;std::string Intent,Location,WantedIntent,WantedLocation,ManualNextIntent,ManualNextLocation;std::string PersonalIntent,PersonalLocation;time_t PersonalDeadline=0;time_t Deadline=3600;AdventureBehaviorPolicy::Day Plan;AdventureInstancePolicy::Visit Instance;AdventureGroupPolicy::Departure Departure;};
bool allowed=true;bool Allowed(Player*,::Location const&,std::string const&){return allowed;}
std::unordered_map<unsigned,Record>_records;int changes=0;
void Generate(Player*,Record&r,unsigned date){r.Date=date;}
void SetWanted(Player*,Record&r,std::string const&i,std::string const&l,time_t end){++changes;r.WantedIntent=i;r.WantedLocation=l;r.Deadline=end;}
std::string InteractionSchedule(Player*);void ResumePersonalPlan(Player*);AdventureGroupPlan GroupPlan(Player*);bool AdoptGroup(Player*,Player*);
};
'''+schedule+'\n'+s[a:]+r'''
int main(){
AdventureBehaviorMgr mgr;Player leader{{29}},member{{31}};auto& a=mgr._records[29];auto& b=mgr._records[31];
a.Intent="groupformation";a.Location="leader-capital";a.Plan[5]={"groupformation","leader-capital"};a.Plan[6]={"instance","deadmines"};
b.Intent="groupformation";b.Location="other-capital";b.Plan[5]={"groupformation","other-capital"};b.Plan[6]={"instance","shadowfang"};
mgr.allowed=false;assert(!mgr.GroupPlan(&member).Enabled);mgr.allowed=true;
auto plan=mgr.GroupPlan(&member);assert(plan.Forming&&plan.NextIntent=="instance"&&plan.NextLocation=="shadowfang");
assert(mgr.AdoptGroup(&member,&leader));assert(b.WantedLocation=="leader-capital"&&b.Deadline==a.Deadline&&b.Schedule);
assert(b.Plan[6].Location=="shadowfang"); // own future plan remains available after departure
a.Intent="instance";a.Location="deadmines";a.Deadline=7200;
assert(mgr.AdoptGroup(&member,&leader));assert(b.WantedIntent=="instance"&&b.WantedLocation=="deadmines"&&b.Deadline==7200);
b.Instance.Active=true;b.Instance.Stage=AdventureInstancePolicy::Phase::Inside;a.Location="other";
int changes=mgr.changes;assert(mgr.AdoptGroup(&member,&leader)&&mgr.changes==changes);
b.Instance.Stage=AdventureInstancePolicy::Phase::Travel;mgr.AdoptGroup(&member,&leader);assert(b.WantedLocation=="other");
a.Enabled=false;assert(!mgr.AdoptGroup(&member,&leader));
b.Instance.Active=false;mgr.ResumePersonalPlan(&member);
assert(!b.GroupOverride&&b.WantedIntent=="groupformation"&&b.WantedLocation=="other-capital");
b.Schedule=false;b.Intent="groupformation";b.ManualNextIntent="raid";b.ManualNextLocation="molten-core";
plan=mgr.GroupPlan(&member);assert(plan.Forming&&plan.NextIntent=="raid"&&plan.NextLocation=="molten-core");
// Different goals are inherited without inventing a personal intent change.
b.GroupOverride=false;b.Instance.Active=false;b.Intent=b.WantedIntent="social";
b.Location=b.WantedLocation="personal-place";b.Deadline=2000;
a.Enabled=true;a.Intent="social";a.Location="leader-place";
assert(mgr.AdoptGroup(&member,&leader));b.Location="leader-place";
assert(mgr.InteractionSchedule(&member)=="social:personal-place");
mgr.ResumePersonalPlan(&member);
assert(b.WantedLocation=="personal-place"&&mgr.InteractionSchedule(&member)=="social:personal-place");
}
'''
with tempfile.TemporaryDirectory() as d:
p=Path(d);(p/'plan.cpp').write_text(code)
subprocess.run(['g++','-std=c++17','-I'+str(root/'src/server/game/World'),str(p/'plan.cpp'),'-o',str(p/'plan')],check=True)
subprocess.run([str(p/'plan')],check=True)
print('Production group plans: leader meeting/goal/deadline inheritance, untouched personal day, manual preparation and instance-state guards passed.')