# This prevents the "More" prompt from triggering for distortion weapons
runrest_ignore_message += distortion
runrest_ignore_message += reaches for .* distortion
runrest_ignore_message += wielding .* distortion
# Optional: If you find other messages stopping you, add them here
runrest_ignore_message += is wielding
{
local function autopickup(it, name)
if it.is_useless then
return false
end
local class = it.class(true)
if class == "armour" then
local good_slots = {cloak="Cloak", helmet="Helmet",
gloves="Gloves", boots="Boots"}
st, _ = it.subtype()
if good_slots[st] ~= nil and
items.equipped_at(good_slots[st]) == nil then
return true
end
end
end
clear_autopickup_funcs()
add_autopickup_func(autopickup)
}
<
farming_enabled = false
macro_timer = 0
user_limit = 5000
-- Prevent engine timeout/crashes
function do_stop()
if stop_activity then stop_activity()
elseif crawl.stop_activity then crawl.stop_activity()
elseif you.stop_activity then you.stop_activity()
else crawl.sendkeys("\27") end
end
function is_ff_active()
if you.status then return you.status("Fusillade") end
if status then return status("Fusillade") end
return false
end
function get_level_turns()
if you.turns_on_level then return you.turns_on_level() end
if turns_on_level then return turns_on_level() end
return 0
end
-- NEW: Helper to check if a monster has specifically dangerous spells
function has_dangerous_spells(mon)
local spells = mon:spells()
if not spells then return false end
for _, sname in ipairs(spells) do
if sname == "Warp Body" or sname == "Brain Bite" or sname == "Call Down Damnation" then
return true
end
end
return false
end
-- SCANNER: Returns the highest threat in LOS and its coordinates
function get_threat_info()
local max_threat = -1
local tx, ty = nil, nil
local adj_x, adj_y = nil, nil
for r = 1, 7 do
for dx = -r, r do
for dy = -r, r do
local mon = monster.get_monster_at(dx, dy)
if mon and not mon:is_safe() then
local threat = mon:threat()
-- NEW LOGIC: Upgrade threat if monster has dangerous spells
if threat < 2 and has_dangerous_spells(mon) then
threat = 2
end
if threat > max_threat then
max_threat = threat
tx, ty = dx, dy
end
if math.max(math.abs(dx), math.abs(dy)) == 1 then
adj_x, adj_y = dx, dy
end
end
end
end
end
return max_threat, tx, ty, adj_x, adj_y
end
-- Helper: Checks for adjacent escape square
function get_escape_square()
for dx = -1, 1 do
for dy = -1, 1 do
if not (dx == 0 and dy == 0) then
local mon = monster.get_monster_at(dx, dy)
if mon and not mon:is_safe() then
local ex, ey = -dx, -dy
if view.is_safe_square(ex, ey) then
return ex, ey
end
end
end
end
end
return nil, nil
end
-- Helper: Movement/Melee Translation
function move_or_attack(dx, dy)
local keys = {
[-1] = {[-1] = "y", [0] = "h", [1] = "b"},
[0] = {[-1] = "k", [1] = "j"},
[1] = {[-1] = "u", [0] = "l", [1] = "n"}
}
if keys[dx] and keys[dx][dy] then
crawl.process_keys(keys[dx][dy])
return true
end
return false
end
-- Toggle function bound to ;
function toggle_pan_farm()
if not farming_enabled then
local res = crawl.yesno("Are you sure you want to start Pan Farming? (y/n)", true, "n")
if not res then return end
if crawl.yesno("Run for a LONG session (10,000 turns)?", true, "n") then
user_limit = 10000
elseif crawl.yesno("Run for a MEDIUM session (5,000 turns)?", true, "n") then
user_limit = 5000
elseif crawl.yesno("Run for a SHORT session (1,000 turns)?", true, "n") then
user_limit = 1000
else
user_limit = 100
end
farming_enabled = true
macro_timer = 0
crawl.mpr("Intelligent Pan Farm: ENABLED (Limit: " .. user_limit .. " turns)")
else
farming_enabled = false
crawl.mpr("Intelligent Pan Farm: DISABLED")
end
end
-- Ready Loop
function ready()
if not farming_enabled then return end
-- 1. SAFETY CHECKS
local cur_hp, max_hp = you.hp()
if cur_hp < (max_hp * 0.73) then
farming_enabled = false
crawl.mpr("HP Low! Emergency Stop.")
do_stop()
return
end
local cur_mp, _ = you.mp()
if cur_mp < 8 then
farming_enabled = false
crawl.mpr("Mana Low! Emergency Stop.")
do_stop()
return
end
if get_level_turns() >= 25000 then
farming_enabled = false
crawl.mpr("Level Turn Limit reached. Stopping macro.")
do_stop()
return
end
-- 2. MACRO TIMER RESET
macro_timer = macro_timer + 1
if macro_timer >= user_limit then
farming_enabled = false
crawl.mpr("Target turns reached (" .. user_limit .. ")! Stopping macro.")
do_stop()
macro_timer = 0
return
end
-- Initial Turn Delay
crawl.delay(15)
-- 3. COMBAT SCAN
local max_threat, tx, ty, adj_x, adj_y = get_threat_info()
if max_threat >= 0 then
-- LOGIC A: SERIOUS THREAT (Threat 2 or 3, or dangerous spells)
if max_threat >= 0 then
if not is_ff_active() then
crawl.mpr("Dangerous enemy! Casting Fusillade...")
if spells.cast("Fulsome Fusillade", tx, ty) then
crawl.delay(100)
return
end
end
if adj_x then
local ex, ey = get_escape_square()
if ex then
crawl.mpr("Kiting dangerous threat...")
move_or_attack(ex, ey)
else
crawl.mpr("Blocked! Blinking...")
spells.cast("Blink", 0, 0)
end
crawl.delay(100)
else
crawl.process_keys(".")
crawl.delay(50)
end
return
end
-- LOGIC B: LOW THREAT (Threat 0 or 1, no dangerous spells)
if max_threat <= 1 then
if adj_x then
crawl.mpr("Low threat adjacent. Melee attack.")
move_or_attack(adj_x, adj_y)
crawl.delay(50)
else
crawl.process_keys(".")
crawl.delay(50)
end
return
end
else
crawl.process_keys(".")
end
end
>
-- Bind the toggle to the semicolon (;) key
macros += M ; ===toggle_pan_farm