Skip to content
Snippets Groups Projects
Commit 11a6cbf5 authored by dg's avatar dg
Browse files

AI wanders around when it looses you

AI can be lost by going out of sight for a while


git-svn-id: http://svn.net-core.org/repos/t-engine4@6214 51575b47-30f0-44d4-a5cc-537603b46e54
parent 8537af74
No related branches found
No related tags found
No related merge requests found
......@@ -24,7 +24,13 @@ local Astar = require "engine.Astar"
newAI("move_simple", function(self)
if self.ai_target.actor then
local tx, ty = self:aiSeeTargetPos(self.ai_target.actor)
local tx, ty
-- Move towards the last seen position if we have one
if self.ai_state.target_last_seen then
tx, ty = self.ai_state.target_last_seen.x, self.ai_state.target_last_seen.y
else
tx, ty = self:aiSeeTargetPos(self.ai_target.actor)
end
return self:moveDirection(tx, ty)
end
end)
......@@ -167,25 +173,44 @@ newAI("move_blocked_astar", function(self)
end
end)
newAI("move_wander", function(self)
local coords = {}
for _, coor in pairs(util.adjacentCoords(self.x, self.y)) do
if self:canMove(coor[1], coor[2]) then
coords[#coords+1] = coor
end
end
if #coords > 0 then
local selected = rng.table(coords)
return self:moveDirection(selected[1], selected[2])
end
end)
newAI("move_complex", function(self)
if self.ai_target.actor and self.x and self.y then
local tx, ty = self:aiSeeTargetPos(self.ai_target.actor)
local moved
-- Can we use A* due to damage?
if not moved and self.ai_state.damaged_turns and self.ai_state.damaged_turns > 0 then
moved = self:runAI("move_astar")
end
-- Wander if it has been a while since we last saw the target
if not moved and self.ai_state.target_last_seen and (game.turn - (self.ai_state.target_last_seen.turn or game.turn)) / (game.energy_to_act / game.energy_per_tick) > 10 then
moved = self:runAI("move_wander")
end
-- Check if we can use dmap
if not moved then
moved = self:runAI("move_dmap")
end
-- Check blocking
if not moved then
if not moved and self:hasLOS(tx, ty) then
-- Make sure that we are indeed blocked
moved = self:runAI("move_simple")
if not moved and self:hasLOS(tx, ty) then
if not moved then
-- Wait at least 5 turns of not moving before switching to blocked_astar
-- add 2 since we remove 1 every turn
self.ai_state.blocked_turns = (self.ai_state.blocked_turns or 0) + 2
......
......@@ -23,7 +23,8 @@
newAI("dumb_talented", function(self)
-- Find available talents
local avail = {}
local target_dist = core.fov.distance(self.x, self.y, self.ai_target.actor.x, self.ai_target.actor.y)
local tx, ty = self:aiSeeTargetPos(self.ai_target.actor)
local target_dist = core.fov.distance(self.x, self.y, tx, ty)
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))
......@@ -33,7 +34,7 @@ newAI("dumb_talented", function(self)
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, self.ai_target.actor.x, self.ai_target.actor.y))
(not self:getTalentRequiresTarget(t) or self:canProject(tg, tx, ty))
then
avail[#avail+1] = tid
print(self.name, self.uid, "dumb ai talents can use", t.name, tid)
......
......@@ -154,14 +154,18 @@ end
function _M:aiSeeTargetPos(target)
if not target then return self.x, self.y end
local tx, ty = target.x, target.y
if target == self.ai_target.actor and self.ai_state.target_last_seen then tx, ty = self.ai_state.target_last_seen.x, self.ai_state.target_last_seen.y end
local spread = 0
if target == self.ai_target.actor and self.ai_state.target_last_seen and not self:hasLOS(self.ai_state.target_last_seen.x, self.ai_state.target_last_seen.y) then
tx, ty = self.ai_state.target_last_seen.x, self.ai_state.target_last_seen.y
spread = spread + math.floor((game.turn - (self.ai_state.target_last_seen.turn or game.turn)) / (game.energy_to_act / game.energy_per_tick))
end
local see, chance = self:canSee(target)
-- Compute the maximum spread if we need to obfuscate
local spread = see and 0 or math.floor((100 - chance) / 10)
-- Additional spread due to last_seen
spread = spread + math.floor((game.turn - (self.ai_state.target_last_seen and self.ai_state.target_last_seen.turn or game.turn)) / (game.energy_to_act / game.energy_per_tick))
-- We don't know the exact position, so we obfuscate
if spread > 0 then
......
......@@ -25,8 +25,9 @@ local canFleeDmapKeepLos = function(self)
if self.never_move then return false end -- Dont move, dont flee
if self.ai_target.actor then
local act = self.ai_target.actor
local ax, ay = self:aiSeeTargetPos(self.ai_target.actor)
local dir, c
if self:hasLOS(act.x, act.y) then
if self:hasLOS(ax, ay) then
dir = 5
c = act:distanceMap(self.x, self.y)
if not c then return end
......@@ -34,7 +35,7 @@ local canFleeDmapKeepLos = function(self)
for _, i in ipairs(util.adjacentDirs()) do
local sx, sy = util.coordAddDir(self.x, self.y, i)
-- Check LOS first
if self:hasLOS(act.x, act.y, nil, nil, sx, sy) then
if self:hasLOS(ax, ay, nil, nil, sx, sy) then
local cd = act:distanceMap(sx, sy)
-- print("looking for dmap", dir, i, "::", c, cd)
if not cd or ((not c or cd < c) and self:canMove(sx, sy)) then c = cd; dir = i end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment