from pathlib import Path from lupa import LuaRuntime setup=''' now=1000;os.time=function()return now end;calls={};people={} function AuthDBQuery(sql)local i=1;return {GetUInt32=function(_,n)return n==0 and i or 10+i end,GetString=function()return i==1 and 'A' or 'B'end,NextRow=function()i=i+1;return i<=2 end} end function GetPlayersInWorld()return people end function CreateLuaEvent(fn)tick=fn end function PrintInfo()end function PrintError(s)error(s)end function make(id,name) local p={id=id,name=name,hp=100,distance=25,ai={}} function p:GetGUIDLow()return self.id end;function p:GetName()return self.name end;function p:GetAccountId()return 10+self.id end function p:IsPlayerbot()return not self.human end;function p:IsDead()return self.dead end;function p:GetBotAI()return self.ai end function p:GetHealthPct()return self.hp end;function p:IsInCombat()return self.combat end function p:IsTaxi()return self.taxi end;function p:IsCasting()return self.cast end;function p:IsRooted()return false end function p:GetGroup()return self.group end;function p:GetVictim()return self.enemy end;function p:GetLevel()return 5 end function p:GetDistance()return self.distance end;function p:GetMapId()return 0 end;function p:GetPhaseMask()return 1 end function p.ai:GetMaster()return p.master end;function p.ai:SetMaster(m)p.master=m end function p.ai:HasGameClientMaster()return p.controlled end;function p.ai:IsMovementImpaired()return false end function p.ai:GetGroupLeader()return leader end;function p.ai:ChangeStrategy(s,state)end function p.ai:DoSpecificAction(s)table.insert(calls,s);return true end return p end A=make(1,'A');B=make(2,'B');people={A,B};leader=A function group() local g={GetMembers=function()return {A,B}end,GetMembersCount=function()return 2 end,IsRaidGroup=function()return false end};A.group=g;B.group=g end function step(n)now=now+n;tick()end ''' def new(): l=LuaRuntime();l.execute(setup);l.execute((Path(__file__).resolve().parents[1]/'ale/azerothai_survival.lua').read_text());l.execute('AzerothAISetSurvivalEnabled(true)');return l l=new();l.execute("A.combat=true;A.hp=20;step(0);assert(calls[1]=='flee');step(10);assert(#calls==1);step(10);assert(#calls==2)") l=new();l.execute("group();A.human=true;B.combat=true;B.hp=20;step(0);assert(#calls==0)") l=new();l.execute("group();step(0);assert(calls[1]=='follow' and B.master==A)") l=new();l.execute("group();B.distance=100;step(0);assert(#calls==0)") l=new();l.execute("A.combat=true;A.hp=20;A.controlled=true;step(0);assert(#calls==0)") l=new();l.execute("A.combat=true;A.hp=20;step(0);A.combat=false;step(20);assert(calls[2]=='eat' and calls[3]=='drink')") l=new();l.execute("group();AzerothAISetSurvivalEnabled(false);step(0);assert(#calls==0)") print('Native survival: retreat cooldown, recovery, regroup range, human-party protection, and disabled grouping passed')