##### 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 game_seed = 93891015573 pregen_dungeon = true # csdc default_manual_training = true autofight_stop = 50 auto_butcher = true auto_eat_chunks = true show_more = false { ----------------------------- ---- Begin char_defaults ---- ----------------------------- -- See README.md for documentation. weapon_skills = {"Unarmed Combat", "Short Blades", "Long Blades", "Axes", "Maces & Flails", "Polearms", "Staves"} ranged_skills = {"Throwing", "Bows", "Crossbows", "Slings"} other_skills = {"Fighting", "Armour", "Dodging", "Shields", "Spellcasting", "Conjurations", "Hexes", "Charms", "Summonings", "Necromancy", "Translocations", "Transmutations", "Fire Magic", "Ice Magic", "Air Magic", "Earth Magic", "Poison Magic", "Invocations", "Evocations","Stealth"} skill_glyphs = { [1] = "+", [2] = "*" } chdat = nil char_combo = you.race() .. you.class() loaded_attempted = false -- Wrapper of crawl.mpr() that prints text in white by default. if not mpr then mpr = function (msg, color) if not color then color = "white" end crawl.mpr("<" .. color .. ">" .. msg .. "") end end function skill_message(prefix, skill, skill_type, value) local msg = "" if prefix then msg = prefix .. ";" end if skill_type then msg = msg .. skill_type .. "(" .. skill .. "):" .. value else msg = msg .. skill .. ":" .. value end return msg end function save_char_defaults(quiet) if you.class() == "Wanderer" then return end if not c_persist.char_defaults then c_persist.char_defaults = { } end c_persist.char_defaults[char_combo] = { } chdat = c_persist.char_defaults[char_combo] local msg = nil local have_weapon = false for _,sk in ipairs(weapon_skills) do if you.train_skill(sk) > 0 then chdat["Weapon"] = you.train_skill(sk) msg = skill_message(nil, sk, "Weapon", skill_glyphs[chdat["Weapon"]]) have_weapon = true break end end if not have_weapon then chdat["Weapon"] = nil end local have_ranged = false for _,sk in ipairs(ranged_skills) do if you.train_skill(sk) > 0 then chdat["Ranged"] = you.train_skill(sk) msg = skill_message(msg, sk, "Ranged", skill_glyphs[chdat["Ranged"]]) have_ranged = true break end end if not have_ranged then chdat["Ranged"] = nil end for _,sk in ipairs(other_skills) do if you.train_skill(sk) > 0 then chdat[sk] = you.train_skill(sk) msg = skill_message(msg, sk, nil, skill_glyphs[chdat[sk]]) else chdat[sk] = nil end end if not quiet then mpr("Saved default for " .. char_combo .. ": " .. msg) end end function have_defaults() return you.class() ~= "Wanderer" and c_persist.char_defaults ~= nil and c_persist.char_defaults[char_combo] ~= nil end function load_char_defaults(quiet) if not have_defaults() then return end local msg = nil local found_weapon = false chdat = c_persist.char_defaults[char_combo] for _,sk in ipairs(weapon_skills) do if you.base_skill(sk) > 0 and chdat["Weapon"] then you.train_skill(sk, chdat["Weapon"]) msg = skill_message(msg, sk, "Weapon", skill_glyphs[chdat["Weapon"]]) found_weapon = true else you.train_skill(sk, 0) end end if chdat["Weapon"] and not found_weapon then you.train_skill("Unarmed Combat", chdat["Weapon"]) msg = skill_message(msg, "Unarmed Combat", "Weapon", skill_glyphs[chdat["Weapon"]]) end local found_ranged = false for _,sk in ipairs(ranged_skills) do if you.base_skill(sk) > 0 and chdat["Ranged"] then you.train_skill(sk, chdat["Ranged"]) msg = skill_message(msg, sk, "Ranged", skill_glyphs[chdat["Ranged"]]) found_ranged = true else you.train_skill(sk, 0) end end if chdat["Ranged"] and not found_ranged then you.train_skill("Throwing", chdat["Ranged"]) msg = skill_message(msg, "Throwing", "Ranged", skill_glyphs[chdat["Ranged"]]) end for _,sk in ipairs(other_skills) do if chdat[sk] then you.train_skill(sk, chdat[sk]) msg = skill_message(msg, sk, nil, skill_glyphs[chdat[sk]]) else you.train_skill(sk, 0) end end if not quiet and msg ~= "" then mpr("Loaded default for " .. char_combo .. ": " .. msg) end end function char_defaults(quiet) if you.turns() ~= 0 then return end if not load_attempted then load_char_defaults(quiet) load_attempted = true -- Open the skill menu if we don't have settings to load. if not have_defaults() then crawl.sendkeys("m") end end end --------------------------- ---- End char_defaults ---- --------------------------- } { --------------------------- ---- Begin force_mores ---- --------------------------- -- See README.md for documentation. last_turn = you.turns() -- Each entry must have a name field with a descriptive name, a pattern field -- giving the regexp matching the appropriate monster(s), a cond field giving -- the condition type, and a cutoff field giving the max value where the -- force-more is active. Possible values for cond are xl and maxhp. Note that -- the final force_more pattern will be "(PATTERN).*into view" where PATTERN is -- the value from the pattern field if that is a string, or if pattern is an -- array, a string made from joining the entries in pattern with '|'. fm_patterns = { -- Fast, early game Dungeon problems for chars with low mhp. {name = "30mhp", cond = "maxhp", cutoff = 30, pattern = "adder|hound"}, -- Dungeon monsters that can damage you for close to 50% of your mhp with a -- ranged attack. {name = "40mhp", cond = "maxhp", cutoff = 40, pattern = "orc priest|electric eel"}, {name = "60mhp", cond = "maxhp", cutoff = 60, pattern = "acid dragon|steam dragon|manticore"}, {name = "70mhp", cond = "maxhp", cutoff = 70, pattern = "centaur|meliai|yaktaur"}, {name = "80mhp", cond = "maxhp", cutoff = 80, pattern = "gargoyle|orc (warlord|knight)"}, {name = "90mhp", cond = "maxhp", cutoff = 90, pattern = "centaur warrior|efreet|molten gargoyle|tengu conjurer"}, {name = "110mhp", cond = "maxhp", cutoff = 110, pattern = {"centaur warrior", "deep elf", "cyclops", "efreet", "molten gargoyle", "tengu conjurer", "yaktaur captain", "necromancer", "deep troll earth mage", "hell knight", "stone giant"} }, {name = "160mhp", cond = "maxhp", cutoff = 160, pattern = {"(fire|ice|quicksilver|shadow|storm) dragon", "(fire|frost) giant", "war gargoyle"} }, } -- end fm_patterns active_fm = {} -- Set to true to get a message when the fm change notify_fm = false -- Wrapper of crawl.mpr() that prints text in white by default. if not mpr then mpr = function (msg, color) if not color then color = "white" end crawl.mpr("<" .. color .. ">" .. msg .. "") end end function init_force_mores() for i,v in ipairs(fm_patterns) do active_fm[#active_fm + 1] = false end end function update_force_mores() local activated = {} local deactivated = {} local hp, maxhp = you.hp() for i,v in ipairs(fm_patterns) do local msg = nil if type(v.pattern) == "table" then for j, p in ipairs(v.pattern) do if msg == nil then msg = p else msg = msg .. "|" .. p end end else msg = v.pattern end msg = "(" .. msg .. ").*into view" local action = nil local fm_name = v.pattern if v.name then fm_name = v.name end if not v.cond and not active_fm[i] then action = "+" elseif v.cond == "xl" then if active_fm[i] and you.xl() >= v.cutoff then action = "-" elseif not active_fm[i] and you.xl() < v.cutoff then action = "+" end elseif v.cond == "maxhp" then if active_fm[i] and maxhp >= v.cutoff then action = "-" elseif not active_fm[i] and maxhp < v.cutoff then action = "+" end end if action == "+" then activated[#activated + 1] = fm_name elseif action == "-" then deactivated[#deactivated + 1] = fm_name end if action ~= nil then local opt = "force_more_message " .. action .. "= " .. msg crawl.setopt(opt) active_fm[i] = not active_fm[i] end end if #activated > 0 and notify_fm then mpr("Activating force_mores: " .. table.concat(activated, ", ")) end if #deactivated > 0 and notify_fm then mpr("Deactivating force_mores: " .. table.concat(deactivated, ", ")) end end local last_turn = nil function force_mores() if last_turn ~= you.turns() then update_force_mores() last_turn = you.turns() end end init_force_mores() ------------------------- ---- End force_mores ---- ------------------------- } { add_autopickup_func(function(it, name) if name:find("throwing net") then return true end local class = it.class(true) local armour_slots = {cloak="Cloak", helmet="Helmet", gloves="Gloves", boots="Boots", body="Armour", shield="Shield"} if (class == "armour") then if it.is_useless then return false end sub_type = it.subtype() equipped_item = items.equipped_at(armour_slots[sub_type]) if (sub_type == "cloak") or (sub_type == "helmet") or (sub_type == "gloves") or (sub_type == "boots") then if not equipped_item then return true else return it.artefact or it.branded or it.ego end end if (sub_type == "body") then if equipped_item then local armourname = equipped_item.name() if equipped_item.artefact or equipped_item.branded or equipped_item.ego or (equipped_item.plus > 2) or armourname:find("dragon") or armourname:find("troll") then return it.artefact else return it.artefact or it.branded or it.ego end end return true end if (sub_type == "shield") then if equipped_item then return it.artefact or it.branded or it.ego end end end end) } { function ready() -- Enable force_mores force_mores() char_defaults() end } ############# # Interface # ############# autofight_throw = false autofight_throw_nomove = false show_travel_trail = true travel_delay = -1 rest_delay = -1 auto_sacrifice = true sacrifice_before_explore = true show_game_time = true warn_hatches = true jewellery_prompt = false equip_unequip = true allow_self_target = never confirm_butcher = never easy_eat_gourmand = true sort_menus = true : equipped, identified, basename, qualname, charged hp_warning = 50 auto_hide_spells = true wall_jump_move = false ############## # Autopickup # ############## ae := autopickup_exceptions # autopickup artifacts ae += scroll of amnesia ae += >scroll of holy word ae ^= wand of random effects # ae += >wand of paralysis # ae += >wand of lightning # ae += >wand of confusion # ae += >wand of digging # ae += >wand of disintegration # ae += >wand of polymorph # ae += >wand of flame # ae += >wand of enslavement ae += ring of stealth ae += >ring of positive energy ae += >ring of fire ae += >ring of ice ae += >ring of magical power ae += >ring of strength ae += >ring of intelligence ae += >ring of dexterity ae += >ring of wizardry ######### # Notes # ######### dump_item_origins = all dump_message_count = 50 dump_book_spells = false ########## # Travel # ########## explore_stop = items,greedy_items,greedy_pickup,greedy_pickup_gold explore_stop += greedy_visited_item_stack,stairs,shops,altars,gates explore_stop += greedy_sacrificeable auto_exclude += oklob,statue,roxanne,hyperactive stop := runrest_stop_message ignore := runrest_ignore_message # Annoyances : if you.god() == "Jiyva" then ignore += Jiyva gurgles merrily ignore += Jiyva appreciates your sacrifice ignore += Jiyva says: Divide and consume ignore += You hear.*splatter : end ignore ^= You feel.*sick ignore += disappears in a puff of smoke ignore += engulfed in a cloud of smoke ignore += standing in the rain ignore += engulfed in white fluffiness ignore += safely over a trap ignore += A.*toadstool withers and dies ignore += toadstools? grow ignore += You walk carefully through the ignore += chunks of flesh in your inventory.*rotted away runrest_ignore_poison = 5:10 runrest_ignore_monster += ^butterfly:1 # Bad things stop += You fall through a shaft stop += An alarm trap emits a blaring wail stop += (blundered into a|invokes the power of) Zot stop += A huge blade swings out and slices into you! stop += flesh start stop += (starving|feel devoid of blood) stop += wrath finds you stop += lose consciousness stop += watched by something stop += appears from out of your range of vision # Expiring effects stop += You feel yourself slow down stop += less insulated stop += You are starting to lose your buoyancy stop += You lose control over your flight stop += Your hearing returns stop += Your transformation is almost over stop += back to life stop += uncertain stop += time is quickly running out stop += life is in your own hands stop += is no longer charmed stop += You start to feel a little slower stop += You are no longer : if you.race() == "Ghoul" then stop += smell.*(rott(ing|en)|decay) stop += something tasty in your inventory : end : if you.god() == "Xom" then stop += god: :else ignore += god: :end ignore += pray: ignore += talk: ignore += talk_visual: ignore += friend_spell: ignore += friend_enchant: ignore += friend_action: ignore += sound: ########### # prompts # ########### flash_screen_message += You feel strangely unstable flash_screen_message += Strange energies course through your body more := force_more_message # distortion more += Space warps horribly around you more += hits you.*distortion more += Space bends around you\. more += Your surroundings suddenly seem different. more += Its appearance distorts for a moment. # ghost moths/antimagic more += watched by something more += You feel your power leaking # torment/holy wrath more += You convulse # dispel breath more += dispelling energy hits you # early unseen horrors more += It hits you! more += Something hits you more += Something. *misses you. # more += You have reached level more += You fall through a shaft # abyss convenience prompts more += Found an abyssal rune more += Found a gateway leading out of the Abyss more += Found a gateway leading deeper into the Abyss # necromutation more += Your transformation is almost over. more += You feel yourself coming back to life # summon greater demon more += is no longer charmed # Announcements of timed portal vaults: more += interdimensional caravan more += distant snort more += roar of battle more += wave of frost more += hiss of flowing sand more += sound of rushing water more += oppressive heat about you more += crackle of arcane power more += Found a gateway leading out of the Abyss more += Found .* abyssal rune of Zot more += You feel a terrible weight on your shoulders more += .* resides here # Interrupts more += You don't.* that spell more += You miscast (Controlled Blink|Blink|Death's|Borg|Necromutation) more += You can't (read|drink|do) that more += That item cannot be evoked more += This wand has no charges more += You are held in a net more += You have disarmed more += You don't have any such object more += do not work when you're silenced more += You can't unwield more += enough magic points more += You feel your control is inadequate more += Something interferes with your magic more += You enter a teleport trap # Bad things more += Your surroundings flicker more += You cannot teleport right now more += The writing blurs in front of your eyes more += You fall through a shaft more += A huge blade swings out and slices into you! more += (blundered into a|invokes the power of) Zot more += Ouch! That really hurt! more += dispelling energy hits you more += You convulse more += You are (blasted|electrocuted) more += You are.*confused more += flesh start more += (starving|devoid of blood) more += god:(sends|finds|silent|anger) more += You feel a surge of divine spite more += lose consciousness more += You are too injured to fight blindly more += calcifying dust hits more += Space warps horribly around you more += hits you.*distortion more += Space bends around you\. more += watched by something more += A sentinel's mark forms upon you more += Your limbs have turned to stone more += You are slowing down more += .*LOW HITPOINT WARNING.* more += warns you.*of distortion more += lethally poison more += space bends around your more += wielding.*of (distortion|chaos) # Gods more += you are ready to make a new sacrifice more += mollified more += wrath finds you more += sends forces more += sends monsters more += Vehumet offers # Hell effects # Re-enabled more += "You will not leave this place." more += "Die, mortal!" more += "We do not forgive those who trespass against us!" more += "Trespassers are not welcome here!" more += "You do not belong in this place!" more += "Leave now, before it is too late!" more += "We have you now!" more += You smell brimstone. more += Brimstone rains from above. more += You feel lost and a long, long way from home... more += You shiver with fear. more += You feel a terrible foreboding... more += Something frightening happens. more += You sense an ancient evil watching you... more += You suddenly feel all small and vulnerable. more += You sense a hostile presence. more += A gut-wrenching scream fills the air! more += You hear words spoken in a strange and terrible language... more += You hear diabolical laughter! # Expiring effects more += You feel yourself slow down more += less insulated more += You are starting to lose your buoyancy more += You lose control over your flight more += Your hearing returns more += Your transformation is almost over more += You have a feeling this form more += You feel yourself come back to life more += uncertain more += time is quickly running out more += life is in your own hands more += is no longer charmed more += shroud falls apart more += You start to feel a little slower more += You flicker more += You feel less protected from missiles # Skill breakpoints more += skill increases # Others # more += You have reached level more += You have finished your manual of more += Your scales start more += You feel monstrous more += zaps a wand more += is unaffected more += Jiyva alters your body # Any uniques and any pan lords - doesn't seem to work more += (?-i:[A-Z]).* comes? into view more += Agnes.*comes? into view. more += Aizul.*comes? into view. more += Antaeus.*comes? into view. more += Arachne.*comes? into view. more += Asmodeus.*comes? into view. more += Asterion.*comes? into view. more += Azrael.*comes? into view. more += Blork the orc.*comes? into view. more += Boris.*comes? into view. more += Cerebov.*comes? into view. more += Crazy Yiuf.*comes? into view. more += Dispater.*comes? into view. more += Dissolution.*comes? into view. more += Donald.*comes? into view. more += Dowan.*comes? into view. more += Duvessa.*comes? into view. more += Edmund.*comes? into view. more += Enchantress.*comes? into view. more += Ereshkigal.*comes? into view. more += Erica.*comes? into view. more += Erolcha.*comes? into view. more += Eustachio.*comes? into view. more += Fannar.*comes? into view. more += Frances.*comes? into view. more += Francis.*comes? into view. more += Frederick.*comes? into view. more += Gastronok.*comes? into view. more += Geryon.*comes? into view. more += Gloorx Vloq.*comes? into view. more += Grinder.*comes? into view. more += Grum.*comes? into view. more += Harold.*comes? into view. more += Ignacio.*comes? into view. more += Ijyb.*comes? into view. more += Ilsuiw.*comes? into view. more += Jorgrun.*comes? into view. more += Jory.*comes? into view. more += Jessica.*comes? into view. more += Joseph.*comes? into view. more += Josephine.*comes? into view. more += Jozef.*comes? into view. more += Khufu.*comes? into view. more += Kirke.*comes? into view. more += Lamia.*comes? into view. more += Lom Lobon.*comes? into view. more += Louise.*comes? into view. more += Mara.*comes? into view. more += Margery.*comes? into view. more += Maud.*comes? into view. more += Maurice.*comes? into view. more += Menkaure.*comes? into view. more += Mennas.*comes? into view. more += Mnoleg.*comes? into view. more += Murray.*comes? into view. more += Natasha.*comes? into view. more += Nergalle.*comes? into view. more += Nessos.*comes? into view. more += Nikola.*comes? into view. more += Norris.*comes? into view. more += Pikel.*comes? into view. more += Polyphemus.*comes? into view. more += Prince Ribbit.*comes? into view. more += Psyche.*comes? into view. more += Purgy.*comes? into view. more += Robin.*comes? into view. more += Roxanne.*comes? into view. more += Rupert.*comes? into view. more += Saint Roka.*comes? into view. more += Sigmund.*comes? into view. more += Snorg.*comes? into view. more += Sojobo.*comes? into view. more += Sonja.*comes? into view. more += Terence.*comes? into view. more += The Lernaean hydra.*comes? into view. more += The royal jelly.*comes? into view. more += The Serpent of Hell.*comes? into view. more += Tiamat.*comes? into view. more += Urug.*comes? into view. more += Vashnia.*comes? into view. more += Wiglaf.*comes? into view. more += Xtahua.*comes? into view. more += 27-headed.*comes? into view. more += .*player ghost.* comes? into view more += .*Ancient Lich.*comes? into view. more += .*Orbs? of Fire.*comes? into view. more += .*Fiend.*comes? into view. more += .*Hellion.*comes? into view. more += .*Tormentor.*comes? into view. more += .*Hell Sentinel.*comes? into view. more += .*Executioner.*comes? into view. more += .*Neqoxec.*comes? into view. more += .*Cacodemon.*comes? into view. more += .*Shining Eye.*comes? into view. more += .*Greater Mummy.*comes? into view. more += .*Mummy Priest.*comes? into view. more += .*Curse Toe.*comes? into view. more += .*Curse Skull.*comes? into view. more += .*('s|s') ghost.*comes? into view. more += .*shrike.*comes? into view. more += .*wretched star.*comes? into view more += .*lurking horror.*comes? into view more += .*Juggernaut.*comes? into view. more += .*Iron Giant.*comes? into view. more += .*Tzitzimimeh.*comes? into view. more += .*Tzitzimitl.*comes? into view. # Paralysis enemies more += .*Giant Eyeball.*comes? into view. more += .*Lich.*comes? into view. more += .*Ogre Mage.*comes? into view. more += .*a Wizard.*comes? into view. more += .*orc sorcerer.*comes? into view. more += .*sphinx.*comes? into view. more += .*Great orb of eyes.*comes? into view. more += .*Vampire knight.*comes? into view. # Other dangerous enemies more += minotaur.*into view more += *guardian serpent.*comes? into view. more += .*vault sentinel.*comes? into view. more += .*vault warden.*comes? into view. more += .*ironbrand convoker.*comes? into view. # Dancing weapon more += Your.*falls from the air. # Xom is scary : if you.god() == "Xom" then more += god: : end #################### # Autoinscriptions # #################### ai := autoinscribe ai += (vampiric):!w ai += (bad|dangerous)_item.*potion:!q ai += (bad|dangerous)_item.*scroll:!r ai += of faith:!P ai += rod of:!a ai += lightning rod:!a ai += [^r]staff of (conj|energy|power|wizardry):!a ai += manual of:!d ai += dispersal:!f ai += tome of Destruction:!d ai += throwing net:!f ai += curare:!f ai += needle of (frenzy|paralysis|sleeping|confusion):!f ai += ration.:!d : if you.god() ~= "Lugonu" then ai += (distortion):!w :end ai += of identify:@r1 ai += remove curse:@r2 ai += curing:@q1 ai += potions? of heal wounds:@q2 ai += wand of heal wounds:@v2 ai += wand of hasting:@v3 ai += potions? of haste:@q3 ai += scrolls? of teleportation:@r4 ai += wand of teleportation:@v4 ai += potions? of blood:@q0 #################### # Mute some messages # #################### msc := message_colour # Muted - unnecessary msc += mute:The (bush|fungus|plant) is engulfed msc += mute:The (bush|fungus|plant) is struck by lightning msc += mute:Cast which spell msc += mute:Use which ability msc += mute:Evoke which item msc += mute:Confirm with # msc += mute:(Casting|Aiming|Aim|Zapping)\: msc += mute:Throwing.*\: msc += mute:You can\'t see any susceptible monsters within range msc += mute:Press\: \? \- help, Shift\-Dir \- straight line, f \- you msc += mute:for a list of commands and other information msc += mute:Firing \(i msc += mute:Fire\/throw which item\? msc += mute:You swap places msc ^= mute:is lightly (damaged|wounded) msc ^= mute:is moderately (damaged|wounded) msc ^= mute:is heavily (damaged|wounded) msc ^= mute:is severely (damaged|wounded) msc ^= mute:is almost (dead|destroyed) msc += mute:Was it this warm in here before msc += mute:The flames dance msc += mute:Your shadow attacks msc += mute:Marking area around msc += mute:Placed new exclusion msc += mute:Reduced exclusion size to a single square msc += mute:Removed exclusion msc += mute:You can access your shopping list by pressing msc += mute:for starvation awaits msc += mute:As you enter the labyrinth msc += mute:previously moving walls settle noisily into place msc += mute:You offer a prayer to Elyvilon msc += mute:You offer a prayer to Nemelex Xobeh msc += mute:You offer a prayer to Okawaru msc += mute:You offer a prayer to Makhleb msc += mute:You offer a prayer to Lugonu msc += mute:Lugonu accepts your kill msc += mute:Okawaru is noncommittal msc += mute:Nemelex Xobeh is (noncommittal|pleased) msc += mute:The plant looks sick msc += mute:You start butchering msc += mute:You continue butchering msc += mute:This raw flesh tastes terrible : if string.find(you.god(), "Jiyva") then msc += mute:You hear a.*slurping noise msc += mute:You hear a.*squelching noise msc += mute:You feel a little less hungry : end ############### # Spell slots # ############### spell_slot += Animate Skeleton:u spell_slot += Animate Dead:u spell_slot += Apportation:c spell_slot += Beastly Appendage:a spell_slot += Blink:b spell_slot += Bolt of Cold:c spell_slot += Bolt of Fire:c spell_slot += Borgnjor's Vile Clutch:f spell_slot += Call Canine Familiar:c spell_slot += Call Imp:x spell_slot += Cause Fear:f spell_slot += Confuse:c spell_slot += Confusing Touch:a spell_slot += Conjure Flame:d spell_slot += Corona:a spell_slot += Corpse Rot:d spell_slot += Dazzling Spray:s spell_slot += Deflect Missiles:r spell_slot += Dispel Undead:d spell_slot += Ensorcelled Hibernation:x spell_slot += Fireball:x spell_slot += Flame Tongue:a spell_slot += Freeze:a spell_slot += Freezing Cloud:d spell_slot += Fulminant Prism:z # spell_slot += Haste:s spell_slot += Ice Form:c spell_slot += Infusion:a spell_slot += Iskenderun's Battlesphere:i spell_slot += Iskenderun's Mystic Blast:x spell_slot += Magic Dart:a spell_slot += Mephitic Cloud:f spell_slot += Olgreb's Toxic Radiance:y spell_slot += Orb of Destruction:zZ spell_slot += Pain:a spell_slot += Passage of Golubria:v spell_slot += Passwall:qQ # spell_slot += Phase Shift:aA spell_slot += Poisonous Vapours:x spell_slot += Portal Projectile:d spell_slot += Regeneration:e # spell_slot += Repel Missiles:r spell_slot += Sandblast:a spell_slot += Searing Ray:s spell_slot += Shock:a spell_slot += Shroud of Golubria:q spell_slot += Silence:g spell_slot += Slow:s spell_slot += Song of Slaying:w spell_slot += Spectral Weapon:t spell_slot += Spider Form:x spell_slot += Static Discharge:d spell_slot += Sticks to Snakes:s spell_slot += Sticky Flame:q spell_slot += Sting:a spell_slot += Stone Arrow:x spell_slot += Sublimation of Blood:Z spell_slot += Summon Butterflies:n spell_slot += Summon Ice Beast:d spell_slot += Summon Lightning Spire:z spell_slot += Summon Mana Viper:w spell_slot += Summon Small Mammal:a spell_slot += Swiftness:s spell_slot += Throw Flame:x spell_slot += Throw Frost:x spell_slot += Throw Icicle:c spell_slot += Tukima's Dance:d spell_slot += Vampiric Draining:q ############### # Item slots # ############### # item_slot += wand of teleportation:g # item_slot += wand of hasting:s # item_slot += wand of heal wounds:e item_slot += wand of digging:v item_slot += wand of disintegration:c # item_slot += wand of confusion:y item_slot += wand of paralysis:u item_slot += wand of iceblast:d item_slot += wand of acid:x # item_slot += wand of lightning:f item_slot += wand of flame:t item_slot += ring of see invisible:z item_slot += ring of protection from magic:l item_slot += ring of protection from fire:i item_slot += ring of protection from cold:o item_slot += ration:e item_slot += potion of blood:q item_slot += poison needle: Q ################# # Ability slots # ################# ability_slot += corrupt:Y #REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE #REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE #MY MACORONS bindkey += [q] CMD_MOVE_UP_LEFT bindkey += [w] CMD_MOVE_UP bindkey += [e] CMD_MOVE_UP_RIGHT bindkey += [a] CMD_MOVE_LEFT bindkey += [d] CMD_MOVE_RIGHT bindkey += [s] CMD_MOVE_DOWN bindkey += [z] CMD_MOVE_DOWN_LEFT bindkey += [c] CMD_MOVE_DOWN_RIGHT bindkey += [Q] CMD_RUN_UP_LEFT bindkey += [W] CMD_RUN_UP bindkey += [E] CMD_RUN_UP_RIGHT bindkey += [A] CMD_RUN_LEFT bindkey += [D] CMD_RUN_RIGHT bindkey += [S] CMD_RUN_DOWN bindkey += [Z] CMD_RUN_DOWN_LEFT bindkey += [C] CMD_RUN_DOWN_RIGHT bindkey += [^Q] CMD_ATTACK_UP_LEFT bindkey += [^W] CMD_ATTACK_UP //bindkey += [^E] CMD_ATTACK_UP_RIGHT bindkey += [^A] CMD_ATTACK_LEFT bindkey += [^D] CMD_ATTACK_RIGHT bindkey += [^S] CMD_ATTACK_DOWN bindkey += [^Z] CMD_ATTACK_DOWN_LEFT bindkey += [^C] CMD_ATTACK_DOWN_RIGHT bindkey += [K] CMD_CLOSE_DOOR bindkey += [r] CMD_USE_ABILITY bindkey += [R] CMD_DISPLAY_MUTATIONS bindkey += [v] CMD_CAST_SPELL bindkey += [V] CMD_FORCE_CAST_SPELL bindkey += [n] CMD_EVOKE_WIELDED bindkey += [N] CMD_EVOKE bindkey += [b] CMD_BUTCHER bindkey += [u] CMD_WIELD_WEAPON bindkey += [U] CMD_WEAR_ARMOUR bindkey += [j] CMD_DROP bindkey += [h] CMD_EAT bindkey += [y] CMD_READ bindkey += [t] CMD_QUAFF bindkey += [T] CMD_QUIVER_ITEM bindkey += [k] CMD_SHOUT bindkey += [^S] CMD_SAVE_GAME bindkey += [q] CMD_TARGET_UP_LEFT bindkey += [w] CMD_TARGET_UP bindkey += [e] CMD_TARGET_UP_RIGHT bindkey += [a] CMD_TARGET_LEFT bindkey += [d] CMD_TARGET_RIGHT bindkey += [s] CMD_TARGET_DOWN bindkey += [z] CMD_TARGET_DOWN_LEFT bindkey += [c] CMD_TARGET_DOWN_RIGHT bindkey += [Q] CMD_TARGET_DIR_UP_LEFT bindkey += [W] CMD_TARGET_DIR_UP bindkey += [E] CMD_TARGET_DIR_UP_RIGHT bindkey += [A] CMD_TARGET_DIR_LEFT bindkey += [D] CMD_TARGET_DIR_RIGHT bindkey += [S] CMD_TARGET_DIR_DOWN bindkey += [Z] CMD_TARGET_DIR_DOWN_LEFT bindkey += [C] CMD_TARGET_DIR_DOWN_RIGHT bindkey += [q] CMD_MAP_MOVE_UP_LEFT bindkey += [w] CMD_MAP_MOVE_UP bindkey += [e] CMD_MAP_MOVE_UP_RIGHT bindkey += [a] CMD_MAP_MOVE_LEFT bindkey += [d] CMD_MAP_MOVE_RIGHT bindkey += [s] CMD_MAP_MOVE_DOWN bindkey += [z] CMD_MAP_MOVE_DOWN_LEFT bindkey += [c] CMD_MAP_MOVE_DOWN_RIGHT bindkey += [Q] CMD_MAP_JUMP_UP_LEFT bindkey += [W] CMD_MAP_JUMP_UP bindkey += [E] CMD_MAP_JUMP_UP_RIGHT bindkey += [A] CMD_MAP_JUMP_LEFT bindkey += [D] CMD_MAP_JUMP_RIGHT bindkey += [S] CMD_MAP_JUMP_DOWN bindkey += [Z] CMD_MAP_JUMP_DOWN_LEFT bindkey += [C] CMD_MAP_JUMP_DOWN_RIGHT bindkey += [8] CMD_MAP_ADD_WAYPOINT bindkey += [^U] CMD_TOGGLE_AUTOPICKUP bindkey += [x] CMD_MAP_EXCLUDE_AREA bindkey += [l] CMD_AUTOFIGHT macros += K1 p ===searchCursor macros += M O ===danceSearched macros += M [ ===pillarDone { crawl.mpr("hello i am my.rc") mon_oks = {} WAYPOINT_NUM = 7 mk = 1 _path = nil _seqForward = nil _seqBackward = nil _seqidx = 0 _dir = true _better = false _xoff = 0 _yoff = 0 _state = "none" function searchCursor() if not crawl.in_map_mode() then crawl.mpr("You must be in map mode to choose a pillar!") return end local x, y = crawl.cursor_pos() if x == nil then crawl.mpr("You must be on the same level as your cursor to choose a pillar!\n") return end pillarDone() doSearch(x, y) if _path ~= nil then _state = "search" else _state = "none" end end function danceSearched() if _state ~= "search" then crawl.mpr("Please find a pillar first.\n") return end doStart() end function pillarDone() if _state == "search" then killPillarTiles() _state = "none" end end function killPillarTiles() _state = "none" local x, y = travel.waypoint_delta(WAYPOINT_NUM) if x == nil or y == nil then crawl.mpr("Stop messing with my waypoints!\n") return end local pathTiles = {} for i, t in ipairs(_path) do pathTiles[{t[1] - x, t[2] - y}] = true end hideTiles(pathTiles) end function doStart() if _path == nil then crawl.mpr("No search selected!\n") return end local x, y = travel.waypoint_delta(WAYPOINT_NUM) if x == nil or y == nil then crawl.mpr("Stop messing with my waypoints!\n") return end local path = _path local idx = 0 for i, xy in ipairs(path) do if xy[1] == x and xy[2] == y then idx = i break end end if idx == 0 then crawl.mpr("Please step on one of the excluded tiles.\n") return end startPillarDance() _seqForward = getSeq(path) _seqBackward = getSeqBackwards(path) _seqidx = idx end do local toOff function getOffset(cmd) toOff = toOff or {CMD_MOVE_UP_LEFT={-1, -1}, CMD_MOVE_UP_RIGHT={1, -1}, CMD_MOVE_DOWN_LEFT={-1, 1}, CMD_MOVE_DOWN_RIGHT={1, 1}, CMD_MOVE_UP={0, -1}, CMD_MOVE_DOWN={0, 1}, CMD_MOVE_LEFT={-1, 0}, CMD_MOVE_RIGHT={1, 0} } return toOff[cmd] end end function is_ok() local ch = crawl.getch() return ch == 121 or ch == 89 end function doNextAction() if not shouldDance() then stopPillarDance() return end assert(_seqForward ~= nil) assert(_seqBackward ~= nil) assert(_seqidx ~= 0) local monsters = getAllMonsters() for n, _ in pairs(mon_oks) do crawl.mpr(n) crawl.mpr(type(n)) end for i, mon in ipairs(monsters) do if string.find(mon:speed_description(), "fast") then crawl.mpr("Fast monster in LOS!\n") stopPillarDance() return end if not mon_oks[mon:name()] and (#(mon:spells()) ~= 0 or mon:has_known_ranged_attack()) then crawl.mpr("Spellcaster/ranged/abilityperson " .. mon:name() .. " in LOS!\n") if crawl.yesno("Is this OK?", true) then mon_oks[mon:name()] = true assert(mon_oks[mon:name()]) else stopPillarDance() return end end if mon:status("fast") or mon:status("covering ground quickly") then crawl.mpr("Hasted/berserked/swifting monster in LOS!\n") stopPillarDance() return end end crawl.mpr("Num monsters: " .. #monsters) local x, y, xdir, ydir, xndir, yndir if _dir then local xy = getOffset(_seqForward[_seqidx]) x = xy[1] y = xy[2] xdir, ydir = x, y else assert(not _dir) local xy = getOffset(_seqBackward[_seqidx]) x = xy[1] y = xy[2] xdir, ydir = x, y end if not tileIsBetter(x, y, monsters) then if not _dir then local xy = getOffset(_seqForward[_seqidx]) x = xy[1] y = xy[2] xndir, yndir = x, y else assert(_dir) local xy = getOffset(_seqBackward[_seqidx]) x = xy[1] y = xy[2] xndir, yndir = x, y end _dir = not _dir if not tileIsBetter(x, y, monsters) then _dir = not _dir x, y = xdir, ydir if not tileIsGood(x, y, monsters) then _dir = not _dir x, y = xndir, yndir if not tileIsGood(x, y, monsters) then crawl.mpr("No good choices to walk!\n") stopPillarDance() return end end end end if not travel.feature_traversable(view.feature_at(x, y)) then crawl.mpr("Path is no longer traversable!\n") stopPillarDance() return end local nextAction if _dir then nextAction = _seqForward[_seqidx] _seqidx = _seqidx + 1 if _seqidx > #_seqForward then _seqidx = 1 end else assert(not _dir) nextAction = _seqBackward[_seqidx] _seqidx = _seqidx - 1 if _seqidx < 1 then _seqidx = #_seqBackward end end crawl.do_commands({nextAction}) end _lastHp = nil function shouldDance() if you.slowed() then crawl.mpr("You're moving too slowly!\n") return false end local cur, max = you.hp() cur = you.poison_survival() or cur local curm, maxm = you.mp() if cur == max and curm == maxm then crawl.mpr("HP and MP regained.\n") return false end if _lastHp and cur < _lastHp then crawl.mpr("You've been hit!\n") return false end if you.hunger_name() == "Starving" then crawl.mpr("You're starving!\n") return false end _lastHp = cur return true end _pillarDance = false function startPillarDance() _pillarDance = true end function stopPillarDance() _pillarDance = false _lastHp = nil end function ready() if _pillarDance then doNextAction() end end function is_candidate_for_attack(m) if not m or m:attitude() ~= 0 then return false end if m:name() == "butterfly" then return false end if m:is_firewood() then --crawl.mpr("... is firewood.") if string.find(m:name(), "ballistomycete") then return true end return false end return true end function getAllMonsters() local monsters = {} local los = you.los() for x_off=-los,los do for y_off=-los,los do if view.cell_see_cell(0, 0, x_off, y_off) then local mon = monster.get_monster_at(x_off, y_off) if is_candidate_for_attack(mon) then monsters[#monsters + 1] = mon end end end end return monsters end function tileIsGood(x, y, monsters) for i, mon in ipairs(monsters) do local d_cur = getDist(0, 0, mon:x_pos(), mon:y_pos()) local d_xy = getDist(x, y, mon:x_pos(), mon:y_pos()) if (d_cur > d_xy or d_xy <= 1) and view.cell_see_cell(x, y, mon:x_pos(), mon:y_pos()) then return false end end return true end function tileIsBetter(x, y, monsters) for i, mon in ipairs(monsters) do if getDist(0, 0, mon:x_pos(), mon:y_pos()) >= getDist(x, y, mon:x_pos(), mon:y_pos()) and view.cell_see_cell(x, y, mon:x_pos(), mon:y_pos()) then return false end end return true end function doSearch(x, y) local pillar = create(x, y) if pillar == nil then return nil end if pillar.tiles == nil then return nil end local xmin, ymin, xmax, ymax = getBbox(pillar.tiles) local x1, y1, x2, y2 = findTwoTilesOnBorder(pillar.tiles, xmin, ymin, xmax, ymax) local tileset = getTilesInBox(xmin, ymin, xmax, ymax) local path = getPath(tileset, x1, y1, x2, y2) -- hide that pathway by setting tiles necessary for it to walls, then path again local next = path[2] if x1 == xmin then mk.put(tileset, x1, next[2], false) mk.put(tileset, x1+1, next[2], false) elseif x1 == xmax then mk.put(tileset, x1, next[2], false) mk.put(tileset, x1-1, next[2], false) elseif y1 == ymin then mk.put(tileset, next[1], y1, false) mk.put(tileset, next[1], y1+1, false) elseif y1 == ymax then mk.put(tileset, next[1], y1, false) mk.put(tileset, next[1], y1-1, false) end local path2 = getPath(tileset, x1, y1, x2, y2) reverse(path2) local prevlen = #path -- skip first and last parts of path because those are dupes for i=2,(#path2-1) do path[prevlen + i - 1] = path2[i] end local pathTiles = {} for i, t in ipairs(path) do pathTiles[t] = true end showTiles(pathTiles) _path = path travel.set_waypoint(7, 0, 0) return path end function getSeq(path) local seq = {} for i, s in ipairs(path) do local t = path[(i + 1)] if i == #path then t = path[1] end local n if t[1]==s[1] and t[2]==s[2]+1 then n = "CMD_MOVE_DOWN" elseif t[1]==s[1] and t[2]==s[2]-1 then n = "CMD_MOVE_UP" elseif t[1]==s[1]+1 and t[2]==s[2] then n = "CMD_MOVE_RIGHT" elseif t[1]==s[1]-1 and t[2]==s[2] then n = "CMD_MOVE_LEFT" elseif t[1]==s[1]+1 and t[2]==s[2]+1 then n = "CMD_MOVE_DOWN_RIGHT" elseif t[1]==s[1]+1 and t[2]==s[2]-1 then n = "CMD_MOVE_UP_RIGHT" elseif t[1]==s[1]-1 and t[2]==s[2]+1 then n = "CMD_MOVE_DOWN_LEFT" elseif t[1]==s[1]-1 and t[2]==s[2]-1 then n = "CMD_MOVE_UP_LEFT" end seq[i] = n end return seq end function getSeqBackwards(path) local seq = {} for i, s in ipairs(path) do local t = path[(i - 1)] if i == 1 then t = path[#path] end local n if t[1]==s[1] and t[2]==s[2]+1 then n = "CMD_MOVE_DOWN" elseif t[1]==s[1] and t[2]==s[2]-1 then n = "CMD_MOVE_UP" elseif t[1]==s[1]+1 and t[2]==s[2] then n = "CMD_MOVE_RIGHT" elseif t[1]==s[1]-1 and t[2]==s[2] then n = "CMD_MOVE_LEFT" elseif t[1]==s[1]+1 and t[2]==s[2]+1 then n = "CMD_MOVE_DOWN_RIGHT" elseif t[1]==s[1]+1 and t[2]==s[2]-1 then n = "CMD_MOVE_UP_RIGHT" elseif t[1]==s[1]-1 and t[2]==s[2]+1 then n = "CMD_MOVE_DOWN_LEFT" elseif t[1]==s[1]-1 and t[2]==s[2]-1 then n = "CMD_MOVE_UP_LEFT" end seq[i] = n end return seq end function getTilesInBox(xmin, ymin, xmax, ymax) local tiles = {} for x=xmin,xmax do for y=ymin,ymax do mk.put(tiles, x, y, travel.feature_traversable(view.feature_at(x, y))) end end return tiles end function create(x, y) local pillar = {} pillar.tiles = getNeighboringTraversable(floodFillType(x, y, "wall")); return pillar end function showTiles(tiles) for xy, _ in pairs(tiles) do local x = xy[1] local y = xy[2] travel.set_exclude(x, y, 0) end end function printTiles(tiles) for i, xy in ipairs(tiles) do crawl.mpr("(" .. xy[1] .. ", " .. xy[2] .. ")") end end function hideTiles(tiles) for xy, _ in pairs(tiles) do local x = xy[1] local y = xy[2] travel.del_exclude(x, y) end end function has(l, t) for k, _ in pairs(l) do print(k) if k[1] == t[1] and k[2] == t[2] then return true end end return false end function floodFillType(x, y, type) local ff = floodFillTypeHelper(x, y, type, {}, {0}) return ff end function floodFillTypeHelper(x, y, type, used, counter) if has(used, {x, y}) or travel.feature_traversable(view.feature_at(x, y)) then return used end counter[1] = counter[1] + 1 if counter[1] >= 1000 then crawl.mpr("Pillar too large! Did you select a map border?\n") return nil end used[{x, y}] = true local n_pos = {} n_pos[{0, 1}] = true n_pos[{0, -1}] = true n_pos[{1, 0}] = true n_pos[{-1, 0}] = true for oxoy, _ in pairs(n_pos) do local off_x = oxoy[1] local off_y = oxoy[2] local ff = floodFillTypeHelper(x+off_x, y+off_y, type, used, counter) if ff == nil then return nil end end return used end function getNeighboringTraversable(tiles) local neighbors = {} local n_pos = {} n_pos[{0, 1}] = true n_pos[{0, -1}] = true n_pos[{1, 0}] = true n_pos[{-1, 0}] = true for xy, _ in pairs(tiles) do local x = xy[1] local y = xy[2] for oxoy, _ in pairs(n_pos) do local off_x = oxoy[1] local off_y = oxoy[2] if travel.feature_traversable(view.feature_at(x+off_x, y+off_y)) then if not has(neighbors, {x+off_x, y+off_y}) then neighbors[{x+off_x, y+off_y}] = true end end end end return neighbors end function getBbox(tiles) local xmin = math.huge local xmax = -math.huge local ymin = math.huge local ymax = -math.huge for tile, _ in pairs(tiles) do local x = tile[1] local y = tile[2] if x > xmax then xmax = x end if x < xmin then xmin = x end if y > ymax then ymax = y end if y < ymin then ymin = y end end return xmin, ymin, xmax, ymax end function tilesOneApart(x1, y1, x2, y2) return math.abs(x1 - x2) <= 1 and math.abs(y1 - y2) <= 1 end function findTwoTilesOnBorder(tiles, xmin, ymin, xmax, ymax) local t1found = false local t1 = nil for tile, _ in pairs(tiles) do local x = tile[1] local y = tile[2] if (x == xmin or x == xmax or y == ymin or y == ymax) then if t1found then if not tilesOneApart(t1[1], t1[2], x, y) then return t1[1], t1[2], x, y end else t1found = true t1 = {x, y} end end end return nil end function getDist(x1, y1, x2, y2) return math.max(math.abs(x1 - x2), math.abs(y1 - y2)) end function getNeighboring(tileset, x, y) local neighbors = {} for ox=-1,1 do for oy=-1,1 do if mk.get(tileset, x+ox, y+oy) ~= nil and not (ox == 0 and oy == 0) then neighbors[{x+ox, y+oy}] = true end end end return neighbors end function getMinTile(nodes, dist) local m = 100000 local t = nil for _, x, y, __ in mk.tuples(nodes) do local cost = mk.get(dist, x, y) if cost ~= nil and cost <= m then m = cost t = {x, y} end end return t end function getPath(tileset, x1, y1, x2, y2) local dist = {} local nodes = {} local prev = {} for _, x, y, trav in mk.tuples(tileset) do if trav then mk.put(dist, x, y, 10000) mk.put(nodes, x, y, true) --crawl.mpr("set: x = " .. x .. " y = " .. y) end end mk.put(dist, x1, y1, 0) while next(nodes) ~= nil do local u = getMinTile(nodes, dist) mk.put(nodes, u[1], u[2], nil) --crawl.mpr("Getting next: x = " .. u[1] .. " y = " .. u[2]) if u[1] == x2 and u[2] == y2 then if mk.get(prev, u[1], u[2]) == nil then crawl.mpr("PANIC U NOT IN PREV") assert(false) end return parsePrev(prev, x1, y1, x2, y2) end for v, _ in pairs(getNeighboring(nodes, u[1], u[2])) do --crawl.mpr("Neighbor: x = " .. v[1] .. " y = " .. v[2]) local altDist = mk.get(dist, u[1], u[2]) + 1 if mk.get(dist, v[1], v[2]) == nil or altDist < mk.get(dist, v[1], v[2]) then mk.put(dist, v[1], v[2], altDist) mk.put(prev, v[1], v[2], u) if u == nil then crawl.mpr("WTF") assert(false) end end end end return nil end function parsePrev(prev, x1, y1, x2, y2) local path = {} local i = 2 local u = {x2, y2} path[1] = u while not (u[1] == x1 and u[2] == y1) do u = mk.get(prev, u[1], u[2]) if u == nil then crawl.mpr("BAD PATH!") return nil end path[i] = u i = i + 1 end reverse(path) return path end function reverse (arr) local i, j = 1, #arr while i < j do arr[i], arr[j] = arr[j], arr[i] i = i + 1 j = j - 1 end end local function getMk() -- simple table adaptor for using multiple keys in a lookup table -- cache some global functions/tables for faster access local assert = assert local select = assert( select ) local next = assert( next ) local setmetatable = assert( setmetatable ) -- sentinel values for the key tree, nil keys, and nan keys local KEYS, NIL, NAN = {}, {}, {} local M = {} local M_meta = { __index = M } function M.new() return setmetatable( { [ KEYS ] = {} }, M_meta ) end setmetatable( M, { __call = M.new } ) function M.clear( t ) for k in next, t do t[ k ] = nil end return t end -- local helper function to map a vararg of keys to the real key local function get_key( key, ... ) for i = 1, select( '#', ... ) do if key == nil then break end local e = select( i, ... ) if e == nil then e = NIL elseif e ~= e then -- can only happen for NaNs e = NAN end key = key[ e ] end return key end function M.get( t, ... ) local key = get_key( t[ KEYS ], ... ) if key ~= nil then return t[ key ] end return nil end -- local helper function for both put variants below local function put( t, idx, val, n, ... ) for i = 1, n do local e = select( i, ... ) if e == nil then e = NIL elseif e ~= e then -- can only happen for NaNs e = NAN end local nextidx = idx[ e ] if not nextidx then nextidx = {} idx[ e ] = nextidx end idx = nextidx end t[ idx ] = val end -- returns true if tab can be removed from the parent table local function del( t, idx, n, ... ) if n > 0 then local e = ... if e == nil then e = NIL elseif e ~= e then -- can only happen for NaNs e = NAN end local nextidx = idx[ e ] if nextidx and del( t, nextidx, n-1, select( 2, ... ) ) then idx[ e ] = nil return t[ idx ] == nil and next( idx ) == nil end return false else t[ idx ] = nil return next( idx ) == nil end end function M.put( t, ... ) local n, keys, val = select( '#', ... ), t[ KEYS ], nil if n > 0 then val = select( n, ... ) n = n - 1 end if val == nil then if keys ~= nil then del( t, keys, n, ... ) end else if keys == nil then keys = {} t[ KEYS ] = keys end put( t, keys, val, n, ... ) end return t end -- same as M.put, but value comes first not last function M.putv( t, val, ... ) local keys = t[ KEYS ] if val == nil then if keys ~= nil then del( t, keys, select( '#', ... ), ... ) end else if keys == nil then keys = {} t[ KEYS ] = keys end put( t, keys, val, select( '#', ... ), ... ) end return t end -- iteration is only available with coroutine support if coroutine ~= nil then local unpack = assert( unpack or table.unpack ) local pairs = assert( pairs ) local ipairs = assert( ipairs ) local co_yield = assert( coroutine.yield ) local co_wrap = assert( coroutine.wrap ) -- internal iterator function local function iterate( iter, t, key, keystack, n ) if t[ key ] ~= nil then keystack[ n+1 ] = t[ key ] co_yield( unpack( keystack, 1, n+1 ) ) end for k,v in iter( key ) do if k == NIL then k = nil elseif k == NAN then k = 0/0 end keystack[ n+1 ] = k iterate( iter, t, v, keystack, n+1 ) end return nil end -- iterator similar to pairs, but since we have multiple keys ... function M.tuples( t, ... ) local vals, n = { true, ... }, select( '#', ... )+1 return co_wrap( function() local key = get_key( t[ KEYS ], unpack( vals, 2, n ) ) if key ~= nil then return iterate( pairs, t, key, vals, n ) end end ) end function M.ituples( t, ... ) local vals, n = { ... }, select( '#', ... ) return co_wrap( function() local key = get_key( t[ KEYS ], unpack( vals, 1, n ) ) if key ~= nil then return iterate( ipairs, t, key, vals, n ) end end ) end -- Lua 5.2 metamethods for iteration M_meta.__pairs = M.tuples M_meta.__ipairs = M.ituples end return M end mk = getMk() } { function print_wd() local x, y = travel.waypoint_delta(7) crawl.mpr(x) crawl.mpr(y) end }