File: autofight.lua

package info (click to toggle)
crawl 2%3A0.7.1-3
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 30,420 kB
  • ctags: 23,018
  • sloc: cpp: 244,317; ansic: 16,144; perl: 2,214; makefile: 984; python: 488; objc: 250; ruby: 200; sh: 140
file content (104 lines) | stat: -rw-r--r-- 2,536 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
---------------------------------------------------------------------------
-- autofight.lua:
-- One-key fighting.
--
-- To use this, add this line to your init.txt:
--   lua_file = lua/autofight.lua
-- Then macro any key to "===hit_closest".
--
-- This uses the very incomplete client monster and view bindings, and
-- is currently very primitive. Improvements welcome!
---------------------------------------------------------------------------

local function delta_to_vi(dx, dy)
  local d2v = {
    [-1] = { [-1] = 'y', [0] = 'h', [1] = 'b'},
    [0]  = { [-1] = 'k',            [1] = 'j'},
    [1]  = { [-1] = 'u', [0] = 'l', [1] = 'n'},
  }
  return d2v[dx][dy]
end

local function sign(a)
  return a > 0 and 1 or a < 0 and -1 or 0
end

local function abs(a)
  return a * sign(a)
end

local function adjacent(dx, dy)
  return abs(dx) <= 1 and abs(dy) <= 1
end

local function reaching(dx, dy)
  local wp = items.equipped_at("weapon")
  if wp and wp.ego_type == "reaching" then
    return dx*dx + dy*dy <= 5
  else
    return nil
  end
end

local function can_move(feat)
  return travel.feature_traversable(feat)
end

local function try_move(dx, dy)
  local feat = view.feature_at(dx, dy)
  if can_move(feat) then
    return delta_to_vi(dx, dy)
  else
    return nil
  end
end

local function move_towards(dx, dy)
  local move = nil
  if reaching(dx, dy) then
    move = 'vf'
  elseif adjacent(dx, dy) then
    move = delta_to_vi(dx, dy)
  elseif abs(dx) > abs(dy) then
    move = try_move(sign(dx), 0)
    if move == nil then move = try_move(sign(dx), sign(dy)) end
    if move == nil then move = try_move(0, sign(dy)) end
  elseif abs(dx) == abs(dy) then
    move = try_move(sign(dx), sign(dy))
    if move == nil then move = try_move(sign(dx), 0) end
    if move == nil then move = try_move(0, sign(dy)) end
  else
    move = try_move(0, sign(dy))
    if move == nil then move = try_move(sign(dx), sign(dy)) end
    if move == nil then move = try_move(sign(dx), 0) end
  end
  if move == nil then
    crawl.mpr("Failed to move towards target.")
  else
    crawl.process_keys(move)
  end
end

local function find_next_monster()
  local r, x, y
  for r = 1,8 do
    for x = -r,r do
      for y = -r,r do
        m = monster.get_monster_at(x, y)
        if m and not m:is_safe() then
          return x, y
        end
      end
    end
  end
  return 0, 0
end

function hit_closest()
  local x, y = find_next_monster()
  if x == 0 and y == 0 then
    crawl.mpr("No unsafe monster in view!")
  else
    move_towards(x, y)
  end
end