Page 1 of 1

[1.0.4] Suggested improvements to dumb ai

Posted: Thu Aug 29, 2013 11:04 am
by jenx
I've been experimenting with the dumb ai, and watching its behavior closely.

I have four major "problems", and with simple coding, I've fixed them. I say "problems" because not everyone might see them as problems. I'm not sure what DG would think.

And because necrotic minions all use dumb ai, even though their equivalent npcs don't all do so, these improvements improve minions quite a lot, but I've only played to early levels.

There might be some unintended consequences to my changes. One thing is clear, the starting zones are much tougher.

So the three changes are:
1. Regen infusions, healing infusions, skeleton reassemble, and conversion (solipsist) are only used if health falls below 60%
2. Archers only use reload if they have no ammo.
3. Any available talents other than plain melee Attack are used before Attack.
4. Any available talents other than shoot for archers, are used before Shoot (i.e. Pinning Shot, Crippling Shot, etc)

How is this different then? Well take the archer using dumb ai. In a non-adjacent position, currently he/she chooses between shoot and reload, at 50/50 chance of each. With my changes, it is always shoot, unless ammo = 0.

But even better, if an archer is adjacent to an enemy, it currently has three available talents, shoot, reload, and attack. changes 2 and 3 combine so that only shoot works.

And a Master Skeleton archer (e.g., one of your minions :)), will use pinning shot and crippling shot before regular shoot !!

Or take for instance a simple orc warrior, as found in Escape from Reknor. He will typically have Crush and Sunder Armour. Both will be used prior to attack. And as soon as they reset, they will be used again. And combined with 1, they are now tougher to beat.

The code is very simple, and someone might even do it better:

Code: Select all

-- Randomly use talents
newAI("dumb_talented", function(self)
	-- Find available talents
	local avail = {}
	local tx, ty = self:aiSeeTargetPos(self.ai_target.actor)
	local target_dist = core.fov.distance(self.x, self.y, tx, ty)

-- JENX ADDED - variable to check for Attack and Shoot
	local canAttack = 0
	local canShoot = 0

	for tid, _ in pairs(self.talents) do
		local t = self:getTalentFromId(tid)
--		print(self.name, self.uid, "dumb ai talents can try use", t.name, tid, "::", t.mode, not self:isTalentCoolingDown(t), target_dist <= self:getTalentRange(t), self:preUseTalent(t, true), self:canProject({type="bolt"}, self.ai_target.actor.x, self.ai_target.actor.y))
		-- For dumb AI assume we need range and LOS
		-- No special check for bolts, etc.
		local total_range = self:getTalentRange(t) + self:getTalentRadius(t)
		local tg = {type=util.getval(t.direct_hit, self, t) and "hit" or "bolt", range=total_range}
		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 self:canProject(tg, tx, ty))
		   then
