Recover non-progressing cast loops and bound host model prompt cache
Core tests / core (push) Successful in 57s

This commit is contained in:
Codex
2026-09-24 03:42:18 +12:00
parent 8e01cdee22
commit 1552e4c165
4 changed files with 113 additions and 18 deletions
+17 -3
View File
@@ -4,8 +4,9 @@ code=(Path(__file__).resolve().parents[1]/'ale/azerothai_recovery.lua').read_tex
setup='''
now=1000;os.time=function()return now end;attempts=0;expired=0;last=nil;active=true;player={x=0};ai={};captured={}
function AuthDBExecute(sql) table.insert(captured,sql);if string.find(sql,'INSERT INTO azerothai_recovery_log',1,true) then last=now end end
function AuthDBQuery(sql) if string.find(sql,'recovery_log',1,true) then return last and now-last<1800 and {} or nil end;return active and {} or nil end
function AuthDBQuery(sql) if string.find(sql,'recovery_leases',1,true) then return nil end;if string.find(sql,'recovery_log',1,true) then return last and now-last<1800 and {} or nil end;return active and {} or nil end
function GetPlayerByName(n) return n=='Test' and player or nil end
hooks={};function RegisterPlayerEvent(n,fn)hooks[n]=fn end
function CreateLuaEvent(fn) tick=fn end
function PrintInfo(s) end
function PrintError(s) error(s) end
@@ -16,6 +17,7 @@ function player:GetBotAI()return ai end
function player:IsDead()return self.dead end
function player:IsInCombat()return self.combat end
function player:IsCasting()return self.casting end
function player:StopSpellCast()self.casting=false;self.interrupted=true end
function player:IsTaxi()return self.taxi end
function player:IsRooted()return self.root end
function player:GetGroup()return self.group end
@@ -31,7 +33,9 @@ function player:MoveClear()end
function ai:HasGameClientMaster()return player.master end
function ai:IsMovementImpaired()return player.impaired end
function ai:Reset(full)attempts=attempts+1 end
function ai:DoSpecificAction(action,silent)assert(action=='move random');return true end
function ai:HasStrategy(s,state)return false end
function ai:ChangeStrategy()end
function ai:DoSpecificAction(action,silent)assert(action=='move random' or action=='release loot');return true end
function step(seconds,action)
now=now+seconds
AzerothAISetRecoveryIntents({{guid=9,account=2,name='Test',action=action or 'quest'}})
@@ -42,7 +46,7 @@ def new():
l=LuaRuntime();l.execute(setup);l.execute(code);return l
l=new();l.execute('step(0);step(599);assert(attempts==0);step(1);assert(attempts==1);step(600);assert(attempts==1);step(1200);assert(attempts==2)')
print('Threshold and persistent cooldown passed')
for field in ['dead','combat','casting','taxi','root','master','impaired']:
for field in ['dead','combat','taxi','root','master','impaired']:
l=new();l.execute(f'player.{field}=true;step(0);step(601);assert(attempts==0)')
print('Death, combat, cast, taxi, root, master and impaired exclusions passed')
for action in ['rest','socialize','trade']:
@@ -60,3 +64,13 @@ l=new();l.execute("step(0);step(600);player.x=8;step(30);assert(string.find(capt
l=new();l.execute("step(0);step(600);step(180);assert(string.find(captured[#captured], '6E6F5F70726F6772657373'))")
l=new();l.execute("step(0);step(600);player.dead=true;step(30);assert(string.find(captured[#captured], '756E7665726966696564'))")
print('Recovery outcomes distinguish native progress, no progress, and unavailable residents')
l=new();l.execute('player.casting=true;step(0);step(599);assert(attempts==0);step(1);assert(attempts==1 and player.interrupted)')
l=new();l.execute('player.casting=true;step(0);now=now+500;hooks[32](32,player);step(0);step(101);assert(attempts==0)')
l=new();l.execute('player.casting=true;step(0);player.combat=true;step(601);assert(attempts==0 and not player.interrupted)')
print('Repeated casts cannot reset idle evidence; productive casts and combat stay protected')
l=new();l.execute("function ai:HasStrategy()return true end;local changes={};function ai:ChangeStrategy(s)table.insert(changes,s)end;step(0);step(600);assert(changes[1]=='-gather' and changes[2]=='-loot');assert(attempts==1)")
print('Recovery pauses gathering before walking, with a durable restoration lease')
l=new();l.execute("local query=AuthDBQuery;local changes={};function ai:ChangeStrategy(s)table.insert(changes,s)end;function AuthDBQuery(sql)if string.find(sql,'SELECT guid,name,account_id,gathering,looting',1,true) then return {GetUInt32=function(_,i)return ({[0]=9,[2]=2,[3]=1,[4]=0})[i] end,GetString=function()return 'Test' end,NextRow=function()return false end} end;return query(sql)end;step(0);assert(changes[1]=='+gather' and #changes==1)")
print('Lease restoration restores only originally enabled strategies')