[1.0.4] logic error in tactical.lua for non targeted attacks

Where bugs go to lie down and rest

Moderator: Moderator

Post Reply
Message
Author
jenx
Sher'Tul Godslayer
Posts: 2263
Joined: Mon Feb 14, 2011 11:16 pm

[1.0.4] logic error in tactical.lua for non targeted attacks

#1 Post by jenx »

about line 70 we have:

Code: Select all

if t.mode == "activated" and not t.no_npc_use and not self:isTalentCoolingDown(t) and self:preUseTalent(t, true, true) and (not self:getTalentRequiresTarget(t) or within_range) then
  	t_avail = true
end
But take a Talent like Frenzy, which returns nil (i.e. false) for TalentRequiresTarget. In this case, the talent Frenzy is available even though you are not within range of the npc.

Find a rare mold with Frenzy and it will cast it continually when no other talents are available, even though you are across the room!

We can fix this with:

Code: Select all

if t.mode == "activated" and not t.no_npc_use and not self:isTalentCoolingDown(t) and self:preUseTalent(t, true, true) and (not (self:getTalentRequiresTarget(t) or 1) or within_range) then
  	t_avail = true
end
I've tested it and it works properly now.
Last edited by jenx on Mon Sep 02, 2013 10:50 am, edited 1 time in total.
MADNESS rocks

jenx
Sher'Tul Godslayer
Posts: 2263
Joined: Mon Feb 14, 2011 11:16 pm

Re: [1.0.4] logic error in tactical.lua for non targeted att

#2 Post by jenx »

jenx wrote:about line 70 we have:

Code: Select all

if t.mode == "activated" and not t.no_npc_use and not self:isTalentCoolingDown(t) and self:preUseTalent(t, true, true) and (not self:getTalentRequiresTarget(t) or within_range) then
  	t_avail = true
end
But take a Talent like Frenzy, which returns nil (i.e. false!). In this case, the talent Frenzy is available even though you are not within range of the npc.

Find a rare mold with Frenzy and it will cast it continually when no other talents are available, even though you are across the room!

We can fix this with:

Code: Select all

if t.mode == "activated" and not t.no_npc_use and not self:isTalentCoolingDown(t) and self:preUseTalent(t, true, true) and (not (self:getTalentRequiresTarget(t) or 1) or within_range) then
  	t_avail = true
end
I've tested it and it works properly now.
oops - unintended consequences !!!

Regen infusions and healing infusions are not "within range". So either we make them within range, or alter the conditional.

I'll have to experiment further !
MADNESS rocks

jenx
Sher'Tul Godslayer
Posts: 2263
Joined: Mon Feb 14, 2011 11:16 pm

Re: [1.0.4] logic error in tactical.lua for non targeted att

#3 Post by jenx »

Man, there are so many combinations, it is impossible to have a simple algorithm.

So, I think it might be simplest just to calculate Frenzy separately and leave existing code as is:

Code: Select all

if t.mode == "activated" and not t.no_npc_use and not self:isTalentCoolingDown(t) and self:preUseTalent(t, true, true) and (not self:getTalentRequiresTarget(t) or within_range) then
	if t.name == "Frenzy" then -- leave like this in case we need to add other such talents
		if  target_dist == 1 then
			t_avail = true
		end
	else
		t_avail = true
end
not perfect, but I think it works. off to test....
MADNESS rocks

jenx
Sher'Tul Godslayer
Posts: 2263
Joined: Mon Feb 14, 2011 11:16 pm

Re: [1.0.4] logic error in tactical.lua for non targeted att

#4 Post by jenx »

This is proving very difficult. There are LOTS of talents that don't require a target, and yet do damage. Talents that do burst damage in a radius around the caster, such as Kinetic Leech, Sun Flare, etc.

These are all available to the tactical ai, even though the enemy is not within range, because they return no target required, as per the example above with frenzy.

We need some way then to capture all those talents that do damage, but don't require a target. If I assume they include tactical = attack or attackarea, that might be a better option. Then we can use radius and target_dist to see if they can be used.

Obviously the tactical ai to date has been pretty dumb actually in the way it fights.

So my new strategy is to adjust within_range for talents such as regeneration. I think there are a lot more talents like Leech, Frenzy, than there are like regen.
MADNESS rocks

jenx
Sher'Tul Godslayer
Posts: 2263
Joined: Mon Feb 14, 2011 11:16 pm

Re: [1.0.4] logic error in tactical.lua for non targeted att

#5 Post by jenx »

ok, so unless someone can think of a smarter way to do this, here is my approach:

Code: Select all

local non_target_talents = {}
		non_target_talents["Infusion: Regeneration"] = true
		non_target_talents["Infusion: Healing"] = true
		non_target_talents["Infusion: Wild"] = true
		non_target_talents["Infusion: Movement"] = true
		non_target_talents["Infusion: Heroism"] = true
		non_target_talents["Rune: Phase Door"] = true
		non_target_talents["Rune: Shielding"] = true
		non_target_talents["Rune: Controlled Phase Door"] = true
		non_target_talents["Rune: Teleportation"] = true
		non_target_talents["Rune: Reflection Shield"] = true
		non_target_talents["Rune: Invisibility"] = true
		non_target_talents["Rune: Speed"] = true
		non_target_talents["Rune: Vision"] = true
		non_target_talents["Rune: Manasurge"] = true
		non_target_talents["Rune of the Rift"] = true
	local deactivatable_sustains = {}
		deactivatable_sustains["Thermal Aura"] = true
		deactivatable_sustains["Kinetic Aura"] = true
		deactivatable_sustains["Charged Aura"] = true
		deactivatable_sustains["Thermal Shield"] = true
		deactivatable_sustains["Kinetic Shield"] = true
		deactivatable_sustains["Charged Shield"] = true
	for tid, lvl in pairs(self.talents) do
		local t = self:getTalentFromId(tid)
		local t_avail = false
		print(self.name, self.uid, "tactical ai talents testing", t.name, tid)
		if t.tactical then
			local tg = self:getTalentTarget(t)
			local default_tg = {type=util.getval(t.direct_hit, self, t) and "hit" or "bolt"}
			-- Only assume range... some talents may no require LOS, etc
			within_range = target_dist and target_dist <= (self:getTalentRange(t) + self:getTalentRadius(t))

	-- JENX the problem is with talents that don't care about the target at all, such as regeneration. So the following code captures these talents, by setting within_range as true.
			if non_target_talents[t.name] then
				within_range = true
			end

			if t.mode == "activated" and not t.no_npc_use and not self:isTalentCoolingDown(t) and self:preUseTalent(t, true, true) and (not (self:getTalentRequiresTarget(t) or 1) or within_range) then
				t_avail = true
			elseif t.mode == "sustained" and not t.no_npc_use and not self:isTalentCoolingDown(t) and self:preUseTalent(t, true, true) then
				if self:isTalentActive(t.id) and deactivatable_sustains[t.name] then
			   		t_avail = true
				elseif not self:isTalentActive(t.id) then
					t_avail = true
				end
			end
MADNESS rocks

Hachem_Muche
Uruivellas
Posts: 744
Joined: Thu Nov 18, 2010 6:42 pm

Re: [1.0.4] logic error in tactical.lua for non targeted att

#6 Post by Hachem_Muche »

Obviously, you don't want to put a whole lot of talent-specific checks in this code.

A better way to handle non-targeted attacks is to make sure that all talents with tactical attack values check the number of targets hit. You can do this by changing the line

Code: Select all

if self:getTalentRequiresTarget(t) or nb_foes_hit > 0 or nb_allies_hit > 0 or nb_self_hit > 0 then
to

Code: Select all

if self:getTalentRequiresTarget(t) or nb_foes_hit > 0 or nb_allies_hit > 0 or nb_self_hit > 0 or (t.tactical and (t.tactical.attack or t.tactical.attackarea or t.tactical.disable)) then
any such talent that doesn't hit anything will get a weight of 0 and be skipped.

also, while debugging, you can comment out tactical.lua line 22 (if you haven't already)

Code: Select all

local print = function() end
to get all the useful ai data to print out in the output log.
Author of the Infinite 500 and PlenumTooltip addons, and the joys of Scaling in ToME.

jenx
Sher'Tul Godslayer
Posts: 2263
Joined: Mon Feb 14, 2011 11:16 pm

Re: [1.0.4] logic error in tactical.lua for non targeted att

#7 Post by jenx »

Hachem_Muche wrote:Obviously, you don't want to put a whole lot of talent-specific checks in this code.

A better way to handle non-targeted attacks is to make sure that all talents with tactical attack values check the number of targets hit. You can do this by changing the line

Code: Select all

if self:getTalentRequiresTarget(t) or nb_foes_hit > 0 or nb_allies_hit > 0 or nb_self_hit > 0 then
to

Code: Select all

if self:getTalentRequiresTarget(t) or nb_foes_hit > 0 or nb_allies_hit > 0 or nb_self_hit > 0 or (t.tactical and (t.tactical.attack or t.tactical.attackarea or t.tactical.disable)) then
any such talent that doesn't hit anything will get a weight of 0 and be skipped.

also, while debugging, you can comment out tactical.lua line 22 (if you haven't already)

Code: Select all

local print = function() end
to get all the useful ai data to print out in the output log.
Many thanks! I'll try these suggestions.
MADNESS rocks

jenx
Sher'Tul Godslayer
Posts: 2263
Joined: Mon Feb 14, 2011 11:16 pm

Re: [1.0.4] logic error in tactical.lua for non targeted att

#8 Post by jenx »

oops - the problem with your suggestion Hachem is that the line you suggest changing comes AFTER it is decided if talents are available to use. The issue is that the AI is excluding lots of talents because the payer is not "within range", but these are talents that don't care about range, such as regeneration, healing, etc.

And because some heal talents do care about range, we can't simply check on tactical.

So I think my list of talents will have to do for the time being.

Ideally, we need to add a new flag (or two) to the talent descriptions, to differentiate more carefully different types of talents.
MADNESS rocks

jenx
Sher'Tul Godslayer
Posts: 2263
Joined: Mon Feb 14, 2011 11:16 pm

Re: [1.0.4] logic error in tactical.lua for non targeted att

#9 Post by jenx »

ok - so I've gone through most of the talents and found the ones that tactical ai will not use unless it is adjacent to you (and therefore you are within range), even though these talents don't care where the player is.

These are talents that don't require a target and don't need to be within range. I've excluded talents with is_heal = true or is_teleport = true.

Code: Select all

local non_target_talents = {}
non_target_talents["Infusion: Regeneration"] = true
non_target_talents["Infusion: Wild"] = true
non_target_talents["Infusion: Movement"] = true
non_target_talents["Infusion: Heroism"] = true
non_target_talents["Rune: Shielding"] = true
non_target_talents["Rune: Reflection Shield"] = true
non_target_talents["Rune: Invisibility"] = true
non_target_talents["Rune: Speed"] = true
non_target_talents["Rune: Manasurge"] = true
non_target_talents["Rune of the Rift"] = true
non_target_talents["Sudden Growth"] = true
non_target_talents["Barrier"] = true
non_target_talents["Providence"] = true 
non_target_talents["Resilience of the Dwarves"] = true 
non_target_talents["Gift of the Highborn"] = true
non_target_talents["Grace of the Eternals"] = true
non_target_talents["Timeless"] = true
non_target_talents["Wrath of the Woods"] = true
non_target_talents["Nature's Pride"] = true
non_target_talents["Luck of the Little Folk"] = true
non_target_talents["Indomitable"] = true
non_target_talents["Rapid Shot"] = true
non_target_talents["Aim"] = true

	if t.is_heal or t.is_teleport or non_target_talents[t.name] then
            	within_range = true
		print("Talent doesn't care for range:", t.name, tid)
	end
There could be more, but this is a good start. Tactical ai barely uses any of these, unless it is adjacent to you, but even then, usually some other talent takes precedence.
MADNESS rocks

Post Reply