Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ##### 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
- # Alternative vi bindings for Dvorak users.
- # include = dvorak_command_keys.txt
- # Alternative vi bindings for Colemak users.
- # include = colemak_command_keys.txt
- # Alternative vi bindings for Neo users.
- # include = neo_command_keys.txt
- # Override the vi movement keys with a non-command.
- # include = no_vi_command_keys.txt
- # Turn the shift-vi keys into safe move, instead of run.
- # include = safe_move_shift.txt
- ##### Ancient versions ##############################################
- # If you're used to the interface of ancient versions of Crawl, you may
- # get back parts of it by uncommenting the following options:
- # include = 034_command_keys.txt
- # And to revert monster glyph and colouring changes:
- # include = 052_monster_glyphs.txt
- # include = 060_monster_glyphs.txt
- # include = 071_monster_glyphs.txt
- # include = 080_monster_glyphs.txt
- # include = 0.9_monster_glyphs.txt
- # include = 0.12_monster_glyphs.txt
- # include = 0.13_monster_glyphs.txt
- # include = 0.14_monster_glyphs.txt
- show_more = false
- # force_spell_targeter -= all
- simple_targeting = true
- macros += M 4 ===cast
- macros += M 3 ===cast_efficient
- macros += M 2 ===berder_test
- macros += M z z*
- macros += M Z Z*
- bindkey = [^D] CMD_LUA_CONSOLE
- # always_use_static_spell_targeters = true
- # casting spells
- # ignition, orbofdestruction, fireball, starburst
- : LOS = 7
- bindkey = [~] CMD_LUA_CONSOLE
- {
- function troll_fighter_set_skills()
- if you.race() == "Troll" and you.class() == "Fighter" then
- you.train_skill("Unarmed Combat", 2)
- you.set_training_target("Dodging",9.9)
- you.set_training_target("Fighting",19.9)
- you.set_training_target("Shields",16.6)
- you.set_training_target("Shapeshifting",23.3)
- -- you.set_training_target("Unarmed Combat",15)
- end
- end
- function ready()
- if you.turns() == 0 then
- troll_fighter_set_skills()
- end
- end
- local monster_array
- local flamewave_start_turn=0
- local flamewave_last_turn=0
- local monster_ac
- -- maps (spell name with optional modifier) .. x .. "," .. y to damage_value
- -- so we don't have to recalculate it
- local mondam_cache = {}
- local acmus2_cache = {}
- -- look at https://github.com/crawl/crawl/blob/0.31.0/crawl-ref/source/l-moninf.cc
- --
- -- c_persist is a persistent data store
- --
- -- TODO: fungus targeting issue (fireball)
- -- should continue flame wave if started even if high risk situation
- -- flame wave should have higher cost if we expect it to end early
- -- investigate nil value in cast_appropriate_spell
- -- for some reason crawl.do_commands({"CMD_WAIT"}) does not work for this
- -- nor does crawl.process_keys(".")
- function wait()
- crawl.sendkeys(".")
- crawl.process_command()
- end
- function berder_test()
- local messages = crawl.messages(100)
- crawl.mpr("#" .. view.feature_at(1,0))
- crawl.mpr(tostring(is_on_stairs()))
- crawl.mpr(you.contaminated())
- initialize_monster_array()
- update_monster_array()
- local x,y
- for x=-LOS,LOS do
- for y=-LOS,LOS do
- if valid_enemy(x, y) then
- local m = monster_array[x][y]
- crawl.mpr(m:name() .. "=" .. damage_value(1000, m))
- end
- end
- end
- -- crawl.mpr("danger:" .. danger())
- end
- function initialize_monster_array()
- monster_array = {}
- local x
- for x = -LOS-5,LOS+5 do
- monster_array[x] = {}
- end
- mondam_cache = {}
- end
- function update_monster_array()
- local x,y
- for x = -LOS,LOS do
- for y = -LOS,LOS do
- monster_array[x][y] = monster.get_monster_at(x, y)
- end
- end
- end
- local max_spellpower_table = {foxfire=25, shock=25, ["flame wave"]=100, ["stone arrow"]=50, scorch=50, ["poisonous vapours"]=50, ["iskenderun's mystic blast"]=100}
- function spellpower(spellname)
- local maxPower = 200
- local low_power = max_spellpower_table[spellname]
- if low_power ~= nil then
- maxPower = low_power
- end
- return spells.power_perc(spellname) * maxPower / 100.0
- end
- function can_target(x, y)
- return you.see_cell_no_trans(x, y)
- end
- function can_smite(x, y)
- return you.see_cell_no_trans(x, y) and not is_wall(x, y)
- end
- function valid_enemy(x, y)
- m = monster_array[x][y]
- if m ~= nil then
- return m and m:attitude() == 0 and you.see_cell_no_trans(x, y) and not m:is_firewood()
- end
- return false
- end
- function valid_enemy_explosion(m, x, y, x2, y2)
- return m and m:attitude() == 0 and not m:is_firewood() and view.cell_see_cell(x, y, x2, y2)
- end
- -- TODO account for: MP efficiency
- -- only account for MP efficiency if we're in MP conserving mode? not against dangerous enemies
- --
- -- accurate evasion calculations (difficult with the info given)
- -- accurate armor calculations (difficult with the info given)
- -- preferring to target close enemies
- -- instead of raw damage, look at something like (enemy danger level) * (damage dealt) / (enemy remaining HP + enemy max HP)
- -- so it rewards for hitting dangerous enemies, and rewards more for hitting dangerous enemies that are low on HP
- function spell_cost(spellname)
- if spellname == "flame wave" then
- if flamewave_turns() > 0 then
- return 1
- else
- return 2 -- because it will cost less later on and we probably won't just do 1 cast
- end
- end
- return spells.mana_cost(spellname)
- end
- -- a number indicating how urgent it is that we kill monsters quickly vs efficiently
- function danger()
- local x,y
- local danger=0
- -- any dangerous monsters within 2 squares?
- for x=-2,2 do
- for y=-2,2 do
- if valid_enemy(x, y) then
- local m = monster_array[x][y]
- if m:threat() >= 2 then
- danger = danger + m:threat()
- end
- end
- end
- end
- -- count dangerous monsters in LOS
- -- 3 make the overall situation dangerous
- for x=-7,7 do
- for y=-7,7 do
- if valid_enemy(x, y) then
- local m = monster_array[x][y]
- if m:threat() >= 2 then
- danger = danger + 0.7
- end
- end
- end
- end
- return danger
- end
- function cast()
- cast_appropriate_spell(false, false)
- end
- function cast_efficient()
- cast_appropriate_spell(true, false)
- end
- function cast_quiet()
- -- assuming we'd usually also like to be efficient, if we're being quiet
- cast_appropriate_spell(true, true)
- end
- -- argmax_x (f(x)) for x in t
- function table_max_by(t, f)
- if #t == 0 then
- return nil
- end
- local best = f(t[1])
- local bestIx = 1
- for i=1,#t do
- local value = f(t[i])
- if value > best then
- best = value
- bestIx = i
- end
- end
- return t[bestIx]
- end
- -- score a value_table entry by efficiency
- function efficiency(x, minDamage)
- local continuingFlameWave = (x == "flame wave" and flamewave_turns() > 0)
- if x[1] < minDamage and not continuingFlameWave then
- return 0 -- even if it's efficient we want to deal decent damage
- -- but don't interrupt an ongoing flame wave so much
- end
- return x[1] / spell_cost(x[2])
- end
- function cast_appropriate_spell(efficient, quiet)
- initialize_monster_array()
- update_monster_array()
- local value_table = {}
- table.insert(value_table, evaluate_ood()) -- targeting on this is a bit iffy
- table.insert(value_table, evaluate_starburst())
- table.insert(value_table, evaluate_foxfire())
- table.insert(value_table, evaluate_stonearrow())
- table.insert(value_table, evaluate_bombard())
- table.insert(value_table, evaluate_scorch())
- table.insert(value_table, evaluate_airstrike())
- table.insert(value_table, evaluate_shock())
- table.insert(value_table, evaluate_flamewave())
- table.insert(value_table, evaluate_irradiate())
- table.insert(value_table, evaluate_lcs())
- table.insert(value_table, evaluate_imb())
- if not quiet then
- table.insert(value_table, evaluate_fireball())
- table.insert(value_table, evaluate_ignition())
- table.insert(value_table, evaluate_firestorm())
- table.insert(value_table, evaluate_lrd())
- end
- if efficient then
- -- local totValue = total_damage_value()
- -- plan is
- local bestDmg = table_max_by(value_table, function (x) return x[1] end)[1]
- local bestEfficiency = table_max_by(value_table, function (x) return efficiency(x, bestDmg / 2) end)
- table.sort(value_table, function (k1, k2) return efficiency(k1, bestDmg / 2) < efficiency(k2, bestDmg / 2) end)
- else
- table.sort(value_table, function (k1, k2) return k1[1] < k2[1] end)
- end
- local best = value_table[#value_table]
- local i
- for i = 1,#value_table do
- -- crawl.mpr(value_table[i][2])
- -- bpr(value_table[i][1])
- -- bpr(value_table[i][1]/spell_cost(value_table[i][2]))
- -- bpr(value_table[i][3])
- -- bpr(value_table[i][4])
- if value_table[i][1] ~= 0 then
- crawl.mpr("(" .. value_table[i][2] .. "=" .. value_table[i][1] .. "|" .. value_table[i][1]/spell_cost(value_table[i][2]) .. "@" .. value_table[i][3] .. "," .. value_table[i][4] .. ")")
- end
- end
- if best[2] == "flame wave" then
- if flamewave_turns() > 0 then
- crawl.mpr("continuing flame wave")
- flamewave_last_turn = you.turns()
- wait()
- return
- end
- flamewave_start_turn = you.turns()
- flamewave_last_turn = you.turns()
- end
- if best[1] > 2 then
- if best[2] == "lee's rapid deconstruction" then
- cast_lrd(best[3], best[4])
- else
- spells.cast(best[2], best[3], best[4])
- end
- end
- end
- function resisted_damage(dmg, res)
- if res == 0 then
- return dmg
- end
- if res <= -1 then
- return dmg*1.5
- end
- if res == 1 then
- return dmg * 0.5
- end
- if res == 2 then
- return 0 -- don't even bother
- -- return dmg * 0.2
- end
- if res == 3 then
- return 0
- end
- return 0
- end
- function guess_ac(m)
- local ac_pips = m:ac()
- -- pips is ceil(mi->ac/5.0) from l-moninfo.cc
- if ac_pips == 0 then
- return 0
- end
- if monster_ac[m:name()] ~= nil then
- if math.ceil(monster_ac[m:name()] / 5.0) == ac_pips then
- return monster_ac[m:name()]
- end
- end
- return 2.5 + (ac_pips - 1) * 5
- end
- -- damage against ac assuming damage is uniformly chosen between 0 and dam
- function ac_damage_linear(dam, m)
- local ac = guess_ac(m)
- local mad = min(ac, dam)
- local numerator = mad * dam*dam*0.5 - mad*mad*dam*0.5 + mad*mad*mad/6.0
- local denom = dam*dam*0.5*ac
- return dam * numerator / denom
- end
- -- sum vectors
- function sv(v1, v2)
- local v3, i
- for i=1,#v1 do
- v3[i] = v1[i] + v2[i]
- end
- return v3
- end
- -- a number indicating how important it is to deal dmg damage to this enemy
- -- TODO: being close increases danger
- -- TODO: certain enemy types can be prioritized: floating eyes are always max danger
- -- shining eyes, ghost moths
- function damage_value(spell_context, dmg, m, kill_bonus)
- if m == nil then
- crawl.mpr("nil m in damage value")
- end
- local mhp = string.gsub(m:max_hp(), "about ", "")
- mhp = string.gsub(mhp, "~", "")
- mhp = tonumber(mhp)
- local hp = mhp * (6 - m:damage_level())/6.0 + 1
- local kill_value = m:threat() + 1
- if dmg > hp * 1.2 then
- dmg = hp * 2
- end
- local multiplier = 100
- if summoned_monster(m) then
- multiplier = 20
- end
- if m:is_safe() then
- multiplier = 10
- end
- local result = (dmg * kill_value / hp + dmg * kill_value / mhp) * multiplier
- if spell_context ~= nil then
- mondam_cache[spell_context .. "|" .. m:x_pos() .. "," .. m:y_pos()] = result
- end
- return result
- end
- function total_damage_value()
- local x,y
- local totValue = 0
- for x=-LOS,LOS do
- for y=-LOS,LOS do
- if valid_enemy(x, y) then
- totValue = totValue + damage_value(nil, 10000, monster_array[x][y])
- end
- end
- end
- return totValue
- end
- -- NdM damage against ac
- -- guess ac based on monster
- function ac_damage_NdM(N, M, m)
- local ac = guess_ac(m)
- return ac_damage_NdM_ac(N, M, ac)
- end
- -- NdM damage against ac
- -- specify ac
- function ac_damage_NdM_ac(N, M, ac)
- local var_NdM = N * (M^2 - 1) / 12.0
- local mean_NdM = N * (M + 1) / 2.0
- return ac_damage_mus2(mean_NdM, var_NdM, ac)
- end
- -- AC damage if the damage is normally approximated with mean mu
- -- and variance s2
- function ac_damage_mus2(mu, s2, ac)
- local cached = acmus2_cache[mu .. "," .. s2 .. "," .. ac]
- if cached then
- return cached
- end
- -- we'll crudely model this with ((3d2) + A) * B
- -- such that it has the same mean and variance
- -- mean of ((3d2) + A)*B is
- -- (3*3/2 + A) * B = mu
- -- var of ((3d2) + A)*B is
- -- B*B*3*(2*2-1)/12 = s2
- local B = math.sqrt(s2/0.75)
- local A = mu / B - 3 * 3 / 2
- local i, j, k, a
- local tdam = 0
- for i=1,2 do
- for j=1,2 do
- for k=1,2 do
- local d = ((i + j + k) + A) * B
- if d > ac then
- -- (sum_a=0^ac d-a) / (ac+1)
- -- = (sum_a=0^ac d - sum_a=0^ac a) / (ac+1)
- -- = (d(ac+1) - ac(ac+1)/2) / (ac+1)
- -- = d - ac/2
- tdam = tdam + d - ac/2
- else
- -- (sum_a=0^d d-a) / (ac+1) + (sum_a=d+1^ac 0) / (ac + 1)
- -- = ((sum_a=0^d d) - (sum_a=0^d a))/(ac+1)
- -- = (d(d+1) - d(d+1)/2)/(ac+1)
- tdam = tdam + (d*(d+1)/2) / (ac+1)
- end
- -- for a=0,ac do
- -- local d =
- -- if d > a then
- -- tdam = tdam + d - a
- -- end
- -- end
- end
- end
- end
- local result = tdam / (2*2*2)
- acmus2_cache[mu .. "," .. s2 .. "," .. ac] = result
- return result
- end
- -- just ask if it has a shield or not
- -- can't be bothered to figure out the actual sh value
- -- (though it would be possible based on monster HD and shield description)
- -- if it has a shield just assume 50% block chance
- function sh_damage(dmg, m)
- local d = m:target_desc()
- -- could be a buckler but then it probably wouldn't be 50% block chance so w/e
- local has_shield = string.find(d, "shield")
- if has_shield then
- return dmg * 0.5
- end
- return dmg
- end
- function summoned_monster(m)
- local d = m:target_desc()
- if string.find(d, "summoned") then
- return true
- end
- return false
- end
- -- a friendly monster that isn't you
- function friendly_at(x, y)
- local m = monster_array[x][y]
- if m ~= nil then
- if m:attitude() > 0 then
- return true -- neutral or friendly monster
- end
- end
- return false
- end
- -- is this beam blocked by an obstacle, so that we'd get an error if we tried to target?
- function blocked_beam(path)
- local i
- for i=1,#path do
- if firewood_at(path[i][1], path[i][2]) then
- return true
- end
- end
- return false
- end
- -- a monster that blocks targeting for fireball
- function firewood_at(x, y)
- local m = monster_array[x][y]
- if m ~= nil then
- return m:is_firewood()
- -- local name = m:name()
- -- if name == "plant" or name == "demonic plant" or name == "withered plant" or name == "fungus" then
- -- return true
- -- end
- end
- return false
- end
- function fireball_damage_at_target(x, y, N, M, avoidPlayer)
- local totDmg = 0
- -- 3d(3.33+Power/6)
- local x2, y2
- for x2 = -1, 1 do
- for y2 = -1, 1 do
- local m = monster_array[x+x2][y+y2]
- if valid_enemy_explosion(m, x+x2, y+y2, x, y) then
- local dmg = mondam_cache["fireball|" .. x .. "," .. y] or damage_value("fireball", resisted_damage(ac_damage_NdM(N, M, m), m:res_fire()), m)
- crawl.mpr("fireball" .. m:name() .. resisted_damage(ac_damage_NdM(N, M, m), m:res_fire()))
- totDmg = totDmg + dmg
- elseif not you.see_cell(x+x2, y+y2) then
- totDmg = totDmg + 0.1 -- just slightly prefer to hit out of sight tiles, in case they have enemies
- elseif avoidPlayer and x+x2 == 0 and y+y2 == 0 then
- return 0 -- don't hit yourself
- elseif friendly_at(x+x2, y+y2) then
- return 0
- end
- end
- end
- return totDmg
- end
- function castable(spellname)
- if not spells.memorised(spellname) then
- return false
- end
- if spells.fail(spellname) > 14 then
- return false
- end
- if you.mp() < spells.level(spellname) then
- return false
- end
- if spells.fail_severity(spellname) > 2 then
- return false
- end
- return true
- end
- function evaluate_fireball()
- if not castable("fireball") then
- return {0, "fireball", 0, 0}
- end
- local bestX = 0
- local bestY = 0
- local bestDmg = 0
- local range = spells.max_range("fireball")
- local x, y
- local N = 3
- local M = 3.33 + spellpower("fireball")/6
- for x = -range,range do
- for y = -range,range do
- if can_target(x, y) then
- local path = spells.path("fireball",x,y)
- if not blocked_beam(path) then
- local x2 = path[#path][1]
- local y2 = path[#path][2]
- local dmg = fireball_damage_at_target(x2, y2, N, M, true)
- if dmg > bestDmg then
- bestDmg = dmg
- bestX = x
- bestY = y
- end
- end
- end
- end
- end
- return {bestDmg * (1 - spells.fail("fireball")/100.0), "fireball", bestX, bestY}
- end
- function evasion_check(m, spellname)
- local s = m:target_spell(spellname)
- local i, j = string.find(s, "%% to hit")
- if i ~= nil then
- local pct = string.sub(s, i-3, i-1)
- if tonumber(pct) == nil then
- pct = string.sub(s, i-2, i-1)
- end
- return tonumber(pct) * 0.01
- end
- return 1.0
- end
- function evaluate_starburst()
- if not castable("starburst") then
- return {0, "starburst", 0, 0}
- end
- local totDmg = 0
- -- 6d(3+Power/9)
- local N = 6
- local M = 3 + spellpower("starburst")/9
- local range = spells.max_range("starburst")
- local ranges = {}
- local x, y
- for x=-1,1 do
- ranges[x] = {}
- for y=-1,1 do
- ranges[x][y] = range
- end
- end
- for R = 1,LOS do
- for x=-1,1 do
- for y=-1,1 do
- if x ~= 0 or y ~= 0 then
- local m = monster_array[R*x][R*y]
- if m ~= nil and valid_enemy(R*x, R*y) and ranges[x][y] >= R then
- local dmg = ac_damage_NdM(N, M, m)
- dmg = damage_value(nil, resisted_damage(dmg, m:res_fire()), m)
- dmg = dmg * evasion_check(m, "starburst")
- totDmg = totDmg + dmg
- ranges[x][y] = ranges[x][y] - 1
- end
- end
- end
- end
- end
- return {totDmg * (1 - spells.fail("starburst")/100.0), "starburst", 0, 0}
- end
- function is_on_stairs()
- if string.find(view.feature_at(0,0), "stairs") then
- return true
- end
- return false
- end
- function is_wall(x, y)
- return travel.feature_solid(view.feature_at(x, y))
- end
- -- TODO track whether the target already has an OOD en route that is likely to kill them, and don't shoot a second
- function ood_damage_at_target(x, y, m)
- -- if dist < 4
- -- 9d((60*dist*3/10 + pow*dist*3/10)/12)
- -- 9d((5 + pow/12) * dist * 3/10)
- --
- -- if dist >= 4, 9d(5 + pow/12)
- -- 9d(5 + Power/12)
- local dist = math.max(math.abs(x), math.abs(y))
- if dist > 3 then
- dist = dist - 1 -- assume enemy will take a step forward before being hit
- end
- local N = 9
- local M = 5 + spellpower("orb of destruction") / 12
- if dist < 4 then
- M = M * dist * 0.3
- end
- local baseDamage = damage_value(nil, ac_damage_NdM(N, M, m), m)
- baseDamage = sh_damage(baseDamage, m)
- baseDamage = baseDamage * (1 - spells.fail("orb of destruction")/100.0)
- local x2, y2
- local xstart, ystart
- local xend, yend
- xstart = 1
- ystart = 1
- xend = x
- yend = y
- if math.abs(x) < math.abs(y) then
- xstart = 0
- end
- if math.abs(y) < math.abs(x) then
- ystart = 0
- end
- if x < 0 then
- xend = -xstart
- xstart = x
- end
- if y < 0 then
- yend = -ystart
- ystart = y
- end
- for x2=xstart,xend do
- for y2=ystart,yend do
- if is_wall(x2, y2) or ((x2 ~= x or y2 ~= y) and monster_array[x2][y2]) then
- return 0
- end
- end
- end
- if x == 0 then
- for x2=-1,1 do
- for y2=ystart,yend do
- if is_wall(x2, y2) or ((x2 ~= x or y2 ~= y) and monster_array[x2][y2]) then
- baseDamage = baseDamage * 0.5
- end
- end
- end
- end
- return baseDamage
- end
- function evaluate_ood()
- if not castable("orb of destruction") then
- return {0, "orb of destruction", 0, 0}
- end
- -- first check if there's an ood adjacent, and don't shoot if so
- local x1, y1
- for x1=-1,1 do
- for y1=-1,1 do
- local m = monster_array[x1][y1]
- if m and m:name() == "orb of destruction" then
- return {0, "orb of destruction", 0, 0}
- end
- end
- end
- local bestDmg=0
- local bestX=0
- local bestY=0
- local x, y
- for x=-LOS,LOS do
- for y=-LOS,LOS do
- local m = monster_array[x][y]
- -- todo monster shields
- if m and m:attitude() == 0 and you.see_cell_solid_see(x, y) then
- local dmg = ood_damage_at_target(x, y, m)
- if dmg > bestDmg then
- bestX = x
- bestY = y
- bestDmg = dmg
- end
- end
- end
- end
- return {bestDmg, "orb of destruction", bestX, bestY}
- end
- function evaluate_ignition()
- if not castable("ignition") then
- return {0, "ignition", 0, 0}
- end
- local totDmg=0
- -- 3d(3.33+Power/9)
- local N = 3
- local M = 3.33 + spellpower("ignition") / 9
- local x, y
- for x=-LOS,LOS do
- for y=-LOS,LOS do
- local m = monster_array[x][y]
- if valid_enemy(x, y) then
- local dmg = fireball_damage_at_target(x, y, N, M, false)
- totDmg = totDmg + dmg
- end
- end
- end
- return {totDmg * (1 - spells.fail("ignition")/100.0), "ignition", 0, 0}
- end
- function flame_cloud_damage(m)
- -- (2d16)/2 + 5
- -- var_NdM = N * (M^2 - 1) / 12.0
- -- mean_NdM = N * (M + 1) / 2.0
- local mu = (2 * (16 + 1) / 2) / 2 + 5
- local s2 = (2 * (16*16 - 1) / 12) / 4
- return resisted_damage(ac_damage_mus2(mu, s2, guess_ac(m)), m:res_fire())
- end
- function firestorm_damage_at_target(x, y, N, M)
- local totDmg = 0
- local x2, y2
- local pow = spellpower("fire storm")
- for x2 = -3, 3 do
- for y2 = -3, 3 do
- local m = monster_array[x+x2][y+y2]
- if valid_enemy_explosion(m, x+x2, y+y2, x, y) and view.cell_see_cell(x, y, x+x2, y+y2) then
- local dmg = mondam_cache["firestorm|" .. (x+x2) .. "," .. (y+y2)]
- if dmg == nil then
- dmg = ac_damage_NdM(N, M, m)
- dmg = resisted_damage(dmg*0.55, m:res_fire()) + dmg * 0.45
- local cloudDmg = flame_cloud_damage(m) * 2 -- assume it stays in the cloud for 2 turns
- -- crawl.mpr("firestorm " .. m:name() .. dmg + cloudDmg)
- dmg = damage_value("firestorm", dmg + cloudDmg, m)
- end
- if math.abs(x2) == 3 or math.abs(y2) == 3 then
- dmg = dmg * pow / 1000.0 -- chance of larger firestorm radius
- end
- totDmg = totDmg + dmg
- elseif math.abs(y2) <= 2 and math.abs(x2) <= 2 and not you.see_cell(x+x2, y+y2) and (view.cell_see_cell(x, y, x+x2, y+y2) or math.abs(x+x2) > LOS or math.abs(y+y2) > LOS) then
- totDmg = totDmg + 0.1 -- just slightly prefer to hit cells out of sight
- elseif math.abs(y2) <= 2 and math.abs(x2) <= 2 and is_wall(x+x2, y+y2) then
- totDmg = totDmg - 0.01 -- all other things equal, prefer to hit an open space
- end
- end
- end
- return totDmg
- end
- function evaluate_firestorm()
- if not castable("fire storm") then
- return {0, "fire storm uncastable", 0, 0}
- end
- local bestX = 0
- local bestY = 0
- local bestDmg = 0
- -- 8d(0.625+Power/8)
- local N = 8
- local M = 0.625 + spellpower("fire storm")/8
- -- also creates clouds
- local range = spells.max_range("fire storm")
- local x, y
- for x = -range,range do
- for y = -range,range do
- if (math.abs(x) > 3 or math.abs(y) > 3) and can_smite(x, y) then
- local dmg = firestorm_damage_at_target(x, y, N, M)
- -- bpr("firestorm at " .. tostring(x) .. tostring(y) .. " dmg" .. tostring(dmg))
- if dmg > bestDmg then
- bestDmg = dmg
- bestX = x
- bestY = y
- end
- end
- end
- end
- return {bestDmg * (1 - spells.fail("fire storm")/100.0), "fire storm", bestX, bestY}
- end
- function evaluate_foxfire()
- if not castable("foxfire") then
- return {0, "foxfire", 0, 0}
- end
- -- 2 * 1d(4+ Power/5)
- local N = 2
- local M = 4 + spellpower("foxfire")/5.0
- local dmg = 0
- local bestDmg = 0
- local closest = LOS
- for x=-LOS,LOS do
- for y=-LOS,LOS do
- if valid_enemy(x, y) then
- local m = monster_array[x][y]
- local r = math.max(math.abs(x), math.abs(y))
- dmg = damage_value(nil, resisted_damage(N*ac_damage_NdM(1, M, m), m:res_fire()), m)
- if r <= closest then
- bestDmg = dmg
- closest = r
- end
- end
- end
- end
- bestDmg = bestDmg * (1 - spells.fail("foxfire")/100.0)
- local freeCount = 0
- for x=-1,1 do
- for y=-1,1 do
- if (x ~= 0 or y ~= 0) and not is_wall(x, y) and not monster_array[x][y] then
- freeCount = freeCount + 1
- end
- end
- end
- if freeCount == 0 then
- return {0, "foxfire", 0, 0}
- end
- if freeCount == 1 then
- return {bestDmg / 4.0, "foxfire", 0, 0}
- end
- if freeCount == 2 then
- return {bestDmg / 2.0, "foxfire", 0, 0}
- end
- return {bestDmg, "foxfire", 0, 0}
- end
- -- Wave status: Wave, Wave+, Wave++, Wave+++
- -- this is not available to lua directly but we can scrape the message buffer
- -- When we cast flamewave, and each turn we maintain it, it says:
- -- "A wave of flame ripples out!"
- -- The first time we cast it, it says:
- -- "(Press . to intensify the flame waves.)"
- -- it ends if we are trampled, blinked, dispersal trap'd, or teleported
- -- "You blink"
- -- also it ends if we cast a spell, take a step, hit with a melee weapon, change jewellery, etc
- function flamewave_turns()
- if flamewave_last_turn ~= you.turns() - 1 then
- return 0
- end
- local messages = crawl.messages(100)
- -- delete messages up to the last cast of flame wave
- messages = string.gsub(messages, ".*A wave of flame ripples out!", "")
- if string.find(messages, "You blink") then
- return 0
- end
- if string.find(messages, "Your surroundings") then -- teleported
- return 0
- end
- if string.find(messages, "stumble backwards") then
- return 0
- end
- if string.find(messages, "drags you backwards") then
- return 0
- end
- if string.find(messages, "You miscast Flame Wave") then
- return 0
- end
- if you.turns() - flamewave_start_turn < spells.max_range("flame wave") then
- return you.turns() - flamewave_start_turn
- end
- return 0
- end
- -- local messages = crawl.messages(100)
- function evaluate_flamewave()
- local flame_range = flamewave_turns() + 1
- if flame_range == 1 and not castable("flame wave") then
- return {0, "flame wave", 0, 0}
- end
- if flame_range > 1 and you.mp() < 1 then
- return {0, "flame wave", 0, 0}
- end
- -- 2d(4.5+Power/6)
- local N = 2
- local M = 4.5 + spellpower("flame wave")/6
- local totDmg = 0
- for x=-flame_range,flame_range do
- for y=-flame_range,flame_range do
- if valid_enemy(x, y) then
- local m = monster_array[x][y]
- local dmg = damage_value(nil, resisted_damage(ac_damage_NdM(N, M, m), m:res_fire()), m)
- totDmg = totDmg + dmg
- end
- end
- end
- return {totDmg * (1 - spells.fail("flame wave")/100.0), "flame wave", 0, 0}
- end
- function evaluate_arrow(spellname, N, M)
- if not castable(spellname) then
- return {0, spellname, 0, 0}
- end
- local range = spells.max_range(spellname)
- local x, y
- local bestDmg = 0
- local bestX = 0
- local bestY = 0
- for x = -range,range do
- for y = -range,range do
- if can_target(x, y) then
- local path = spells.path(spellname,x,y)
- if not blocked_beam(path) then
- local cell
- local totDmg = 0
- local reachChance = 1.0
- for cell = 1,#path do
- local x2, y2
- x2 = path[cell][1]
- y2 = path[cell][2]
- local m = monster_array[x2][y2]
- if valid_enemy(x2, y2) and totDmg ~= -1 then
- local hitChance = evasion_check(m, spellname)
- local dmg = mondam_cache[spellname .. "|" .. x2 .. "," .. y2] or damage_value(spellname, ac_damage_NdM(N, M, m), m)
- dmg = sh_damage(dmg * reachChance * hitChance, m)
- reachChance = reachChance * (1 - hitChance)
- totDmg = totDmg + dmg
- elseif m then -- non-enemy monster in the way
- totDmg = -1
- end
- end
- if totDmg > bestDmg then
- bestDmg = totDmg
- bestX = x
- bestY = y
- end
- end
- end
- end
- end
- return {bestDmg * (1 - spells.fail(spellname)/100.0), spellname, bestX, bestY}
- end
- function evaluate_stonearrow()
- -- 3d(7+power/8)
- local N = 3
- local M = 7 + spellpower("stone arrow")/8
- return evaluate_arrow("stone arrow", N, M)
- end
- function evaluate_lcs()
- -- 10d(2.3 + power/10)
- local N = 10
- local M = 2.3 + spellpower("lehudib's crystal spear")/10
- return evaluate_arrow("lehudib's crystal spear", N, M)
- end
- function evaluate_bombard()
- -- 9d(1.44+Power/13)
- if is_on_stairs() then
- -- don't bombard ourselves off the stairs!
- return {0, "bombard", 0, 0}
- end
- local N = 9
- local M = 1.44 + spellpower("bombard")/13
- return evaluate_arrow("bombard", N, M)
- end
- -- callable from a macro if you want, ===maybe_cast_lrd
- function maybe_cast_lrd()
- initialize_monster_array()
- update_monster_array()
- local eval = evaluate_lrd()
- if eval[1] == 0 then
- return
- end
- cast_lrd(eval[3], eval[4])
- end
- -- returns number of dice and explosion radius, and whether it's ice. see spl-damage.cc
- function lrd_dice_terrain(feature)
- feature = string.lower(feature)
- if string.find(feature, "stair") then
- return {0, 0, false}
- end
- local featuresRock = {"stone", "rock", "door", "slimy_wall", "petrified", "statue"}
- local featuresMetal = {"metal", "iron"}
- local featuresCrystal = {"crystal"}
- local i
- for i = 1,#featuresRock do
- if string.find(feature, featuresRock[i]) then
- return {3, 1, false}
- end
- end
- for i = 1,#featuresMetal do
- if string.find(feature, featuresMetal[i]) then
- return {4, 1, false}
- end
- end
- for i = 1,#featuresCrystal do
- if string.find(feature, featuresCrystal[i]) then
- return {4, 2, false}
- end
- end
- return {0, 0, false}
- end
- -- number of dice, radius, and whether it's ice. see mon-data.cc and spl-damage.cc
- function lrd_dice_monster(monster)
- monster = string.lower(monster)
- local monstersMetal = {"iron golem", "iron elemental", "peacekeeper", "war gargoyle"}
- local monstersIce = {"ice beast", "simula", "ice statue"}
- local monstersRockBone = {"toenail", "earth elemental", "saltling", "ushabti", "statue", "gargoyle", "skelet", "bone", "ancient champion", "revenant", "skull", "Murray", "rockslime"}
- local monstersCrystal = {"orange statue", "crystal", "obsidian", "roxanne", "glass eye"}
- -- check metal first because of war gargoyle/gargoyle
- for i = 1,#monstersMetal do
- if string.find(monster, monstersMetal[i]) then
- return {4, 1, false}
- end
- end
- for i = 1,#monstersCrystal do
- if string.find(monster, monstersCrystal[i]) then
- return {4, 2, false}
- end
- end
- for i = 1,#monstersRockBone do
- if string.find(monster, monstersRockBone[i]) then
- return {3, 1, false}
- end
- end
- for i = 1,#monstersIce do
- if string.find(monster, monstersIce[i]) then
- return {3, 1, true}
- end
- end
- return {0, 0, false}
- end
- function lrd_damage_at_target(x, y, dmgPerDice, dice, radius, fromMonster, fromIce)
- local x2, y2
- local totDmg = 0
- for x2 = -radius,radius do
- for y2 = -radius,radius do
- local m = monster_array[x+x2][y+y2]
- if valid_enemy(x+x2, y+y2) then
- if x2 == 0 and y2 == 0 and fromMonster then
- totDmg = totDmg + damage_value(nil, dmgPerDice * dice, m)
- elseif not fromIce then
- totDmg = totDmg + damage_value(nil, ac_damage_NdM_ac(dice, dmgPerDice, guess_ac(m)*3), m)
- else
- totDmg = totDmg + damage_value(nil, resisted_damage(ac_damage_NdM_ac(dice, dmgPerDice, guess_ac(m)), m:res_cold()), m)
- end
- elseif friendly_at(x+x2, y+y2) then
- return 0 -- don't hit neutrals, even unfriendly ones.
- elseif x+x2 == 0 and y+y2 == 0 then
- return 0 -- don't hit the player
- end
- end
- end
- return totDmg
- end
- function evaluate_lrd()
- if not castable("lee's rapid deconstruction") then
- return {0, "lee's rapid deconstruction", 0, 0}
- end
- local dmgPerDice = math.floor(5 + spellpower("lee's rapid deconstruction")/5.0)
- local bestX = 0
- local bestY = 0
- local bestDmg = 0
- local range = spells.max_range("lee's rapid deconstruction")
- local x, y
- for x = -range,range do
- for y = -range,range do
- if you.see_cell_solid_see(x, y) then
- local feature = view.feature_at(x, y)
- local lrdDice = {0, 0}
- local m = monster_array[x][y]
- local fromMonster = false
- if m then
- lrdDice = lrd_dice_monster(m:name())
- end
- if lrdDice[1] == 0 then
- lrdDice = lrd_dice_terrain(feature)
- else
- fromMonster = true
- end
- if lrdDice[1] ~= 0 then
- local dmg = lrd_damage_at_target(x, y, dmgPerDice, lrdDice[1], lrdDice[2], fromMonster, lrdDice[3])
- if dmg > bestDmg then
- bestDmg = dmg
- bestX = x
- bestY = y
- end
- end
- end
- end
- end
- return {bestDmg * (1 - spells.fail("lee's rapid deconstruction")/100.0), "lee's rapid deconstruction", bestX, bestY}
- end
- -- for some reason lrd can't be cast with spells.cast
- -- so this is a workaround
- function cast_lrd(x, y)
- local cmdStr = "Z" .. spells.letter("lee's rapid deconstruction") .. "r"
- local x2, y2
- if x < 0 then
- for x2 = x,-1 do
- cmdStr = cmdStr .. "h"
- end
- elseif x > 0 then
- for x2 = 1,x do
- cmdStr = cmdStr .. "l"
- end
- end
- if y < 0 then
- for y2 = y,-1 do
- cmdStr = cmdStr .. "k"
- end
- elseif y > 0 then
- for y2 = 1,y do
- cmdStr = cmdStr .. "j"
- end
- end
- cmdStr = cmdStr .. "."
- crawl.process_keys(cmdStr)
- end
- function evaluate_scorch()
- if not castable("scorch") then
- return {0, "scorch", 0, 0}
- end
- -- 2d(5+Power/10)
- local N = 2
- local M = 5 + spellpower("scorch")/10
- local range = spells.range("scorch")
- local x, y
- local totDmg = 0
- local numEnemies = 0
- for x=-range,range do
- for y=-range,range do
- local m = monster_array[x][y]
- if valid_enemy(x, y) then
- totDmg = totDmg + damage_value(nil, resisted_damage(ac_damage_NdM(N, M, m), m:res_fire()), m)
- numEnemies = numEnemies + 1
- end
- end
- end
- if numEnemies == 0 then
- return {0, "scorch", 0, 0}
- end
- -- too many enemies in range isn't good because it hits randomly
- if numEnemies > 2 then
- return {0.5 * totDmg / numEnemies, "scorch", 0, 0}
- end
- return {totDmg / numEnemies * (1 - spells.fail("scorch")/100.0), "scorch", 0, 0}
- end
- function count_empty_spaces(x, y)
- local x2, y2
- local emptyCount = 0
- for x2=-1,1 do
- for y2=-1,1 do
- if not is_wall(x+x2, y+y2) and not monster_array[x+x2][y+y2] then
- emptyCount = emptyCount + 1
- end
- end
- end
- return emptyCount
- end
- function evaluate_airstrike()
- if not castable("airstrike") then
- return {0, "airstrike", 0, 0}
- end
- -- 2d([power + 13]/14 + 2m) where m = empty spaces
- local N = 2
- local M = (spellpower("airstrike") + 13)/14 -- + 2m
- local bestX=0
- local bestY=0
- local bestDmg = 0
- local x, y
- for x=-LOS,LOS do
- for y=-LOS,LOS do
- local m = monster_array[x][y]
- if valid_enemy(x, y) and can_smite(x, y) then
- local dmg = damage_value(nil, ac_damage_NdM(N, M + 2 * count_empty_spaces(x, y), m), m)
- if dmg > bestDmg then
- bestDmg = dmg
- bestX = x
- bestY = y
- end
- end
- end
- end
- return {bestDmg * (1 - spells.fail("airstrike")/100.0), "airstrike", bestX, bestY}
- end
- -- TODO account for bounces
- function evaluate_shock()
- if not castable("shock") then
- return {0, "shock", 0, 0}
- end
- -- 1d(3+power/4)
- local N = 1
- local M = 3 + spellpower("shock")/4
- local range = spells.max_range("shock")
- local x, y
- local bestDmg = 0
- local bestX = 0
- local bestY = 0
- for x = -range,range do
- for y = -range,range do
- if can_target(x, y) then
- local path = spells.path("shock",x,y)
- local cell
- local totDmg = 0
- for cell = 1,#path do
- local x2, y2
- x2 = path[cell][1]
- y2 = path[cell][2]
- local m = monster_array[x2][y2]
- if valid_enemy(x2, y2) and totDmg ~= -1 then
- local dmg = mondam_cache["shock|" .. x2 .. "," .. y2] or damage_value("shock", resisted_damage(ac_damage_NdM_ac(N, M, guess_ac(m)/2), m:res_shock()), m) * evasion_check(m, "shock")
- totDmg = totDmg + dmg
- elseif friendly_at(x2, y2) then -- friend monster in the way
- totDmg = -1
- end
- end
- if totDmg > bestDmg then
- bestDmg = totDmg
- bestX = x
- bestY = y
- end
- end
- end
- end
- return {bestDmg * (1 - spells.fail("shock")/100.0), "shock", bestX, bestY}
- end
- function evaluate_irradiate()
- if not castable("irradiate") then
- return {0, "irradiate", 0, 0}
- end
- if you.contaminated() > 1 then -- another cast of this might give yellow contam
- return {0, "irradiate", 0, 0}
- end
- -- 3d(11.66 + power/6)
- local N = 3
- -- +10 because the malmutate status is worth something
- local M = 11.66 + spellpower("irradiate")/6 + 10
- local totDmg = 0
- local totEnemyThreat = 0
- for x=-1,1 do
- for y=-1,1 do
- if valid_enemy(x, y) then
- local m = monster_array[x][y]
- totDmg = totDmg + damage_value(nil, ac_damage_NdM(N, M, m), m)
- totEnemyThreat = totEnemyThreat + m:threat()
- end
- end
- end
- if totEnemyThreat < 3 and you.mp() > 10 then
- -- don't cast irradiate without a good reason, i.e. multiple dangerous adjacent enemies or low on mp
- return {0, "irradiate", 0, 0}
- end
- return {totDmg * (1 - spells.fail("irradiate")/100.0), "irradiate", 0, 0}
- end
- function evaluate_imb()
- if not castable("iskenderun's mystic blast") then
- return {0, "iskenderun's mystic blast", 0, 0}
- end
- -- 3d(11.66 + power/6)
- local N = 2
- local M = 3 + spellpower("iskenderun's mystic blast")/6
- local range = spells.range("iskenderun's mystic blast")
- local totDmg = 0
- local totEnemyThreat = 0
- for x=-range,range do
- for y=-range,range do
- if valid_enemy(x, y) then
- local m = monster_array[x][y]
- totDmg = totDmg + damage_value(nil, ac_damage_NdM(N, M, m), m)
- end
- end
- end
- return {totDmg * (1 - spells.fail("iskenderun's mystic blast")/100.0), "iskenderun's mystic blast", 0, 0}
- end
- -- function evaluate_poisonousvapours()
- -- if not castable("poisonous vapours") then
- -- return {0, "poisonous vapours", 0, 0}
- -- end
- -- -- there isn't a specific damage formula for poisonous vapours
- -- -- we'll begin by assuming it is similar in value to scorch
- -- -- (below is the damage formula for scorch)
- -- local dmgPerHit = 2 * 0.5 * math.floor(6 + spellpower("poisonous vapours")/10.0)
- -- -- targeting: we only want to target non-poison-resistant creatures
- -- -- that are not already maximally poisoned
- -- -- giving priority to the monster that is currently the most poisoned
- -- -- and breaking ties going to the most dangerous monster
- -- -- status() can be "poisoned", "very poisoned", "extremely poisoned"
- -- local bestDmg = 0
- -- local bestX, bestY
- -- local x, y
- -- local range = spells.max_range("poisonous vapours")
- -- for x=-range,range do
- -- for y=-range,range do
- -- local m = monster_array[x][y]
- -- if m and m:res_poison() <= 0 and not m:status("extremely poisoned") then
- -- local dmg = damage_value(nil, dmgPerHit, m)
- -- if m:threat() < 2 then
- -- dmg = dmg * 0.5
- -- elseif m:threat() > 3 then
- -- dmg = dmg * 1.5
- -- end
- -- if m:status("very poisoned") then
- -- dmg = dmg * 1.1
- -- elseif m:status("poisoned") then
- -- dmg = dmg * 1.05
- -- end
- -- if dmg > bestDmg then
- -- bestDmg = dmg
- -- bestX = x
- -- bestY = y
- -- end
- -- end
- -- end
- -- end
- -- return {bestDmg, "poisonous vapours", bestX, bestY}
- -- end
- function bpr(message)
- crawl.mpr(tostring(message))
- end
- monster_ac = {["adder"] = 1 ,["jelly"] = 0 ,["Tiamat"] = 30 ,["Sonja"] = 2 ,["jumping spider"] = 6 ,["spatial vortex"] = 0 ,["formicid"] = 3 ,["queen bee"] = 10 ,["acid dragon"] = 5 ,["rime drake"] = 3 ,["dwarf"] = 2 ,["centaur"] = 3 ,["orb of destruction"] = 0 ,["deep elf zephyrmancer"] = 0 ,["hobgoblin"] = 2 ,["Amaemon"] = 3 ,["deep troll shaman"] = 6 ,["shadow imp"] = 3 ,["human"] = 3 ,["eldritch tentacle segment"] = 13 ,["twister"] = 0 ,["bat"] = 1 ,["glowing shapeshifter"] = 0 ,["Bai Suzhen"] = 22 ,["golden dragon"] = 15 ,["draconian annihilator"] = -1 ,["ophan"] = 10 ,["white draconian"] = 9 ,["death knight"] = 2 ,["radroach"] = 13 ,["Rupert"] = 0 ,["sky beast"] = 3 ,["test spawner"] = 127 ,["ballistomycete spore"] = 0 ,["black mamba"] = 4 ,
- ["the Serpent of Hell"] = 16 ,["Gloorx Vloq"] = 10 ,["Roxanne"] = 20 ,["withered plant"] = 0 ,["white imp"] = 4 ,["Grinder"] = 3 ,["thermic dynamo"] = 4 ,["deep elf sorcerer"] = 0 ,["spectral thing"] = 8 ,["deep elf blademaster"] = 0 ,["bunyip"] = 6 ,["flayed ghost"] = 0 ,["kraken"] = 20 ,["bone dragon"] = 20 ,["bombardier beetle"] = 4 ,["tentacle segment"] = 5 ,["shard shrike"] = 2 ,["yaktaur"] = 4 ,["alligator"] = 4 ,["the Royal Jelly"] = 8 ,["emperor scorpion"] = 18 ,["snake"] = 0 ,["curse skull"] = 35 ,["tentacle"] = 5 ,["Gastronok"] = 2 ,["small abomination"] = 0 ,["minotaur"] = 6 ,["acid blob"] = 1 ,["deep elf master archer"] = 0 ,["orange demon"] = 3 ,["Executioner"] = 10 ,["naga"] = 6 ,["frilled lizard"] = 0 ,["oni"] = 1 ,["Louise"] = 0 ,["Murray"] = 30 ,["water elemental"] = 4 ,["bound soul"] = 8 ,["culicivora"] = 2 ,["mummy priest"] = 8 ,["green draconian"] = 9 ,["tentacled starspawn"] = 5 ,["faun"] = 2 ,["fire crab"] = 9 ,["yaktaur captain"] = 5 ,["pandemonium lord"] = 1 ,
- ["servant of whispers"] = 1 ,["komodo dragon"] = 7 ,["occultist"] = 0 ,["goliath frog"] = 3 ,["hydra"] = 0 ,["hellwing"] = 16 ,["Mara"] = 10 ,["orc"] = 0 ,["dream sheep"] = 2 ,["wolf"] = 4 ,["gargoyle"] = 18 ,["Urug"] = 2 ,["Norris"] = 1 ,["ribbon worm"] = 1 ,["Sojobo"] = 2 ,["boggart"] = 0 ,["skyshark"] = 6 ,["Maggie"] = 0 ,["trivial sensed monster"] = 0 ,["reaper"] = 15 ,["Lom Lobon"] = 10 ,["large simulacrum"] = 10 ,["small zombie"] = 0 ,["satyr"] = 2 ,["fire vortex"] = 0 ,["ancient champion"] = 15 ,["mutant beast"] = 8 ,["demigod"] = 2 ,["snapping turtle"] = 16 ,["hell hound"] = 6 ,["spark wasp"] = 9 ,["deep troll earth mage"] = 12 ,["draconian"] = 10 ,["deep elf death mage"] = 0 ,["manticore"] = 5 ,["sun demon"] = 10 ,["giant cockroach"] = 3 ,["starspawn tentacle"] = 8 ,["spriggan air mage"] = 1 ,["ice dragon"] = 10 ,["halazid warlock"] = 8 ,["laughing skull"] = 4 ,["will-o-the-wisp"] = 4 ,["very ugly thing"] = 6 ,["Duvessa"] = 2 ,["Ijyb"] = 2 ,["hell lord"] = 0 ,["quicksilver dragon"] = 10 ,["entropy weaver"] = 7 ,["Natasha"] = 2 ,["deep elf high priest"] = 3 ,["ghost moth"] = 8 ,["balrug"] = 5 ,["hellion"] = 5 ,["fire elemental"] = 4 ,["dire elephant"] = 13 ,["silent spectre"] = 5 ,["chaos spawn"] = 4 ,["hell rat"] = 7 ,["walking divine tome"] = 10 ,["fungus"] = 0 ,["Sigmund"] = 0 ,["training dummy"] = 0 ,["demonspawn warmonger"] = 3 ,["foxfire"] = 0 ,["molten gargoyle"] = 14 ,["water moccasin"] = 2 ,["starcursed mass"] = 10 ,["Josephine"] = 0 ,["ogre mage"] = 1 ,["merfolk siren"] = 4 ,
- ["draconian stormcaller"] = 0 ,["easy sensed monster"] = 0 ,["polar bear"] = 7 ,["demonspawn corrupter"] = 3 ,["Psyche"] = 0 ,["harpy"] = 2 ,["inugami"] = 5 ,["angel"] = 10 ,["quasit"] = 5 ,["Parghit"] = 1 ,["moth"] = 0 ,["eleionoma"] = 2 ,["spectral weapon"] = 5 ,["Zenata"] = 10 ,["sixfirhy"] = 2 ,["royal mummy"] = 10 ,["orc knight"] = 2 ,["blazeheart golem"] = 9 ,["merfolk avatar"] = 4 ,["vault guard"] = 1 ,["halfling"] = 2 ,["orb of fire"] = 20 ,["iron elemental"] = 20 ,["ancient lich"] = 20 ,["curse toe"] = 25 ,["demonspawn blood saint"] = 6 ,["tengu conjurer"] = 2 ,["boulder"] = 10 ,["orc sorcerer"] = 5 ,["Vv"] = 27 ,["purple draconian"] = 9 ,["guardian mummy"] = 6 ,["draconian monk"] = -3 ,["eidolon"] = 12 ,["sphinx"] = 5 ,["ynoxinul"] = 3 ,["fire bat"] = 1 ,["ironbound frostheart"] = 0 ,["death drake"] = 6 ,["shadow"] = 7 ,["stone giant"] = 12 ,["wight"] = 4 ,["bloated husk"] = 5 ,["ironbound preserver"] = 0 ,["wyvern"] = 5 ,["broodmother"] = 2 ,["frost giant"] = 9 ,["water nymph"] = 2 ,["hog"] = 2 ,["Mnoleg"] = 11 ,["Nessos"] = 4 ,["mummy"] = 3 ,["armataur"] = 15 ,["Agnes"] = 0 ,["sea snake"] = 2 ,["iron imp"] = 6 ,["golem"] = 0 ,["smoke demon"] = 5 ,["daeva"] = 10 ,["iron golem"] = 25 ,["Grum"] = 2 ,["Mennas"] = 15 ,["ghoul"] = 4 ,["formless jellyfish"] = 0 ,["animated tree"] = 0 ,["pillar of salt"] = 1 ,["lava snake"] = 2 ,["shadow demon"] = 7 ,["lightning spire"] = 13 ,["nasty sensed monster"] = 0 ,["merfolk javelineer"] = 0 ,["merfolk impaler"] = 0 ,["deep elf demonologist"] = 0 ,["sickly merfolk siren"] = 4 ,["sacred lotus"] = 24 ,["tyrant leech"] = 5 ,["phantasmal warrior"] = 12 ,
- ["djinni"] = 5 ,["naga mage"] = 6 ,["Polyphemus"] = 10 ,["quokka"] = 2 ,["ball lightning"] = 0 ,["deathcap"] = 5 ,["snaplasher vine segment"] = 6 ,["Terence"] = 0 ,["fire dragon"] = 10 ,["hornet"] = 6 ,["wendigo"] = 4 ,["lich"] = 10 ,["briar patch"] = 10 ,["kobold demonologist"] = 2 ,["naga ritualist"] = 6 ,["fire giant"] = 8 ,["Ignacio"] = 10 ,["bennu"] = 6 ,["Crazy Yiuf"] = 2 ,["ufetubus"] = 2 ,["malarious merfolk avatar"] = 4 ,["giant"] = 0 ,["grey draconian"] = 16 ,["hell hog"] = 2 ,["living spell"] = 0 ,["shambling mangrove"] = 13 ,["sleepcap"] = 5 ,["bullfrog"] = 0 ,["death yak"] = 9 ,["player"] = 0 ,["Dissolution"] = 10 ,["the Lernaean hydra"] = 0 ,["ballistomycete"] = 1 ,["walking frostbound tome"] = 10 ,["elemental wellspring"] = 8 ,["Jory"] = 10 ,["deep elf annihilator"] = 0 ,["iron giant"] = 18 ,["spriggan"] = 1 ,["pale draconian"] = 9 ,["Joseph"] = 0 ,["the Serpent of Hell"] = 20 ,["ancient zyme"] = 6 ,["Chuck"] = 14 ,["nargun"] = 25 ,["ironbound convoker"] = 0 ,["kobold blastminer"] = 4 ,
- ["peacekeeper"] = 20 ,["dragon"] = 0 ,["deep elf knight"] = 0 ,["small simulacrum"] = 10 ,["shock serpent"] = 2 ,["protean progenitor"] = 7 ,["Margery"] = 0 ,["animated armour"] = 8 ,["Lodul"] = 3 ,["snaplasher vine"] = 4 ,["mana viper"] = 3 ,["goblin"] = 0 ,["imperial myrmidon"] = 1 ,["tengu reaver"] = 2 ,["deep elf elementalist"] = 0 ,["worldbinder"] = 12 ,["orc warrior"] = 0 ,["Frederick"] = 0 ,["Jessica"] = 0 ,["elephant slug"] = 2 ,["moon troll"] = 20 ,["Pikel"] = 4 ,["starspawn tentacle segment"] = 8 ,["Azrael"] = 10 ,["draconian scorcher"] = -1 ,["Asmodeus"] = 30 ,["seraph"] = 10 ,["soul eater"] = 18 ,["great orb of eyes"] = 10 ,["crystal guardian"] = 20 ,["Khufu"] = 10 ,["salamander"] = 5 ,["golden eye"] = 0 ,["orange crystal statue"] = 12 ,["caustic shrike"] = 8 ,["two-headed ogre"] = 3 ,["rust devil"] = 10 ,["Maurice"] = 1 ,["Nellie"] = 13 ,["naga warrior"] = 6 ,["plant"] = 0 ,["floating eye"] = 0 ,["orc wizard"] = 1 ,["revenant"] = 8 ,["ice beast"] = 5 ,["death cob"] = 10 ,["holy swine"] = 2 ,["fenstrider witch"] = 3 ,["thrashing horror"] = 5 ,["meliai"] = 2 ,["drowned soul"] = 0 ,["demonspawn"] = 3 ,["glowing orange brain"] = 2 ,["war gargoyle"] = 25 ,["pearl dragon"] = 10 ,["spriggan berserker"] = 2 ,["spriggan druid"] = 1 ,["Prince Ribbit"] = 0 ,["vault sentinel"] = 1 ,["Cloud Mage"] = 0 ,["vine stalker"] = 2 ,["Kirke"] = 0 ,["green death"] = 5 ,["centaur warrior"] = 4 ,["basilisk"] = 3 ,["dancing weapon"] = 10 ,["tainted leviathan"] = 15 ,["draconian knight"] = 9 ,["orc warlord"] = 3 ,["raiju"] = 4 ,["diamond obelisk"] = 12 ,["warg"] = 9 ,["electric golem"] = 5 ,["Nergalle"] = 9 ,["fulminant prism"] = 3 ,["scrub nettle"] = 8 ,["martyred shade"] = 0 ,["ugly thing"] = 4 ,["demonspawn black sun"] = 9 ,["Vashnia"] = 6 ,["giant lizard"] = 0 ,["ice devil"] = 12 ,["orc priest"] = 1 ,["Saint Roka"] = 3 ,["storm dragon"] = 13 ,["eldritch tentacle"] = 13 ,["crystal echidna"] = 10 ,["burial acolyte"] = 0 ,["Robin"] = 1 ,["tormentor"] = 12 ,["Jorgrun"] = 2 ,["ironbound thunderhulk"] = 1 ,["glass eye"] = 2 ,["Fannar"] = 4 ,["toenail golem"] = 8 ,["block of ice"] = 15 ,["Hellbinder"] = 0 ,["red devil"] = 7 ,
- ["ancestor"] = 5 ,["giant frog"] = 0 ,["Killer Klown"] = 10 ,["necromancer"] = 0 ,["meteoran"] = 2 ,["torpor snail"] = 8 ,["electric eel"] = 1 ,["juggernaut"] = 20 ,["hell beast"] = 5 ,["apocalypse crab"] = 11 ,["red draconian"] = 9 ,["tengu warrior"] = 2 ,["rat"] = 1 ,["guardian serpent"] = 6 ,["large zombie"] = 8 ,["Arachne"] = 3 ,["creeping inferno"] = 0 ,["spectator"] = 0 ,["slime creature"] = 1 ,["felid"] = 2 ,["merfolk aquamancer"] = 0 ,["demonic plant"] = 0 ,["doom hound"] = 6 ,["earth elemental"] = 14 ,["merfolk"] = 4 ,["iron dragon"] = 20 ,["Blork the orc"] = 0 ,["elephant"] = 8 ,["cacodemon"] = 11 ,["orc high priest"] = 1 ,["hell knight"] = 0 ,["lemure"] = 4 ,["gnoll sergeant"] = 2 ,["shadow dragon"] = 15 ,["Snorg"] = 0 ,["weeping skull"] = 7 ,["Xtahua"] = 18 ,["phantom"] = 3 ,["Ice Fiend"] = 15 ,["antique champion"] = 20 ,["Aizul"] = 8 ,["spellforged servitor"] = 10 ,["crimson imp"] = 3 ,["Ilsuiw"] = 5 ,["hexer"] = 5 ,["river rat"] = 5 ,["yellow draconian"] = 9 ,["titan"] = 10 ,["wolf spider"] = 3 ,["small skeleton"] = 0 ,["Orb Guardian"] = 13 ,["naga sharpshooter"] = 6 ,["vault warden"] = 1 ,
- ["the Serpent of Hell"] = 16 ,["ball python"] = 0 ,["the Serpent of Hell"] = 30 ,["steam dragon"] = 5 ,["salamander tyrant"] = 5 ,["swamp worm"] = 3 ,["Frances"] = 0 ,["battlemage"] = 5 ,["death scarab"] = 7 ,["black bear"] = 2 ,["quicksilver ooze"] = 3 ,["arcanist"] = 0 ,["freezing wraith"] = 12 ,["test blob"] = 0 ,["yak"] = 4 ,["Jeremiah"] = 2 ,["deep elf pyromancer"] = 0 ,["jackal"] = 2 ,["spriggan rider"] = 1 ,["insubstantial wisp"] = 0 ,["necrophage"] = 2 ,["tentacled monstrosity"] = 5 ,["efreet"] = 10 ,["saltling"] = 15 ,["nameless horror"] = 8 ,["lost soul"] = 0 ,["octopode"] = 1 ,["Nikola"] = 1 ,["Edmund"] = 0 ,["ragged hierophant"] = 0 ,["strange machine"] = 12 ,["unseen horror"] = 5 ,["spriggan defender"] = 3 ,["shadow"] = 3 ,["dread lich"] = 20 ,["hound"] = 2 ,["nagaraja"] = 6 ,["Bai Suzhen"] = 14 ,["Brimstone Fiend"] = 15 ,["jiangshi"] = 10 ,["large skeleton"] = 0 ,["elemental"] = 0 ,["alligator snapping turtle"] = 19 ,["vampire mage"] = 10 ,["drake"] = 0 ,["catoblepas"] = 10 ,["tarantella"] = 3 ,["lindwurm"] = 8 ,["putrid mouth"] = 5 ,["Josephina"] = 10 ,["skeleton"] = 0 ,["swamp dragon"] = 7 ,
- ["vampire mosquito"] = 2 ,["Mlioglotl"] = 10 ,["Donald"] = 3 ,["boulder beetle"] = 20 ,["vampire"] = 10 ,["troll"] = 3 ,["bush"] = 15 ,["ice statue"] = 12 ,["kobold"] = 2 ,["gnoll bouda"] = 2 ,["Geryon"] = 15 ,["eye of devastation"] = 12 ,["cerulean imp"] = 3 ,["cyclops"] = 5 ,["toadstool"] = 1 ,["ghost"] = 0 ,["vampire knight"] = 10 ,["simulacrum"] = 10 ,["kobold brigand"] = 3 ,["Menkaure"] = 3 ,["walking earthen tome"] = 20 ,["shapeshifter"] = 0 ,["bear"] = 0 ,["Ereshkigal"] = 10 ,["scorpion"] = 5 ,["blizzard demon"] = 10 ,["rakshasa"] = 6 ,["orb spider"] = 3 ,["spatial maelstrom"] = 0 ,["Pargi"] = 1 ,["Cerebov"] = 30 ,["black draconian"] = 9 ,["Hell Sentinel"] = 25 ,["Harold"] = 0 ,["neqoxec"] = 4 ,["draconian shifter"] = -1 ,["gnoll"] = 2 ,["statue"] = 12 ,["rockslime"] = 27 ,["wandering mushroom"] = 5 ,["friendly sensed monster"] = 0 ,["Antaeus"] = 28 ,["quicksilver elemental"] = 1 ,["battlesphere"] = 0 ,["Head Instructor"] = 0 ,["Grunn"] = 6 ,["salamander mystic"] = 5 ,["the Enchantress"] = 1 ,["Dispater"] = 35 ,["apis"] = 9 ,["hellephant"] = 13 ,["azure jelly"] = 5 ,["Erolcha"] = 3 ,["Asterion"] = 4 ,["zombie"] = 0 ,["cherub"] = 10 ,["program bug"] = 0 ,["lorocyproca"] = 10 ,["orc apostle"] = 2 ,
- ["steelbarb worm"] = 11 ,["obsidian statue"] = 12 ,["test statue"] = 0 ,["deep dwarf"] = 2 ,["blazeheart core"] = 0 ,["cactus giant"] = 1 ,["walking crystal tome"] = 15 ,["shadow wraith"] = 7 ,["iguana"] = 5 ,["pharaoh ant"] = 4 ,["brain worm"] = 1 ,["redback"] = 2 ,["Dowan"] = 0 ,["anaconda"] = 4 ,["wraith"] = 10 ,["killer bee"] = 2 ,["merged slime creature"] = 0 ,["butterfly"] = 0 ,["endoplasm"] = 1 ,["moth of wrath"] = 0 ,["wind drake"] = 3 ,["crab"] = 0 ,["aspiring flesh"] = 2 ,["searing wretch"] = 4 ,["jorogumo"] = 4 ,["crocodile"] = 4 ,["starflower"] = 16 ,["barachi"] = 0 ,["ettin"] = 9 ,["ghost crab"] = 9 ,["profane servitor"] = 10 ,["shining eye"] = 3 ,["dryad"] = 6 ,["tough sensed monster"] = 0 ,["thorn hunter"] = 9 ,["demonic crawler"] = 10 ,["bog body"] = 1 ,["stoker"] = 5 ,["sensed monster"] = 0 ,["wretched star"] = 10 ,["deep troll"] = 6 ,["Eustachio"] = 0 ,["elf"] = 1 ,["vampire bat"] = 1 ,["cane toad"] = 6 ,["tengu"] = 2 ,["oklob plant"] = 10 ,["skeletal warrior"] = 15 ,["swamp drake"] = 3 ,["lurking horror"] = 0 ,["player ghost"] = 1 ,["iron troll"] = 20 ,["ushabti"] = 9 ,["Erica"] = 0 ,["howler monkey"] = 1 ,["blink frog"] = 0 ,["dart slug"] = 1 ,["spider"] = 0 ,["sun moth"] = 6 ,["ogre"] = 1 ,["knight"] = 5 ,["player illusion"] = 1 ,["Tzitzimitl"] = 12 ,["air elemental"] = 2 ,["walking tome"] = 0 ,["large abomination"] = 0 ,["deep elf archer"] = 0 ,["Boris"] = 12 ,["oklob sapling"] = 10}
- }
- ability_slot += berserk:B
- ability_slot += potion petition:P
- include +=HDamage.rc
- include +=HDAForceMore.rc
- include +=HDAColors.rc
- ### General ###
- explore_auto_rest = true
- #autofight_throw = true
- #autofight_throw_nomove = true
- autofight_stop = 50
- autopickup_starting_ammo = true
- pickup_thrown = true
- chunks_autopickup = true
- explore_greedy = true
- explore_wall_bias = 1
- more := force_more_message
- more += LOW HITPOINT
- more += You feel like a meek peon again
- more += You have got your breath back
- more += Your skin stops crawling
- more += Your transformation is almost over
- more += calcifying dust hits you
- more += crystal spear hits you
- more += feel a terrible chill
- more += is wielding .*distortion
- more += is wielding .*electrocution
- more += mighty Pandemonium lord
- more += skill increases
- more += skill increases to
- more += strangely unstable
- more += strikes you in flight
- more += watched by something
- more += wracked with pain
- more += you are burned terribly
- more += you convulse
- more += you have finished your manual of
- more += you have got your breath back
- more += you have mastered
- ### Inscriptions ###
- ai := autoinscribe
- ai += throwing net:!f
- ai += potions? of mutation:!q
- ai += potions? of degeneration:!q!q
- ai += potions? of lignification:!q
- ai += scrolls? of torment:!r
- ai += scrolls? of vulnerability:!r
- ai += scrolls? of silence:!r
- ai += scrolls? of noise:!r!r
- ai += scrolls? of summoning:!r
- ai += staff of (conjuration|energy|wizardry|power):!a
- ai += amulet of faith:!P
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement