{
dcss_versions = {"0.29.1"}
small_races = {
Spriggan={}}
medium_races = {
Demigod={},
Human={}}
big_races = {
Naga={},
Troll={}}
-- TODO: move to a context table and fill races
equipment_slots = { -- clua armor slots
cloak="Cloak",
helmet="Helmet",
gloves="Gloves",
boots="Boots",
body="Body Armour"}
-- there is also shield="Shield", but it's often excluded due to AC computations
-- so if one wants, can use raw "Shield" exceptionally
-- TODO: jewellry
-- TODO: move to a context table
Options = { -- crawl RC setters/appenders
set_as = function (option, alias)
crawl.setopt(alias .. ":=" .. option)
end,
set = function (option, value)
crawl.setopt(option .. "=" .. value)
end,
append = function (option, value)
crawl.setopt(option .. "+=" .. value)
end} -- end of Options
Player = { -- player extension functions
AC = function (args)
local total = 0
for _, slotname in pairs(equipment_slots) do
it = items.equipped_at(slotname)
if it then total = total + it.ac + it.plus end
end
return total
end} -- end of Player
Utility = { -- utility functions
concat = function (...)
local m = ""
for _, v in ipairs(...) do m = m .. tostring(v) end
return m
end,
tagged = function (message, tag) -- returns `message`
local ltag = "<" .. tag .. ">"
local rtag = "" .. tag .. ">"
return ltag .. message .. rtag
end,
gdr = function (AC) -- calculate GDR % and real reduction it calculates to
local gdr_percent = math.pow(AC, 0.25) * 16
local gdr_real = AC * gdr_percent / 100
return gdr_percent, gdr_real
end,
percent_of = function (value, base) -- what % of `base` `value` calculates to
return value * 100 / base
end,
delayed = function (delay, func, ...) -- execute `func` every `delay` turns
if math.fmod(you.turns(), delay) == 0 then
func(...)
end
end} -- end of Utility
Color = { -- crawl recognized colors
white="white", lightgrey="lightgrey", darkgrey="darkgrey", lightgreen="lightgreen",
green="green", yellow="yellow", red="red", magenta="magenta", lightmagenta="lightmagenta",
blue="blue", lightblue="lightblue", cyan="cyan", lightcyan="lightcyan", lightred="lightred",
brown="brown", black="black"}
Channel = { -- crawl's recognized channel names
plain="plain", friend_action="friend_action", prompt="prompt", god="god",
duration="duration", danger="danger", warning="warning", recovery="recovery",
sound="sound", talk="talk", talk_visual="talk_visual",intrinsic_gain="intrinsic_gain",
mutation="mutation", monster_spell="monster_spell", monster_enchant="monster_enchant",
friend_spell="friend_spell", friend_enchant="friend_enchant", monster_damage="monster_damage",
monster_target="monster_target", banishment="banishment", equipment="equipment",
floor="floor", multiturn="multiturn", examine="examine", examine_filter="examine_filter",
diagnostic="diagnostic", error="error", tutorial="tutorial", orb="orb",
timed_portal="timed_portal", hell_effect="hell_effect", monster_warning="monster_warning",
dgl_message="dgl_message"}
Console = { -- crawl console I/O
print_c = function (color, message, ...) -- print in specified color
if color == nil then color = Color.lightgrey end
crawl.mpr(Utility.tagged(string.format(message, ...), color))
end,
print = function (message, ...)
if message ~= nil then
-- TODO: typechecking and printing other types
crawl.mpr(string.format(message, ...))
end
end,
print_ch = function (ch, message, ...) -- print to specific channel
if message ~= nil then
if ch == nil then ch = Channel.plain end
crawl.mpr(string.format(message, ...), ch)
end
end,
warning = function (message, ...)
Console.print_ch(Channel.warning, message, ...)
end,
danger = function (message, ...)
Console.print_ch(Channel.danger, message, ...)
crawl.more()
end,
prompt = function (message, ...)
Console.print_ch(Channel.prompt, message, ...)
return crawl.getch()
end,
input = function ()
local input_value = crawl.c_input_line()
if input_value ~= nil then
crawl.mpr(">>> " .. input_value, Channel.dgl_message)
return input_value
end
end} -- end of Console
Announce = { -- functions meant to run every action
gdr_change = function (force)
local current_AC = Player.AC()
if buffer.previous_AC ~= current_AC then
local gdr_proc, gdr_real = Utility.gdr(current_AC)
local msg = "GDR: %.0f%% / %.0fdmg"
if buffer.previous_AC < current_AC then -- AC increased
msg = msg .. Utility.tagged(" -> %.0f%% / %.0fdmg", Color.lightgreen)
else -- AC descreased
msg = msg .. Utility.tagged(" -> %.0f%% / %.0fdmg", Color.lightred)
end
local prev_proc, prev_real = Utility.gdr(buffer.previous_AC)
Console.print(msg, prev_proc, prev_real, gdr_proc, gdr_real)
elseif force ~= nil then
Console.print("GDR: %.0f%% / %.0fdmg", Utility.gdr(Player.AC()))
end
buffer.previous_AC = current_AC
end,
hp_change = function ()
local current_HP, max_HP = you.hp()
if buffer.previous_HP ~= current_HP then
local hp_diff = current_HP - buffer.previous_HP
local percent = Utility.percent_of(math.abs(hp_diff), max_HP)
if hp_diff < 0 and percent > 20 then -- issue warning if hit by more than 20% of max hp
Console.danger("MASSIVE (%d) damage taken!", math.abs(hp_diff))
elseif hp_diff > 1 then -- announce any healing bigger than what regen gives
Console.print_c(Color.lightgreen, "Healed for %d (%d%%)", hp_diff, percent)
end
buffer.previous_HP = current_HP
end
end,
gold_change = function ()
local current_gold = you.gold()
if buffer.previous_gold ~= current_gold then
local gold_diff = current_gold - buffer.previous_gold
if gold_diff < 0 then -- inform on lost gold
Console.print_c(Color.yellow, "Lost %d gold! (%d)", math.abs(gold_diff), current_gold)
elseif gold_diff > 0 then -- announce any healing bigger than what regen gives
Console.print_c(Color.yellow, "Gained %d gold! (%d)", gold_diff, current_gold)
end
buffer.previous_gold = current_gold
end
end} -- end of Announce
function cmd() -- run command passed via crawl input
-- by default set to F2 as macro by set_defaults() function
Console.print(assert(loadstring("return " .. Console.input()))())
end -- end of cmd()
function enable_aliases() -- ingame cmd convenience aliases
print = Console.print
print_c = Console.print_c
percent = Utility.percent_of
gdr = function () Announce.gdr_change(true) end
Options.append("macros", "M \\{F5} ===gdr")
end -- end of enable_aliases()
function adjust_autofight()
-- Adjust autofight_stop option according to the player state.
local hp, max_hp = you.hp()
local af_stop = 50 -- base autofight stop %
if medium_races[you.race()] ~= nil then
if max_hp < 100 then
af_stop = 55
elseif max_hp < 200 then
af_stop = 40
else
af_stop = 25
end
end -- end of level setting
Options.set("autofight_stop", af_stop)
end -- end of adjust_autofight()
function adjust_autodrop()
return nil -- TODO autodrop according to level etc.
end -- end of adjust_autodrop()
function adjusted_autopickup(item, name)-- meant for add_autopickup_func()
if item.is_useless then return end
if item.artefact then return true end
-- Pickup missing must-have items.
if item.class(true) == "armour" then
slot, _ = item.subtype()
return (equipment_slots[slot] ~= nil and items.equipped_at(equipment_slots[slot]) == nil)
end
end -- end of adjusted_autopickup()
function set_defaults() -- Set default rc options
local set_opts = {
default_manual_training = "true",
hp_warning = 30,
hp_colour = "100:green, 95:lightgreen, 80:yellow, 40:lightred, 25:red",
mp_warning = 40,
mp_colour = "100:blue, 70:lightblue, 55:yellow, 40:lightred, 25:red",
stat_colour = "1:lightred, 3:red, 10:yellow, 30:lightgreen, 50:green, 70:cyan",
clear_messages = "true",
equip_bar = "true",
always_show_zot = "true"}
-- TODO add repr and put long values into lua arrays
local append_opts = {
macros = {"M \\{F2} ===cmd"}} -- bind commandline to F2 key
-- TODO add colours? or move them to adjust_*()
for opt, value in pairs(set_opts) do
Options.set(opt, value)
end
for opt, values in pairs(append_opts) do
for _, value in ipairs(values) do
Options.append(opt, value)
end
end
end -- end of set_defaults()
set_defaults()
add_autopickup_func(adjusted_autopickup)
-- open skills at start
if you.turns() == 0 then crawl.sendkeys("m") end
buffer = { -- global buffer context
previous_AC = Player.AC(),
previous_HP = (you.hp()),
previous_gold = you.gold()}
function ready() -- Main function executed after every action.
Announce.gdr_change()
Announce.hp_change()
Announce.gold_change()
Utility.delayed(10, adjust_autofight)
end -- end of ready()
}
-- TODO: walkable tiles according to resistances
-- TODO: spellcasting penalty according to armor worn http://crawl.chaosforge.org/Encumbrance_rating
-- TODO: dynamic type recognition in print for tables, arrays, etc.
-- TODO: add namespace
-- TODO: player settings
-- TODO: add spellpower change announce (with enhancements at least)
-- convenience aliases