# HDA Default files
include += HDAColors.rc
include += PikaroSpoilers.rc
include += HDamage.rc
include += HDAForceMore.rc
include += PikaroMiscDefaults.rc
#################
# Magic options #
#################
allow_self_target = prompt
slot := spell_slot
# d fghi klm o rs vwxz
slot = animate dead:d
slot += flight:f
slot += regeneration:g
slot += haste:h
slot += deflect missiles:i
slot += animate skeleton:k
slot += delayed fireball:l
slot += simulacrum:m
slot += orb of destruction:o
slot += repel missiles:r
slot += stoneskin:s
slot += condensation shield:v
slot += swiftness:w
slot += sublimation of blood:x
slot += ozocubu.*armor:z
:if you.class()=="Conjurer" or you.class()=="Wizard" then
# abc e j mn p tu
slot += magic dart:a
slot += mystic blast:b
slot += conjure flame:c
slot += fireball:e
slot += iron shot:j
slot += mephitic cloud:q
slot += force lance:n
slot += poison cloud:p
slot += battlesphere:t
slot += freezing cloud:u
:elseif you.class()=="Transmuter" then
# ab i n p
slot += beastly appendage:a
slot += blade hands:b
slot += ice form:i
slot += spider form:p
slot += sticks to snakes:n
:elseif you.class()=="Fire Elementalist" then
# a c e
slot += flame tongue:a
slot += conjure flame:c
slot += fireball:e
:elseif you.class()=="Air Elementalist" then
# abc
slot += shock:a
slot += static discharge:b
slot += lightning bolt:c
:elseif you.class()=="Earth Elementalist" then
# ab
slot += sandblast:a
slot += stone arrow:b
:elseif you.class()=="Necromancer" then
slot += pain:a
:elseif you.class()=="Ice Elementalist" then
slot += freeze:a
slot += throw frost:b
:end
slot += .*:ABCDEFGHIJKLMNOPQRSTUVWXYZ
#############
# Autofight #
#############
auto_switch = false
autofight_stop = 20
autofight_throw = false
automagic_enable = true
automagic_stop = 20
automagic_fight = false
##############
# Autopickup #
##############
: if (you.god():find("Trog")) then
autopickup += $?!:"/}\
: else
autopickup += $?!:"/}\|
: end
ae -= dangerous_item
###############
# Autoexplore #
###############
explore_stop -= stairs
interrupt_travel -= hungry,sense_monster,mimic
#############
# Interface #
#############
view_delay = 0
skill_focus = toggle
menu_colour ^= blue:(corpse|chunk)
menu_colour ^= blue:bread ration
menu_colour ^= blue:meat ration
menu_colour ^= blue:jerk
menu_colour ^= blue:jell
menu_colour ^= blue:fruit
menu_colour ^= blue:pizza
menu_colour ^= darkgrey:inedible
############
# Messages #
############
msc := message_colour
msc ^= mute:Things that are here:
msc ^= mute:accepts your kill
msc ^= mute:There is an open door here
msc ^= mute:You open the door.
more := force_more_message
more ^= skill increases.*0
more ^= skill increases.*5
more ^= Shields skill increases to level 4
more ^= have mastered
more ^= skill gains
more ^= strange energies course
more ^= a corruption grows
more ^= begins to chant
more ^= drag you back to the ground
more -= cast banishment
more -= cast paralyse
more -= cast Torment
more -= You.*teleport [^f]
more -= Your amulet of stasis
more -= You don't.* that spell
########################################################################################################################################################################################################################################
############################################################################################## FUNCTIONS #############################################################################################################################
########################################################################################################################################################################################################################################
#####################################################
# Ready Function - gets called when action required #
#####################################################
{
reminded_mindelay = {}
function ready()
crawl.enable_more(true)
UpdateKnowledge()
--if recentmessages ~= nil then newmessages = string.gsub(crawl.messages(100),recentmessages,"BREEEEEAK") else newmessages = "" end
newmessages = crawl.messages(50)
--debug("m", newmessages)
if newmessages:find("finish memorising") or newmessages:find("unravels") then
known_spells = init_spells()
end
if you.skill(weapon_skill) >= weapon_target_skill and reminded_mindelay[weapon_type] ~= true then
crawl.mpr("Your wielded weapon is at mindelay!")
sendkeys('m')
reminded_mindelay[weapon_type] = true
end
check_safe_invisible(newmessages)
--if newmessages:find("you kill") or newmessages:find("the.*dies") then
-- debug("m","something died")
--end
AnnounceDamage()
if hp <= max_hp * 0.25 and not warning_25 then
crawl.mpr(string.format("HP at %i%%!",hp / max_hp * 100))
crawl.more()
warning_25 = true
warning_50 = true
elseif hp <= max_hp * 0.5 and not warning_50 then
crawl.mpr(string.format("HP at %i%%!",hp / max_hp * 100))
crawl.more()
warning_50 = true
end
if hp > max_hp * 0.25 then warning_25 = false end
if hp > max_hp * 0.5 then warning_50 = false end
local casted_permanent_spells = false
if options.autopick_on and you_safe then
Autobutcher()
casted_permanent_spells = PermanentSpells()
end
--SpoilerAlert()
OpenSkills()
if not casted_permanent_spells then FinishResting() end
end
function permanent_vars()
vars = ""
vars = vars .. stringify_var("safe_from_invisible",safe_from_invisible)
vars = vars .. stringify_array("want_item",want_item)
return vars
end
table.insert(chk_lua_save, permanent_vars)
}
#############
# Debugging #
#############
{
function DebugOutput()
debug("status",you.status())
debug("safe",you_are_safe())
debug("save inv", safe_from_invisible)
debug("ap", options.autopick_on)
debug("apoff", autopickup_off_because)
debug("energy",is_equipped("Weapon","staff of energy"))
debug("energy_alt",is_alternative_weapon("staff of energy"))
debug("missiles_have",stringify_array(missiles_have))
debug("equipped_at",stringify_array(equipped_at))
debug("have_chunks",stringify_array(have_chunks))
debug("rot",you_rot)
debug("hunger",you_hunger)
debug("last_butchered",last_butchered)
debug("god",you.god())
debug("should_rest",you_should_rest)
debug("debuffs",stringify_array(you_debuffs))
debug("debuffed",you_debuffed)
debug("like_chunks",you_like_chunks)
debug("see_corpses",see_corpses())
debug("over_corpses",over_corpses())
debug("see_skeletons",see_skeletons())
debug("over_skeletons",over_skeletons())
debug("you_spells",stringify_array(you_spells))
debug("want_item",stringify_array(want_item))
end
}
######################
# Calculate Artprops #
######################
{
function CalculateArtprops()
local attr = { Str = 0, Dex = 0, Int = 0, HP = 0, MP = 0, Slay = 0, EV = 0, AC = 0 }
local pluses = { rF = 0, rC = 0, Stlth = 0, rN = 0, MR = 0 }
local actions = { Blink = 0, Inv = 0, Fly = 0 }
local intr = { rMut = 0, rPois = 0, rElec = 0, SInv = 0, rCorr = 0, Regen = 0, Clar = 0, Ward = 0, Spirit = 0 }
local ignore = { Contam = 0, channel = 0 }
for it in inventory() do
if it.equipped then
local name = it.name()
if name:find("{") then
if it.class(true) == "weapon" then
name = name:gsub(".*,","")
name = name:gsub("}.*","")
else
name = name:gsub(".*{","")
name = name:gsub("[},].*","")
end
for prop in name:gmatch("%S+") do
propname = prop:gsub("%A","")
if attr[propname] ~= nil then
if prop ~= "+MP" then
local count = tonumber(prop:gsub("%D",""),10)
if prop:find("%+") then
attr[propname] = attr[propname] + count
elseif prop:find("%-") then
attr[propname] = attr[propname] - count
end
end
elseif pluses[propname] ~= nil then
local count = prop:gsub("%a","")
if count:find("%+") then count = count:len()
elseif count:find("%-") then count = count:len() *-1
end
pluses[propname] = pluses[propname] + count
elseif actions[propname] ~= nil then
actions[propname] = actions[propname] + 1
elseif intr[propname] ~= nil then
intr[propname] = intr[propname] + 1
elseif ignore[propname] == nil then
crawl.mpr(string.format("What is %s?",prop))
end
end
end
end
end
local arrs = { ["Attributes: "] = attr, ["Pluses: "] = pluses, ["Actions: "] = actions, ["Intrinsics: "] = intr }
for name,arr in pairs(arrs) do
local outstr = name
for stat,val in pairs(arr) do
outstr = outstr .. stat .. ": " .. tostring(val) .. ", "
end
crawl.mpr(string.format("%s",outstr:gsub(", $","")))
end
end
}
#########################
# Autotoggle Autopickup #
#########################
{
function ToggleAutopickupLastItem()
local toggleitems_disappearing = { "potion", "scroll" }
local toggleitems_permanent = { "ring", "wand", "amulet", "staff" }
for _,name in pairs(toggleitems_disappearing) do
if newmessages:find(name) then
debug("n",name)
end
end
for _,name in pairs(toggleitems_permanent) do
if newmessages:find(name) then
debug("n",name)
end
end
end
}
######################################
# Inventory Knowledge for Autothings #
######################################
{
have_knowledge = false
autopickup_slots = {cloak=true, helmet=true, gloves=true, boots=true}
equipment_slots = {cloak="Cloak", helmet="Helmet", gloves="Gloves", boots="Boots", body="Armour", shield="Shield", weapon="Weapon"}
itemcount = 0
have_chunks = {edible=nil, clean=nil, poisonous=nil}
equipped_at = {cloak=nil, helmet=nil, gloves=nil, boots=nil, armour=nil, shield=nil, weapon=nil}
missiles_have = {}
have_poison_resistance = false
you_race = you.race()
you_like_chunks = you_race ~= "Mummy" and you_race ~= "Spriggan" and you_race ~= "Vampire"
you_spells = { ["Regeneration"]=false, ["Deflect Missiles"]=false, ["Repel Missiles"]=false, ["Delayed Fireball"]=false, ["Sublimation of Blood"]=false, ["Animate Dead"]=false, ["Animate Skeleton"]=false, ["Simulacrum"]=false }
you_buffs = { ["lich"]=false, ["regen"]=false, ["deflect missiles"]=false, ["repel missiles"]=false, ["delayed fireball"]=false }
wait_debuffs = { "vulnerable", "confused", "corona", "exhausted", "petrifying", "silence", "marked", "barbs", "corroded", "slowed" }
if want_item == nil then
want_item = {}
want_item["wand"] = { slowing=1, hasting=-1 }
want_item["ring"] = { fire=2, ice=2 }
want_item["evocable"] = { ["disc of storms"]=1 }
want_item["deck"] = { plain=0, ornate=-1, legendary=-1 }
end
function UpdateKnowledge()
itemcount = 0
missiles_have = {["bolt"]={},["arrow"]={},["sling bullet"]={},["needle"]={},["stone"]={},["large rock"]={},["throwing net"]={},["tomahawk"]={},["javelin"]={}}
for it in inventory() do
if it.class(true) == "missile" then
missiles_have[it.subtype(true)][tostring(it.ego(true))] = true
end
itemcount = itemcount + 1
end
you_status = you.status()
you_can_cast = can_cast_spells()
if you_can_cast then
for spell,_ in pairs(you_spells) do you_spells[spell] = can_cast(spell) end
for buff,_ in pairs(you_buffs) do you_buffs[buff] = (you_status:find(buff) ~= nil) end
end
you_debuffs = {}
you_debuffed = false
for _,debuff in pairs(wait_debuffs) do
if you_status:find(debuff) ~= nil then
you_debuffs[debuff] = true
you_debuffed = true
end
end
if you_like_chunks ~= 0 then
have_chunks["edible"] = have_edible_chunks()
have_chunks["clean"] = have_clean_chunks()
have_chunks["poisonous"] = have_poisonous_chunks()
end
have_poison_resistance = you.res_poison()
hp,max_hp = you.hp()
mp,max_mp = you.mp()
you_time = you.time()
you_gourmand = you_are_gourmand()
you_hunger = you.hunger()
you_starving = (you_hunger == 0 and you_race ~= "Vampire")
you_berserk = you.berserk()
you_poisoned = you.poisoned()
you_rot = you.rot()
you_safe = you_are_safe()
you_should_rest = should_rest()
you_can_cast = can_cast_spells()
you_god = you.god()
local oldweapon = equipped_at["weapon"]
for name,slot in pairs(equipment_slots) do
equipped_at[name] = items.equipped_at(slot)
end
if equipped_at["weapon"] ~= oldweapon or weapon_target_skill == 0 then check_new_weapon() end
have_knowledge = true
end
}
####################
# Custom Autpickup #
####################
{
local strfind = string.find
add_autopickup_func(function(it, name)
if not have_knowledge then return nil end
local class = it.class(true)
if class == "missile" then
return missiles_have[it.subtype(true)][tostring(it.ego(true))]
end
if class == "food" then
if it.is_useless then return false end
if strfind(name,"chunk") then
local poisonous = strfind(name,"poison")
if itemcount < 52 then
if poisonous and not have_poison_resistance then return false else return true end
else
if poisonous and have_chunks["poisonous"] and have_poison_resistance then return true
elseif not poisonous and have_chunks["clean"] then return true
else return false
end
end
else
return true
end
end
if class == "armour" then
if it.is_useless then return false end
local sub_type = it.subtype()
if autopickup_slots[sub_type] then
if not equipped_at[sub_type] then
return true
else
return (it.artefact or it.branded or it.ego)
end
end
end
end)
}
###############
# Autobutcher #
###############
{
look_again = false
last_butchered = nil
function Autobutcher()
if not you_like_chunks then return false end
local oec = over_edible_corpse()
local oeh = over_edible_chunk()
local cec = can_eat_chunks()
local wnc = want_new_chunks()
if cec and ( oeh or have_chunks["edible"] ) then
sendkeys("e")
look_again = true
elseif oec and ( cec or ( itemcount < 52 and ( wnc or not have_chunks["edible"] ) ) ) then
sendkeys("c")
last_butchered = you_time
look_again = true
elseif look_again then
local itemlist = ""
for it in floor_items() do itemlist = itemlist .. it.name_coloured() .. ", " end
if itemlist ~= "" then
crawl.mpr(string.format("Items here: %s",itemlist:sub(1,-3)))
end
look_again = false
end
end
function want_new_chunks()
return last_butchered==nil or you_time >= last_butchered + 1000
end
function can_eat_chunks()
if you_race=="Ghoul" then
return you_hunger<4 or you_rot>0 or hp= spells.level(spell) then return true else return false end
end
function PermanentSpells()
if you_can_cast then
if not you_buffs["deflect missiles"] and you_spells["Deflect Missiles"] then
sendkeys("zi")
return true
elseif not you_buffs["deflect missiles"] and not you_buffs["repel missiles"] and you_spells["Repel Missiles"] then
sendkeys("zr")
return true
end
if not you_buffs["delayed fireball"] and you_spells["Delayed Fireball"] then
sendkeys("zl")
return true
end
end
return false
end
}
##############################
# Rest up before autoexplore #
##############################
{
function FinishRestingThenAutoexplore()
waiting_to_autoexplore = true
but_dont_autoexplore = false
end
function TriggerFinishResting()
waiting_to_autoexplore = true
but_dont_autoexplore = true
end
waiting_to_autoexplore = false
but_dont_autoexplore = false
time_start_wait = 0
autoswitched_to_staff_of_energy = false
tried_spells = {}
function over_corpses()
return remains_at(0,0,"corpse")
end
function see_corpses()
local x,y
for x=-8,8 do for y=-8,8 do if remains_at(x,y,"corpse") then return true end end end
return false
end
function over_skeletons()
return remains_at(0,0,"skeleton")
end
function see_skeletons()
local x,y
for x=-8,8 do for y=-8,8 do if remains_at(x,y,"skeleton") then return true end end end
return false
end
function remains_at(x,y,what)
if not you.see_cell_no_trans(x,y) then return false end
local pile = items.get_items_at(x,y)
if pile ~= nil then
for it in iter.invent_iterator:new(pile) do
if string.find(it.name(),what) then return true end
end
end
return false
end
function FinishResting()
if waiting_to_autoexplore and not PermanentSpells() then
if time_start_wait == 0 then time_start_wait = you_time end
if you_safe and not you_starving then
crawl.enable_more(false)
if you_can_cast then
if not you_buffs["lich"] and you_spells["Sublimation of Blood"] and mp < max_mp and ((max_mp-mp)*3 <= 0.5*hp) then
sendkeys("zx")
return true
elseif not you_buffs["lich"] and you_spells["Regeneration"] and hp < max_hp and not you_buffs["regen"] then
sendkeys("zg")
return true
end
if not tried_spells["Simulacrum"] and you_spells["Simulacrum"] and over_corpses() then
sendkeys("zm")
tried_spells["Simulacrum"] = true
return true
elseif not tried_spells["Animate Dead"] and you_spells["Animate Dead"] and (see_corpses() or see_skeletons()) then
sendkeys("zd")
tried_spells["Animate Dead"] = true
return true
elseif not tried_spells["Animate Skeleton"] and known_spells["Animate Skeleton"] then
if over_corpses() then
sendkeys("c")
return true
end
if over_skeletons() and you_spells["Animate Skeleton"] then
sendkeys("zk")
tried_spells["Animate Skeleton"] = true
return true
end
end
end
if is_equipped("weapon","staff of energy") and mp < max_mp and (have_chunks["edible"] or you_like_chunks==0) then
sendkeys("v")
elseif is_alternative_weapon("staff of energy") and mp < max_mp and (have_chunks["edible"] or you_like_chunks==0) then
sendkeys("'")
autoswitched_to_staff_of_energy = true
elseif (you_should_rest and you_god ~= "Jiyva") or (you_should_rest and you_god == "Jiyva" and but_dont_autoexplore) then
rest()
else
tried_spells = {}
if autoswitched_to_staff_of_energy then
sendkeys("'")
autoswitched_to_staff_of_energy = false
return true
end
waiting_to_autoexplore = false
if you_time - time_start_wait > 10 then
crawl.mpr(string.format("Total turns waited: %s",(you_time - time_start_wait)/10))
elseif but_dont_autoexplore then
crawl.mpr("No need to wait!")
end
time_start_wait = 0
if not but_dont_autoexplore then
crawl.enable_more(true)
autoexplore()
else
but_dont_autoexplore = false
end
end
else
if you_time - time_start_wait > 10 then
crawl.mpr(string.format("Total turns waited: %s",(you_time - time_start_wait)/10))
else
reason = you_are_safe_reason()
if reason == "unsafe" then
crawl.mpr("There are monsters nearby!")
elseif reason == "invis" then
crawl.mpr("There are invisible monsters nearby!")
elseif reason == "pois" then
crawl.mpr("The poison in your blood would kill you!")
elseif reason == "pillar" then
crawl.mpr("You are pillardancing!")
elseif you_starving then
crawl.mpr("Starvation!")
elseif you_berserk then
crawl.mpr("You are berserking!")
end
end
tried_spells = {}
time_start_wait = 0
waiting_to_autoexplore = false
but_dont_autoexplore = false
end
end
end
}
##########################################
# Toggle Autopickup for last picked item #
##########################################
{
function ToggleAutopickupLast()
last_item()
end
}
##################################
# Auxiliary Function Definitions #
##################################
{
function debug(name,what)
crawl.mpr(string.format("%s: %s",tostring(name),tostring(what)))
end
function stringify_array(arr)
if type(arr) ~= 'table' then return type(arr) end
local res = '{ '
for index, value in pairs(arr) do
if type(value) == "table" then
value = stringify_array(value)
end
if type(index) == "string" then
res = res .. index .. ' = ' .. tostring(value) .. ', '
else
res = res .. tostring(value) .. ', '
end
end
return res .. '}\n'
end
function stringify_var(varname, var)
return varname .. " = " .. tostring(var) .. "\n"
end
function stringify_sorted_array(arr, order, aname)
local res = aname .. " = { "
for _, index in pairs(order) do
res = res .. '["' .. string.format("%s",index) .. '"] = "' .. string.format("%s",arr[index]) .. '", '
end
res = res .. "}\n"
res = res .. aname .. "_order = { "
for _, index in pairs(order) do
res = res .. '"' .. string.format("%s",index) .. '", '
end
res = res .. "}\n"
return res
end
function you_are_safe()
return safe_from_invisible and you.feel_safe() and (you.poison_survival() > 0) and not pillardancing and not you.berserk()
end
autopickup_off_because = false
function check_safe_invisible(newmessages)
if newmessages:find("eactivating autopickup") then
autopickup_off_because = "monster"
elseif newmessages:find("utopickup is now off") then
autopickup_off_because = "user"
end
if not options.autopick_on and autopickup_off_because == "monster" then
safe_from_invisible = false
else
safe_from_invisible = true
end
end
function you_are_safe_reason()
if not safe_from_invisible then
return "invis"
elseif not you.feel_safe() then
return "unsafe"
elseif not (you.poison_survival() > 0) then
return "pois"
elseif pillardancing then
return "pillar"
else
return true
end
end
function sendkeys(command)
crawl.flush_input()
crawl.sendkeys(command)
crawl.flush_input()
--coroutine.yield(true)
end
function should_rest()
return
you_poisoned
or mp < max_mp
or ( hp < max_hp and you_race~="Deep Dwarf" and ( you_race~="Vampire" or you_hunger>0 ) )
or you_debuffed
end
function you_are_gourmand() return you.gourmand() or you_race=="Troll" or you_race=="Kobold" or you_race=="Ghoul" or you_race=="Felid" end
function autoexplore() sendkeys('o') end
function rest() sendkeys('5') end
function is_in_inventory(str)
for it in inventory() do
if string.find(it.name(), str) then
return true
end
end
return false
end
function inventory()
return iter.invent_iterator:new(items.inventory())
end
function last_item()
local inv = items.inventory()
debug("ni",inv[#inv].name())
end
function floor_items()
return iter.invent_iterator:new(you.floor_items())
end
function is_equipped(where,str)
if equipped_at[where] then
return string.find(equipped_at[where].name(), str)
else
return false
end
end
weapon_target_skill = 0
weapon_skill = ""
weapon_type = ""
function check_new_weapon()
if equipped_at["weapon"] == nil then
weapon_target_skill = 28
return true
end
local delay = equipped_at["weapon"].delay
local old_weapon_skill = weapon_skill
weapon_skill = equipped_at["weapon"].weap_skill
local maxdelay = delay + math.floor(you.skill(weapon_skill) / 2)
local mindelay = maxdelay / 2
if skill == "Short Blades" and mindelay > 5 then mindelay = 5 end
if mindelay > 7 then mindelay = 7 end
if skill == "Crossbows" and mindelay < 10 then mindelay = 10 end
mindelay = math.max(mindelay,maxdelay - 14)
if mindelay < 3 then mindelay = 3 end
local old_weapon_target_skill = weapon_target_skill
weapon_target_skill = (maxdelay - mindelay) * 2
weapon_type = equipped_at["weapon"].subtype()
end
function is_alternative_weapon(str)
local slot_a = items.inslot(items.letter_to_index("a"))
local slot_b = items.inslot(items.letter_to_index("b"))
local weapon = equipped_at["weapon"]
if slot_a and not slot_a.cursed then slot_a = slot_a.name() else return false end
if slot_b and not slot_b.cursed then slot_b = slot_b.name() else return false end
if weapon and not weapon.cursed then weapon = weapon.name() else return false end
if weapon ~= slot_a and weapon ~= slot_b then return false end
return (weapon == slot_a and string.find(slot_b,str)) or (weapon == slot_b and string.find(slot_a,str))
end
--Escapes the special characters in a string for pattern matching
function escape(str)
--Escapes parens and dash "()-"
local escaped = str:gsub('[%(%)%-]','\\%1')
--Removes any coloration parts of the string
return (escaped:gsub('<[^<]*>',''))
end
local need_skills_opened = true
function OpenSkills()
if you.turns() == 0 and need_skills_opened then
need_skills_opened = false
sendkeys("m")
end
end
function init_spells()
local spell_list = {}
for _, spell_name in ipairs(you.spells()) do
spell_list[spell_name] = true
end
return spell_list
end
known_spells = init_spells()
}