##### Crawl Init file ###############################################
# For descriptions of all options, as well as some more in-depth information
# on setting them, consult the file
# options_guide.txt
# in your /docs directory. If you can't find it, the file is also available
# online at:
# https://github.com/crawl/crawl/blob/master/crawl-ref/docs/options_guide.txt
#
# Crawl uses the first file of the following list as its option file:
# * init.txt in the -rcdir directory (if specified)
# * .crawlrc in the -rcdir directory (if specified)
# * init.txt (in the Crawl directory)
# * ~/.crawl/init.txt (Unix only)
# * ~/.crawlrc (Unix only)
# * ~/init.txt (Unix only)
# * settings/init.txt (in the Crawl directory)
##### Some basic explanation of option syntax #######################
# Lines beginning with '#' are comments. The basic syntax is:
#
# field = value or field.subfield = value
#
# Only one specification is allowed per line.
#
# The terms are typically case-insensitive except in the fairly obvious
# cases (the character's name and specifying files or directories when
# on a system that has case-sensitive filenames).
#
# White space is stripped from the beginning and end of the line, as
# well as immediately before and after the '='. If the option allows
# multiple comma/semicolon-separated terms (such as
# autopickup_exceptions), all whitespace around the separator is also
# trimmed. All other whitespace is left intact.
#
# There are three broad types of Crawl options: true/false values (booleans),
# arbitrary values, and lists of values. The first two types use only the
# simple =, with later options - which includes your options that are different
# from the defaults - overriding earlier ones. List options allow using +=, ^=,
# -=, and = to append, prepend, remove, and reset, respectively. Usually you will
# want to use += to add to a list option. Lastly, there is := which you can use
# to create an alias, like so:
# ae := autopickup_exceptions
# From there on, 'ae' will be treated as if it you typed autopickup_exceptions,
# so you can save time typing it.
#
##### Other files ###################################################
# You can include other files from your options file using the 'include'
# option. Crawl will treat it as if you copied the whole text of that file
# into your options file in that spot. You can uncomment some of the following
# lines by removing the beginning '#' to include some of the other files in
# this folder.
# Some useful, more advanced options, implemented in LUA.
# include = advanced_optioneering.txt
####### Do not modify the following values
{
AUTO_MAGIC_NONE = 0 -- No auto magic at all
AUTO_MAGIC_PERSIST = 1 -- Only magic which persists across stairs
-- like shroud of golubria
AUTO_MAGIC_ALL = 2 -- All auto magic, including that which does
-- not persists across stairs like summons
SPELL_COST_SHROUD_OF_G = 2
SPELL_COST_BATTLESPHERE = 5
SPELL_COST_SPELLFORGED_SERVITOR = 7
SPELL_FAIL_SEVERITY_SAFE = 0 -- Grey
SPELL_FAIL_SEVERITY_SLIGHTLY_DANGEROUS = 1 -- White
SPELL_FAIL_SEVERITY_DANGEROUS = 2 -- Yellow
SPELL_FAIL_SEVERITY_QUITE_DANGEROUS = 3 -- Light Red
SPELL_FAIL_SEVERITY_EXTREMELY_DANGEROUS = 4 -- Red
SPELL_FAIL_SEVERITY_POTENTIALLY_LETHAL = 5 -- Purple
SATIATION_STARVING = 0
SATIATION_NEAR_STARVING = 1
SATIATION_VERY_HUNGRY = 2
SATIATION_HUNGRY = 3
SATIATION_NOT_HUNGRY = 4
SATIATION_NOT_HUNGRY_AND_HAS_EDIBLE_CHUNK = 1000
SATIATION_FULL = 5
SATIATION_VERY_FULL = 6
SATIATION_ENGORGED = 7
SATIATION_ABOVE_ENGORGED = 8
SPELL_ISKENDERUNS_BATTLESPHERE = "Iskenderun's Battlesphere"
SPELL_SHROUD_OF_GOLUBRIA = "Shroud of Golubria"
SPELL_SPELLFORGED_SERVITOR = "Spellforged Servitor"
}
####### Do not modify the previous values
# Set travel delay to -1 for instant-travel, set to 1 to see travel paths
show_travel_trail=true
travel_key_stop = true
default_manual_training = true
travel_delay = 5
#include = macros_offline.txt
prefer_safe_chunks=true
easy_eat_chunks = true
# streamline food
auto_butcher = true
easy_eat_chunks = true
# just keep exploring
explore_stop -= stairs, items
explore_stop += glowing_items, artefacts, runes
{
MIN_MP_REST_PERCENT = 100
MIN_HP_REST_PERCENT = 100
SPELL_MIN_SATIATION_SHROUD_OF_G = SATIATION_NEAR_STARVING
SPELL_MIN_SATIATION_BATTLESPHERE = SATIATION_NEAR_STARVING
SPELL_MIN_SATIATION_SPELLFORGED_SERVITOR = SATIATION_ABOVE_ENGORGED
-- Spells will only be autocast if their fail rate is
-- this or better and their severity is yellow or better.
-- Or if their fail rate is twice this or better and
-- their severity is white or better.
SPELL_REQUIRED_FAIL_RATE = 7
}
{
function xx()
end
}
#####################################################
# Ready Function - gets called when action required #
#####################################################
{
itemcount = 0
automagic = AUTO_MAGIC_NONE
auto_resting = false
auto_exploring = false
auto_buffing = false
function ready()
LuthTravel()
end
}
{
-- Requirements which apply to all auto spells
function general_allow_auto_spell()
local near_starving_or_worse = you_are_starving() or you_are_near_starving()
local res = (
you.feel_safe()
and automagic>AUTO_MAGIC_NONE
and not you_are_starving()
and you.contaminated()==0
)
--crawl.mpr ("general_allow_auto_spell()="..tostring(res))
return res
end
}
##############
# Auto magic #
##############
{
function num_castable_spells()
local num = 0
if is_castable_battlesphere() then num = num+1 end
if is_castable_shroud_of_g() then num = num+1 end
if is_castable_spellforged_servitor then num = num+1 end
return num
end
function num_active_spells()
local num = 0
if battlesphere_is_active() then num = num+1 end
if is_active_shroud_of_g() then num = num+1 end
if spellforged_servitor_is_active then num = num+1 end
return num
end
function total_cost_castable()
local cost = 0
if is_castable_battlesphere() then cost = cost+SPELL_COST_BATTLESPHERE end
if is_castable_shroud_of_g() then cost = cost+SPELL_COST_SHROUD_OF_G end
if is_castable_spellforged_servitor() then cost = cost+SPELL_COST_SPELLFORGED_SERVITOR end
return cost
end
function total_cost_needed_spells()
local cost = 0
if need_cast_battlesphere() then cost = cost+SPELL_COST_BATTLESPHERE end
if need_cast_shroud_of_golubria() then cost = cost+SPELL_COST_SHROUD_OF_G end
if need_cast_spellforged_servitor() then cost = cost+SPELL_COST_SPELLFORGED_SERVITOR end
return cost
end
-- Returns true if a spell was cast
function auto_spell_maybe()
if general_allow_auto_spell() then
-- crawl.mpr("ready check spells;");
if cast_battlesphere_maybe() then return true end
if cast_shroud_of_g_maybe() then return true end
if cast_spellforged_servitor_maybe() then return true end
end
return false
end
function spell_is_safe(spell)
return ( spells.fail_severity(spell) <= SPELL_FAIL_SEVERITY_SLIGHTLY_DANGEROUS and spells.fail(spell) <= SPELL_REQUIRED_FAIL_RATE ) or
( spells.fail_severity(spell) <= SPELL_FAIL_SEVERITY_DANGEROUS and spells.fail(spell) <= SPELL_REQUIRED_FAIL_RATE*2 )
end
function is_spell_hunger_ok(required_hunger)
if required_hunger==SATIATION_NOT_HUNGRY_AND_HAS_EDIBLE_CHUNK then
if you.hunger() >= SATIATION_FULL then return true; end
if you.hunger() < SATIATION_NOT_HUNGRY then return false; end
return have_edible_chunks()
else
return you.hunger()>=required_hunger
end
end
}
######################
# Control auto magic #
######################
{
function enable_automagic()
if automagic>=AUTO_MAGIC_ALL then
crawl.mpr("All automagic is already enabled")
else
automagic = automagic+1
if automagic == AUTO_MAGIC_ALL then
crawl.mpr("Enabled all automagic")
else
crawl.mpr("Enabled persistent across stairs automagic")
end
end
end
function disable_automagic()
if automagic<=AUTO_MAGIC_NONE then
crawl.mpr("All automagic is already disabled")
else
automagic = automagic-1
if automagic == AUTO_MAGIC_NONE then
crawl.mpr("Disabled all automagic")
else
crawl.mpr("Disabled some automagic but across stairs is still enabled")
end
end
end
}
##################################
# Auto Iskenderun's Battlesphere #
##################################
{
lastTime = you.time()
function cast_battlesphere_maybe()
local mp, max_mp = you.mp()
--crawl.mpr( "need_cast_battlesphere()=" .. tostring(need_cast_battlesphere()))
--crawl.mpr( "should_rest_magic(mp, max_mp)=" .. tostring(should_rest_magic(mp, max_mp)))
if need_cast_battlesphere() and
not should_rest_magic(mp, max_mp) then
crawl.mpr("Casting Iskenderun's Battlesphere.")
c=spells.letter(SPELL_ISKENDERUNS_BATTLESPHERE)
sendkeys("z"..c)
return true
end
if ( you.time()-lastTime > 200 ) then
--crawl.mpr( "shouldbattlesphere()=[" .. tostring(need_cast_battlesphere()) .. "," .. tostring(should_rest_magic(mp, max_mp)) .. "]" )
lastTime = you.time()
end
return false
end
}
{
function battlesphere_is_active()
local monsters = {}
for x = -7,7 do
for y = -7,7 do
m = monster.get_monster_at(x, y)
local attitude_friendly = 4
if m and (m:attitude() == attitude_friendly) then
name = m:name()
if name == "battlesphere" then
return true
end
end
end
end
return false
end
}
{
function is_castable_battlesphere()
--crawl.mpr("you.hunger() >=SPELL_MIN_SATIATION_BATTLESPHERE ----"..tostring(you.hunger())..","..tostring(SPELL_MIN_SATIATION_BATTLESPHERE))
return automagic >= AUTO_MAGIC_ALL and
known_spells[SPELL_ISKENDERUNS_BATTLESPHERE]~=nil and
spell_is_safe(SPELL_ISKENDERUNS_BATTLESPHERE) and
is_spell_hunger_ok(SPELL_MIN_SATIATION_BATTLESPHERE)
end
}
{
function need_cast_battlesphere()
--crawl.mpr("automagic>=AUTO_MAGIC_ALL=" .. tostring(automagic>=AUTO_MAGIC_ALL))
--crawl.mpr("known_spells[SPELL_ISKENDERUNS_BATTLESPHERE]~=nil = " .. tostring(known_spells[SPELL_ISKENDERUNS_BATTLESPHERE]~=nil) )
--crawl.mpr( "spell_is_safe(SPELL_ISKENDERUNS_BATTLESPHERE) = " ..
-- tostring(spell_is_safe(SPELL_ISKENDERUNS_BATTLESPHERE)))
--crawl.mpr("battlesphere_is_active() = " .. tostring(battlesphere_is_active()))
return is_castable_battlesphere() and not battlesphere_is_active()
end
}
#############################
# Auto Spellforged Servitor #
#############################
{
lastTimeSpellforged = you.time()
function cast_spellforged_servitor_maybe()
local mp, max_mp = you.mp()
--crawl.mpr( "need_cast_spellforged_servitor()=" .. tostring(need_cast_spellforged_servitor()))
--crawl.mpr( "should_rest_magic(mp, max_mp)=" .. tostring(should_rest_magic(mp, max_mp)))
if need_cast_spellforged_servitor() and
not should_rest_magic(mp, max_mp) then
crawl.mpr("Casting Spellforged Servitor.")
c=spells.letter(SPELL_SPELLFORGED_SERVITOR)
sendkeys("z"..c)
return true
end
if ( you.time()-lastTimeSpellforged > 200 ) then
--crawl.mpr( "need_cast_spellforged_servitor()=[" .. tostring(need_cast_spellforged_servitor()) .. "," .. tostring(should_rest_magic(mp, max_mp)) .. "]" )
lastTimeSpellforged = you.time()
end
return false
end
function spellforged_servitor_is_active()
local monsters = {}
for x = -7,7 do
for y = -7,7 do
m = monster.get_monster_at(x, y)
local attitude_friendly = 4
if m and (m:attitude() == attitude_friendly) then
name = m:name()
if name == "spellforged servitor" then
return true
end
end
end
end
return false
end
function is_castable_spellforged_servitor()
--crawl.mpr("automagic>=AUTO_MAGIC_ALL=" .. tostring(automagic>=AUTO_MAGIC_ALL))
--crawl.mpr("known_spells[SPELL_SPELLFORGED_SERVITOR]~=nil = " .. tostring(known_spells[SPELL_SPELLFORGED_SERVITOR]~=nil) )
--crawl.mpr( "spell_is_safe(SPELL_SPELLFORGED_SERVITOR) = " ..
-- tostring(spell_is_safe(SPELL_SPELLFORGED_SERVITOR)))
--crawl.mpr("you.hunger() >= SPELL_MIN_SATIATION_SPELLFORGED_SERVITOR ----"..tostring(you.hunger())..","..tostring(SPELL_MIN_SATIATION_SPELLFORGED_SERVITOR))
local res = automagic >= AUTO_MAGIC_ALL and
known_spells[SPELL_SPELLFORGED_SERVITOR]~=nil and
spell_is_safe(SPELL_SPELLFORGED_SERVITOR) and
is_spell_hunger_ok(SPELL_MIN_SATIATION_SPELLFORGED_SERVITOR)
if res then
crawl.mpr("is castable servitor")
crawl.mpr("SPELL_MIN_SATIATION_SPELLFORGED_SERVITOR="..tostring(SPELL_MIN_SATIATION_SPELLFORGED_SERVITOR).." you.hunger()="..tostring(you.hunger()))
crawl.mpr("is_spell_hunger_ok(SPELL_MIN_SATIATION_SPELLFORGED_SERVITOR)"..tostring(is_spell_hunger_ok(SPELL_MIN_SATIATION_SPELLFORGED_SERVITOR)))
end
end
function need_cast_spellforged_servitor()
--crawl.mpr("spellforged_servitor_is_active() = " .. tostring(spellforged_servitor_is_active()))
return is_castable_spellforged_servitor() and not spellforged_servitor_is_active()
end
}
###########################
# Auto Shroud of Golubria #
###########################
{
SPELL_COST_SHROUD_OF_G = 2
SPELL_COST_BATTLESPHERE = 5
function cast_shroud_of_g_maybe()
local mp, max_mp = you.mp()
--crawl.mpr("need_cast_shroud_of_golubria()="..tostring(need_cast_shroud_of_golubria()))
--crawl.mpr("should_rest_magic("..tostring(mp)..","..tostring(max_mp)..")="..tostring(should_rest_magic(mp, max_mp)))
if need_cast_shroud_of_golubria() and
not should_rest_magic(mp, max_mp) then
crawl.mpr("Casting Shroud of Golubria.")
c=spells.letter(SPELL_SHROUD_OF_GOLUBRIA)
sendkeys("z"..c)
return true
end
return false
end
function is_castable_shroud_of_g()
--crawl.mpr ( "known_spells[SPELL_SHROUD_OF_GOLUBRIA]="..tostring(known_spells[SPELL_SHROUD_OF_GOLUBRIA]~=nil))
--crawl.mpr ( "spell_is_safe(SPELL_SHROUD_OF_GOLUBRIA) = " .. tostring(spell_is_safe(SPELL_SHROUD_OF_GOLUBRIA)) )
--crawl.mpr ( "you.status(shrouded)=" .. tostring( you.status("shrouded") ) )
--crawl.mpr("you.hunger() >= SPELL_MIN_SATIATION_SHROUD_OF_G ----"..tostring(you.hunger())..","..tostring(SPELL_MIN_SATIATION_SHROUD_OF_G))
return automagic>=AUTO_MAGIC_PERSIST and
known_spells[SPELL_SHROUD_OF_GOLUBRIA]~=nil and
spell_is_safe(SPELL_SHROUD_OF_GOLUBRIA) and
is_spell_hunger_ok(SPELL_MIN_SATIATION_SHROUD_OF_G)
end
function is_active_shroud_of_g()
return you.status("shrouded")
end
function need_cast_shroud_of_golubria()
return is_castable_shroud_of_g() and not is_active_shroud_of_g()
end
}
#############
# Auto rest #
#############
{
function StartLuthTravel()
--crawl.mpr("StartLuthTravel;")
--crawl.mpr("auto exploring")
auto_exploring = true
num_rests = 0
LuthTravel()
end
function LuthTravel()
--crawl.mpr("LuthTravel")
local rested=false
if auto_resting or auto_exploring then
--crawl.mpr("continue rest time=" .. tostring(you.time()))
rested = auto_rest()
end
--crawl.mpr("rested="..tostring(rested).." auto_exploring="..tostring(auto_exploring))
if rested then return end
if auto_exploring then
if auto_butcher_maybe() then
--crawl.mpr("auto_butchered")
return
end
--if (string.find(crawl.messages(10), escape("Done exploring"))~=nil) or
-- (string.find(crawl.messages(10), escape("Partly explored"))~=nil) then
-- auto_exploring = false
-- --crawl.mpr("Done exploring jjj")
-- return
--end
if auto_spell_maybe() then
--crawl.mpr("spell_maybe is true");
return
end
--crawl.mpr("spell_maybe is false");
--if floor_has_corpse() then
-- crawl.mpr("Stop travel because corpse in floor")
-- auto_exploring = false
-- return
--end
--crawl.mpr("Continue travel")
auto_exploring = false
autoexplore()
end
end
num_rests = 0
function auto_rest_start()
num_rests = 0
auto_buffing = true
auto_exploring = false
auto_rest()
end
-- Returns true rest was performed
function auto_rest()
if (not you.feel_safe()) then
--This will provide the "foo is nearby" message
autoexplore()
auto_exploring = false
auto_resting = false
auto_buffing = false
return false
end
local rested = rest_maybe()
if rested then
num_rests=num_rests + 1
else
--crawl.mpr("Rested "..tostring(num_rests).." time(s)")
end
if (not you.feel_safe()) then
--This will provide the "foo is nearby" message
autoexplore()
auto_exploring = false
auto_resting = false
auto_buffing = false
else
auto_resting = rested or auto_buffing
end
if rested then return true end
if auto_buffing then
if auto_butcher_maybe() then return true end
if auto_spell_maybe() then return true end
auto_buffing = false
end
return false
end
function at_feet()
return iter.invent_iterator:new(you.floor_items())
end
function floor_has_corpse()
for it in at_feet() do
if it.is_corpse then
crawl.mpr("name=\""..it:name().."\"")
crawl.mpr("is_bad_food=\""..tostring(it.is_bad_food).."\"")
crawl.mpr("is_useless=\""..tostring(it.is_useless).."\"")
return true
end
end
return false
end
}
#########
# Aux #
#########
###############
# Autobutcher #
###############
{
function auto_butcher_maybe()
if options.autopick_on and you.feel_safe() then
if can_eat_chunks() and ( over_edible_chunk() or have_edible_chunks() ) then
crawl.mpr("auto eating;")
sendkeys("e")
return true
end
if not asked_butcher() and over_edible_corpse() then
crawl.mpr("auto chopping;")
sendkeys("c")
return true
end
end
return false
end
function asked_butcher()
local res = string.find(crawl.messages(10), escape("Butcher.*es.*o.*uit"))
return res
end
function m_asked_butcher()
local res = string.find(crawl.messages(10), escape("Butcher.*es.*o.*uit"))
crawl.mpr("asked=\""..tostring(res).."\"")
return false
end
function can_eat_chunks()
if you.race()=="Spriggan" then return false end
if you.gourmand() or you.race()=="Kobold" or you.race()=="Felid" then
return you.hunger()<7
end
return you.hunger()<4
end
function edible_corpse(item)
if you.race()=="Spriggan" then return false end
if food.dangerous(item) then return false end
return string.find(item.name(),"corpse")
end
function edible_chunk(item)
if food.dangerous(item) or item.is_useless then return false end
return string.find(item.name(),"chunk")
end
function over_edible_corpse()
for item_under_you in floor_items() do
if edible_corpse(item_under_you) then return true end
end
return false
end
function over_edible_chunk()
for item_under_you in floor_items() do
if edible_chunk(item_under_you) then return true end
end
return false
end
function have_edible_chunks()
for it in inventory() do
if edible_chunk(it) then return true end
end
return false
end
}
##################################
# Auxiliary Function Definitions #
##################################
{
function debug(name,what)
if what == nil then
crawl.mpr(string.format("%s: nil",name))
elseif type(what) == "boolean" then
crawl.mpr(string.format("%s: %s",name,what and "true" or "false"))
else
crawl.mpr(string.format("%s: %s",name,what))
end
end
}
{
function you_are_starving() return you.hunger() == 0 end
}
{
function you_are_near_starving() return you.hunger() == 1 end
}
{
function you_are_very_hungry() return you.hunger() == 2 end
}
{
function you_are_hungry() return you.hunger() == 3 end
}
{
function you_are_not_hungry() return you.hunger() == 4 end
}
{
function you_are_full() return you.hunger() == 5 end
}
{
function you_are_very_full() return you.hunger() == 6 end
}
{
function you_are_engorged() return you.hunger() == 7 end
}
{
last_time_autoexplore = 0.0
times_not_advance = 0
function autoexplore()
--if (last_time_autoexplore==you.time() and times_not_advance>2 ) then
-- auto_exploring = false
-- times_not_advance = 0
-- crawl.mpr("Not exploring because time did not advance")
-- return
--end
--if (last_time_autoexplore==you.time() ) then
-- times_not_advance = times_not_advance + 1
--else
-- times_not_advance = 0
--end
crawl.mpr("sending key o")
sendkeys("o")
end
}
{
function rest_once()
sendkeys(".")
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 floor_items()
return iter.invent_iterator:new(you.floor_items())
end
}
{
function is_equipped(where,str)
local eq = items.equipped_at(where)
if weapon then
return string.find(eq.name(), str)
else
return false
end
end
}
{
local 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()
}
{
function sendkeys(command)
--crawl.flush_input()
----crawl.sendkeys(command)
--crawl.process_keys(command)
----crawl.process_command()
--crawl.flush_input()
crawl.flush_input()
crawl.sendkeys(command)
crawl.flush_input()
end
}
{
function should_rest_magic(mp, max_mp)
if mp==max_mp then return false end
local min_mp = max_mp*(MIN_MP_REST_PERCENT/100.0)
local percent2 = 100.0 - (total_cost_castable()*1.0/max_mp)
if (percent2 10)
and not you_are_deep_dwarf)
--crawl.mpr("should_rest_magic(mp, mp)="..tostring(should_rest_magic(mp, max_mp)))
return ( need_mp
or need_hp
or need_mummy
or you.slowed()
or you.poisoned()
or you.confused()
or you.exhausted()
)
end
}
{
function have_barbs()
return string.find(crawl.messages(10), escape("The barbed spikes become lodged in your body"))
or string.find(crawl.messages(10), escape("The barbed spikes dig painfully into your body as you move"))
end
}
{
function already_animated()
return string.find(crawl.messages(20), escape("Autocasting Animate Dead"))
end
}
{
function removed_barbs()
return string.find(crawl.messages(10), escape("You carefully extract the manticore spikes from your body"))
or string.find(crawl.messages(10), escape("The manticore spikes snap loose"))
end
}
{
function no_results()
return string.find(crawl.messages(10), escape("Can't find anything matching that"))
or string.find(crawl.messages(10), escape("You may need something to eat soon"))
end
}
{
function dont_know_how_to_get_there()
return string.find(crawl.messages(10), escape("know how to get there"))
or string.find(crawl.messages(10), escape("Have to go through"))
end
}
{
function can_not_animate()
return string.find(crawl.messages(10), escape("There is nothing here that can be animated"))
end
}
{
function can_not_bottle()
return string.find(crawl.messages(10), escape("There isn't anything to bottle here"))
end
}
{
function recently_mass_animated()
return string.find(crawl.messages(10), escape("Autocasting Mass Animate Remains"))
end
}
{
function can_not_butcher()
return string.find(crawl.messages(10), escape("anything suitable to butcher here"))
or string.find(crawl.messages(10), escape("isn't edible"))
end
}
{
function can_not_eat_that()
return string.find(crawl.messages(10), escape("You can't eat that"))
--These strings don't seem to show up in messages
--or string.find(crawl.messages(10), escape("Not only inedible but also greatly harmful"))
--or string.find(crawl.messages(10), escape("It is caustic"))
end
}
{
function you_are_gourmand()
return you.gourmand() or (not you_are_not_ghoul()) or (not you_are_not_felid()) or (not you_are_not_troll()) or (string.find(you.race(), "Kobold"))
end
}
{
function have_no_chunks()
for it in inventory() do
if string.find(it.name(), "chunk") then
return false
end
end
return true
end
}
{
function have_rotten_chunks()
for it in inventory() do
if string.find(it.name(), "chunk") and string.find(it.name(), "rott") then
return false
end
end
return true
end
}
{
function number_of_chunks()
for it in inventory() do
--if string.find(it.name(), "chunk") then
--crawl.mpr(it.name() .." is edible: " .. (food.can_eat(it) and "True" or "False") .. " and dangerous: " .. (food.dangerous(it) and "True" or "False"))
--end
if string.find(it.name(), "chunk") and (not string.find(it.name(), "book")) and food.can_eat(it) and not food.dangerous(it) then
return it.quantity
end
end
return 0
end
}
{
function weapon_in_inventory()
for it in inventory() do
if string.find(it.class(true), "weapon") then
return true
end
end
return false
end
}
{
function weapon_in_slot_a()
local it = items.inslot(0)
if it then
return string.find(it.class(true), "weapon")
else
return false
end
end
}
{
function find_item_letter(str)
for i = 0,51 do
it = items.inslot(i)
if it then
if string.find(it.name(), str) then
return items.index_to_letter(i)
end
end
end
return false
end
}
{
function you_worship_sacrifice_god()
return string.find(you.god(), "Trog")
--or string.find(you.god(), "Oka")
--or string.find(you.god(), "Makhleb")
or string.find(you.god(), "Beogh")
or string.find(you.god(), "Lugonu")
--or string.find(you.god(), "Nemelex")
end
}
{
function on_corpses()
local fl = you.floor_items()
for it in iter.invent_iterator:new(fl) do
if string.find(it.name(), "corpse")
and not string.find(it.name(), "rotting")
and not string.find(it.name(), "plague") then
return true
end
end
return false
end
}
{
function on_chunks()
for it in floor_items() do
if string.find(it.name(), "chunk") then
return true
else
return false
end
end
end
}
{
function you_are_carnivore()
return you.saprovorous()
end
}
{
function you_are_not_ghoul()
return not (string.find(you.race(), "Ghoul"))
end
}
{
function you_are_not_troll()
return not (string.find(you.race(), "Troll"))
end
}
{
function you_are_not_felid()
return not (string.find(you.race(), "Felid"))
end
}
{
function you_are_not_octopode()
return not (string.find(you.race(), "Octopode"))
end
}
{
function find_corpses()
local race = you.race()
local god = you.god()
local exclude_this = ""
if string.find(god, "Shining") then
exlude_this = race
end
sendkeys(string.char(6) .. "@corpse&&!!rott&&!!skel&&!!sky&&!!necrop&&!!ugly&&!!vampire&&!!corpse rot&&!!&&!!botono" .. exclude_this .. "\ra\r")
end
}
{
function no_weapon()
return (items.equipped_at("Weapon") == nil) and not uses_unarmed()
end
}
{
function uses_unarmed()
return not you_are_not_ghoul()
or not you_are_not_troll()
or not you_are_not_felid()
or (you.skill("Unarmed Combat") >= 3)
end
}
{
function is_weapon(str)
local weapon = items.equipped_at("Weapon")
if weapon then
return string.find(weapon.name(), str)
else
return false
end
end
}
{
function is_ring(str)
local ring1 = items.equipped_at("Left Ring")
local ring2 = items.equipped_at("Right Ring")
if ring1 and ring2 then
return string.find(ring1.name(), str) or string.find(ring2.name(), str)
elseif ring1 then
return string.find(ring1.name(), str)
elseif ring2 then
return string.find(ring2.name(), str)
else
return false
end
end
}
{
function item_in_view(str)
local x,y
for x = -8,8 do
for y = -8,8 do
if not (x == 0 and y == 0) then
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(), str) and you.see_cell_no_trans(x,y) then
return true
end
end
end
end
end
end
return false
end
}
{
-- Returns a table where the key is the monster description and value is the total number of that mob in your vision
function getMonsterList()
local monsters = {}
for x = -7,7 do
for y = -7,7 do
m = monster.get_monster_at(x, y)
local attitude_hostile = 0
if m and (m:attitude() == attitude_hostile) and not (m:is_firewood()) then
desc = m:desc()
if (monsters[desc] == nil) then
monsters[desc] = 1
else
monsters[desc] = monsters[desc] + 1
end
end
end
end
return monsters
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
}
{
-- Returns true if an action has been performed
-- False otherwise.
function rest_maybe()
if (not you.feel_safe()) then return false end
local mp, max_mp = you.mp()
local hp, max_hp = you.hp()
local first_monster = next(getMonsterList())
local already_checked = (no_results() or dont_know_how_to_get_there())
local you_are_barbed = (have_barbs() and not removed_barbs())
local is_safe = (first_monster == nil)
local missing_mp = (mp < max_mp)
local missing_hp = (hp < max_hp)
local need_to_recover = should_rest(hp, mp, max_hp, max_mp)
local have_no_chunks = have_no_chunks()
local you_are_sif = string.find(you.god(), "Sif")
local you_are_yred = string.find(you.god(), "Yred")
local you_are_zin = string.find(you.god(), "Zin")
local you_are_good = string.find(you.god(), "Shining") or string.find(you.god(), "Elyvilon") or you_are_zin
local sacrifice_god = you_worship_sacrifice_god()
local you_are_mummy = string.find(you.race(), "Mummy")
local you_are_vampire = string.find(you.race(), "Vampire")
local you_are_bloodless = you.hunger_name() == "bloodless"
local you_are_ghoul = string.find(you.race(), "Ghoul")
local you_are_bloodless = you.hunger_name() == "bloodless"
local you_do_not_eat = string.find(you.race(), "Spriggan") or you_are_mummy
local lichform = string.find(you.transform(), "lich")
local bladehands = string.find(you.transform(), "blade")
local dragonform = string.find(you.transform(), "dragon")
local melded_weapon = (bladehands or dragonform)
local you_are_regen = you.regenerating()
local you_know_sublimation = known_spells["Sublimation of Blood"] and (spells.fail("Sublimation of Blood") < 20) and (mp>3)
local you_know_animate_skeleton = known_spells["Animate Skeleton"] and (spells.fail("Animate Skeleton") < 20) and (mp>1)
local you_know_animate_dead = known_spells["Animate Dead"] and (spells.fail("Animate Dead") < 20) and (mp>4)
local chunks_are_equipped = is_weapon("chunk")
local distort_weapon = is_weapon("distort")
local vamp_weapon = is_weapon("vamp") and not chunks_are_equipped
local have_a_weapon = weapon_in_inventory()
local gourmand_and_hungry = you_are_gourmand() and not (you_are_very_full() or you_are_engorged() or you_are_ghoul)
local ghoul_missing_hp = you_are_ghoul and ((hp < (max_hp - 5)) or you.rot() > 0)
local want_to_eat = (you_are_hungry() or gourmand_and_hungry or ghoul_missing_hp) and not you_do_not_eat
local have_spare_chunks = not have_no_chunks and not you_are_hungry()
local you_have_staff_of_energy = is_in_inventory("staff of energy")
local have_potion_of_blood = is_in_inventory("potion of blood") or is_in_inventory("potions of blood")
local staff_of_energy_is_equipped = is_weapon("staff of energy")
local staff_of_power_is_equipped = is_weapon("staff of power")
local staff_of_energy_letter = find_item_letter("staff of energy")
local chunks_letter = find_item_letter("chunk")
local you_are_hungerless = you_are_mummy or lichform
local near_starving_or_worse = you_are_starving() or you_are_near_starving()
local no_food_issues = (you_are_hungerless or have_spare_chunks)
local should_channel_mp = (need_to_recover and (max_mp>mp) ) and no_food_issues
local can_cast_regen = known_spells["Regeneration"] and (mp>3) and (spells.fail("Regeneration") < 20)
local you_have_regen_ring = is_in_inventory("regeneration")
local regen_ring_letter = find_item_letter("regeneration")
local regen_ring_is_equipped = is_ring("regeneration")
local should_regen_hp = (not (you_are_good or you_are_regen or lichform)) and ((hp/max_hp) < 0.80) and (you_have_regen_ring or can_cast_regen) and not you_are_bloodless
local should_sublimate = (not (you_are_good or lichform)) and ((mp/max_mp) < 0.60) and you_know_sublimation and mp>2 and ((hp/max_hp) > 0.95)
local should_animate_skeleton = (not you_are_good) and you_know_animate_skeleton and mp>1 and (not can_not_animate())
local should_animate_dead = (not you_are_good) and you_know_animate_dead and mp>4 and (not can_not_animate())
local you_want_spare_chunks = (not (have_spare_chunks or you_do_not_eat)) and (can_cast_regen or you_have_staff_of_energy or you_are_sif)
local you_want_chunks = (not you_are_hungerless and (number_of_chunks() == 0) and (want_to_eat or you_want_spare_chunks)) or you_are_vampire or (you_are_ghoul and number_of_chunks() < 4)
-- (not melded_weapon) and
--crawl.mpr("(should_channel_mp and you_have_staff_of_energy and no_food_issues) = " .. tostring(should_channel_mp and you_have_staff_of_energy and no_food_issues))
--crawl.mpr("should_channel_mp="..tostring(should_channel_mp))
--crawl.mpr("you_have_staff_of_energy="..tostring(you_have_staff_of_energy))
--crawl.mpr("no_food_issues="..tostring(no_food_issues))
--crawl.mpr("need_to_recover="..tostring(need_to_recover))
--crawl.mpr("(max_mp>mp)="..tostring(max_mp>mp))
-- and (not (distort_weapon or vamp_weapon)) and you_are_not_felid() then
if you_are_barbed then
rest_once()
elseif should_sublimate and not (you_are_vampire or lichform) then
crawl.mpr("Autocasting Sublimation of Blood.")
sendkeys('zm')
--elseif should_channel_mp and you_are_sif and (you.piety_rank() > 0) then
-- crawl.mpr("Autochanneling using Sif.")
-- sendkeys('aa')
elseif should_regen_hp and can_cast_regen then
crawl.mpr("Autocasting Regen.")
--This assumes casting regen is bound to zr
sendkeys('zr')
elseif (not melded_weapon) and (should_channel_mp and you_have_staff_of_energy and no_food_issues) and (not (distort_weapon or vamp_weapon)) and you_are_not_felid() then
if not staff_of_energy_is_equipped then
crawl.mpr("Switching to staff of energy.")
auto_resting = true
sendkeys('w' .. staff_of_energy_letter )
else
crawl.mpr("Autochanneling using staff of energy.")
auto_resting = true
sendkeys('v')
end
elseif (weapon_in_slot_a() or uses_unarmed()) and
(no_weapon() and have_a_weapon) or (staff_of_energy_is_equipped and (not (staff_of_energy_letter == 'a')) or (chunks_are_equipped and (not (chunks_letter == 'a')))) then
if uses_unarmed() then
crawl.mpr("Switching to unarmed.")
sendkeys('w-')
else
crawl.mpr("Switching to main weapon.")
sendkeys('wa')
end
elseif want_to_eat and number_of_chunks() > 0 then
crawl.mpr("Autoeating chunks.")
sendkeys('e')
elseif you_want_chunks and on_corpses() and not on_chunks() and (not can_not_butcher()) then
if should_animate_skeleton then
crawl.mpr("Autocasting Animate Skeleton for chunks.")
sendkeys('zA')
else
crawl.mpr("Autochopping corpse.")
sendkeys("c")
return true -- JADO
end
--elseif you_want_chunks and (not (you_are_zin or need_to_recover or on_chunks() or on_corpses() or already_checked)) then
-- crawl.mpr("You may need something to eat soon, looking for food.")
-- find_corpses()
--elseif (you_are_starving() or you_are_near_starving()) and (number_of_chunks == 0) and (not (on_chunks() or on_corpses())) then
-- local have_bread = is_in_inventory("bread ration")
-- local have_meat = is_in_inventory("meat ration")
-- if have_bread or have_meat then
-- local result = crawl.yesnoquit("Eat a ration?", true, 'e')
-- if result == 1 and have_bread then
-- sendkeys('e1')
-- elseif result == 1 then
-- sendkeys('e2')
-- elseif result == 0 then
-- autoexplore()
-- end
-- if not (is_in_inventory("bread ration") or is_in_inventory("meat ration")) then
-- crawl.mpr("That was your last ration! You should go get more.")
-- end
-- else
-- crawl.mpr("No rations left! You should look for food.")
-- end
elseif need_to_recover and not you_are_starving() then
-- if you_are_bloodless and have_potion_of_blood then
-- crawl.mpr("Autoquaffing potion of blood.")
-- sendkeys('q1')
-- else
-- crawl.mpr("DEBUG: Doing normal rest")
rest_once()
-- end
--elseif you_are_yred and (you.piety_rank() >= 3) and (item_in_view("corpse") or item_in_view("skeleton") or on_corpses()) and not recently_mass_animated() then
-- crawl.mpr("Autocasting Mass Animate Remains.")
-- sendkeys('aa')
--elseif (not sacrifice_god) and (item_in_view("corpse") or item_in_view("skeleton") or on_corpses()) and should_animate_dead and not already_animated() then
-- crawl.mpr("Autocasting Animate Dead.")
-- sendkeys('zA')
--elseif (not sacrifice_god) and on_corpses() and should_animate_skeleton then
-- crawl.mpr("Autocasting Animate Skeleton.")
-- sendkeys('zA')
--elseif you_are_yred and (you.piety_rank() >= 1) and on_corpses() then
-- crawl.mpr("Autocasting Animate Remains.")
-- sendkeys('aa')
else
--crawl.mpr("DEBUG: return false - no rest")
return false -- No resting to be done
end
--crawl.mpr("DEBUG: return true - something done")
return true -- Rest was performed
end
}
# Other config
explore_wall_bias = 100
#################
# Online macros #
#################
bindkey = [^K] CMD_DISPLAY_RELIGION
#bindkey = [^D] CMD_DISPLAY_RELIGION
#spell_slot += mystic blast:b
#spell_slot += conjure flame:c
#spell_slot += dazzling spray:d
#spell_slog += regeneration:g
#spell_slot += haste:h
spell_slot += conjure ball lightning:L
# Key Mappings:
# +: auto rest
macros += K + ===auto_rest_start
# o: auto explore
macros += M \{-1013} ===StartLuthTravel
#F1 Enable automagic
macros += M \{-1011} ===enable_automagic
#F2 Disable automagic
macros += M \{-1012} ===disable_automagic
#F3 Show status
#macros += M \{-1013} ===xx
spell_slot ^= magic dart:a
macros += M \{-1018} zaf
macros += K2 \{-1018} f
#macros += M \{-1018} zA
spell_slot += searing ray:b
macros += M \{-1012} zb
macros += K2 \{-1012} f
#macros += M \{-1012} zB
#Numpad insert
macros += K \{-1000} .
macros += K2 \{-1000} .
#F10 Ozo
macros += M \{-274} zO
#F9
spell_slot += Iskenderun's Mystic Blast:i
macros += M \{-273} zi
macros += K2 \{-273} f
#F8
macros += M \{-272} zp
macros += K2 \{-272} f
spell_slot += fulminant prism:p
#F7
macros += M \{-271} zD
macros += K2 \{-27} f
#F6
macros += M \{-270} zC
macros += K2 \{-270} f
#F5 Fireball
spell_slot += Fireball:F
macros += M \{-269} zF
macros += K2 \{-269} f
#F4 Meph
macros += M \{-268} za
macros += K2 \{-268} f
spell_slot += .*:ABCDEFGHIJKLMNOPQRSTUVWXYZ