-- JENX ADDED: only use regen infusion or healing if life < 60% max life
			if t.name == "Infusion: Regeneration" or t.name == "Infusion: Healing" or t.name == "Skeleton Reassemble" or t.name == "Conversion" then
				local life = 100 * self.life / self.max_life
				if life < 60 then
					avail[#avail+1] = tid
					print(self.name, self.uid, "dumb ai talents can use", t.name, tid)
				end
-- JENX ADDED: only use reload if ammo = 0
			elseif t.name == "Reload" then
--				print(self.name, self.uid, "ammo fix <<<<<<<<<<<<")
				local a = self:hasAmmo()
--				print(self.name, self.uid, a, a.combat.shots_left, a.combat.capacity)
				if a then
					if a.combat.shots_left == 0 then
						avail[#avail+1] = tid
						print(self.name, self.uid, "dumb ai talents can use", t.name, tid)
					end
				end
			else
				avail[#avail+1] = tid
				print(self.name, self.uid, "dumb ai talents can use", t.name, tid)
				if t.name == "Attack" then
					canAttack = #avail
					print(self.name, self.uid, "canAttack <<<<<<<<<<<<", #avail)
				end
				if t.name == "Shoot" then
					canShoot = #avail
					print(self.name, self.uid, "canShoot <<<<<<<<<<<<", #avail)
				end
			end
		elseif t.mode == "sustained" and not t.no_npc_use and not self:isTalentCoolingDown(t) and
		   not self:isTalentActive(t.id) and
		   self:preUseTalent(t, true, true)
		   then
			avail[#avail+1] = tid
			print(self.name, self.uid, "dumb ai talents can activate", t.name, tid)
		end
	end

-- JENX ADDED - if more than one talent and attack is available, do the talent rather than attack
	if #avail > 1 and canAttack > 0 then
		table.remove(avail,canAttack)
	end
-- then remove shoot, if other (shooting?) talents available
	if #avail > 1 and canShoot > 0 then
		table.remove(avail,canShoot)
	end
--JENX end

	if #avail > 0 then
		local tid = avail[rng.range(1, #avail)]
		print("dumb ai uses", tid)
		self:useTalent(tid)
		return true
	end
end)

Re: [1.0.4] Suggested improvements to dumb ai

Posted: Thu Aug 29, 2013 6:15 pm
by Hachem_Muche
This looks like progress towards a smarter AI for most NPCs. The main reason to use the "dumb_talented" ai over the much more effective tactical ai is for speed. With that in mind, I suggest a couple of tweaks:

Let regen be used whenever life < 80% to allow for preemptive healing.
Let reload be used whenever ammo is low (say 1/4 of capacity) rather than empty.

Note that some heals will still be used at full health. A more general way to fix those would be to check the talent.tactical table for the heal flag and disable those talents when above the healing threshold. Something like:

Code: Select all

if t.tactical and t.tactical.heal then 
<code to decide if healing is allowed or not>
...

Re: [1.0.4] Suggested improvements to dumb ai

Posted: Fri Aug 30, 2013 12:39 pm
by Dekar
Nice, I like smarter AI in general. Might require some rebalancing of the game though.

Re: [1.0.4] Suggested improvements to dumb ai

Posted: Sat Aug 31, 2013 2:24 am
by jenx
I've been playing a bulwark with this addon, and I think it is a good improvement to the game. And it could be developed further.

Enemies actually do a lot wider range of things, particularly as they can't choose attack or shoot if they have another option.

So for example, little ole mice, now regularly cast Hide in Plain Sight. And so I'm not seeing the mice as much until I bump into them.

I think the big test will be places like elven ruins, dreadfell, etc, with lots of archers pinging me non-stop. Let's see how that goes!

If others have ideas as to how to improve the dumb ai, let me know!

Re: [1.0.4] Suggested improvements to dumb ai

Posted: Sun Sep 01, 2013 3:58 am
by jenx
Hachem_Muche wrote:This looks like progress towards a smarter AI for most NPCs. The main reason to use the "dumb_talented" ai over the much more effective tactical ai is for speed. With that in mind, I suggest a couple of tweaks:

Let regen be used whenever life < 80% to allow for preemptive healing.
Let reload be used whenever ammo is low (say 1/4 of capacity) rather than empty.

Note that some heals will still be used at full health. A more general way to fix those would be to check the talent.tactical table for the heal flag and disable those talents when above the healing threshold. Something like:

Code: Select all

if t.tactical and t.tactical.heal then 
<code to decide if healing is allowed or not>
...
I don't understand why some will still heal at full health, as my code prohibits the talent even entering the hash table doesn't it?

Re: [1.0.4] Suggested improvements to dumb ai

Posted: Sun Sep 01, 2013 4:03 am
by jenx
Update

I've updated the add-on in several ways.

1. I've introduced a scaling threshold for activation of healing talents. This is based on my own experience. Early in the game, I use heals/regens sooner rather than later. so I've changed the code to make the threshold 80% - maxlife/100. So at 100 life, it is 79% and at 2000 life it is 60%.
2. I've introduced a force heal. That is, if the criteria above is reached, the heal always occurs, regardless of how many talents are available.
3. I've improved the log output.

So here is an example of the new log format, with the forced heal being used by a spitting spider:

Code: Select all

AI took for target	87779	spitting spider	::	1538	Lekra	4	<	100
AI took for target	87043	thought-forged warrior	::	87779	spitting spider	4	<	100

[LOG]	#UID:1538:0#Lekra hits spitting spider for #YELLOW#4 mind#LAST#, #GREY#3 darkness#LAST# damage (total 6.62).
[LOG]	#UID:87779:0#Spitting spider hits Lekra for #LIGHT_GREEN#14 nature#LAST# damage.

[LOG]	#UID:87043:0#Thought-forged warrior hits spitting spider for #aaaaaa#45 physical#LAST#, #LIGHT_GREEN#2 nature#LAST# damage (total 46.71).

[LOG]	#UID:1538:0#Lekra hits spitting spider for #YELLOW#4 mind#LAST#, #GREY#3 darkness#LAST# damage (total 6.62).
[LOG]	#UID:87779:0#Spitting spider hits Lekra for #LIGHT_GREEN#13 nature#LAST# damage.

[LOG]	#UID:87043:0#Thought-forged warrior hits spitting spider for #aaaaaa#50 physical#LAST#, #LIGHT_GREEN#2 nature#LAST# damage (total 51.71).

spitting spider	87779	dumb ai talents can use	Infusion: Healing	T_INFUSION:_HEALING_1
spitting spider	87779	dumb ai talents can use	Infusion: Sun	T_INFUSION:_SUN_2
spitting spider	87779	dumb ai talents can use	Attack	T_ATTACK
spitting spider	87779	dumb ai talents can use	Lay Web	T_LAY_WEB
spitting spider	87779	dumb ai talents can use	Spit Poison	T_SPIT_POISON
spitting spider	87779	dumb ai talents can use	Web	T_SPIDER_WEB
dumb ai uses	T_INFUSION:_HEALING_1
spitting spider	87779	Healing talent forced use <<<<<<<<<<<<	1
[LOG]	Spitting spider uses Infusion: Healing.
[HEALING]	87779	spitting spider	for	101.35
See how in this example, the spider has as options healing infusion, sun infusion, attack (which would be forbidden), lay web, spit poison and spider web. This line indicates that the dumb ai has been forced to use the healing infusion:

spitting spider 87779 Healing talent forced use <<<<<<<<<<<< 1

Hence the dumb ai is slightly tougher to beat now!!

Have fun.

Re: [1.0.4] Suggested improvements to dumb ai

Posted: Sun Sep 01, 2013 4:46 pm
by Hellcommander
Seems the current update causes the profile to revert to the offline profile.

Re: [1.0.4] Suggested improvements to dumb ai

Posted: Sun Sep 01, 2013 5:25 pm
by Hachem_Muche
jenx wrote:I don't understand why some will still heal at full health, as my code prohibits the talent even entering the hash table doesn't it?
Your code only applies the healing check to Healing and Regeneration Infusions and to Skeleton Reassemble. The ai could still use other healing talents (like Nature's Touch or Healing Light) at full health. I'm suggesting a simple way to check if (almost) any talent is a healing talent and act appropriately.

Re: [1.0.4] Suggested improvements to dumb ai

Posted: Tue Apr 22, 2014 4:05 pm
by Zireael
Any chance of getting an update for 1.1.5?

Re: [1.0.4] Suggested improvements to dumb ai

Posted: Thu Apr 24, 2014 11:59 pm
by jenx
Zireael wrote:Any chance of getting an update for 1.1.5?
not from me. but please feel free to take my code and rework it.