Autopray.lua


Questions, Explanations, Howtos

Spider Stomper

Posts: 243

Joined: Sunday, 28th August 2011, 14:04

Post Saturday, 21st April 2012, 19:44

Autopray.lua

I have made a lua script that sacrifices all the corpses in view. This script will only work if have a very recent version of crawl (the function items.get_item_at was committed today). Another limitation is that it won't do anything if you worship Nemelex or Elyvilon. It only works with Makhleb, Lugonu, Okawaru, Trog, and Beogh.

How to use it:

1) Download autopray.lua to the folder 'dat/lua' (the one that constains autofight.lua, etc)
2) Add this line to init.txt:
  Code:
lua_file = lua/autopray.lua

3) Run Crawl and macro a key to ===offer_all
  Code:
~m*===offer_all (macro * to ===offer_all)
~s (save macro)


autopray.lua v1 (this version doesn't work anymore, get v2):
http://pastebin.com/GhKkEPhY

autopray.lua v2:
http://pastebin.com/ij4RpadA
Last edited by CommanderC on Tuesday, 24th April 2012, 16:02, edited 2 times in total.

For this message the author CommanderC has received thanks: 4
BlackSheep, Blade, galehar, Neon
User avatar

Abyss Ambulator

Posts: 1249

Joined: Sunday, 18th September 2011, 02:11

Post Saturday, 21st April 2012, 19:58

Re: Autopray.lua

Oh, cool. Nice job.

This seems like it might be appropriate to add as an option to autoexplore, so that you don't have to press one key for autopray and one for explore when you've finished a fight and want to get moving.

Spider Stomper

Posts: 243

Joined: Sunday, 28th August 2011, 14:04

Post Saturday, 21st April 2012, 20:50

Re: Autopray.lua

Blade, that's easy to do. Add these two lines at the end of the function offer_all:
  Code:
crawl.process_keys('o') --autoexplore after autopray
coroutine.yield(true)

Maybe, the interrupt hook will need a modification. I haven't tested it.

Spider Stomper

Posts: 243

Joined: Sunday, 28th August 2011, 14:04

Post Sunday, 22nd April 2012, 14:32

Re: Autopray.lua

Second version of autopray.lua. This one uses items.get_items_at, so it doesn't have to travel to all the stashes in view. If the option autopray_explore is set to true in init.txt, you will enter autoexplore mode after offering the corpses.

  Code:
---------------------------------------------------------------------------
-- autopray.lua:
-- Sacrifice any corpse in LOS.
--
-- To use this, add this line to your init.txt:
--   lua_file = lua/autopray.lua
-- then macro a key to ===offer_all
--
---------------------------------------------------------------------------

AUTOPRAY_EXPLORE = false

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 try_move(dx, dy)
  m = monster.get_monster_at(dx, dy)
  -- attitude > ATT_NEUTRAL should mean you can push past the monster
  if view.is_safe_square(dx, dy) and (not m or m:attitude() > ATT_NEUTRAL) then
    delta = {}
    delta.dx = dx
    delta.dy = dy
    return delta
  else
    return nil
  end
end

local function move_towards(dx, dy)
  local move = nil
  if abs(dx) > abs(dy) then
    if abs(dy) == 1 then
      move = try_move(sign(dx), 0)
    end
    if move == nil then move = try_move(sign(dx), sign(dy)) end
    if move == nil then move = try_move(sign(dx), 0) end
    if move == nil and abs(dx) > abs(dy)+1 then
      move = try_move(sign(dx), 1)
    end
    if move == nil and abs(dx) > abs(dy)+1 then
      move = try_move(sign(dx), -1)
    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
    if abs(dx) == 1 then
      move = try_move(0, sign(dy))
    end
    if move == nil then move = try_move(sign(dx), sign(dy)) end
    if move == nil then move = try_move(0, sign(dy)) end
    if move == nil and abs(dy) > abs(dx)+1 then
      move = try_move(1, sign(dy))
    end
    if move == nil and abs(dy) > abs(dx)+1 then
      move = try_move(-1, 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
    local vi_move = delta_to_vi(move.dx, move.dy)
    if vi_move ~= nil then
      crawl.process_keys(vi_move)
    else
      return nil     
    end
  end
  return move
end

local function is_rotting(item)
  return string.find(item.name(), 'rotting')
end

local function is_skeleton(item)
   return string.find(item.name(), 'skeleton')
end

local function is_good_corpse(item)
  if not item then
    return false
  end
  if item.class() == 'Carrion' and not is_rotting(item) and not is_skeleton(item) then
    if you.god() ~= 'Beogh' or string.find(item.name(), 'orc ') ~= nil then
       return true
    else
       return false
    end
  else
    return false
  end
end

local function is_candidate_for_offering(x, y)
  floor_items = items.get_items_at(x, y)
  if not floor_items then
    return false
  end
  for i, el in ipairs(floor_items) do
    if is_good_corpse(el) then
      return true
    end
  end
  return false
end

local function move_to(dx, dy)
  while dx ~= 0 or dy ~= 0 do
     local move = move_towards(dx, dy)
     if move then
       coroutine.yield(true)
       dx = dx - move.dx
       dy = dy - move.dy
     else
       return false
     end
  end
  return true
end

local function offer()
   crawl.process_keys('p')
   coroutine.yield(true)
end

local function get_all_targets()
  local targets = {}
  local index = 1
  for x = -8,8 do
    for y = -8,8 do
      if is_candidate_for_offering(x, y) then
        targets[index] = {x=x, y=y}
        targets[index].d = (abs(x) > abs(y)) and abs(x) or abs(y)       
        index = index + 1
      end
    end
  end
  return targets
end

local function set_ap_explore(key, value)
   AUTOPRAY_EXPLORE = string.lower(value) ~= false
end

local function do_offer()
  table.sort(targets, function (a, b) return (a.d < b.d) end)
  local last_move = {x=0, y=0}

  crawl.more_autoclear(true)
  for _,t in ipairs(targets) do
    if move_to(t.x - last_move.x, t.y - last_move.y) then
      offer()

      last_move.x = t.x
      last_move.y = t.y
    else
      -- pathing problems? return to initial position, and try again
      if move_to(-last_move.x, -last_move.y) then
        if move_to(t.x, t.y) then
          offer()
          last_move.x = t.x
          last_move.y = t.y
        else
          -- can't go to the initial pos
          return
        end
       else
        -- can't go to t
        return
      end
    end
  end
  crawl.more_autoclear(false)
end

function offer_all()
  if you.confused() then
    crawl.mpr("You are too confused!")
    return
  elseif caught then
    crawl.mpr("You are " .. caught .. "!")
    return
 end

  local god = you.god()
  if god == 'Makhleb' or god == 'Lugonu' or god == 'Okawaru'
     and god == 'Trog' and god == 'Beogh' then
    local targets = get_all_targets()
    if table.getn(targets) > 0 then
      do_offer()
    end
  end 
  if AUTOPRAY_EXPLORE then
    crawl.process_keys('o')
    --coroutine.yield(true)
  end
end

function autopray_interrupt_macro(interrupt_name)
    return interrupt_name == "hp_loss" or interrupt_name == "stat" or
           interrupt_name == "monster" or interrupt_name == "force"
end

-- Add a macro interrupt hook so that we don't get stopped by any old interrupt
chk_interrupt_macro.offer_all = autopray_interrupt_macro

chk_lua_option.autopray_explore = set_ap_explore

Dungeon Master

Posts: 553

Joined: Wednesday, 22nd December 2010, 10:12

Post Sunday, 22nd April 2012, 18:25

Re: Autopray.lua

Heh, this actually the second autopray feature for crawl. The old one was removed in 0.4, I believe (back then you had to pray before killing stuff).

Your script looks pretty handy, next time I play with a blood god I'm going to try it.

Return to Coding

Who is online

Users browsing this forum: No registered users and 8 guests

cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.