##### 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_appropriate_spell bindkey = [^D] CMD_LUA_CONSOLE always_use_static_spell_targeters = true # casting spells # ignition, orbofdestruction, fireball, starburst : LOS = 7 { local monster_array function initialize_monster_array() monster_array = {} local x for x = -LOS-5,LOS+5 do monster_array[x] = {} end 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 function spellpower(spellname) local maxPower = 200 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(m, x, y) return m and m:attitude() == 0 and you.see_cell_no_trans(x, y) end function cast_appropriate_spell() initialize_monster_array() update_monster_array() local value_table = {} table.insert(value_table, evaluate_fireball()) table.insert(value_table, evaluate_ood()) table.insert(value_table, evaluate_starburst()) table.insert(value_table, evaluate_ignition()) table.insert(value_table, evaluate_firestorm()) table.sort(value_table, function (k1, k2) return k1[1] < k2[1] end) best = value_table[#value_table] crawl.mpr(best[1]) crawl.mpr(best[2]) crawl.mpr(best[3]) crawl.mpr(best[4]) if best[1] > 0 then spells.cast(best[2], best[3], best[4]) 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 -- TODO account for: value to HP ratio of target -- spellpower -- casting fail chance function fireball_damage_at_target(x, y, dmgPerHit) local totDmg = 0 local x2, y2 for x2 = -1, 1 do for y2 = -1, 1 do local m = monster_array[x+x2][y+y2] if valid_enemy(m, x+x2, y+y2) then local dmg = resisted_damage(dmgPerHit, 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 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 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 -- 3d(3.33+Power/6) local dmgPerHit = 3 * math.floor(3.33 + spellpower("fireball") / 6 + 1) * 0.5 crawl.mpr("fireball ") crawl.mpr(tostring(dmgPerHit)) crawl.mpr(spellpower("fireball")) dmgPerHit = dmgPerHit * (1 - spells.fail("fireball")/100.0) local range = spells.max_range("fireball") local x, y for x = -range,range do for y = -range,range do if can_target(x, y) then local path = spells.path("fireball",x,y) local x2 = path[#path][1] local y2 = path[#path][2] local dmg = fireball_damage_at_target(x2, y2, dmgPerHit) if dmg > bestDmg then bestDmg = dmg bestX = x bestY = y end end end end return {bestDmg, "fireball", bestX, bestY} end function evasion_check(monsterEv, spellToHit) return 0.8 -- todo. also todo: dmsl end function evaluate_starburst() if not castable("starburst") then return {0, "starburst", 0, 0} end local totDmg = 0 -- 6d(3+Power/9) local dmgPerHit = 6 * 0.5 * math.floor(1+3+spellpower("starburst")/9) crawl.mpr("starburst ") crawl.mpr(tostring(dmgPerHit)) crawl.mpr(spellpower("starburst")) dmgPerHit = dmgPerHit * (1 - spells.fail("starburst")/100.0) 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 and ranges[x][y] >= R then local dmg = resisted_damage(dmgPerHit, m:res_fire()) dmg = dmg * evasion_check(m:ev(), spellpower("starburst")) totDmg = totDmg + dmg ranges[x][y] = ranges[x][y] - 1 end end end end end return {totDmg, "starburst", 0, 0} end function is_wall(x, y) return travel.feature_solid(view.feature_at(x, y)) end function ood_damage_at_target(x, y) -- 9d([60 + Power]/12) local baseDamage = 9 * 0.5 * math.floor((60 + spellpower("orb of destruction")) / 12) crawl.mpr("ood ") crawl.mpr(tostring(baseDamage)) crawl.mpr(spellpower("orb of destruction")) 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 x < 0 then xstart = x xend = -1 end if y < 0 then ystart = y yend = -1 end if x == 0 then xstart = 0 end if y == 0 then ystart = 0 end for x2=xstart,xend do for y2=ystart,yend do if is_wall(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) then return baseDamage * 0.5 end end end end if math.abs(x) == 1 and math.abs(y) == 1 then return baseDamage * 0.5 end if math.abs(x) <= 2 and math.abs(y) <= 2 then return baseDamage * 0.75 end return baseDamage end function evaluate_ood() if not castable("orb of destruction") then return {0, "orb of destruction", 0, 0} 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) 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 dmgPerHit =0.5 * 3 * math.floor(3.33 + spellpower("ignition") / 9) crawl.mpr("ignition ") crawl.mpr(tostring(dmgPerHit)) crawl.mpr(spellpower("ignition")) dmgPerHit = dmgPerHit * (1 - spells.fail("ignition")/100.0) local x, y for x=-LOS,LOS do for y=-LOS,LOS do local m = monster_array[x][y] if valid_enemy(m, x, y) then local dmg = fireball_damage_at_target(x, y, dmgPerHit) totDmg = totDmg + dmg end end end return {totDmg, "ignition", 0, 0} end function firestorm_damage_at_target(x, y, dmgPerHit) local totDmg = 0 local x2, y2 for x2 = -3, 3 do for y2 = -3, 3 do local m = monster_array[x+x2][y+y2] if valid_enemy(m, x+x2, y+y2) then local dmg = resisted_damage(dmgPerHit*0.55, m:res_fire()) + dmgPerHit * 0.45 if math.abs(x2) == 3 or math.abs(y2) == 3 then dmg = dmg * 0.5 -- on fringe of aoe: assume 50% chance of hitting end totDmg = totDmg + dmg elseif not you.see_cell(x+x2, y+y2) then totDmg = totDmg + 0.1 -- just slightly prefer to hit cells out of sight end end end return totDmg end function evaluate_firestorm() if not castable("fire storm") then return {0, "firestorm", 0, 0} end local bestX = 0 local bestY = 0 local bestDmg = 0 -- 8d(0.625+Power/8) local dmgPerHit = 8 * 0.5 * math.floor(0.625 + spellpower("fire storm") / 8 + 1) crawl.mpr("fire storm ") crawl.mpr(tostring(dmgPerHit)) crawl.mpr(spellpower("fire storm")) dmgPerHit = dmgPerHit * (1 - spells.fail("fire storm")/100.0) 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 and math.abs(y) > 3 and can_smite(x, y) then local path = spells.path("fire storm",x,y) local x2 = path[#path][1] local y2 = path[#path][2] local dmg = firestorm_damage_at_target(x2, y2, dmgPerHit) if dmg > bestDmg then bestDmg = dmg bestX = x bestY = y end end end end return {bestDmg, "fire storm", bestX, bestY} end function throw_fireball() local path = spells.path("fireball",0,-5) for k,v in pairs(path) do crawl.mpr(tostring(v[1])) crawl.mpr(tostring(v[2])) end spells.cast("fireball", 0, -5) end }