summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/CREDITS.txt8
-rw-r--r--crawl-ref/docs/develop/levels/advanced.txt17
-rw-r--r--crawl-ref/docs/develop/levels/syntax.txt2
-rw-r--r--crawl-ref/docs/develop/levels/triggerables.txt515
-rwxr-xr-xcrawl-ref/dolinks.sh12
-rw-r--r--crawl-ref/source/abl-show.cc22
-rw-r--r--crawl-ref/source/abyss.cc51
-rw-r--r--crawl-ref/source/acr.cc72
-rw-r--r--crawl-ref/source/actor-los.cc5
-rw-r--r--crawl-ref/source/actor.h5
-rw-r--r--crawl-ref/source/arena.cc69
-rw-r--r--crawl-ref/source/art-data.h196
-rw-r--r--crawl-ref/source/art-data.txt26
-rw-r--r--crawl-ref/source/art-func.h20
-rw-r--r--crawl-ref/source/artefact.cc6
-rw-r--r--crawl-ref/source/artefact.h4
-rw-r--r--crawl-ref/source/attitude-change.cc271
-rw-r--r--crawl-ref/source/beam.cc122
-rw-r--r--crawl-ref/source/cloud.cc2
-rw-r--r--crawl-ref/source/clua.cc1
-rw-r--r--crawl-ref/source/cmd-keys.h1
-rw-r--r--crawl-ref/source/cmd-name.h1
-rw-r--r--crawl-ref/source/command.cc3
-rw-r--r--crawl-ref/source/coord-circle.cc2
-rw-r--r--crawl-ref/source/dat/altar.des328
-rw-r--r--crawl-ref/source/dat/clua/lm_trig.lua4
-rw-r--r--crawl-ref/source/dat/database/monspeak.txt14
-rw-r--r--crawl-ref/source/dat/descript/monsters.txt2
-rw-r--r--crawl-ref/source/dat/entry.des8
-rw-r--r--crawl-ref/source/dat/float.des28
-rw-r--r--crawl-ref/source/dat/icecave.des146
-rw-r--r--crawl-ref/source/dat/mini.des33
-rw-r--r--crawl-ref/source/dat/pan.des36
-rw-r--r--crawl-ref/source/dat/shrine.des406
-rw-r--r--crawl-ref/source/dat/temple.des333
-rw-r--r--crawl-ref/source/dat/uniques.des76
-rw-r--r--crawl-ref/source/dat/volcano.des5
-rw-r--r--crawl-ref/source/dbg-util.cc2
-rw-r--r--crawl-ref/source/decks.cc53
-rw-r--r--crawl-ref/source/delay.cc4
-rw-r--r--crawl-ref/source/describe.cc49
-rw-r--r--crawl-ref/source/directn.cc21
-rw-r--r--crawl-ref/source/dungeon.cc238
-rw-r--r--crawl-ref/source/dungeon.h11
-rw-r--r--crawl-ref/source/effects.cc88
-rw-r--r--crawl-ref/source/enum.h40
-rw-r--r--crawl-ref/source/exclude.cc46
-rw-r--r--crawl-ref/source/fight.cc16
-rw-r--r--crawl-ref/source/files.cc4
-rw-r--r--crawl-ref/source/fixary.h50
-rw-r--r--crawl-ref/source/fixvec.h5
-rw-r--r--crawl-ref/source/ghost.cc19
-rw-r--r--crawl-ref/source/godabil.cc21
-rw-r--r--crawl-ref/source/goditem.cc18
-rw-r--r--crawl-ref/source/goditem.h1
-rw-r--r--crawl-ref/source/godwrath.cc27
-rw-r--r--crawl-ref/source/hiscores.cc76
-rw-r--r--crawl-ref/source/hiscores.h12
-rw-r--r--crawl-ref/source/it_use2.cc4
-rw-r--r--crawl-ref/source/it_use3.cc13
-rw-r--r--crawl-ref/source/item_use.cc93
-rw-r--r--crawl-ref/source/itemname.cc24
-rw-r--r--crawl-ref/source/itemname.h6
-rw-r--r--crawl-ref/source/itemprop.cc4
-rw-r--r--crawl-ref/source/items.cc4
-rw-r--r--crawl-ref/source/kills.cc2
-rw-r--r--crawl-ref/source/l_defs.h1
-rw-r--r--crawl-ref/source/l_dgnmon.cc4
-rw-r--r--crawl-ref/source/l_libs.h1
-rw-r--r--crawl-ref/source/l_mons.cc34
-rw-r--r--crawl-ref/source/l_travel.cc54
-rw-r--r--crawl-ref/source/lev-pand.cc2
-rw-r--r--crawl-ref/source/makefile56
-rw-r--r--crawl-ref/source/makefile.obj8
-rw-r--r--crawl-ref/source/makeitem.cc31
-rw-r--r--crawl-ref/source/mapdef.cc101
-rw-r--r--crawl-ref/source/mapdef.h3
-rw-r--r--crawl-ref/source/maps.cc6
-rw-r--r--crawl-ref/source/matrix.h59
-rw-r--r--crawl-ref/source/menu.cc2
-rw-r--r--crawl-ref/source/message.cc2
-rw-r--r--crawl-ref/source/mgrow.cc4
-rw-r--r--crawl-ref/source/misc.cc37
-rw-r--r--crawl-ref/source/misc/src-pkg-excludes.lst14
-rw-r--r--crawl-ref/source/mon-abil.cc117
-rw-r--r--crawl-ref/source/mon-act.cc40
-rw-r--r--crawl-ref/source/mon-behv.cc15
-rw-r--r--crawl-ref/source/mon-cast.cc108
-rw-r--r--crawl-ref/source/mon-data.h14
-rw-r--r--crawl-ref/source/mon-gear.cc4
-rw-r--r--crawl-ref/source/mon-info.cc2
-rw-r--r--crawl-ref/source/mon-info.h2
-rw-r--r--crawl-ref/source/mon-iter.cc87
-rw-r--r--crawl-ref/source/mon-iter.h49
-rw-r--r--crawl-ref/source/mon-place.cc (renamed from crawl-ref/source/monplace.cc)205
-rw-r--r--crawl-ref/source/mon-place.h (renamed from crawl-ref/source/monplace.h)28
-rw-r--r--crawl-ref/source/mon-speak.cc (renamed from crawl-ref/source/monspeak.cc)60
-rw-r--r--crawl-ref/source/mon-speak.h (renamed from crawl-ref/source/monspeak.h)3
-rw-r--r--crawl-ref/source/mon-spll.h6
-rw-r--r--crawl-ref/source/mon-stuff.cc (renamed from crawl-ref/source/monstuff.cc)298
-rw-r--r--crawl-ref/source/mon-stuff.h (renamed from crawl-ref/source/monstuff.h)4
-rw-r--r--crawl-ref/source/mon-util.cc21
-rw-r--r--crawl-ref/source/monster.cc52
-rw-r--r--crawl-ref/source/monster.h7
-rw-r--r--crawl-ref/source/mtransit.cc2
-rw-r--r--crawl-ref/source/newgame.cc5
-rw-r--r--crawl-ref/source/ng-init.cc127
-rw-r--r--crawl-ref/source/ng-init.h1
-rw-r--r--crawl-ref/source/ouch.cc66
-rw-r--r--crawl-ref/source/output.cc2
-rw-r--r--crawl-ref/source/player.cc39
-rw-r--r--crawl-ref/source/player.h3
-rw-r--r--crawl-ref/source/religion.cc75
-rw-r--r--crawl-ref/source/religion.h2
-rw-r--r--crawl-ref/source/rltiles/dc-player.txt1
-rw-r--r--crawl-ref/source/rltiles/dc-unrand.txt28
-rw-r--r--crawl-ref/source/rltiles/item/weapon/artefact/urand_cutlass.pngbin0 -> 972 bytes
-rw-r--r--crawl-ref/source/rltiles/item/weapon/artefact/urand_storm_bow.pngbin0 -> 625 bytes
-rw-r--r--crawl-ref/source/rltiles/player/hand1/artefact/cutlass.pngbin0 -> 209 bytes
-rw-r--r--crawl-ref/source/rltiles/tiledef-unrand.cc4
-rw-r--r--crawl-ref/source/rng.cc6
-rw-r--r--crawl-ref/source/shout.cc132
-rw-r--r--crawl-ref/source/spells1.cc42
-rw-r--r--crawl-ref/source/spells2.cc162
-rw-r--r--crawl-ref/source/spells3.cc62
-rw-r--r--crawl-ref/source/spells3.h2
-rw-r--r--crawl-ref/source/spells4.cc16
-rw-r--r--crawl-ref/source/spl-book.cc10
-rw-r--r--crawl-ref/source/spl-cast.cc35
-rw-r--r--crawl-ref/source/spl-data.h19
-rw-r--r--crawl-ref/source/spl-mis.cc10
-rw-r--r--crawl-ref/source/stash.cc2
-rw-r--r--crawl-ref/source/store.cc151
-rw-r--r--crawl-ref/source/store.h19
-rw-r--r--crawl-ref/source/stuff.cc35
-rw-r--r--crawl-ref/source/stuff.h2
-rw-r--r--crawl-ref/source/tags.cc23
-rw-r--r--crawl-ref/source/tags.h5
-rw-r--r--crawl-ref/source/terrain.cc4
-rw-r--r--crawl-ref/source/tilepick.cc8
-rw-r--r--crawl-ref/source/tilereg.cc5
-rw-r--r--crawl-ref/source/tilereg.h1
-rw-r--r--crawl-ref/source/traps.cc2
-rw-r--r--crawl-ref/source/travel.cc2
-rw-r--r--crawl-ref/source/tutorial.cc1
-rwxr-xr-xcrawl-ref/source/util/art-data.pl4
-rw-r--r--crawl-ref/source/view.cc101
-rw-r--r--crawl-ref/source/viewmap.cc11
-rw-r--r--crawl-ref/source/wiz-dgn.cc44
-rw-r--r--crawl-ref/source/wiz-fsim.cc7
-rw-r--r--crawl-ref/source/wiz-item.cc26
-rw-r--r--crawl-ref/source/wiz-mon.cc28
-rw-r--r--crawl-ref/source/xom.cc138
153 files changed, 4424 insertions, 2390 deletions
diff --git a/crawl-ref/CREDITS.txt b/crawl-ref/CREDITS.txt
index 5d295dd7a3..359268d66e 100644
--- a/crawl-ref/CREDITS.txt
+++ b/crawl-ref/CREDITS.txt
@@ -40,8 +40,8 @@ Rob Grant Arien Malec William Tanksley, Jr.
John Greenberg Paul Maloney Marc H. Thoben
GreyKnight Neil 'Mu' Middleton Matt Titus
Joshua Gross Shawn M Moore Steven Wheeler
-Brian Haase Eva Myers Jeremey Wilson
-Shayne Halvorson Wille Mäntylä Yelve Yakut
-Ciaran Hamilton Erkki Nurmi Zooko
-Chris Hamons Mattias Nyberg
+Brian Haase Eva Myers Thomas Willem
+Shayne Halvorson Wille Mäntylä Jeremey Wilson
+Ciaran Hamilton Erkki Nurmi Yelve Yakut
+Chris Hamons Mattias Nyberg Zooko
diff --git a/crawl-ref/docs/develop/levels/advanced.txt b/crawl-ref/docs/develop/levels/advanced.txt
index 361116cc6c..a9d986daf6 100644
--- a/crawl-ref/docs/develop/levels/advanced.txt
+++ b/crawl-ref/docs/develop/levels/advanced.txt
@@ -14,7 +14,7 @@ Contents: I. Conditionalising levels
O. Map generation
This document describes the advanced features of vault making. This includes
-usage of lua and how to create portal vaults.
+usage of lua and how to create portal vaults. Triggerables are covered in a separate document: triggerables.txt.
I. Conditionalising levels
@@ -703,12 +703,22 @@ dungeon cell which they are on:
forcing them to open and close as separate doors. See the Evil
Zoo (minivault_9) in dat/mini.des for an example.
+* door_description_prefix: A string to prepend to the description of
+ any door the marker is on. This should be used for doors
+ rather than the feature_description property since it elemintates
+ the need to track if the door is opened or closed, plus it will
+ have no effect on secret doors which have yet to be detected.
+
* door_description_suffix: A string to append to the description of
any door the marker is on. This should be used for doors
rather than the feature_description property since it elemintates
the need to track if the door is opened or closed, plus it will
have no effect on secret doors which have yet to be detected.
+* door_open_prompt: If placed on top of a door, the use will be prompted
+ before opening the door, with the value of the property used as
+ the prompt string.
+
* feature_description: What to use as the short description of the
cell's feature.
@@ -869,8 +879,9 @@ O. Map Generation
Full-debug Crawl builds (see above for more information) include a test for
generating specific vaults and outputting a copy of the map to a text file for
-inspection. This is most useful for portal and other encompass vaults which
-use randomisation heavily.
+inspection (you can also define the macro DEBUG_TESTS on an ordinary debug
+build, like "make EXTERNAL_DEFINES=-DDEBUG_TESTS wizard"). This is most useful
+for portal and other encompass vaults which use randomisation heavily.
To use the test, you must edit source/test/vault_generation.lua. Fill in the
following variables:
diff --git a/crawl-ref/docs/develop/levels/syntax.txt b/crawl-ref/docs/develop/levels/syntax.txt
index bd3e8b5000..1a1f7aff5d 100644
--- a/crawl-ref/docs/develop/levels/syntax.txt
+++ b/crawl-ref/docs/develop/levels/syntax.txt
@@ -11,7 +11,7 @@ Contents: G. Glyphs
This document contains the syntax needed for making maps and vaults. It
does not say anything about principles of vault making; for this, see
introduction.txt. For more technical aspects, including tests, lua and
-portal vaults, refer to advanced.txt.
+portal vaults, refer to advanced.txt. For Triggerables, please see triggerables.txt.
G. Glyphs
===========
diff --git a/crawl-ref/docs/develop/levels/triggerables.txt b/crawl-ref/docs/develop/levels/triggerables.txt
new file mode 100644
index 0000000000..d2c540cf95
--- /dev/null
+++ b/crawl-ref/docs/develop/levels/triggerables.txt
@@ -0,0 +1,515 @@
+How to make levels for Dungeon Crawl Stone Soup
+-----------------------------------------------
+
+Part IV: TRIGGERABLES
+ ============
+
+Contents: A. Introduction
+ B. Sample syntax
+ C. Examples of usage
+ D. Convenience functions
+ E. List of triggerers
+ F. Master and slaves
+
+This document describes the usage of Triggerables, a modular, extensible and
+highly flexible Lua marker systen used for making vaults. For more general
+syntax and other advanced Lua topics, see introduction.txt, syntax.txt and
+advanced.txt.
+
+A. Introduction
+=================
+
+Triggerables are an event-driven framework that can be used to further randomise
+Dungeon Crawl Stone Soup maps, specifically at runtime. They can be used in
+every-day minivaults, portal vaults, branch endings and more.
+
+You've probably already used Triggerables in vaults, or seen them in action:
+FogMachines are a randomised Triggerable, while the removal of no
+controlled-teleport from some branch ends upon pickup of the rune is achieved
+through a Triggerable. These often used Triggerables are wrapped in convenience
+functions (see section D).
+
+However, Triggerables can be combined with pre-defined Lua functions to achieve
+extremely complicated game mechanics: in the "Collapsing Caverns" Volcano vault,
+they are used to randomly close cave entrances, while in the "Overflow" Volcano
+vault, they are used to increase and decrease the amount of lava present.
+
+Triggerables are usually only limited by the amount of triggers (see
+the list in section E), and Lua wrappers available. As these are constantly
+increasing, you are really only limited by imagination and vault design ethics.
+
+Sections B and C cover customised Triggerables (using examples from the Volcano
+portal vaults), while section D covers convenience functions (using examples
+from Branch ends).
+
+B. Sample syntax
+==================
+
+Customised Triggerers usually use the non-abstracted TriggerableFunction
+mechanic. Consider this (trimmed) example from the Volcano portal vault (see
+dat/volcano.des for the full vault):
+
+-----------------------------
+
+{{
+local function collapse_doorways (data, triggerable, triggerer, marker, ev)
+ if triggerer.type ~= "turn" or triggerer.sub_type ~= "countdown" then
+ return
+ end
+
+ [Doorway collapse code]
+
+ -- Don't collapse same doorway twice.
+ triggerable:remove(marker)
+end
+
+local collapse_marker = TriggerableFunction:new (
+ {
+ func=collapse_doorways,
+ repeated=true,
+ props = {
+ -- Only collapse one doorway at a time, randomly.
+ single_random_slave="true"
+ }
+ }
+)
+
+collapse_marker:add_triggerer(DgnTriggerer:new {
+ type="turn",
+ delay_min=50,
+ delay_max=200
+})
+
+}}
+
+-----------------------------
+
+As you can see, a TriggerableFunction consists of three parts: firstly, the
+function that is to be triggered, which is provided five parameters:
+
+ * data, a pre-defined Lua table which can be used for persistent data storage.
+ * triggerable, the instance of the Triggerable that is triggering the
+ function.
+ * triggerer, the instance of the DgnTriggerer that has fired
+ * marker, the marker object
+ * ev, the event object
+
+In most instances, the used parameters are "data", "triggerer" and "marker". The
+first of these allows for the storage of any function-required data persistently
+(such as the number of doorways already collapsed, the number of doorways left
+to collapse, etc).
+
+"Triggerer" is regularly used in randomised functions to determine whether or
+not the function is actually being fired. For example, if the Triggerer is not
+of the "turns" type and "countdown" subtype; see the WarningMachines in
+dat/clua/lm_fog.lua for examples of functions being triggered randomly, and
+being triggered a certain number of turns before a FogMachine is fired).
+
+Finally, "marker" is usually used to determine the position of the Triggerable
+by colling the "marker:pos()" function.
+
+-----------------------------
+
+The second part of the TriggerableFunction is the actual marker. In this case,
+it is an instance of TriggerableFunction, called via TriggerableFunction:new.
+This requires the "func" parameter, the name of the function that is to be
+called.
+
+It also optionally takes the following parameters: "repeated" which defaults to
+'false': a non-repeated Triggerable will be removed after its first firing, and
+will not be subsequently fired.
+
+"props". A table consisting of one or more properties. In this instance takes
+the "single_random_slave" parameter, which is linked into Master and Slave
+mechanics (see Section F).
+
+"data". A table consisting of data used by the function. This defaults to a
+blank table, but can be specified with on creation of the marker. (See the
+"Overflow" Volcano map in dat/volcano.des).
+
+-----------------------------
+
+The third and final part of the Triggerable is the actual trigger itself: this
+is an instance of DgnTriggerer, and is added to the marker with the
+"add_triggerer" function. See section E, "List of triggerers" for more
+information.
+
+-----------------------------
+
+In our example, all of this combined creates a Triggerable which does the
+following (ignoring the master/slave mechanics):
+
+1. Randomly every "50" and "200" "turns"[1]
+2. Pick a random slave
+3. Trigger the function "collapse_doorways" at the slave
+4. Remove the triggerer from that slave.
+
+This is repeated until all of the triggerers have been removed, or the player
+leaves the level.
+
+[1]: "Turns" are a misnomer. The countdown operates off the value of ev:ticks(),
+ a value which may be, but is not always, "10" for every turn. In practice,
+ for randomised functions, you can times your values by 10 to roughly get
+ a "turns" value: therefore, "50" ~= every 5 turns, "200" ~= every 20 turns.
+
+The following section will provide some annotated examples of customised
+TriggerableFunctions.
+
+C. Examples of usage
+====================
+
+These vaults have been taken in whole from the current crawl code repository,
+and may have been updated since their original inclusion. Please see the
+referenced files for the current version.
+
+Annotations are marked as "** <text of annotation>".
+
+-----------------------------
+
+From dat/volcano.des:
+
+NAME: volcano_overflow
+WEIGHT: 10
+ORIENT: encompass
+TAGS: volcano no_item_gen no_monster_gen no_rotate
+MONS: nothing, nothing, nothing
+{{
+
+** The function takes five parameters, as noted, though only acts on two.
+
+function convert_lava (data, triggerable, triggerer, marker, ev)
+ ** This piece of code ensures that the function is only triggered at the
+ ** end of the countdown.
+ if triggerer.type ~= "turn" or triggerer.sub_type ~= "countdown" then
+ return
+ end
+
+ ** Here, values stored in the persistent table are altered.
+ data.lava_phase = data.lava_phase + 1
+ local lp = data.lava_phase
+ local my_slaves = {}
+
+ ** This code converts a square either from floor to lava, or from lava to
+ ** floor.
+ -- So we don't have to duplicate code too much.
+ local function convert_slaves_to_lava (mslaves, opposite)
+ local yp = dgn.point(you.pos())
+ for _, pos in ipairs(mslaves) do
+ if pos ~= yp then
+ if opposite then
+ dgn.terrain_changed(pos.x, pos.y, "floor", false, false, false)
+ else
+ dgn.terrain_changed(pos.x, pos.y, "lava", false, false, false)
+ end
+ end
+ end
+ end
+
+ ** The use of slaves in this function is slightly different to the normal
+ ** slaved Triggerables. Instead, we access the slave fetching functions
+ ** directly in the code.
+ if lp == 1 then
+ crawl.mpr("The ground shudders ominously.", "warning")
+ elseif lp == 2 then
+ my_slaves = dgn.find_marker_positions_by_prop("lava_phase", 2)
+ crawl.mpr("In the distance, the volano explodes with a roar! Lava spreads "
+ .. "onto the path.", "warning")
+ convert_slaves_to_lava(my_slaves)
+ elseif lp == 3 then
+ crawl.mpr("The air is thick with the scent of sulphur.", "warning")
+ elseif lp == 4 then
+ my_slaves = dgn.find_marker_positions_by_prop("lava_phase", 4)
+ crawl.mpr("There is another distant roar. More lava overflows!", "warning")
+ convert_slaves_to_lava(my_slaves)
+ elseif lp == 5 then
+ crawl.mpr("The ground moves violently!", "warning")
+ elseif lp == 6 then
+ my_slaves = dgn.find_marker_positions_by_prop("lava_phase", 6)
+ crawl.mpr("The volcano erupts again! A thin layer of lava overflows to " ..
+ "fill the cavern.", "warning")
+ convert_slaves_to_lava(my_slaves)
+ elseif lp == 7 then
+ my_slaves = dgn.find_marker_positions_by_prop("lava_phase", 6)
+ crawl.mpr("The ground shudders. Some of the lava has hardened enough to walk " ..
+ "over!", "warning")
+ convert_slaves_to_lava(my_slaves, true)
+ end
+end
+
+** This sets up the various slaves, using a portal descriptor with the
+** lava_phase being parameter used to locate them.
+
+-- So we know what to convert.
+lua_marker("1", portal_desc { lava_phase=2 })
+lua_marker("2", portal_desc { lava_phase=4 })
+lua_marker("3", portal_desc { lava_phase=6 })
+
+** The marker for the TriggerableFunction, and the initial setup of the data
+** table.
+-- And finally, let's convert it
+local sink_marker = TriggerableFunction:new {
+ func = convert_lava,
+ repeated = true,
+ data = {lava_phase=0}
+}
+
+** The triggerer is randomly every 5 to 20 turns.
+sink_marker:add_triggerer(DgnTriggerer:new {
+ type="turn",
+ delay_min=50,
+ delay_max=200, })
+
+** While we need the marker on the map, it doesn't actually use or manipulate
+** anything at its location, hence it's inclusion outside of the bounds of the
+** map. This could easily be applied to any permanent feature included on the
+** map, such as the "<" or "A" symbols.
+lua_marker("M", sink_marker)
+}}
+SUBST: M = c
+NSUBST: 123 = 8:d / 8:e / 8:f / 8:g / 8:h / *:.
+: volcano_setup(_G)
+MAP
+ xxxx xxx xxx xxx
+ xxxxx xx33xxx xxx3xxx3xxxx xxxxx xxx xx3xx
+ xx333xxxx32233xxx xxx3323332333xxxx33xxx3xxx xxx323xx
+ xxx321133332112233xxx332211221121333322333233xxx332123xx
+ xxx3321l122221ll11133333311ll111l111222212211223332211123xx
+ xxx3321llll1111llllll111111lllllllllll11111111111222111123xx
+xx3321llllllllllllllllllllllllllllllllllll11233321111ll123xx
+ xx3321lllllllllllllllllllllllllllllllllll123xxx3321lll123xx
+ xxx321lllllllllllllllllllllllllllllllll123xxAxxx321lll123xx
+ xx321lllllllllllllllll111lllllllllll123xx<...xx3211ll123xx
+ xx321lll11llllllll122333221lllllllll123xxx...xx321lll123x
+ x321ll1221llllll1223xxx3211llllllll11233x....3321llll13xx
+ xxx321l133321llll1233xx xx3221llllllll123xx...xx321ll1123xx
+ xx3321133xxx33211123xxx xx3321llll11233333.xxx322111233xx
+ x332233xxx xxx33233xx xxx332111233xxxxxxx xx332233xxx
+ xxx33xxx xxx3xxx M xxx33233xxx xxx33xxx
+ xxxx xxx xxx3xxx xxxx
+ xxx
+ENDMAP
+
+-----------------------------
+
+From dat/float.des
+
+NAME: ancient_champions_mu
+DEPTH: D:15-26, Vault, Crypt
+ORIENT: float
+FLAGS: no_item_gen no_monster_gen
+KFEAT: ABCDEFG = metal_wall
+** This vault uses named monsters to differentiate on the monster_dies trigger.
+KMONS: 1 = col:gold skeletal warrior name:ancient_champion name_replace \
+ spells:iron_shot;.;haste;pain;.;. actual_spells \
+ ; plate mail ego:fire_resistance | plate mail ego:cold_resistance . \
+ great sword ego:pain | great sword ego:draining | great sword \
+ ego:flaming | w:3 triple sword ego:vorpal
+KMONS: 2 = col:gold skeletal warrior name:ancient_champion name_replace \
+ spells:bolt_of_draining;.;haste;throw_frost;.;. actual_spells \
+ ; plate mail ego:fire_resistance | plate mail ego:cold_resistance . \
+ great mace ego:vorpal | great mace ego:draining
+KMONS: 3 = col:gold skeletal warrior name:ancient_champion name_replace \
+ spells:venom_bolt;.;haste;haunt;.;. actual_spells \
+ ; plate mail ego:fire_resistance | plate mail ego:cold_resistance . \
+ battleaxe ego:vorpal | battleaxe ego:pain | \
+ w:3 executioner's axe ego:vorpal
+KMONS: 4 = col:gold skeletal warrior name:ancient_champion name_replace \
+ spells:iskenderun's_mystic_blast;slow;haste;.;.;. actual_spells \
+ ; plate mail ego:fire_resistance | plate mail ego:cold_resistance . \
+ great sword ego:pain | great sword ego:draining | great sword \
+ ego:flaming | battleaxe ego:vorpal | battleaxe ego:pain | \
+ triple sword ego:vorpal | executioner's axe ego:vorpal
+SHUFFLE: 123
+KPROP: ]v.1234+ABCDEFG!n$wr|" = no_rtele_into
+KITEM: w = acquire weapon
+KITEM: r = acquire armour
+NSUBST: $ = 1:w / 1:r / 4:| / *:$
+COLOUR: " = yellow
+KFEAT: " = .
+
+{{
+
+** In this vault, killing one of the name skeletal warriors causes part of the
+** wall to slide back. These sections of wall have to be individually marker as
+** such.
+-- First off, slave marker magic.
+lua_marker("A", portal_desc { skele_slave=1 })
+lua_marker("B", portal_desc { skele_slave=2 })
+lua_marker("C", portal_desc { skele_slave=3 })
+lua_marker("D", portal_desc { skele_slave=4 })
+lua_marker("E", portal_desc { skele_slave=5 })
+lua_marker("F", portal_desc { skele_slave=6 })
+lua_marker("G", portal_desc { skele_slave=7 })
+
+** Again, taking five parameters.
+
+-- Then the actual function which does everything.
+function skele_death (data, triggerable, triggerer, marker, ev)
+ data.skele_number = data.skele_number + 1
+ ** However, as this is a monster_dies function, we don't need to worry about
+ ** it being triggered erroneously.
+
+ ** And again, using the persistent data table to store the amount of skeletal
+ ** warriors that have been destroyed.
+ -- Only 7 skeles!
+ if data.skele_number > 7 then
+ return
+ end
+
+ ** Like the overflow vault from volcano.des, this directly accesses the
+ ** network of slaves in order to find out which section of wall should be
+ ** replaced.
+ local function get_slave (slavenum)
+ local myslaves = dgn.find_marker_positions_by_prop("skele_slave", slavenum)
+ return myslaves[1]
+ end
+
+ local wall_pos = get_slave(data.skele_number)
+ if wall_pos == nil then
+ crawl.mpr("Couldn't find a slave!")
+ end
+
+ dgn.terrain_changed(wall_pos.x, wall_pos.y, "floor", false, false, false)
+
+ if you.see_cell(wall_pos.x, wall_pos.y) then
+ crawl.mpr("As the champion dies, a metal wall slides away!")
+ else
+ crawl.mpr("As the champion dies, you hear a distant grinding noise.")
+ end
+end
+
+local skele_death_marker = TriggerableFunction:new {
+ func=skele_death,
+ repeated=true,
+ data={skele_number=0} }
+
+** This uses the "monster_dies" type of triggerer, and links it in to the
+** changed description of the skeletal warriors.
+skele_death_marker:add_triggerer(DgnTriggerer:new {
+ type="monster_dies",
+ target="ancient champion" })
+
+** Again, like the Overflow vault, the marker in question doesn't act upon
+** anything at its location; assigning it to all of the skeletal warriors
+** would cause confusion, and placing it off the map would be impossible as
+** this is not an encompass vault; therefore, it is linked to a solid feature.
+lua_marker("]", skele_death_marker)
+}}
+
+MAP
+vvvvvvvvvvvvvvvvvvv
+v..".1v.."..v.."..v
+v.""".v.""".v.""".v
+v"""""C"""""B"""""v
+v.""".v.""".v.""".v
+v.."..v..".3v..".2v
+vvvDvvvvvvvvvvvAvvv
+v..".2v$$$$$v.."..v
+v.""".v$$$$$v.""".v
+v"""""v$$.$$v"""""v
+v.""".v$$.$$v.""".v
+v.."..v$...$v1."..v
+vvvEvvvvvGvvvvv+vvv
+v3."..v.."..v.."..v
+v.""".v.""".v.""".v
+v"""""F"""""v""]""v
+v.""".v.""".v.""".v
+v.."..v4."..v.."..v
+vvvvvvvvvvvvvvvvvvv
+ENDMAP
+
+D. Convenience functions
+========================
+
+Previously, we have discussed completely customised Triggerables, using the
+TriggerableFunction marker. There also exist a large variety of other markers
+and convenience functions which use Triggerables as a base.
+
+Markers which use Triggerables as a base include FogMachines, MonsterOnTrigger,
+feat_change_change_flags, item_pickup_change_flags, and so on. These are
+documented in their own individual files.
+
+Currently, convenience functions for Triggerables include:
+
+ * message_at_spot, which can be used to trigger a single or repeated message
+ whenever the player crosses or reaches a certain point.
+
+E. List of triggerers
+========================
+
+This list taken from dat/clua/lm_trig.lua, listing the different "type"
+parameters that an instance of DgnTriggerer may accept, and the required
+parameters for each.
+
+ * monster_dies: Waits for a monster to die. Needs the parameter
+ "target", who's value is the name of the monster who's death
+ we're wating for. Doesn't matter where the triggerable/marker
+ is placed.
+ * feat_change: Waits for a cell's feature to change. Accepts the
+ optional parameter "target", which if set delays the trigger
+ until the feature the cell turns into contains the target as a
+ substring. The triggerable/marker must be placed on top of the
+ cell who's feature you wish to monitor.
+ * item_moved: Wait for an item to move from one cell to another.
+ Needs the parameter "target", who's value is the name of the
+ item that is being tracked, or which can be "auto", in which
+ case it will pick the item placed by the vault. The
+ triggerable/marker must be placed on top of the cell containing
+ the item.
+ * item_pickup: Wait for an item to be picked up. Needs the parameter
+ "target", who's value is the name of the item that is being tracked,
+ or which can be "auto", in which case it will pick the item placed
+ by the vault. The triggerable/marker must be placed on top of the
+ cell containing the item. Automatically takes care of the item
+ moving from one square to another without being picked up.
+ * player_move: Wait for the player to move to a cell. The
+ triggerable/marker must be placed on top of cell in question.
+ * player_los: Wait for the player to come into LOS of a cell, which
+ must contain a notable feature.. The triggerable/marker must be
+ placed on top of cell in question.
+ * turn: Called once for each player turn that passes. Optionally accepts a
+ "delay_min", "delay_max" or "delay" parameters, in which case a
+ countdown is performed.
+ * entered_level: Called when player enters the level, after all level
+ setup code has completed.
+
+F. Master and slaves
+========================
+
+Multiple Triggerables can be combined together in a master/slave setup. There
+are multiple methods of doing this. The simplest is to to provide a
+"master_name" parameter to the main marker, and then provide "slave_to" at all
+of the individual slave markers, setting the same value for each.
+
+When a Triggerable is fired and it has a "master_name" property, it will execute
+at each of the slave locations as defined above, unless the master has the
+parameter "single_random_slave" (set to anything but empty), in which case it
+will randomly chose one slave and execute there. Further, the master marker may
+be slaved to itself in order to have execution occur there.
+
+Triggerables that depend on position (such as player_move) will only fire when
+the player moves over the master marker. For them to fire at either slave or
+master, provide the "listen_to_slaves" property. Finally, to have only the slave
+that fired be executed, provide the "only_at_slave" parameter.
+
+-----------------------------
+
+An example from dat/hells.des, using the MonsterOnTriggerer marker, a subset of
+Triggerables, and master/slave mechanics:
+
+MARKER: 1 = lua:monster_on_death { \
+ death_monster="Dispater", new_monster="generate_awake iron golem", \
+ message_seen="The iron statue comes to life!", \
+ message_unseen="You hear a grinding sound.", \
+ master_name="dispater" \
+ }
+MARKER: o = lua:props_marker { \
+ veto_fragmentation="veto", veto_disintegrate="veto", \
+ slaved_to="dispater" \
+ }
+
+-----------------------------
+
+If you have any comments, questions, or issues with Triggerables, your best bet
+would be to contact the crawl-ref-discuss mailing list on SourceForge, or to try
+##crawl-dev on irc.freenode.org.
diff --git a/crawl-ref/dolinks.sh b/crawl-ref/dolinks.sh
index 072555e7bc..c6c6c6e862 100755
--- a/crawl-ref/dolinks.sh
+++ b/crawl-ref/dolinks.sh
@@ -1,10 +1,18 @@
#!/usr/bin/env bash
+dolinks() {
+ mkdir -p source
+ cd source
+ ln -sf ../../source/*.{cc,h,txt} .
+ ln -sf ../../source/makefile* .
+ ln -sf ../../source/{util,contrib,rltiles,prebuilt,dat} .
+}
+
mkdir -p NORMAL
mkdir -p WIZARD
-pushd NORMAL ; mkdir -p source ; cd source ; ln -sf ../../source/* . ; popd
-pushd WIZARD ; mkdir -p source ; cd source ; ln -sf ../../source/* . ; popd
+pushd NORMAL ; dolinks ; popd
+pushd WIZARD ; dolinks ; popd
if [ -d dat ]; then
true
diff --git a/crawl-ref/source/abl-show.cc b/crawl-ref/source/abl-show.cc
index 73dc7b730c..ceb47a2064 100644
--- a/crawl-ref/source/abl-show.cc
+++ b/crawl-ref/source/abl-show.cc
@@ -37,7 +37,7 @@
#include "message.h"
#include "menu.h"
#include "misc.h"
-#include "monplace.h"
+#include "mon-place.h"
#include "mutation.h"
#include "notes.h"
#include "ouch.h"
@@ -1482,7 +1482,8 @@ static bool _do_ability(const ability_def& abil)
break;
case ABIL_RAISE_DEAD:
- animate_dead(&you, you.experience_level * 5, BEH_FRIENDLY, MHITYOU);
+ animate_dead(&you, you.experience_level * 5, BEH_FRIENDLY,
+ MHITYOU, &you);
break;
case ABIL_CONTROL_DEMON:
@@ -1609,7 +1610,7 @@ static bool _do_ability(const ability_def& abil)
mpr("You attempt to give life to the dead...");
if (animate_remains(you.pos(), CORPSE_BODY, BEH_FRIENDLY,
- MHITYOU, GOD_YREDELEMNUL) < 0)
+ MHITYOU, &you, "", GOD_YREDELEMNUL) < 0)
{
mpr("There are no remains here to animate!");
}
@@ -1625,7 +1626,7 @@ static bool _do_ability(const ability_def& abil)
mpr("You call on the dead to walk for you...");
animate_dead(&you, 1 + you.skills[SK_INVOCATIONS], BEH_FRIENDLY,
- MHITYOU, GOD_YREDELEMNUL);
+ MHITYOU, &you, "", GOD_YREDELEMNUL);
exercise(SK_INVOCATIONS, 2 + random2(4));
break;
@@ -1928,12 +1929,15 @@ static bool _do_ability(const ability_def& abil)
{
int count = fungal_bloom();
- if (count)
+ if (!count)
{
- simple_god_message(" appreciates your contribution to the "
- "ecosystem.", GOD_FEDHAS);
+ canned_msg(MSG_NOTHING_HAPPENS);
+ return (false);
}
+ simple_god_message(" appreciates your contribution to the "
+ "ecosystem.", GOD_FEDHAS);
+
// We are following the blood god sacrifice piety gain model, given as:
// if (random2(level + 10) > 5)
// piety_change = 1;
@@ -1993,9 +1997,11 @@ static bool _do_ability(const ability_def& abil)
case ABIL_JIYVA_CALL_JELLY:
{
- mgen_data mg(MONS_JELLY, BEH_STRICT_NEUTRAL, 0, 0, you.pos(),
+ mgen_data mg(MONS_JELLY, BEH_STRICT_NEUTRAL, 0, 0, 0, you.pos(),
MHITNOT, 0, GOD_JIYVA);
+ mg.non_actor_summoner = "Jiyva";
+
if (create_monster(mg) == -1)
return (false);
diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc
index cf3f74267d..af78932c24 100644
--- a/crawl-ref/source/abyss.cc
+++ b/crawl-ref/source/abyss.cc
@@ -18,8 +18,9 @@
#include "mapmark.h"
#include "message.h"
#include "misc.h"
+#include "mon-iter.h"
#include "mon-util.h"
-#include "monplace.h"
+#include "mon-place.h"
#include "mtransit.h"
#include "player.h"
#include "dungeon.h"
@@ -181,6 +182,7 @@ static void _generate_area(const coord_def& topleft,
// Nuke map.
env.map_knowledge.init(map_cell());
+ env.pgrid.init(0);
// Generate level composition vector.
for (int i = 0; i < 5; i++)
@@ -319,6 +321,21 @@ static void _generate_area(const coord_def& topleft,
mpr("Placing altar.", MSGCH_DIAGNOSTICS);
#endif
}
+
+ if (one_chance_in(20000))
+ {
+ // Not a vital thing, items shouldn't hurt.
+ grd(*ri) = DNGN_ENTER_PANDEMONIUM;
+#ifdef DEBUG_ABYSS
+ mpr("Placing a Pan portal.", MSGCH_DIAGNOSTICS);
+#endif
+ }
+
+ if (one_chance_in(10000))
+ {
+ // purely decorative
+ grd(*ri) = DNGN_STONE_ARCH;
+ }
}
}
@@ -442,16 +459,11 @@ void area_shift(void)
_xom_check_nearness_setup();
- for (unsigned int i = 0; i < MAX_MONSTERS; i++)
+ // Remove non-nearby monsters.
+ for (monster_iterator mi; mi; ++mi)
{
- monsters &m = menv[i];
-
- if (!m.alive())
- continue;
-
- // Remove non-nearby monsters.
- if (grid_distance(m.pos(), you.pos()) > 10)
- _abyss_lose_monster(m);
+ if (grid_distance(mi->pos(), you.pos()) > 10)
+ _abyss_lose_monster(**mi);
}
for (rectangle_iterator ri(5); ri; ++ri)
@@ -546,12 +558,9 @@ void area_shift(void)
void save_abyss_uniques()
{
- for (int i = 0; i < MAX_MONSTERS; ++i)
- {
- monsters &m = menv[i];
- if (m.alive() && m.needs_transit())
- m.set_transit( level_id(LEVEL_ABYSS) );
- }
+ for (monster_iterator mi; mi; ++mi)
+ if (mi->needs_transit())
+ mi->set_transit(level_id(LEVEL_ABYSS));
}
void abyss_teleport( bool new_area )
@@ -602,9 +611,8 @@ void abyss_teleport( bool new_area )
tile_init_flavour();
#endif
- for (int i = 0; i < MAX_MONSTERS; ++i)
- if (menv[i].alive())
- _abyss_lose_monster(menv[i]);
+ for (monster_iterator mi; mi; ++mi)
+ _abyss_lose_monster(**mi);
// Orbs and fixed artefacts are marked as "lost in the abyss".
for (int i = 0; i < MAX_ITEMS; ++i)
@@ -702,7 +710,10 @@ static bool _spawn_corrupted_servant_near(const coord_def &pos)
const beh_type beh =
one_chance_in(5 + you.skills[SK_INVOCATIONS] / 4) ? BEH_HOSTILE
: BEH_NEUTRAL;
- const int mid = create_monster(mgen_data(mons, beh, 5, 0, p));
+ mgen_data mg(mons, beh, 0, 5, 0, p);
+ mg.non_actor_summoner = "Lugonu's corruption";
+
+ const int mid = create_monster(mg);
return (mid != -1);
}
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index ff1a1ccd3b..fe11c6612f 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -89,8 +89,9 @@
#include "misc.h"
#include "mon-act.h"
#include "mon-cast.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-iter.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "mutation.h"
#include "newgame.h"
@@ -2503,7 +2504,7 @@ static void _decrement_durations()
Options.tutorial_events[TUT_YOU_ENCHANTED] = tut_slow;
}
- if (you.duration[DUR_BACKLIGHT] && !--you.duration[DUR_BACKLIGHT]
+ if (you.duration[DUR_CORONA] && !--you.duration[DUR_CORONA]
&& !you.backlit())
{
mpr("You are no longer glowing.", MSGCH_DURATION);
@@ -3280,23 +3281,53 @@ static void _open_door(coord_def move, bool check_confused)
const char *adj, *noun;
get_door_description(all_door.size(), &adj, &noun);
- int skill = you.dex
- + (you.skills[SK_TRAPS_DOORS] + you.skills[SK_STEALTH]) / 2;
-
- if (is_exclude_root(doorpos) && !(check_confused && you.confused()))
+ if (!(check_confused && you.confused()))
{
- std::string prompt =
- make_stringf("This %s%s is marked as excluded! Open it "
- "anyway?", adj, noun);
+ std::string door_open_prompt =
+ env.markers.property_at(doorpos, MAT_ANY, "door_open_prompt");
+
+ bool ignore_exclude = false;
- if (!yesno(prompt.c_str(), true, 'n', true, false))
+ if (!door_open_prompt.empty())
{
- canned_msg(MSG_OK);
- interrupt_activity(AI_FORCE_INTERRUPT);
- return;
+ door_open_prompt += " (y/N)";
+ if (!yesno(door_open_prompt.c_str(), true, 'n', true, false))
+ {
+ if (is_exclude_root(doorpos))
+ canned_msg(MSG_OK);
+ else
+ {
+ if (yesno("Put travel exclusion on door? (Y/n)",
+ true, 'y'))
+ {
+ // Zero radius exclusion right on top of door.
+ set_exclude(doorpos, 0);
+ }
+ }
+ interrupt_activity(AI_FORCE_INTERRUPT);
+ return;
+ }
+ ignore_exclude = true;
+ }
+
+ if (!ignore_exclude && is_exclude_root(doorpos))
+ {
+ std::string prompt =
+ make_stringf("This %s%s is marked as excluded! Open it "
+ "anyway?", adj, noun);
+
+ if (!yesno(prompt.c_str(), true, 'n', true, false))
+ {
+ canned_msg(MSG_OK);
+ interrupt_activity(AI_FORCE_INTERRUPT);
+ return;
+ }
}
}
+ int skill = you.dex
+ + (you.skills[SK_TRAPS_DOORS] + you.skills[SK_STEALTH]) / 2;
+
if (you.berserk())
{
// XXX: Better flavour for larger doors?
@@ -3564,6 +3595,7 @@ static bool _initialise(void)
igrd.init(NON_ITEM);
mgrd.init(NON_MONSTER);
env.map_knowledge.init(map_cell());
+ env.pgrid.init(0);
you.unique_creatures.init(false);
you.unique_items.init(UNIQ_NOT_EXISTS);
@@ -3734,8 +3766,9 @@ static bool _initialise(void)
// Mark items in inventory as of unknown origin.
origin_set_inventory(origin_set_unknown);
- // For a new game, wipe out monsters in LOS.
- zap_los_monsters();
+ // For a new game, wipe out monsters in LOS, and
+ // for new tutorial games also the items.
+ zap_los_monsters(Options.tutorial_events[TUT_SEEN_FIRST_OBJECT]);
// For a newly started tutorial, turn secret doors into normal ones.
if (Options.tutorial_left)
@@ -4025,9 +4058,8 @@ static void _move_player(coord_def move)
mprf(MSGCH_DIAGNOSTICS, "Number of items present: %d", j);
j = 0;
- for (int i = 0; i < MAX_MONSTERS; ++i)
- if (menv[i].type != -1)
- ++j;
+ for (monster_iterator mi; mi; ++mi)
+ ++j;
mprf(MSGCH_DIAGNOSTICS, "Number of monsters present: %d", j);
mprf(MSGCH_DIAGNOSTICS, "Number of clouds present: %d", env.cloud_no);
@@ -4380,7 +4412,7 @@ static void _compile_time_asserts()
COMPILE_CHECK(SP_VAMPIRE == 30 , c3);
COMPILE_CHECK(SPELL_DEBUGGING_RAY == 103 , c4);
COMPILE_CHECK(SPELL_PETRIFY == 155 , c5);
- COMPILE_CHECK(NUM_SPELLS == 206 , c6);
+ COMPILE_CHECK(NUM_SPELLS == 207 , c6);
//jmf: NEW ASSERTS: we ought to do a *lot* of these
COMPILE_CHECK(NUM_SPECIES < SP_UNKNOWN , c7);
diff --git a/crawl-ref/source/actor-los.cc b/crawl-ref/source/actor-los.cc
index 85e66fd8ab..06eb063a13 100644
--- a/crawl-ref/source/actor-los.cc
+++ b/crawl-ref/source/actor-los.cc
@@ -30,6 +30,11 @@ bool player::see_cell_no_trans(const coord_def &p) const
return (los_no_trans.see_cell(p));
}
+const los_def& actor::get_los() const
+{
+ return (los);
+}
+
const los_def& actor::get_los_no_trans()
{
return (los_no_trans);
diff --git a/crawl-ref/source/actor.h b/crawl-ref/source/actor.h
index 97bae34914..10dd3f7bda 100644
--- a/crawl-ref/source/actor.h
+++ b/crawl-ref/source/actor.h
@@ -121,6 +121,7 @@ public:
virtual void update_los();
+ virtual const los_def& get_los() const;
// Could be const for player, but monsters updates it on the fly.
virtual const los_def& get_los_no_trans();
@@ -156,8 +157,8 @@ public:
virtual void confuse(actor *attacker, int strength) = 0;
virtual void expose_to_element(beam_type element, int strength = 0) = 0;
virtual void drain_stat(int stat, int amount, actor* attacker) { }
- virtual bool can_sleep(bool holi_only = false) const = 0;
- virtual void put_to_sleep(int power = 0) = 0;
+ virtual bool can_hibernate(bool holi_only = false) const = 0;
+ virtual void hibernate(int power = 0) = 0;
virtual void check_awaken(int disturbance) = 0;
virtual bool wearing_light_armour(bool = false) const { return (true); }
diff --git a/crawl-ref/source/arena.cc b/crawl-ref/source/arena.cc
index dcae744e65..31512cd621 100644
--- a/crawl-ref/source/arena.cc
+++ b/crawl-ref/source/arena.cc
@@ -22,10 +22,11 @@
#include "maps.h"
#include "message.h"
#include "mon-behv.h"
+#include "mon-iter.h"
#include "mon-pick.h"
#include "mon-util.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "spl-mis.h"
#include "spl-util.h"
#include "state.h"
@@ -139,12 +140,8 @@ namespace arena
void adjust_monsters()
{
- for (int i = 0; i < MAX_MONSTERS; i++)
+ for (monster_iterator mon; mon; ++mon)
{
- monsters *mon = &menv[i];
- if (!mon->alive())
- continue;
-
const bool friendly = mon->friendly();
// Set target to the opposite faction's home base.
mon->target = friendly ? place_b : place_a;
@@ -543,16 +540,12 @@ namespace arena
faction_a.active_members = 0;
faction_b.active_members = 0;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mons; mons; ++mons)
{
- const monsters *mons(&menv[i]);
- if (mons->alive())
- {
- if (mons->attitude == ATT_FRIENDLY)
- faction_a.active_members++;
- else if (mons->attitude == ATT_HOSTILE)
- faction_b.active_members++;
- }
+ if (mons->attitude == ATT_FRIENDLY)
+ faction_a.active_members++;
+ else if (mons->attitude == ATT_HOSTILE)
+ faction_b.active_members++;
}
if (orig_a != faction_a.active_members
@@ -601,35 +594,27 @@ namespace arena
void report_foes()
{
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mons; mons; ++mons)
{
- monsters *mons(&menv[i]);
- if (mons->alive())
+ if (mons->type == MONS_SIGMUND)
{
- if (mons->type == MONS_SIGMUND)
- {
- coord_def where;
- if (mons->get_foe())
- where = mons->get_foe()->pos();
- mprf("%s (%d,%d) foe: %s (%d,%d)",
- mons->name(DESC_PLAIN).c_str(),
- mons->pos().x, mons->pos().y,
- mons->get_foe()? mons->get_foe()->name(DESC_PLAIN).c_str()
- : "(none)",
- where.x, where.y);
- }
+ coord_def where;
+ if (mons->get_foe())
+ where = mons->get_foe()->pos();
+ mprf("%s (%d,%d) foe: %s (%d,%d)",
+ mons->name(DESC_PLAIN).c_str(),
+ mons->pos().x, mons->pos().y,
+ mons->get_foe()? mons->get_foe()->name(DESC_PLAIN).c_str()
+ : "(none)",
+ where.x, where.y);
}
}
}
void fixup_foes()
{
- for (int i = 0; i < MAX_MONSTERS; ++i)
- {
- monsters *mons(&menv[i]);
- if (mons->alive())
- behaviour_event(mons, ME_DISTURB, MHITNOT, mons->pos());
- }
+ for (monster_iterator mons; mons; ++mons)
+ behaviour_event(*mons, ME_DISTURB, MHITNOT, mons->pos());
}
void dump_messages()
@@ -718,15 +703,13 @@ namespace arena
if (!miscasts)
return;
- for (int i = 0; i < MAX_MONSTERS; i++)
+ for (monster_iterator mon; mon; ++mon)
{
- monsters* mon = &menv[i];
-
- if (!mon->alive() || mon->type == MONS_TEST_SPAWNER)
+ if (mon->type == MONS_TEST_SPAWNER)
continue;
- MiscastEffect(mon, i, SPTYP_RANDOM, random_range(1, 3),
- "arena miscast", NH_NEVER);
+ MiscastEffect(*mon, mon->mindex(), SPTYP_RANDOM,
+ random_range(1, 3), "arena miscast", NH_NEVER);
}
}
diff --git a/crawl-ref/source/art-data.h b/crawl-ref/source/art-data.h
index abf00dfaee..0fa2709a17 100644
--- a/crawl-ref/source/art-data.h
+++ b/crawl-ref/source/art-data.h
@@ -23,7 +23,7 @@
#define ART_DATA_H
-/* 1: UNRAND_DUMMY1 */
+/* UNRAND_DUMMY1 */
{
"DUMMY UNRANDART 1", "DUMMY UNRANDART 1",
OBJ_UNASSIGNED, 250, 250, 250, BLACK, 0,
@@ -42,7 +42,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 2: UNRAND_SINGING_SWORD */
+/* UNRAND_SINGING_SWORD */
{
"Singing Sword", "golden long sword",
OBJ_WEAPONS, WPN_LONG_SWORD, +7, +7, ETC_GOLD, 1200,
@@ -61,7 +61,7 @@
_SINGING_SWORD_equip, _SINGING_SWORD_unequip, NULL, { NULL }, NULL,
},
-/* 3: UNRAND_TROG */
+/* UNRAND_TROG */
{
"Wrath of Trog", "bloodstained battleaxe",
OBJ_WEAPONS, WPN_BATTLEAXE, +3, +11, ETC_BLOOD, 1000,
@@ -80,7 +80,7 @@
_TROG_equip, _TROG_unequip, NULL, { _TROG_melee_effect }, NULL,
},
-/* 4: UNRAND_VARIABILITY */
+/* UNRAND_VARIABILITY */
{
"Mace of Variability", "shimmering mace",
OBJ_WEAPONS, WPN_MACE, 0, 0, ETC_RANDOM, 700,
@@ -99,7 +99,7 @@
NULL, NULL, _VARIABILITY_world_reacts, { NULL }, NULL,
},
-/* 5: UNRAND_PRUNE */
+/* UNRAND_PRUNE */
{
"Glaive of Prune", "purple glaive",
OBJ_WEAPONS, WPN_GLAIVE, 0, +12, MAGENTA, 1000,
@@ -118,7 +118,7 @@
_PRUNE_equip, NULL, NULL, { NULL }, NULL,
},
-/* 6: UNRAND_POWER */
+/* UNRAND_POWER */
{
"Sword of Power", "chunky great sword",
OBJ_WEAPONS, WPN_GREAT_SWORD, 0, 0, RED, 1000,
@@ -137,7 +137,7 @@
_POWER_equip, NULL, _POWER_world_reacts, { NULL }, NULL,
},
-/* 7: UNRAND_OLGREB */
+/* UNRAND_OLGREB */
{
"Staff of Olgreb", "green glowing staff",
OBJ_WEAPONS, WPN_QUARTERSTAFF, 0, 0, ETC_POISON, 1000,
@@ -156,7 +156,7 @@
_OLGREB_equip, _OLGREB_unequip, _OLGREB_world_reacts, { NULL }, _OLGREB_evoke,
},
-/* 8: UNRAND_WUCAD_MU */
+/* UNRAND_WUCAD_MU */
{
"Staff of Wucad Mu", "ephemeral quarterstaff",
OBJ_WEAPONS, WPN_QUARTERSTAFF, 0, 0, ETC_MAGIC, 1000,
@@ -175,7 +175,7 @@
_WUCAD_MU_equip, _WUCAD_MU_unequip, _WUCAD_MU_world_reacts, { _WUCAD_MU_melee_effect }, _WUCAD_MU_evoke,
},
-/* 9: UNRAND_VAMPIRES_TOOTH */
+/* UNRAND_VAMPIRES_TOOTH */
{
"Vampire's Tooth", "ivory dagger",
OBJ_WEAPONS, WPN_DAGGER, +3, +4, ETC_BONE, 1000,
@@ -194,7 +194,7 @@
_VAMPIRES_TOOTH_equip, NULL, NULL, { NULL }, NULL,
},
-/* 10: UNRAND_CURSES */
+/* UNRAND_CURSES */
{
"Scythe of Curses", "warped scythe",
OBJ_WEAPONS, WPN_SCYTHE, +13, +13, ETC_NECRO, 800,
@@ -213,7 +213,7 @@
_CURSES_equip, NULL, _CURSES_world_reacts, { _CURSES_melee_effect }, NULL,
},
-/* 11: UNRAND_TORMENT */
+/* UNRAND_TORMENT */
{
"Sceptre of Torment", "jewelled golden mace",
OBJ_WEAPONS, WPN_MACE, +7, +6, ETC_GOLD, 1200,
@@ -232,7 +232,7 @@
_TORMENT_equip, NULL, _TORMENT_world_reacts, { _TORMENT_melee_effect }, NULL,
},
-/* 12: UNRAND_ZONGULDROK */
+/* UNRAND_ZONGULDROK */
{
"Sword of Zonguldrok", "bone long sword",
OBJ_WEAPONS, WPN_LONG_SWORD, +9, +9, ETC_BONE, 1250,
@@ -251,11 +251,11 @@
_ZONGULDROK_equip, NULL, _ZONGULDROK_world_reacts, { _ZONGULDROK_melee_effect }, NULL,
},
-/* 13: UNRAND_CEREBOV */
+/* UNRAND_CEREBOV */
{
"Sword of Cerebov", "great serpentine sword",
OBJ_WEAPONS, WPN_GREAT_SWORD, +6, +6, ETC_FIRE, 2000,
- UNRAND_FLAG_SPECIAL | UNRAND_FLAG_UNHOLY,
+ UNRAND_FLAG_SPECIAL | UNRAND_FLAG_EVIL,
{
SPWPN_FLAMING, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -270,11 +270,11 @@
NULL, NULL, NULL, { _CEREBOV_melee_effect }, NULL,
},
-/* 14: UNRAND_DISPATER */
+/* UNRAND_DISPATER */
{
"Staff of Dispater", "golden staff",
OBJ_WEAPONS, WPN_QUARTERSTAFF, +4, +4, ETC_GOLD, 1200,
- UNRAND_FLAG_SPECIAL | UNRAND_FLAG_UNHOLY,
+ UNRAND_FLAG_SPECIAL | UNRAND_FLAG_EVIL,
{
SPWPN_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -289,7 +289,7 @@
NULL, NULL, NULL, { _DISPATER_melee_effect }, _DISPATER_evoke,
},
-/* 15: UNRAND_ASMODEUS */
+/* UNRAND_ASMODEUS */
{
"Sceptre of Asmodeus", "ruby sceptre",
OBJ_WEAPONS, WPN_QUARTERSTAFF, +7, +7, ETC_BLOOD, 1500,
@@ -308,7 +308,7 @@
NULL, NULL, NULL, { _ASMODEUS_melee_effect }, _ASMODEUS_evoke,
},
-/* 16: UNRAND_BLOODBANE */
+/* UNRAND_BLOODBANE */
{
"long sword \"Bloodbane\"", "blackened long sword",
OBJ_WEAPONS, WPN_LONG_SWORD, +7, +8, ETC_DARK, 0,
@@ -327,7 +327,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 17: UNRAND_FLAMING_DEATH */
+/* UNRAND_FLAMING_DEATH */
{
"scimitar of Flaming Death", "smoking scimitar",
OBJ_WEAPONS, WPN_SCIMITAR, +7, +5, ETC_FIRE, 0,
@@ -346,7 +346,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 18: UNRAND_BRILLIANCE */
+/* UNRAND_BRILLIANCE */
{
"mace of Brilliance", "brightly glowing mace",
OBJ_WEAPONS, WPN_MACE, +5, +5, ETC_HOLY, 0,
@@ -365,7 +365,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 19: UNRAND_LEECH */
+/* UNRAND_LEECH */
{
"demon blade \"Leech\"", "runed demon blade",
OBJ_WEAPONS, WPN_DEMON_BLADE, +13, +4, MAGENTA, 0,
@@ -384,7 +384,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 20: UNRAND_CHILLY_DEATH */
+/* UNRAND_CHILLY_DEATH */
{
"dagger of Chilly Death", "sapphire dagger",
OBJ_WEAPONS, WPN_DAGGER, +5, +7, ETC_ICE, 0,
@@ -403,7 +403,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 21: UNRAND_MORG */
+/* UNRAND_MORG */
{
"dagger \"Morg\"", "rusty dagger",
OBJ_WEAPONS, WPN_DAGGER, -1, +4, LIGHTRED, 0,
@@ -422,7 +422,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 22: UNRAND_FINISHER */
+/* UNRAND_FINISHER */
{
"scythe \"Finisher\"", "blackened scythe",
OBJ_WEAPONS, WPN_SCYTHE, +3, +5, ETC_DARK, 0,
@@ -441,7 +441,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 23: UNRAND_PUNK */
+/* UNRAND_PUNK */
{
"sling \"Punk\"", "blue sling",
OBJ_WEAPONS, WPN_SLING, +9, +12, ETC_ICE, 0,
@@ -460,7 +460,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 24: UNRAND_KRISHNA */
+/* UNRAND_KRISHNA */
{
"bow of Krishna \"Sharnga\"", "golden bow",
OBJ_WEAPONS, WPN_BOW, +8, +8, ETC_GOLD, 0,
@@ -479,7 +479,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 25: UNRAND_SKULLCRUSHER */
+/* UNRAND_SKULLCRUSHER */
{
"giant club \"Skullcrusher\"", "brutal giant club",
OBJ_WEAPONS, WPN_GIANT_CLUB, +0, +5, BROWN, 0,
@@ -498,7 +498,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 26: UNRAND_GUARD */
+/* UNRAND_GUARD */
{
"glaive of the Guard", "polished glaive",
OBJ_WEAPONS, WPN_GLAIVE, +5, +8, ETC_ELECTRICITY, 0,
@@ -517,7 +517,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 27: UNRAND_JIHAD */
+/* UNRAND_JIHAD */
{
"sword of Jihad", "crystal sword",
OBJ_WEAPONS, WPN_LONG_SWORD, +12, +10, ETC_HOLY, 0,
@@ -536,7 +536,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 28: UNRAND_HELLFIRE */
+/* UNRAND_HELLFIRE */
{
"crossbow \"Hellfire\"", "flaming crossbow",
OBJ_WEAPONS, WPN_CROSSBOW, +6, +9, ETC_FIRE, 0,
@@ -555,7 +555,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 29: UNRAND_DOOM_KNIGHT */
+/* UNRAND_DOOM_KNIGHT */
{
"sword of the Doom Knight", "adamantine great sword",
OBJ_WEAPONS, WPN_GREAT_SWORD, +13, +13, BLUE, 0,
@@ -574,7 +574,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 30: UNRAND_EOS */
+/* UNRAND_EOS */
{
"\"Eos\"", "encrusted morningstar",
OBJ_WEAPONS, WPN_MORNINGSTAR, +5, +5, ETC_JEWEL, 0,
@@ -593,7 +593,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 31: UNRAND_BOTONO */
+/* UNRAND_BOTONO */
{
"spear of the Botono", "ebony spear",
OBJ_WEAPONS, WPN_SPEAR, +2, +10, ETC_UNHOLY, 0,
@@ -612,7 +612,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 32: UNRAND_OCTOPUS_KING */
+/* UNRAND_OCTOPUS_KING */
{
"trident of the Octopus King", "mangy trident",
OBJ_WEAPONS, WPN_TRIDENT, +10, +4, ETC_WATER, 0,
@@ -631,7 +631,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 33: UNRAND_ARGA */
+/* UNRAND_ARGA */
{
"mithril axe \"Arga\"", "mithril axe",
OBJ_WEAPONS, WPN_WAR_AXE, +10, +6, WHITE, 0,
@@ -650,7 +650,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 34: UNRAND_ELEMENTAL_STAFF */
+/* UNRAND_ELEMENTAL_STAFF */
{
"Elemental Staff", "black staff",
OBJ_WEAPONS, WPN_QUARTERSTAFF, +3, +1, DARKGREY, 0,
@@ -669,7 +669,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 35: UNRAND_SNIPER */
+/* UNRAND_SNIPER */
{
"hand crossbow \"Sniper\"", "black crossbow",
OBJ_WEAPONS, WPN_HAND_CROSSBOW, +10, +0, ETC_DARK, 0,
@@ -688,7 +688,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 36: UNRAND_PIERCER */
+/* UNRAND_PIERCER */
{
"longbow \"Piercer\"", "very long metal bow",
OBJ_WEAPONS, WPN_LONGBOW, +2, +10, CYAN, 0,
@@ -707,7 +707,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 37: UNRAND_BLOWGUN_ASSASSIN */
+/* UNRAND_BLOWGUN_ASSASSIN */
{
"blowgun of the Assassin", "tiny blowgun",
OBJ_WEAPONS, WPN_BLOWGUN, +6, +6, WHITE, 0,
@@ -726,7 +726,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 38: UNRAND_WYRMBANE */
+/* UNRAND_WYRMBANE */
{
"Wyrmbane", "scale-covered lance",
OBJ_WEAPONS, WPN_SPEAR, +9, +6, LIGHTGREEN, 0,
@@ -745,7 +745,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 39: UNRAND_SPRIGGANS_KNIFE */
+/* UNRAND_SPRIGGANS_KNIFE */
{
"Spriggan's Knife", "dainty little knife",
OBJ_WEAPONS, WPN_KNIFE, +4, +10, LIGHTCYAN, 0,
@@ -764,7 +764,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 40: UNRAND_PLUTONIUM_SWORD */
+/* UNRAND_PLUTONIUM_SWORD */
{
"plutonium sword", "glowing long sword",
OBJ_WEAPONS, WPN_LONG_SWORD, +12, +16, ETC_RANDOM, 0,
@@ -783,7 +783,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 41: UNRAND_UNDEADHUNTER */
+/* UNRAND_UNDEADHUNTER */
{
"great mace \"Undeadhunter\"", "great steel mace",
OBJ_WEAPONS, WPN_GREAT_MACE, +7, +7, LIGHTGREY, 0,
@@ -802,7 +802,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 42: UNRAND_SERPENT_SCOURGE */
+/* UNRAND_SERPENT_SCOURGE */
{
"whip \"Serpent-Scourge\"", "forked whip",
OBJ_WEAPONS, WPN_WHIP, +5, +10, DARKGREY, 0,
@@ -821,7 +821,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 43: UNRAND_ACCURACY */
+/* UNRAND_ACCURACY */
{
"knife of Accuracy", "thin dagger",
OBJ_WEAPONS, WPN_DAGGER, +27, -1, LIGHTCYAN, 0,
@@ -840,7 +840,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 44: UNRAND_CRYSTAL_SPEAR */
+/* UNRAND_CRYSTAL_SPEAR */
{
"Lehudib's crystal spear", "crystal spear",
OBJ_WEAPONS, WPN_SPEAR, +6, +6, GREEN, 0,
@@ -859,7 +859,45 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 45: UNRAND_IGNORANCE */
+/* UNRAND_CAPTAINS_CUTLASS */
+{
+ "captain's cutlass", "black cutlass",
+ OBJ_WEAPONS, WPN_SABRE, +6, +7, DARKGRAY, 0,
+ UNRAND_FLAG_NONE,
+ {
+ SPWPN_SPEED, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0,
+ },
+ "",
+ "",
+ "This infamous weapon was used by a vile pirate captain to slaughter countless innocents. Finally, he met his destiny when a kraken swallowed his ship with all the crew aboard. The cutlass was thought to be forever lost, but now you have a proof to the contrary in your very hands.",
+ NULL, NULL, NULL, { NULL }, NULL,
+},
+
+/* UNRAND_STORM_BOW */
+{
+ "storm bow", "night blue bow",
+ OBJ_WEAPONS, WPN_LONGBOW, +8, +8, BLUE, 0,
+ UNRAND_FLAG_SPECIAL,
+ {
+ SPWPN_ELECTROCUTION, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0,
+ },
+ "This bow has the color of dark rain clouds, and the smell of wet ozone.",
+ "",
+ "",
+ NULL, NULL, _STORM_BOW_world_reacts, { NULL }, NULL,
+},
+
+/* UNRAND_IGNORANCE */
{
"shield of Ignorance", "dull large shield",
OBJ_ARMOUR, ARM_LARGE_SHIELD, +8, 0, BROWN, 0,
@@ -878,7 +916,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 46: UNRAND_AUGMENTATION */
+/* UNRAND_AUGMENTATION */
{
"robe of Augmentation", "silk robe",
OBJ_ARMOUR, ARM_ROBE, +4, 0, LIGHTRED, 0,
@@ -897,7 +935,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 47: UNRAND_THIEF */
+/* UNRAND_THIEF */
{
"cloak of the Thief", "tattered cloak",
OBJ_ARMOUR, ARM_CLOAK, +1, 0, ETC_DARK, 0,
@@ -916,7 +954,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 48: UNRAND_BULLSEYE */
+/* UNRAND_BULLSEYE */
{
"shield \"Bullseye\"", "round shield",
OBJ_ARMOUR, ARM_SHIELD, +15, 0, RED, 0,
@@ -935,7 +973,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 49: UNRAND_DYROVEPREVA */
+/* UNRAND_DYROVEPREVA */
{
"crown of Dyrovepreva", "jewelled bronze crown",
OBJ_ARMOUR, ARM_CAP, +3, 0, ETC_JEWEL, 0,
@@ -954,7 +992,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 50: UNRAND_BEAR_SPIRIT */
+/* UNRAND_BEAR_SPIRIT */
{
"hat of the Bear Spirit", "fur hat",
OBJ_ARMOUR, ARM_CAP, +2, 0, DARKGREY, 0,
@@ -973,7 +1011,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 51: UNRAND_MISFORTUNE */
+/* UNRAND_MISFORTUNE */
{
"robe of Misfortune", "fabulously ornate robe",
OBJ_ARMOUR, ARM_ROBE, -5, 0, MAGENTA, 0,
@@ -992,7 +1030,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 52: UNRAND_FLASH */
+/* UNRAND_FLASH */
{
"cloak of Flash", "vibrating cloak",
OBJ_ARMOUR, ARM_CLOAK, +3, 0, ETC_GILA, 0,
@@ -1011,7 +1049,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 53: UNRAND_BOOTS_ASSASSIN */
+/* UNRAND_BOOTS_ASSASSIN */
{
"boots of the Assassin", "soft boots",
OBJ_ARMOUR, ARM_BOOTS, +2, 0, BROWN, 0,
@@ -1030,7 +1068,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 54: UNRAND_LEAR */
+/* UNRAND_LEAR */
{
"Lear's chain mail", "golden chain mail",
OBJ_ARMOUR, ARM_CHAIN_MAIL, -1, 0, ETC_GOLD, 0,
@@ -1049,7 +1087,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 55: UNRAND_ZHOR */
+/* UNRAND_ZHOR */
{
"skin of Zhor", "smelly skin",
OBJ_ARMOUR, ARM_ANIMAL_SKIN, +4, 0, BROWN, 0,
@@ -1068,7 +1106,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 56: UNRAND_SALAMANDER */
+/* UNRAND_SALAMANDER */
{
"salamander hide armour", "red leather armour",
OBJ_ARMOUR, ARM_LEATHER_ARMOUR, +3, 0, ETC_FIRE, 0,
@@ -1087,7 +1125,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 57: UNRAND_WAR */
+/* UNRAND_WAR */
{
"gauntlets of War", "thick gauntlets",
OBJ_ARMOUR, ARM_GLOVES, +3, 0, BROWN, 0,
@@ -1106,7 +1144,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 58: UNRAND_RESISTANCE */
+/* UNRAND_RESISTANCE */
{
"shield of Resistance", "bronze shield",
OBJ_ARMOUR, ARM_SHIELD, +5, 0, LIGHTRED, 0,
@@ -1125,7 +1163,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 59: UNRAND_FOLLY */
+/* UNRAND_FOLLY */
{
"robe of Folly", "dull robe",
OBJ_ARMOUR, ARM_ROBE, -1, 0, LIGHTGREY, 0,
@@ -1144,7 +1182,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 60: UNRAND_MAXWELL */
+/* UNRAND_MAXWELL */
{
"Maxwell's patent armour", "weird-looking armour",
OBJ_ARMOUR, ARM_PLATE_MAIL, +10, 0, LIGHTGREEN, 0,
@@ -1163,7 +1201,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 61: UNRAND_DRAGONMASK */
+/* UNRAND_DRAGONMASK */
{
"mask of the Dragon", "blue mask",
OBJ_ARMOUR, ARM_CAP, 0, 0, ETC_SHIMMER_BLUE, 0,
@@ -1182,7 +1220,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 62: UNRAND_NIGHT */
+/* UNRAND_NIGHT */
{
"robe of Night", "black robe",
OBJ_ARMOUR, ARM_ROBE, +4, 0, ETC_DARK, 0,
@@ -1201,7 +1239,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 63: UNRAND_DRAGON_KING */
+/* UNRAND_DRAGON_KING */
{
"armour of the Dragon King", "shiny dragon armour",
OBJ_ARMOUR, ARM_GOLD_DRAGON_ARMOUR, +5, 0, ETC_GOLD, 0,
@@ -1220,7 +1258,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 64: UNRAND_ALCHEMIST */
+/* UNRAND_ALCHEMIST */
{
"hat of the Alchemist", "dirty hat",
OBJ_ARMOUR, ARM_WIZARD_HAT, +2, 0, MAGENTA, 0,
@@ -1239,7 +1277,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 65: UNRAND_FENCERS_GLOVES */
+/* UNRAND_FENCERS_GLOVES */
{
"Fencer's gloves", "silk gloves",
OBJ_ARMOUR, ARM_GLOVES, +2, 0, WHITE, 0,
@@ -1258,7 +1296,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 66: UNRAND_STARLIGHT */
+/* UNRAND_STARLIGHT */
{
"cloak of Starlight", "phosphorescent cloak",
OBJ_ARMOUR, ARM_CLOAK, 0, 0, ETC_ICE, 0,
@@ -1277,7 +1315,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 67: UNRAND_RATSKIN_CLOAK */
+/* UNRAND_RATSKIN_CLOAK */
{
"ratskin cloak", "motley cloak",
OBJ_ARMOUR, ARM_CLOAK, +1, 0, ETC_BEOGH, 0,
@@ -1296,7 +1334,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 68: UNRAND_AIR */
+/* UNRAND_AIR */
{
"amulet of the Air", "sky-blue amulet",
OBJ_JEWELLERY, AMU_CONTROLLED_FLIGHT, 0, 0, ETC_ELECTRICITY, 0,
@@ -1315,7 +1353,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 69: UNRAND_SHADOWS */
+/* UNRAND_SHADOWS */
{
"ring of Shadows", "black ring",
OBJ_JEWELLERY, RING_INVISIBILITY, 0, 0, ETC_DARK, 0,
@@ -1334,7 +1372,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 70: UNRAND_CEKUGOB */
+/* UNRAND_CEKUGOB */
{
"amulet of Cekugob", "crystal amulet",
OBJ_JEWELLERY, AMU_WARDING, 0, 0, LIGHTGREY, 0,
@@ -1353,7 +1391,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 71: UNRAND_FOUR_WINDS */
+/* UNRAND_FOUR_WINDS */
{
"amulet of the Four Winds", "jade amulet",
OBJ_JEWELLERY, AMU_CLARITY, 0, 0, ETC_POISON, 0,
@@ -1372,7 +1410,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 72: UNRAND_BLOODLUST */
+/* UNRAND_BLOODLUST */
{
"necklace of Bloodlust", "blood-stained necklace",
OBJ_JEWELLERY, AMU_RAGE, 0, 0, ETC_BLOOD, 0,
@@ -1391,7 +1429,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 73: UNRAND_SHAOLIN */
+/* UNRAND_SHAOLIN */
{
"ring of Shaolin", "jade ring",
OBJ_JEWELLERY, RING_EVASION, +8, 0, ETC_POISON, 0,
@@ -1410,7 +1448,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 74: UNRAND_ROBUSTNESS */
+/* UNRAND_ROBUSTNESS */
{
"ring of Robustness", "steel ring",
OBJ_JEWELLERY, RING_PROTECTION, +8, 0, LIGHTGREY, 0,
@@ -1429,7 +1467,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 75: UNRAND_MAGE */
+/* UNRAND_MAGE */
{
"ring of the Mage", "sapphire ring",
OBJ_JEWELLERY, RING_WIZARDRY, 0, 0, ETC_ENCHANT, 0,
@@ -1448,7 +1486,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 76: UNRAND_SHIELDING */
+/* UNRAND_SHIELDING */
{
"brooch of Shielding", "shield-shaped amulet",
OBJ_JEWELLERY, AMU_WARDING, 0, 0, ETC_MAGIC, 0,
@@ -1467,7 +1505,7 @@
NULL, NULL, NULL, { NULL }, NULL,
},
-/* 77: UNRAND_DUMMY2 */
+/* UNRAND_DUMMY2 */
{
"DUMMY UNRANDART 2", "DUMMY UNRANDART 2",
OBJ_UNASSIGNED, 250, 250, 250, BLACK, 0,
diff --git a/crawl-ref/source/art-data.txt b/crawl-ref/source/art-data.txt
index 95b381db10..9b3b1a889a 100644
--- a/crawl-ref/source/art-data.txt
+++ b/crawl-ref/source/art-data.txt
@@ -705,6 +705,32 @@ TILE_EQ: crystal_spear
INT: 3
DESC_END: Presumably this relic led to the invention of the famous spell, or maybe the other way around.
+NAME: captain's cutlass
+APPEAR: black cutlass
+OBJ: OBJ_WEAPONS/WPN_SABRE
+PLUS: +6/+7
+COLOUR: DARKGRAY
+TILE: urand_cutlass
+TILE_EQ: cutlass
+BRAND: SPWPN_SPEED
+DAM: 3
+DESC_END: This infamous weapon was used by a vile pirate captain to
+ slaughter countless innocents. Finally, he met his destiny
+ when a kraken swallowed his ship with all the crew aboard.
+ The cutlass was thought to be forever lost, but now you have
+ a proof to the contrary in your very hands.
+
+NAME: storm bow
+APPEAR: night blue bow
+OBJ: OBJ_WEAPONS/WPN_LONGBOW
+PLUS: +8/+8
+COLOUR: BLUE
+TILE: urand_storm_bow
+TILE_EQ: bow_blue
+BRAND: SPWPN_ELECTROCUTION
+BOOL: special
+DESC: This bow has the color of dark rain clouds, and the smell of wet ozone.
+
NAME: shield of Ignorance
APPEAR: dull large shield
OBJ: OBJ_ARMOUR/ARM_LARGE_SHIELD
diff --git a/crawl-ref/source/art-func.h b/crawl-ref/source/art-func.h
index f4c076e478..b460304502 100644
--- a/crawl-ref/source/art-func.h
+++ b/crawl-ref/source/art-func.h
@@ -21,10 +21,11 @@
#define ART_FUNC_H
+#include "cloud.h" // For storm's bow rain
#include "effects.h" // For Sceptre of Torment tormenting
#include "food.h" // For evokes
-#include "monplace.h" // For Sceptre of Asmodeus evoke
-#include "monstuff.h" // For Scythe of Curses cursing items
+#include "mon-place.h" // For Sceptre of Asmodeus evoke
+#include "mon-stuff.h" // For Scythe of Curses cursing items
#include "spells3.h" // For Zonguldrok animating dead
#include "spl-cast.h" // For evokes
#include "spl-mis.h" // For Staff of Wucad Mu miscasts
@@ -73,6 +74,7 @@ static bool _evoke_sceptre_of_asmodeus()
summon_any_demon(DEMON_COMMON));
const bool good_summon = create_monster(
mgen_data::hostile_at(mon,
+ "the Sceptre of Asmodeus",
true, 6, 0, you.pos())) != -1;
if (good_summon)
@@ -461,7 +463,8 @@ static void _ZONGULDROK_world_reacts(item_def *item)
{
if (one_chance_in(5))
{
- animate_dead(&you, 1 + random2(3), BEH_HOSTILE, MHITYOU);
+ animate_dead(&you, 1 + random2(3), BEH_HOSTILE, MHITYOU, 0,
+ "the Sword of Zonguldrok");
did_god_conduct(DID_NECROMANCY, 1);
}
}
@@ -477,3 +480,14 @@ static void _ZONGULDROK_melee_effect(item_def* weapon, actor* attacker,
///////////////////////////////////////////////////
+static void _STORM_BOW_world_reacts(item_def *item)
+{
+ if (!one_chance_in(300))
+ return;
+
+ for (radius_iterator ri(you.pos(), 2); ri; ++ri)
+ if (!cell_is_solid(*ri) && env.cgrid(*ri) == EMPTY_CLOUD && one_chance_in(5))
+ place_cloud( CLOUD_RAIN, *ri, random2(20), KC_OTHER, 3);
+}
+
+///////////////////////////////////////////////////
diff --git a/crawl-ref/source/artefact.cc b/crawl-ref/source/artefact.cc
index fb2687526a..0ac8f3ac0c 100644
--- a/crawl-ref/source/artefact.cc
+++ b/crawl-ref/source/artefact.cc
@@ -769,6 +769,12 @@ void static _get_randart_properties(const item_def &item,
{
proprt[ARTP_BRAND] = SPWPN_NORMAL;
}
+
+ if (atype == WPN_CROSSBOW && one_chance_in(5)
+ || atype == WPN_HAND_CROSSBOW && one_chance_in(10))
+ {
+ proprt[ARTP_BRAND] = SPWPN_ELECTROCUTION;
+ }
}
}
diff --git a/crawl-ref/source/artefact.h b/crawl-ref/source/artefact.h
index 9b19c03a06..5375c2f03e 100644
--- a/crawl-ref/source/artefact.h
+++ b/crawl-ref/source/artefact.h
@@ -13,7 +13,7 @@
class bolt;
// NOTE: NO_UNRANDARTS is automatically set by util/art-data.pl
-#define NO_UNRANDARTS 77
+#define NO_UNRANDARTS 79
#define ART_PROPERTIES ARTP_NUM_PROPERTIES
@@ -81,6 +81,8 @@ enum unrand_type
UNRAND_SERPENT_SCOURGE, // whip "Serpent-Scourge"
UNRAND_ACCURACY, // knife of Accuracy
UNRAND_CRYSTAL_SPEAR, // Lehudib's crystal spear
+ UNRAND_CAPTAINS_CUTLASS, // captain's cutlass
+ UNRAND_STORM_BOW, // storm bow
UNRAND_IGNORANCE, // shield of Ignorance
UNRAND_AUGMENTATION, // robe of Augmentation
UNRAND_THIEF, // cloak of the Thief
diff --git a/crawl-ref/source/attitude-change.cc b/crawl-ref/source/attitude-change.cc
index 509525fb65..0cb8d91949 100644
--- a/crawl-ref/source/attitude-change.cc
+++ b/crawl-ref/source/attitude-change.cc
@@ -16,9 +16,10 @@
#include "goditem.h"
#include "message.h"
#include "mon-behv.h"
+#include "mon-iter.h"
#include "mon-util.h"
#include "monster.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "player.h"
#include "random.h"
#include "religion.h"
@@ -145,44 +146,42 @@ static bool _holy_beings_on_level_attitude_change()
{
bool success = false;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
- if (monster->alive()
- && monster->is_holy())
- {
+ if (!mi->is_holy())
+ continue;
+
#ifdef DEBUG_DIAGNOSTICS
- mprf(MSGCH_DIAGNOSTICS, "Holy attitude changing: %s on level %d, branch %d",
- monster->name(DESC_PLAIN).c_str(),
- static_cast<int>(you.your_level),
- static_cast<int>(you.where_are_you));
+ mprf(MSGCH_DIAGNOSTICS, "Holy attitude changing: %s on level %d, branch %d",
+ mi->name(DESC_PLAIN).c_str(),
+ static_cast<int>(you.your_level),
+ static_cast<int>(you.where_are_you));
#endif
- // If you worship a good god, you get another chance to make
- // neutral and hostile holy beings good neutral.
- if (is_good_god(you.religion) && !monster->wont_attack())
- {
- if (testbits(monster->flags, MF_ATT_CHANGE_ATTEMPT))
- {
- monster->flags &= ~MF_ATT_CHANGE_ATTEMPT;
-
- success = true;
- }
- }
- // If you don't worship a good god, you make all friendly
- // and good neutral holy beings that worship a good god
- // hostile.
- else if (!is_good_god(you.religion) && monster->wont_attack()
- && is_good_god(monster->god))
+ // If you worship a good god, you get another chance to make
+ // neutral and hostile holy beings good neutral.
+ if (is_good_god(you.religion) && !mi->wont_attack())
+ {
+ if (testbits(mi->flags, MF_ATT_CHANGE_ATTEMPT))
{
- monster->attitude = ATT_HOSTILE;
- monster->del_ench(ENCH_CHARM, true);
- behaviour_event(monster, ME_ALERT, MHITYOU);
- // For now CREATED_FRIENDLY/WAS_NEUTRAL stays.
+ mi->flags &= ~MF_ATT_CHANGE_ATTEMPT;
success = true;
}
}
+ // If you don't worship a good god, you make all friendly
+ // and good neutral holy beings that worship a good god
+ // hostile.
+ else if (!is_good_god(you.religion) && mi->wont_attack()
+ && is_good_god(mi->god))
+ {
+ mi->attitude = ATT_HOSTILE;
+ mi->del_ench(ENCH_CHARM, true);
+ behaviour_event(*mi, ME_ALERT, MHITYOU);
+ // For now CREATED_FRIENDLY/WAS_NEUTRAL stays.
+
+ success = true;
+ }
}
return (success);
@@ -197,32 +196,29 @@ static bool _unholy_and_evil_beings_on_level_attitude_change()
{
bool success = false;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
- if (monster->alive()
- && (monster->is_unholy()
- || monster->is_evil()))
- {
+ if (!mi->is_unholy() && !mi->is_evil())
+ continue;
+
#ifdef DEBUG_DIAGNOSTICS
- mprf(MSGCH_DIAGNOSTICS, "Unholy/evil attitude changing: %s "
- "on level %d, branch %d",
- monster->name(DESC_PLAIN, true).c_str(),
- static_cast<int>(you.your_level),
- static_cast<int>(you.where_are_you));
+ mprf(MSGCH_DIAGNOSTICS, "Unholy/evil attitude changing: %s "
+ "on level %d, branch %d",
+ mi->name(DESC_PLAIN, true).c_str(),
+ static_cast<int>(you.your_level),
+ static_cast<int>(you.where_are_you));
#endif
- // If you worship a good god, you make all friendly and good
- // neutral unholy and evil beings hostile.
- if (is_good_god(you.religion) && monster->wont_attack())
- {
- monster->attitude = ATT_HOSTILE;
- monster->del_ench(ENCH_CHARM, true);
- behaviour_event(monster, ME_ALERT, MHITYOU);
- // For now CREATED_FRIENDLY/WAS_NEUTRAL stays.
+ // If you worship a good god, you make all friendly and good
+ // neutral unholy and evil beings hostile.
+ if (is_good_god(you.religion) && mi->wont_attack())
+ {
+ mi->attitude = ATT_HOSTILE;
+ mi->del_ench(ENCH_CHARM, true);
+ behaviour_event(*mi, ME_ALERT, MHITYOU);
+ // For now CREATED_FRIENDLY/WAS_NEUTRAL stays.
- success = true;
- }
+ success = true;
}
}
@@ -238,33 +234,30 @@ static bool _chaotic_beings_on_level_attitude_change()
{
bool success = false;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
- if (monster->alive()
- && monster->is_chaotic())
- {
+ if (!mi->is_chaotic())
+ continue;
+
#ifdef DEBUG_DIAGNOSTICS
- mprf(MSGCH_DIAGNOSTICS, "Chaotic attitude changing: %s on level %d, branch %d",
- monster->name(DESC_PLAIN).c_str(),
- static_cast<int>(you.your_level),
- static_cast<int>(you.where_are_you));
+ mprf(MSGCH_DIAGNOSTICS, "Chaotic attitude changing: %s on level %d, branch %d",
+ mi->name(DESC_PLAIN).c_str(),
+ static_cast<int>(you.your_level),
+ static_cast<int>(you.where_are_you));
#endif
- // If you worship Zin, you make all friendly and good neutral
- // chaotic beings hostile.
- if (you.religion == GOD_ZIN && monster->wont_attack())
- {
- monster->attitude = ATT_HOSTILE;
- monster->del_ench(ENCH_CHARM, true);
- behaviour_event(monster, ME_ALERT, MHITYOU);
- // For now CREATED_FRIENDLY/WAS_NEUTRAL stays.
+ // If you worship Zin, you make all friendly and good neutral
+ // chaotic beings hostile.
+ if (you.religion == GOD_ZIN && mi->wont_attack())
+ {
+ mi->attitude = ATT_HOSTILE;
+ mi->del_ench(ENCH_CHARM, true);
+ behaviour_event(*mi, ME_ALERT, MHITYOU);
+ // For now CREATED_FRIENDLY/WAS_NEUTRAL stays.
- success = true;
- }
+ success = true;
}
}
-
return (success);
}
@@ -277,30 +270,28 @@ static bool _spellcasters_on_level_attitude_change()
{
bool success = false;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
- if (monster->alive()
- && monster->is_actual_spellcaster())
- {
+ if (!mi->is_actual_spellcaster())
+ continue;
+
#ifdef DEBUG_DIAGNOSTICS
- mprf(MSGCH_DIAGNOSTICS, "Spellcaster attitude changing: %s on level %d, branch %d",
- monster->name(DESC_PLAIN).c_str(),
- static_cast<int>(you.your_level),
- static_cast<int>(you.where_are_you));
+ mprf(MSGCH_DIAGNOSTICS, "Spellcaster attitude changing: %s on level %d, branch %d",
+ mi->name(DESC_PLAIN).c_str(),
+ static_cast<int>(you.your_level),
+ static_cast<int>(you.where_are_you));
#endif
- // If you worship Trog, you make all friendly and good neutral
- // magic users hostile.
- if (you.religion == GOD_TROG && monster->wont_attack())
- {
- monster->attitude = ATT_HOSTILE;
- monster->del_ench(ENCH_CHARM, true);
- behaviour_event(monster, ME_ALERT, MHITYOU);
- // For now CREATED_FRIENDLY/WAS_NEUTRAL stays.
+ // If you worship Trog, you make all friendly and good neutral
+ // magic users hostile.
+ if (you.religion == GOD_TROG && mi->wont_attack())
+ {
+ mi->attitude = ATT_HOSTILE;
+ mi->del_ench(ENCH_CHARM, true);
+ behaviour_event(*mi, ME_ALERT, MHITYOU);
+ // For now CREATED_FRIENDLY/WAS_NEUTRAL stays.
- success = true;
- }
+ success = true;
}
}
@@ -322,18 +313,17 @@ static bool _make_god_gifts_on_level_disappear(bool seen = false)
: GOD_NO_GOD;
int count = 0;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
- if (is_follower(monster)
- && monster->has_ench(ENCH_ABJ)
- && mons_is_god_gift(monster, god))
+ if (is_follower(*mi)
+ && mi->has_ench(ENCH_ABJ)
+ && mons_is_god_gift(*mi, god))
{
- if (!seen || simple_monster_message(monster, " abandons you!"))
+ if (!seen || simple_monster_message(*mi, " abandons you!"))
count++;
// The monster disappears.
- monster_die(monster, KILL_DISMISSED, NON_MONSTER);
+ monster_die(*mi, KILL_DISMISSED, NON_MONSTER);
}
}
@@ -366,18 +356,17 @@ static bool _make_holy_god_gifts_on_level_good_neutral(bool seen = false)
: GOD_NO_GOD;
int count = 0;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
- if (is_follower(monster)
- && !monster->has_ench(ENCH_CHARM)
- && monster->is_holy()
- && mons_is_god_gift(monster, god))
+ if (is_follower(*mi)
+ && !mi->has_ench(ENCH_CHARM)
+ && mi->is_holy()
+ && mons_is_god_gift(*mi, god))
{
// monster changes attitude
- monster->attitude = ATT_GOOD_NEUTRAL;
+ mi->attitude = ATT_GOOD_NEUTRAL;
- if (!seen || simple_monster_message(monster, " becomes indifferent."))
+ if (!seen || simple_monster_message(*mi, " becomes indifferent."))
count++;
}
}
@@ -412,18 +401,17 @@ static bool _make_god_gifts_on_level_hostile(bool seen = false)
: GOD_NO_GOD;
int count = 0;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
- if (is_follower(monster)
- && mons_is_god_gift(monster, god))
+ if (is_follower(*mi)
+ && mons_is_god_gift(*mi, god))
{
// monster changes attitude and behaviour
- monster->attitude = ATT_HOSTILE;
- monster->del_ench(ENCH_CHARM, true);
- behaviour_event(monster, ME_ALERT, MHITYOU);
+ mi->attitude = ATT_HOSTILE;
+ mi->del_ench(ENCH_CHARM, true);
+ behaviour_event(*mi, ME_ALERT, MHITYOU);
- if (!seen || simple_monster_message(monster, " turns against you!"))
+ if (!seen || simple_monster_message(*mi, " turns against you!"))
count++;
}
}
@@ -457,33 +445,32 @@ static bool _yred_slaves_on_level_abandon_you()
{
bool success = false;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
- if (_is_yred_enslaved_body_and_soul(monster))
+ if (_is_yred_enslaved_body_and_soul(*mi))
{
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Undead soul abandoning: %s on level %d, branch %d",
- monster->name(DESC_PLAIN).c_str(),
+ mi->name(DESC_PLAIN).c_str(),
static_cast<int>(you.your_level),
static_cast<int>(you.where_are_you));
#endif
- yred_make_enslaved_soul(monster, true, true, true);
+ yred_make_enslaved_soul(*mi, true, true, true);
success = true;
}
- else if (is_yred_undead_slave(monster))
+ else if (is_yred_undead_slave(*mi))
{
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Undead abandoning: %s on level %d, branch %d",
- monster->name(DESC_PLAIN).c_str(),
+ mi->name(DESC_PLAIN).c_str(),
static_cast<int>(you.your_level),
static_cast<int>(you.where_are_you));
#endif
- monster->attitude = ATT_HOSTILE;
- behaviour_event(monster, ME_ALERT, MHITYOU);
+ mi->attitude = ATT_HOSTILE;
+ behaviour_event(*mi, ME_ALERT, MHITYOU);
// For now CREATED_FRIENDLY stays.
success = true;
@@ -499,20 +486,19 @@ static bool _beogh_followers_on_level_abandon_you()
// Note that orc high priests' summons are gifts of Beogh, so we
// can't use is_orcish_follower() here.
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
- if (mons_is_god_gift(monster, GOD_BEOGH))
+ if (mons_is_god_gift(*mi, GOD_BEOGH))
{
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Orc abandoning: %s on level %d, branch %d",
- monster->name(DESC_PLAIN).c_str(),
+ mi->name(DESC_PLAIN).c_str(),
static_cast<int>(you.your_level),
static_cast<int>(you.where_are_you));
#endif
- monster->attitude = ATT_HOSTILE;
- behaviour_event(monster, ME_ALERT, MHITYOU);
+ mi->attitude = ATT_HOSTILE;
+ behaviour_event(*mi, ME_ALERT, MHITYOU);
// For now CREATED_FRIENDLY stays.
success = true;
@@ -526,20 +512,19 @@ static bool _jiyva_slimes_on_level_abandon_you()
{
bool success = false;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
- if (is_fellow_slime(monster))
+ if (is_fellow_slime(*mi))
{
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Slime abandoning: %s on level %d, branch %d",
- monster->name(DESC_PLAIN).c_str(),
+ mi->name(DESC_PLAIN).c_str(),
static_cast<int>(you.your_level),
static_cast<int>(you.where_are_you));
#endif
- monster->attitude = ATT_HOSTILE;
- behaviour_event(monster, ME_ALERT, MHITYOU);
+ mi->attitude = ATT_HOSTILE;
+ behaviour_event(*mi, ME_ALERT, MHITYOU);
// For now WAS_NEUTRAL stays.
success = true;
@@ -625,27 +610,25 @@ bool yred_slaves_abandon_you()
static bool _fedhas_plants_on_level_hostile()
{
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
- if (monster->alive()
- && mons_is_plant(monster))
+ if (mons_is_plant(*mi))
{
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Plant hostility: %s on level %d, branch %d",
- monster->name(DESC_PLAIN).c_str(),
+ mi->name(DESC_PLAIN).c_str(),
static_cast<int>(you.your_level),
static_cast<int>(you.where_are_you));
#endif
// You can potentially turn an oklob or whatever neutral
// again by going back to Fedhas.
- if (testbits(monster->flags, MF_ATT_CHANGE_ATTEMPT))
- monster->flags &= ~MF_ATT_CHANGE_ATTEMPT;
+ if (testbits(mi->flags, MF_ATT_CHANGE_ATTEMPT))
+ mi->flags &= ~MF_ATT_CHANGE_ATTEMPT;
- monster->attitude = ATT_HOSTILE;
- monster->del_ench(ENCH_CHARM, true);
- behaviour_event(monster, ME_ALERT, MHITYOU);
+ mi->attitude = ATT_HOSTILE;
+ mi->del_ench(ENCH_CHARM, true);
+ behaviour_event(*mi, ME_ALERT, MHITYOU);
// For now WAS_NEUTRAL stays.
}
}
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 27600e0a31..973962a6af 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -45,8 +45,9 @@
#include "message.h"
#include "misc.h"
#include "mon-behv.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-iter.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "mutation.h"
#include "ouch.h"
@@ -1180,14 +1181,14 @@ const zap_info zap_data[] = {
},
{
- ZAP_BACKLIGHT,
+ ZAP_CORONA,
"0",
100,
NULL,
NULL,
BLUE,
true,
- BEAM_BACKLIGHT,
+ BEAM_CORONA,
DCHAR_SPACE,
false,
false,
@@ -1196,14 +1197,14 @@ const zap_info zap_data[] = {
},
{
- ZAP_SLEEP,
+ ZAP_HIBERNATION,
"0",
100,
NULL,
NULL,
BLACK,
true,
- BEAM_SLEEP,
+ BEAM_HIBERNATION,
DCHAR_SPACE,
false,
false,
@@ -1321,6 +1322,22 @@ const zap_info zap_data[] = {
false,
false,
0
+ },
+
+ {
+ ZAP_SLEEP,
+ "0",
+ 100,
+ NULL,
+ NULL,
+ BLACK,
+ true,
+ BEAM_SLEEP,
+ DCHAR_SPACE,
+ false,
+ false,
+ false,
+ 0
}
};
@@ -2615,26 +2632,18 @@ bool mass_enchantment( enchant_type wh_enchant, int pow, int origin,
const kill_category kc = (origin == MHITYOU ? KC_YOU : KC_OTHER);
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi(&you.get_los()); mi; ++mi)
{
- monsters* const monster = &menv[i];
-
- if (!monster->alive())
- continue;
-
- if (!mons_near(monster))
- continue;
-
- if (monster->has_ench(wh_enchant))
+ if (mi->has_ench(wh_enchant))
continue;
if (m_attempted)
++*m_attempted;
- if (_monster_resists_mass_enchantment(monster, wh_enchant, pow))
+ if (_monster_resists_mass_enchantment(*mi, wh_enchant, pow))
continue;
- if (monster->add_ench(mon_enchant(wh_enchant, 0, kc)))
+ if (mi->add_ench(mon_enchant(wh_enchant, 0, kc)))
{
if (m_succumbed)
++*m_succumbed;
@@ -2649,11 +2658,11 @@ bool mass_enchantment( enchant_type wh_enchant, int pow, int origin,
default: msg = NULL; break;
}
if (msg)
- msg_generated = simple_monster_message(monster, msg);
+ msg_generated = simple_monster_message(*mi, msg);
// Extra check for fear (monster needs to reevaluate behaviour).
if (wh_enchant == ENCH_FEAR)
- behaviour_event(monster, ME_SCARE, origin);
+ behaviour_event(*mi, ME_SCARE, origin);
}
}
@@ -2889,7 +2898,7 @@ void fire_tracer(const monsters *monster, bolt &pbolt, bool explode_only)
// When a mimic is hit by a ranged attack, it teleports away (the slow
// way) and changes its appearance - the appearance change is in
-// monster_teleport() in monstuff.cc.
+// monster_teleport() in mon-stuff.cc.
void mimic_alert(monsters *mimic)
{
if (!mimic->alive())
@@ -3124,6 +3133,7 @@ void bolt::affect_ground()
int rc = create_monster(mgen_data(MONS_BALLISTOMYCETE,
beh,
+ agent(),
0,
0,
pos(),
@@ -3355,8 +3365,8 @@ void bolt::affect_place_explosion_clouds()
(whose_kill() == KC_OTHER ? BEH_HOSTILE : BEH_FRIENDLY);
mons_place(
- mgen_data(MONS_FIRE_VORTEX, att, 2, SPELL_FIRE_STORM, p,
- MHITNOT, 0, god));
+ mgen_data(MONS_FIRE_VORTEX, att, agent(), 2, SPELL_FIRE_STORM,
+ p, MHITNOT, 0, god));
}
}
}
@@ -3667,9 +3677,8 @@ void bolt::tracer_affect_player()
for (unsigned int i = 0; i < messages.size(); ++i)
mpr(messages[i].c_str(), MSGCH_WARN);
- range_used += range_used_on_hit(&you);
-
apply_hit_funcs(&you, 0);
+ range_used += range_used_on_hit(&you);
}
bool bolt::misses_player()
@@ -3823,11 +3832,15 @@ void bolt::affect_player_enchantment()
switch (flavour)
{
+ case BEAM_HIBERNATION:
+ you.hibernate(ench_power);
+ break;
+
case BEAM_SLEEP:
you.put_to_sleep(ench_power);
break;
- case BEAM_BACKLIGHT:
+ case BEAM_CORONA:
you.backlight();
obvious_effect = true;
break;
@@ -4053,11 +4066,11 @@ void bolt::affect_player_enchantment()
}
}
+ apply_hit_funcs(&you, 0);
+
// Regardless of effect, we need to know if this is a stopper
// or not - it seems all of the above are.
range_used += range_used_on_hit(&you);
-
- apply_hit_funcs(&you, 0);
}
@@ -4324,8 +4337,8 @@ void bolt::tracer_enchantment_affect_monster(monsters* mon)
handle_stop_attack_prompt(mon);
if (!beam_cancelled)
{
- range_used += range_used_on_hit(mon);
apply_hit_funcs(mon, 0);
+ range_used += range_used_on_hit(mon);
}
}
@@ -4484,9 +4497,10 @@ void bolt::tracer_nonenchantment_affect_monster(monsters* mon)
mpr(messages[i].c_str(), MSGCH_MONSTER_DAMAGE);
}
+ apply_hit_funcs(mon, final);
+
// Either way, we could hit this monster, so update range used.
range_used += range_used_on_hit(mon);
- apply_hit_funcs(mon, final);
}
void bolt::tracer_affect_monster(monsters* mon)
@@ -4585,8 +4599,8 @@ void bolt::enchantment_affect_monster(monsters* mon)
beogh_follower_convert(mon, true);
}
- range_used += range_used_on_hit(mon);
apply_hit_funcs(mon, 0);
+ range_used += range_used_on_hit(mon);
}
void bolt::monster_post_hit(monsters* mon, int dmg)
@@ -4980,9 +4994,8 @@ void bolt::affect_monster(monsters* mon)
mon = &orig;
}
- range_used += range_used_on_hit(mon);
-
apply_hit_funcs(mon, final, corpse);
+ range_used += range_used_on_hit(mon);
}
bool bolt::has_saving_throw() const
@@ -5040,8 +5053,8 @@ bool _ench_flavour_affects_monster(beam_type flavour, const monsters* mon)
rc = !mon->res_negative_energy();
break;
- case BEAM_SLEEP:
- rc = mon->can_sleep();
+ case BEAM_HIBERNATION:
+ rc = mon->can_hibernate();
break;
case BEAM_PORKALATOR:
@@ -5186,7 +5199,7 @@ mon_resist_type bolt::apply_enchantment_to_monster(monsters* mon)
}
// The monster can be no more than lightly wounded/damaged,
- // using the formula from monstuff.cc:mons_get_damage_level().
+ // using the formula from mon-stuff.cc:mons_get_damage_level().
if (mon->hit_points <= mon->max_hit_points * 3 / 4)
{
simple_monster_message(mon, "'s soul is too badly injured.");
@@ -5245,17 +5258,17 @@ mon_resist_type bolt::apply_enchantment_to_monster(monsters* mon)
mon->hurt(agent(), damage.roll(), flavour);
return (MON_AFFECTED);
- case BEAM_SLEEP:
- if (mon->can_sleep())
+ case BEAM_HIBERNATION:
+ if (mon->can_hibernate())
{
if (simple_monster_message(mon, " looks drowsy..."))
obvious_effect = true;
- mon->put_to_sleep();
+ mon->hibernate();
return (MON_AFFECTED);
}
return (MON_UNAFFECTED);
- case BEAM_BACKLIGHT:
+ case BEAM_CORONA:
if (backlight_monsters(mon->pos(), hit, 0))
{
obvious_effect = true;
@@ -5350,6 +5363,17 @@ mon_resist_type bolt::apply_enchantment_to_monster(monsters* mon)
}
return (MON_AFFECTED);
+ case BEAM_SLEEP:
+ if (mon->has_ench(ENCH_SLEEPY))
+ return (MON_UNAFFECTED);
+
+ if (mon->add_ench(mon_enchant(ENCH_SLEEPY, 0, whose_kill())))
+ {
+ if (simple_monster_message(mon, " falls asleep!"))
+ obvious_effect = true;
+ }
+ return (MON_AFFECTED);
+
case BEAM_INVISIBILITY:
{
// Store the monster name before it becomes an "it" -- bwr
@@ -5358,7 +5382,7 @@ mon_resist_type bolt::apply_enchantment_to_monster(monsters* mon)
if (!mon->has_ench(ENCH_INVIS) && mon->add_ench(ENCH_INVIS))
{
// A casting of invisibility erases backlight.
- mon->del_ench(ENCH_BACKLIGHT);
+ mon->del_ench(ENCH_CORONA);
// Can't use simple_monster_message() here, since it checks
// for visibility of the monster (and it's now invisible).
@@ -5404,13 +5428,20 @@ mon_resist_type bolt::apply_enchantment_to_monster(monsters* mon)
if (mons_is_ghost_demon(mon->type))
return (MON_UNAFFECTED);
- monster_type orig_type = mon->type;
+ monsters orig_mon(*mon);
if (monster_polymorph(mon, (mon->holiness() == MH_DEMONIC ?
MONS_HELL_HOG : MONS_HOG)))
{
obvious_effect = true;
+
+ // Don't restore items to monster if it reverts.
+ orig_mon.inv = mon->inv;
+
+ // For monster reverting to original form.
+ mon->props[ORIG_MONSTER_KEY] = orig_mon;
}
- mon->number = ((int) orig_type + 1);
+
+
return (MON_AFFECTED);
}
@@ -5913,7 +5944,7 @@ bool bolt::nasty_to(const monsters *mon) const
// degeneration / sleep / enslave soul
if (flavour == BEAM_DEGENERATE
- || flavour == BEAM_SLEEP
+ || flavour == BEAM_HIBERNATION
|| flavour == BEAM_ENSLAVE_SOUL)
{
return (mon->holiness() == MH_NATURAL);
@@ -6161,8 +6192,9 @@ std::string beam_type_name(beam_type type)
case BEAM_ENSLAVE_DEMON: return ("enslave demon");
case BEAM_BLINK: return ("blink");
case BEAM_PETRIFY: return ("petrify");
- case BEAM_BACKLIGHT: return ("backlight");
+ case BEAM_CORONA: return ("backlight");
case BEAM_PORKALATOR: return ("porkalator");
+ case BEAM_HIBERNATION: return ("hibernation");
case BEAM_SLEEP: return ("sleep");
case BEAM_BERSERK: return ("berserk");
case BEAM_POTION_BLACK_SMOKE: return ("black smoke");
diff --git a/crawl-ref/source/cloud.cc b/crawl-ref/source/cloud.cc
index fda354706a..b1a6069c50 100644
--- a/crawl-ref/source/cloud.cc
+++ b/crawl-ref/source/cloud.cc
@@ -925,7 +925,7 @@ killer_type cloud_struct::whose_to_killer(kill_category whose)
{
case KC_YOU: return(KILL_YOU_MISSILE);
case KC_FRIENDLY: return(KILL_MON_MISSILE);
- case KC_OTHER: return(KILL_MON_MISSILE);
+ case KC_OTHER: return(KILL_MISC);
case KC_NCATEGORIES: ASSERT(false);
}
return (KILL_NONE);
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc
index 64fd63b768..4f25a2d362 100644
--- a/crawl-ref/source/clua.cc
+++ b/crawl-ref/source/clua.cc
@@ -622,6 +622,7 @@ void CLua::init_lua()
cluaopen_file(_state);
cluaopen_moninf(_state);
cluaopen_options(_state);
+ cluaopen_travel(_state);
cluaopen_view(_state);
cluaopen_globals(_state);
diff --git a/crawl-ref/source/cmd-keys.h b/crawl-ref/source/cmd-keys.h
index 5294c04ae0..d9610d58d3 100644
--- a/crawl-ref/source/cmd-keys.h
+++ b/crawl-ref/source/cmd-keys.h
@@ -242,6 +242,7 @@
{CONTROL('W'), CMD_MAP_ADD_WAYPOINT},
{'e', CMD_MAP_EXCLUDE_AREA},
{CONTROL('E'), CMD_MAP_CLEAR_EXCLUDES},
+{'R', CMD_MAP_EXCLUDE_RADIUS},
{'b', CMD_MAP_MOVE_DOWN_LEFT},
{'h', CMD_MAP_MOVE_LEFT},
{'j', CMD_MAP_MOVE_DOWN},
diff --git a/crawl-ref/source/cmd-name.h b/crawl-ref/source/cmd-name.h
index 9940b8e548..0d58833c4d 100644
--- a/crawl-ref/source/cmd-name.h
+++ b/crawl-ref/source/cmd-name.h
@@ -114,6 +114,7 @@
{CMD_MAP_ADD_WAYPOINT, "CMD_MAP_ADD_WAYPOINT"},
{CMD_MAP_EXCLUDE_AREA, "CMD_MAP_EXCLUDE_AREA"},
{CMD_MAP_CLEAR_EXCLUDES, "CMD_MAP_CLEAR_EXCLUDES"},
+{CMD_MAP_EXCLUDE_RADIUS, "CMD_MAP_EXCLUDE_RADIUS"},
{CMD_MAP_MOVE_LEFT, "CMD_MAP_MOVE_LEFT"},
{CMD_MAP_MOVE_DOWN, "CMD_MAP_MOVE_DOWN"},
{CMD_MAP_MOVE_UP, "CMD_MAP_MOVE_UP"},
diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc
index 457a598224..aef0bc00a1 100644
--- a/crawl-ref/source/command.cc
+++ b/crawl-ref/source/command.cc
@@ -2425,7 +2425,8 @@ int list_wizard_commands(bool do_redraw_screen)
"<w>k</w> : shift section of a labyrinth\n"
"<w>u</w>/<w>d</w> : shift up/down one level\n"
"<w>~</w> : go to a specific level\n"
- "<w>:</w> : find branches in the dungeon\n"
+ "<w>:</w> : find branches and overflow\n"
+ " temples in the dungeon\n"
"<w>{</w> : magic mapping\n"
"\n"
"<yellow>Debugging commands</yellow>\n"
diff --git a/crawl-ref/source/coord-circle.cc b/crawl-ref/source/coord-circle.cc
index 4170662b10..9072c6fa3e 100644
--- a/crawl-ref/source/coord-circle.cc
+++ b/crawl-ref/source/coord-circle.cc
@@ -41,8 +41,8 @@ void circle_def::init(int param, circle_type ctype)
break;
case C_CIRCLE:
shape = SH_CIRCLE;
- radius = static_cast<int>(ceil(sqrt(radius_sq)));
radius_sq = param;
+ radius = static_cast<int>(ceil(sqrt(radius_sq)));
break;
case C_ROUND:
shape = SH_CIRCLE;
diff --git a/crawl-ref/source/dat/altar.des b/crawl-ref/source/dat/altar.des
index 633caf24da..dd0fd6ebbf 100644
--- a/crawl-ref/source/dat/altar.des
+++ b/crawl-ref/source/dat/altar.des
@@ -19,14 +19,14 @@ TAGS: allow_dup
# More common than the others.
WEIGHT: 20
MAP
-cccccccccc
-cBcBcBcBcc
-G.c.c.c.Bc
-@.......Bc
-@.......Bc
-G.c.c.c.Bc
-cBcBcBcBcc
-cccccccccc
+cccccccccccc
+cBcBcBcBcBcc
+G.c.c.c.c.Bc
+@.........Bc
+@.........Bc
+G.c.c.c.c.Bc
+cBcBcBcBcBcc
+cccccccccccc
ENDMAP
NAME: jmf_multi_god_temple
@@ -273,14 +273,13 @@ ENDMAP
# III Special altars
######################################
-# XXX - The WEIGHTs and PLACE of these Fedhas vaults are temporary.
-# Remove once the Ecumenical Temple is updated to cater for
-# more than 12 gods.
+# NOTE: A vault tagged with only temple_overflow_FOO will only ever be used
+# for overflow temples, but one tagged with both temple_overflow_FOO and
+# uniq_altar_FOO can be generated either randomly or as an overflow temple.
NAME: fedhas_altar_1
-TAGS: uniq_altar_fedhas
+TAGS: uniq_altar_fedhas temple_overflow_fedhas
DEPTH: D:2-7
-WEIGHT: 75
KFEAT: C = altar_fedhas
MONS: plant
MAP
@@ -292,9 +291,8 @@ MAP
ENDMAP
NAME: fedhas_altar_2
-TAGS: uniq_altar_fedhas
+TAGS: uniq_altar_fedhas temple_overflow_fedhas
DEPTH: D:2-7
-WEIGHT: 75
KFEAT: C = altar_fedhas
NSUBST: w = 2:W / *:w
SUBST: . = ..wW
@@ -308,9 +306,8 @@ MAP
ENDMAP
NAME: fedhas_altar_3
-TAGS: uniq_altar_fedhas
+TAGS: uniq_altar_fedhas temple_overflow_fedhas
DEPTH: D:2-7
-WEIGHT: 75
KFEAT: C = altar_fedhas
NSUBST: b = 1:. / *:1
MONS: plant w:5 / fungus / nothing w:3
@@ -323,9 +320,8 @@ MAP
ENDMAP
NAME: fedhas_altar_4
-TAGS: uniq_altar_fedhas
+TAGS: uniq_altar_fedhas temple_overflow_fedhas
DEPTH: D:2-7
-WEIGHT: 75
KFEAT: C = altar_fedhas
FTILE: . = floor_lair
FTILE: t = floor_lair
@@ -345,33 +341,31 @@ ENDMAP
NAME: fedhas_altar_5
TAGS: uniq_altar_fedhas
-PLACE: D:8
-KFEAT: C = altar_fedhas
+KFEAT: _ = altar_fedhas
MONS: centaur, bush
MAP
......
.2222..
.21222.
-.22C22.
+.22_22.
...22..
.222..
ENDMAP
NAME: cheibriados_altar_1
-TAGS: uniq_altar_cheibriados
-PLACE: D:7
-KFEAT: C = altar_cheibriados
+TAGS: uniq_altar_cheibriados temple_overflow_cheibriados
+KFEAT: _ = altar_cheibriados
MAP
...
-.C.
+._.
...
ENDMAP
NAME: cheibriados_altar_2
TAGS: uniq_altar_cheibriados
DEPTH: D:2-6
-WEIGHT: 100
-KFEAT: C = altar_cheibriados
+WEIGHT: 5
+KFEAT: _ = altar_cheibriados
MONS: giant slug, giant snail, elephant slug
SUBST: 1 : 1:50 2:30 3:10 4:10
NSUBST: 4 = 1:1 / 1:2 / 1:3
@@ -380,7 +374,7 @@ MAP
.mmm...
.m1m...
.mmmmm.
-..Cm1m.
+.._m1m.
.mmmmm.
.m1m...
.mmm...
@@ -388,16 +382,15 @@ MAP
ENDMAP
NAME: cheibriados_altar_3
-TAGS: uniq_altar_cheibriados
+TAGS: uniq_altar_cheibriados temple_overflow_cheibriados
DEPTH: D:2-6
-WEIGHT: 100
-KFEAT: C = altar_cheibriados
+KFEAT: _ = altar_cheibriados
ITEM: potion of slowing
ITEM: apple, pear, orange, banana
SUBST: e : efgh
MAP
.d.
-eCe
+e_e
.d.
ENDMAP
@@ -411,14 +404,14 @@ MONS: patrolling Daeva / patrolling Angel
: else
MONS: patrolling Angel
: end
-KFEAT: C = altar_elyvilon / altar_zin / altar_shining_one
+KFEAT: _ = altar_elyvilon / altar_zin / altar_shining_one
MAP
.....
..xmx..
..xx>xx..
..xxx.xxx..
.xxxx1xxxx.
-.m>..C..>m.
+.m>.._..>m.
.xxxx.xxxx.
..xxx.xxx..
..xx>xx..
@@ -436,15 +429,15 @@ SUBST: 3 = 3L
SUBST: 1 = 1:20 4
: end
SUBST: L = l.
-SUBST: C = C P:1
-KFEAT: C = altar_lugonu/altar_yredelemnul/altar_kikubaaqudgha/altar_makhleb
+SUBST: _ = _ P:1
+KFEAT: _ = altar_lugonu/altar_yredelemnul/altar_kikubaaqudgha/altar_makhleb
KFEAT: P = enter_abyss
MAP
..LLllLL....
.LllllllLLL..
..Lll323lllLLL.
.LLl32123lllLL.
-.LLl33C33llLL..
+.LLl33_33llLL..
..Lll323llLL...
..LLll3llL.....
...LLlllL...
@@ -457,11 +450,11 @@ NAME: david_defended_altar_orc
DEPTH: D:7-20, Orc
MONS: patrolling orc priest
TAGS: uniq_defended_altar
-KFEAT: D = altar_beogh / w:1 altar_okawaru / w:1 altar_makhleb / w:1 altar_trog
+KFEAT: _ = altar_beogh / w:1 altar_okawaru / w:1 altar_makhleb / w:1 altar_trog
MAP
ccccc...
c1..c...
-c1D.+.I@
+c1_.+.I@
c1..c...
ccccc...
ENDMAP
@@ -480,14 +473,14 @@ ENDMAP
NAME: lemuel_blue_sif_altar
DEPTH: D:2-18, Elf, Vault
-TAGS: no_monster_gen mini_float
+TAGS: no_monster_gen mini_float temple_overflow_sif_muna uniq_altar_sif_muna
COLOUR: . = blue
FTILE: . = floor_hall, C = floor_hall, @ = floor_hall, + = floor_hall
-KFEAT: C = altar_sif_muna
+KFEAT: _ = altar_sif_muna
MAP
xxxxxxxxxxxxxx
...........xxx
-@..........+Cx
+@..........+_x
...........xxx
xxxxxxxxxxxxxx
ENDMAP
@@ -498,12 +491,12 @@ TAGS: no_pool_fixup
MONS: rat zombie / giant bat zombie / nothing w:200
KMONS: w = giant goldfish zombie / big fish zombie / nothing w:200
KFEAT: w = deep_water
-KFEAT: C = altar_kikubaaqudgha / altar_yredelemnul
+KFEAT: _ = altar_kikubaaqudgha / altar_yredelemnul
MAP
xxxxxxxxxxxxxxxx
xxxxwwwwwwwwxxxx
xxxx11111111xxxx
-@.............Cx
+@............._x
xxxx11111111xxxx
xxxxwwwwwwwwxxxx
xxxxxxxxxxxxxxxx
@@ -534,10 +527,10 @@ MONS: w:50 human zombie/orc zombie/elf zombie/w:5 ogre zombie/w:5 troll zombie
MONS: w:50 human skeleton/orc skeleton/elf skeleton/w:5 ogre skeleton/\
w:5 troll skeleton
MONS: mummy, wight, wraith, necrophage, ghoul
-NSUBST: ? = 1:C / *:1
+NSUBST: ? = 1:_ / *:1
SUBST: 1 = 1:25 2 3 4:8 5:6 6:4 7:2
-KFEAT: C = altar_kikubaaqudgha / altar_yredelemnul
-KMONS: C = human zombie
+KFEAT: _ = altar_kikubaaqudgha / altar_yredelemnul
+KMONS: _ = human zombie
MAP
ccccccccccccccc
c?c?c?c?c?c?ccG
@@ -552,15 +545,15 @@ ENDMAP
# Nemelex altar (Shiori)
# Perhaps could have different parameters for the two types of clouds,
# and different patterns.
-NAME: nemelx_altar_shiori
-DEPTH: !Lair, !Orc
-TAGS: no_pool_fixup no_monster_gen no_item_gen
-TAGS: generate_awake patrolling mini_float no_rotate
-TAGS: layout_rooms layout_city layout_open layout_cross
-KFEAT: _ = altar_nemelex_xobeh
-SUBST: b:aa. , a:n. , d:c. , c:nn. , f:ee. , e:nn. , h:g. , g:n.
-SUBST: G:GTUVblw> , C=c
-KFEAT: z = teleport trap
+NAME: nemelex_altar_shiori
+DEPTH: !Lair, !Orc
+TAGS: no_pool_fixup no_monster_gen no_item_gen
+TAGS: generate_awake patrolling mini_float no_rotate
+TAGS: layout_rooms layout_city layout_open layout_cross
+KFEAT: _ = altar_nemelex_xobeh
+SUBST: b:aa. , a:n. , d:c. , c:nn. , f:ee. , e:nn. , h:g. , g:n.
+SUBST: G:GTUVblw> , C=c
+KFEAT: z = teleport trap
MARKER: R = lua:fog_machine { cloud_type="flame", walk_dist=1, size=9, \
pow_max=20, delay=10, buildup_amnt=14, buildup_time=7, \
spread_rate=3, start_clouds=1 }
@@ -599,13 +592,13 @@ MARKER: P = lua:fog_machine { cloud_type="blue smoke", walk_dist=1, \
size=9, pow_max=20, delay=10, buildup_amnt=14, buildup_time=7, \
spread_rate=3, start_clouds=1 }
: if crawl.coinflip() then
-KFEAT: L = altar_lugonu
+KFEAT: _ = altar_lugonu
KFEAT: P = enter_abyss
: kmons("1 = kobold w:" .. you.absdepth() .. " ; quick blade ego:distortion " ..
: "w:6 | sabre ego:distortion | short sword ego:distortion / kobold " ..
: "w:80 ; short sword | sabre | quick blade w:3")
: else
-KFEAT: L = altar_xom
+KFEAT: _ = altar_xom
: if crawl.one_chance_in(4) then
KMONS: P = orange crystal statue
: else
@@ -623,7 +616,7 @@ cc..P..cc
ccc.cccc
ccyy.yyyccc
cy..111.yyc
-cc..1L1..cc
+cc..1_1..cc
cyy.111..yc
cccyy..yycc
ccc..ccc
@@ -633,14 +626,217 @@ ENDMAP
###############################################################################
# Blood-stained Trog altar!
-NAME: bloody_trog
-DEPTH: D:7-20
-TAGS: uniq_bloody_trog
-KPROP: . = bloody / nothing
-KFEAT: _ = altar_trog
-KITEM: _ = animal skin, knife
+NAME: bloody_trog
+TAGS: uniq_altar_trog temple_overflow_trog
+DEPTH: D:2-20, Orc, Vault
+KPROP: . = bloody / nothing
+KFEAT: _ = altar_trog
+KITEM: _ = animal skin, knife
MAP
...
._.
...
ENDMAP
+
+###############################################################################
+# Fedhas altar by TGW.
+# Threat: two big fish. Loot: some fruits.
+# The oklob plant may be abusable (if so, remove it).
+NAME: tgw_fedhas
+TAGS: no_item_gen no_monster_gen
+DEPTH: Lair, D:2-20
+KFEAT: _ = altar_fedhas
+MONS: plant, fungus, oklob plant, big fish, bush, toadstool col:random
+SUBST: x = TTPPPPP.
+SHUFFLE: PQR, TU, ..."
+SUBST: P = 112 , Q = 115, R = 111235
+SUBST: T = xt, U = xx
+SUBST: " = .....6
+COLOUR: . = green / none
+COLOUR: ' = green
+COLOUR: x = green / none w:30
+NSUBST: w = 2:4 / *:w
+SUBST: 6 = 112
+ITEM: apple / apricot / orange / pear / grape / strawberry / nothing w:70
+MAP
+ccccccccccccccccccccccc
+cxxxxxxxxxxxxxxxxxxxxxc
+cxxxxxxxxxxxxxxPxxd3xxc
+cxxxxxxxxxxxxxxPddddxxc
+cxxxxxxxxxxxxxxPPPx.dxc
+cxxxxxxx.......xxPPxxxc
+cxxxxxx..wwdww..xxPPxxc
+cxxxxx..wwwdwww..xxxPxc
+cxxxx..wwwwdwwww..xxxxc
+cxxxx.wwwwwdwwwww.xxxxc
+cxxxx.wwww'''wwww.xxxxc
+cxxxx.wwww'_'wwww.xxxxc
+cxxxx.wwww'''wwww.xxxxc
+cxxxx.wwwwwwwwwww.xxxxc
+cxxxx..wwwwwwwww..xxxxc
+cxxxxx..wwwwwww..xxxxxc
+cxxxxxx..wwwww..xxxxxxc
+cxxxxxxx.......xxxxxxxc
+cxxxxxxxxxc.cxxxxxxxxxc
+cxxxxxxxxxc.cxxxxxxxxxc
+ccccccccccc@ccccccccccc
+ENDMAP
+
+###############################################################################
+# Altars to the good gods by TGW.
+NAME: tgw_good
+TAGS: no_item_gen no_monster_gen
+SHUFFLE: XYZ
+KFEAT: X = altar_shining_one
+KFEAT: Y = altar_elyvilon
+KFEAT: Z = altar_zin
+COLOUR: a = darkgrey / red / blue w:3 / lightred w:2
+COLOUR: b = darkgrey w:100 / red w:50 / lightgrey / blue w:30 / cyan / lightred
+COLOUR: c = darkgrey w:7 / red w:2 / lightgrey w:4 / blue w:4 / cyan w:2
+COLOUR: d = darkgrey w:4 / lightgrey w:4 / blue / cyan w:4
+COLOUR: e = blue / cyan w:4
+COLOUR: f = blue / cyan w:7
+SUBST: abcdef = w
+SUBST: G = ...BBC
+NSUBST: H = 2:C / *:H
+SUBST: H = .BBCCC
+COLOUR: B = white
+COLOUR: C = yellow
+SUBST: B = .
+NSUBST: C = 1:M / 3:d / *:.
+ITEM: any scroll / scroll of holy word
+MONS: human; falchion / human; falchion ego:holy_wrath w:1 \
+ / human; quarterstaff / human; quarterstaff ego:holy_wrath w:1 \
+ / human
+MONS: gnoll; falchion / gnoll; falchion ego:holy_wrath w:1 / gnoll; \
+ quarterstaff / gnoll; quarterstaff ego:holy_wrath w:1 / gnoll
+MONS: orc; falchion / orc; falchion ego:holy_wrath w:1 \
+ / orc; quarterstaff / orc; quarterstaff ego:holy_wrath w:1 / orc
+SUBST: M = 123
+MAP
+ xxxxxxxxxxxxx
+ xxaaaaaaaaaaaxx
+ xxbbbbbbbbbbbbbxx
+ xxcccccccccccccccxx
+ xxdddddddddddddddddxx
+ xxeeeeeeeeeeeeeeeeeeexx
+xxxxxxxxxxxxfffffffffffffffffffffxx
+x..........GGGGGGHHHHHHHHHHHGGGGGGxx
+@..........GGGGGGHHHXHHYHHZHHHGGGGGGx
+x..........GGGGGGHHHHHHHHHHHGGGGGGxx
+xxxxxxxxxxxxfffffffffffffffffffffxx
+ xxeeeeeeeeeeeeeeeeeeexx
+ xxdddddddddddddddddxx
+ xxcccccccccccccccxx
+ xxbbbbbbbbbbbbbxx
+ xxaaaaaaaaaaaxx
+ xxxxxxxxxxxxx
+ENDMAP
+
+###############################################################################
+# Altar to Xom by TGW.
+NAME: tgw_xom
+TAGS: no_item_gen no_monster gen
+KFEAT: _ = altar_xom
+MONS: orc; club ego:chaos / orc; dagger ego:chaos / orc; spear ego:chaos
+MONS: gnoll; club ego:chaos / gnoll; dagger ego:chaos / gnoll; spear ego:chaos
+MONS: place:D:1-8
+NSUBST: ' = 1:_ / *:.
+SUBST: . = .:200 ~:70 W:60 w:50 x:80 n:80 v b l Z T U M:20
+NSUBST: Z = 1:* / *:%
+SUBST: M : 123333M, 1 = 1.., 2 = 2.., M = 123.
+COLOUR: . = random
+MAP
+ xxxxxx@xxxxxx
+ xx...........xx
+ xx.............xx
+xx...............xx
+x.................x
+x.................x
+x'...............'x
+x'...............'x
+xx'.............'xx
+ xx'''''''''''''xx
+ xx'''''''''''xx
+ xxxxxxxxxxxxx
+ENDMAP
+
+###############################################################################
+# Altar to Trog by TGW.
+# Features berserk monsters, so we're careful: no intelligent monsters, so you
+# close the door. Provide a chokepoint.
+NAME: tgw_trog
+TAGS: no_item_gen no_monster_gen
+KFEAT: _ = altar_trog
+MONS: moth of wrath, rat / worm w:5
+ITEM: any weapon
+NSUBST: M = 4:d / *:.
+MAP
+ xxxxxxx
+ xxxMMMxxx
+ xxMMM2MMMxx
+ xxMM22_22MMxx
+ xx.........xx
+ x....ooo....x
+ x...oo1oo...x
+ x....ooo....x
+ x...........x
+ xx.........xx
+ xx.......xx
+ xxxx+xxxx
+ xx@xx
+ENDMAP
+
+###############################################################################
+# Altar to Sif by TGW.
+NAME: tgw_sif
+TAGS: no_item_gen no_monster_gen no_pool_fixup
+KFEAT: _ = altar_sif_muna
+MONS: orc wizard w:15 / Jessica / Blork the Orc
+NSUBST: M = 1:1 / *:"
+SUBST: ' : "'., ' = ''.
+COLOUR: . = blue
+SUBST: ' = ., " = .
+ITEM: potion of gain intelligence w:2 / potion of brilliance /\
+ potion of magic / any book w:1
+MAP
+ xx@xx
+ x...x
+ x...x
+ xxx...xxx
+ xx'''''''xx
+ xx'''...'''xx
+ x'''.www.'''x
+ xx''.wwwww.''xx
+ x''.wwM"Mww.''x
+ x''.wwM>Mww.''x
+ x''.wwMMMww.''x
+ xx''.wwwww.''xx
+ x'''.www.'''x
+ xx'''...'''xx
+ xx''d'd''xx
+ xxx...xxx
+ x._.x
+ x...x
+ xxxxx
+ENDMAP
+
+###############################################################################
+# TSO's small temple (1KB)
+# Idea stolen from protected_by_tso_3.
+NAME: tso_altar
+TAGS: no_item_gen no_rotate temple_overflow_the_shining_one
+COLOUR: _ = yellow
+SUBST: _ = .
+COLOUR: c = white
+KFEAT: A = altar_shining_one
+MAP
+ xxxxx
+xxxcccxxx
+xcccAcccx
+xc.___.cx
+xct._.tcx
+xc.._..cx
+xct...tcx
+xccc+cccx
+ENDMAP
diff --git a/crawl-ref/source/dat/clua/lm_trig.lua b/crawl-ref/source/dat/clua/lm_trig.lua
index 336da856b0..d17ea9e0da 100644
--- a/crawl-ref/source/dat/clua/lm_trig.lua
+++ b/crawl-ref/source/dat/clua/lm_trig.lua
@@ -274,7 +274,7 @@ function Triggerable:do_trigger(triggerer, marker, ev)
slaves = { slave_marker }
else
- dgn.find_markers_by_prop("slaved_to", master_name)
+ slaves = dgn.find_markers_by_prop("slaved_to", master_name)
end
-- If all slaves are gone, we're done.
@@ -693,7 +693,7 @@ function DgnTriggerer:monster_dies(triggerable, marker, ev)
error("DgnTriggerer:monster_dies() didn't get a valid monster index")
end
- if mons.name == self.target then
+ if mons.full_name == self.target then
triggerable:do_trigger(self, marker, ev)
end
end
diff --git a/crawl-ref/source/dat/database/monspeak.txt b/crawl-ref/source/dat/database/monspeak.txt
index e28a854cc9..78c0f659af 100644
--- a/crawl-ref/source/dat/database/monspeak.txt
+++ b/crawl-ref/source/dat/database/monspeak.txt
@@ -1351,7 +1351,7 @@ VISUAL:@The_monster@ counts something out on his fingers.
%%%%
_crazy_yiuf_speech_
-w:30
+w:300
@The_monster@ @_crazy_yiuf_speech_verbs_@, "@_crazy_yiuf_sentence_@"
VISUAL:@The_monster@ waves his quarterstaff at you. @player_only@
@@ -1732,6 +1732,10 @@ Dowan
w:2
@_Dowan_rare_@
%%%%
+fleeing Dowan
+
+VISUAL:@The_monster@ cries in horror.
+%%%%
_Dowan_common_
VISUAL:@The_monster@ smirks and points a slender finger @at_foe@.
@@ -1773,6 +1777,10 @@ _Dowan_Duvessa_dies_invisible_
@The_monster@ screams, "No! No! NO!"
%%%%
+_Dowan_Duvessa_dies_distance_
+
+You hear a distant wail of despair.
+%%%%
############ DUANE ### A mercenary guarding the dungeon
Duane
@@ -1825,6 +1833,10 @@ _Duvessa_Dowan_dies_invisible_
@The_monster@ shouts wrathfully, "No!"
%%%%
+_Duvessa_Dowan_dies_distance_
+
+You hear a distant scream of rage.
+%%%%
############ EDMUND ### A mercenary guarding the dungeon
Edmund
diff --git a/crawl-ref/source/dat/descript/monsters.txt b/crawl-ref/source/dat/descript/monsters.txt
index 4e4c7572a7..a6d8023c67 100644
--- a/crawl-ref/source/dat/descript/monsters.txt
+++ b/crawl-ref/source/dat/descript/monsters.txt
@@ -62,7 +62,7 @@ A being of pure chaos, its form is constantly shifting, growing and then losing
%%%%
Crazy Yiuf
-A withered old goblin with a long silver beard, wielding a quarterstaff and wearing a cloak. He looks like a figure from mythology! Wait, is his beard held on to his ears with hooks?
+A withered old gnoll with a long silver beard, wielding a quarterstaff and wearing a cloak. He looks like a figure from mythology! Wait, is his beard held on to his ears with hooks?
%%%%
Daeva
diff --git a/crawl-ref/source/dat/entry.des b/crawl-ref/source/dat/entry.des
index d720877302..ee22731e97 100644
--- a/crawl-ref/source/dat/entry.des
+++ b/crawl-ref/source/dat/entry.des
@@ -191,14 +191,12 @@ MARKER: A = lua:fog_machine { \
SUBST: A = a , a = a m:1
FTILE: a = floor_slime
COLOUR: a = lightgreen
-KPROP: a = force_exclude
SUBST: a = .
MARKER: W = lua:fog_machine{\
pow_max = 10, delay_min = 50, delay_max = 300, \
size = 8, start_clouds = 1, \
cloud_type = "freezing vapour"}
SUBST: W = w
-KPROP: w = force_exclude
SUBST: w : Ww'" , ' = wwW"
COLOUR: " = blue
SUBST: " = .
@@ -208,7 +206,6 @@ MARKER: F = lua:fog_machine {\
size = 8, start_clouds = 1, \
cloud_type = "flame"}
SUBST: F = f
-KPROP: f = force_exclude
SUBST: f : fflF , f = llf , F = f
FTILE: f = floor_rough_red
COLOUR: f = red
@@ -224,6 +221,11 @@ SUBST: e =.
SHUFFLE: XZ
NSUBST: Z = ) / ]
NSUBST: X = ( / [
+MARKER: = = lua:props_marker { \
+ door_open_prompt="This door is covered in warnings. Open " .. \
+ "it anyways?", \
+ door_description_prefix="warning scrawled " \
+ }
MAP
...
ccc===ccc
diff --git a/crawl-ref/source/dat/float.des b/crawl-ref/source/dat/float.des
index 5f1dc8d421..82796011e0 100644
--- a/crawl-ref/source/dat/float.des
+++ b/crawl-ref/source/dat/float.des
@@ -520,7 +520,7 @@ ENDMAP
#
NAME: onia_ninara_012_swampy_vault
TAGS: no_pool_fixup no_monster_gen
-DEPTH: D:16-20, Lair:3-10, Swamp, Snake, Slime
+DEPTH: D:16-20, Lair:3-10, Swamp, Snake
ORIENT: float
SHUFFLE: AB@
SUBST: x = .:30 W x:4
@@ -868,7 +868,7 @@ ENDMAP
# Elemental Laboratory (by Mu.)
#
NAME: elemental_lab_mu
-DEPTH: D:16-26, Elf:1-6
+DEPTH: D:13-26, Elf:1-6
ORIENT: float
FLAGS: no_monster_gen no_item_gen no_pool_fixup
MARKER: ! = lua:fog_machine { \
@@ -890,7 +890,7 @@ KMONS: 1 = fire elemental
NSUBST: ; = 3:2 / *=.ll
KMONS: 2 = molten gargoyle
KMONS: e = earth elemental
-SUBST: E = ecxxx..
+SUBST: E = exxx....
NSUBST: ' = 3:3 / 3:W / *:.
KMONS: 3 = clay golem
NSUBST: w = 3:4 / *:w
@@ -900,13 +900,25 @@ NSUBST: " = 3:5 / *:.
KMONS: 5 = vapour
KMONS: 6 = air elemental
KMONS: 7 = fire vortex
+#
: if you.in_branch("elf") then
-KMONS: Z = deep elf sorcerer ; robe ego:fire_resistance race:elven | \
- robe ego:cold_resistance race:elven | \
- robe ego:resistance race:elven
+KMONS: Z = col:gila deep elf sorcerer \
+ name:deep_elf_elementalist name_replace \
+ spells:iron_shot;summon_air_elementals;sticky_flame;\
+ summon_water_elementals;haste;blink actual_spells \
+ ; robe ego:fire_resistance race:elven | \
+ robe ego:cold_resistance race:elven | \
+ robe ego:resistance race:elven . dagger ego:freezing race:elven | \
+ dagger ego:flaming race:elven | dagger ego:electrocution race:elven
: else
-KMONS: Z = wizard ; robe ego:fire_resistance | robe ego:cold_resistance | \
- robe ego:resistance
+KMONS: Z = col:gila vault guard \
+ name:master_elementalist name_replace \
+ spells:iron_shot;summon_air_elementals;sticky_flame;\
+ summon_water_elementals;haste;blink actual_spells \
+ ; robe ego:fire_resistance | robe ego:cold_resistance | \
+ robe ego:resistance \
+ . dagger ego:freezing | dagger ego:flaming | \
+ dagger ego:electrocution
: end
KITEM: B = any book
KITEM: | = staff of fire / staff of cold / staff of earth / staff of air
diff --git a/crawl-ref/source/dat/icecave.des b/crawl-ref/source/dat/icecave.des
index c5d1f55f63..fe5ee6868a 100644
--- a/crawl-ref/source/dat/icecave.des
+++ b/crawl-ref/source/dat/icecave.des
@@ -330,10 +330,10 @@ ITEM: potion of resistance w:5 / potion of gain strength / \
potion of might / potion of confusion / potion of levitation / \
potion of experience w:2
MAP
- xxxx xxxxxxxx
- xxxx..xxxx xxxx12....xx
- xxxxxxxx...xx...xxxx...2xxx...xxxx
- xxxx......1..xxxxx..x212.xxxxxxx...1xxxx
+ xxxxx xxxxxxxx
+ xxx...xxxx xxxx12....xx
+ xxxxxxxx...x....xxxx...2.x....xxxx
+ xxxx......1..xxxx...x212.xxxxxxx...1xxxx
xx.......1..1.xxxxxx....xxxxxxxxxxxx21..xxx
xxx...xxxx.3.1....xxxxxxxxxxxxxwwwxxxxxx....xxx
xx...xxxfgxx.1..1...xxxxxxxxxxwwwwwxxxxxxxx....xxx
@@ -342,34 +342,34 @@ MAP
x...x....$$xx.....xxxxwwwwxxwwwwwwwwwwwwxxxxxx11xx
xx.......xxx.....xxwwwwxxxxxxxxxwwwwwwxxxxx...2xx
xx............xxxwwwwxxxxxxxxxxxwwwxxxx......xx
- xxx"xx.........x'wwwwwxxxxxxxxxxxxwxxxx...xxxxxx
-xxwwxxxxxxxxxxxxxxwwwxxxxxxxxxxxxxxxxxx..xxx
+ xxx"xx.........x'wwwwwxxxxxxxxxxxxwxxxx...x.xxxx
+xxwwwxxxxxxxxxxxxxwwwxxxxxxxxxxxxxxxxxx..xxxxx
xxwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxx..xx
- xwwwwwwwwwwwwwwwwwx'xxxxxxxxxxxxxxx5...xxx
+ xwwwwwwwwwwwwwwwww''xxxxxxxxxxxxxxx5...xxx
xwwwxxxxxxxxxxwwxx'x'xxxxxxxxxxxxx.......xxx
-xxwwxxxxxxxxxxxwwxxx'xxxxxxxxxxxxxxxx.......xxx
-x"xxxxxxxxxxxxxxwxx'xxxxxx"xxxxxxxxxxx....2...xx
-xx"xxxxxxxxxxxxxxx'xxxxxxx""""x..xxxxxxx2......x
- xx"xxxxxxxxxxxxx'xxxxxxx"xxxx.......xxx.......x
- x"xxxxxxxxxxxxx''xxxxx"xxx''xx......21x.....xx
- xx""xxxxxxxxxxxxx'xxx"xxx'xxxxx....1..2....xx
- xxx""""xxxxxxxxxx'xx"xxx'xxwwxx.1......1.xx
- xxxxx"xxxxxxxxx'xxx"xxx'xxwwxx.x....x.xx
- xxx"xxxxxxxxx'xxx"xxxxx'xxwwxxxx..xxxx
- xx""xxxxxxxxx'xxx"xxxxxx'xxxwwxxx..x
- xx"xxxxxxxxxxx''xxx"xxxxxx'xxwwxx..xx
- xx"xxxxxxxxxxxxx'xxxx""xxxx'xxwxx..xx
- xx"xxxxxxxxxxxxxxx'xxxx"xxx'xxxwwx...xx
- x"xxxxxxxxxxxxxxxxx'xxxx"x'xxxxwwxx...xx
- x"xxxxxxxxxxxxxxxxx'xxxxx2xxxxxwwxxx44.x
- xx"xxxxxxxxxxxxxxxxx'x..x.xxxxxwwxxxx4.4x
- x"xxxxxxxxxxxxxxxxxxx.hx.xxxxxxwwxxx...xx
-xx"xxxxxxxxxxxxxxxx.1xhxhx.xxxxwwwxxx...xx
-x"xxxxxxxxxxxxxxxxx.xhxhxh.xxxwwwxxx.....xx
-xx"xxxxxxxxx"xxxxxxx1.....xx xxwwxx...A...x
- xx"""xxx"""x""xxx""xxxxxxx xwwxx.......x
- xxxx"""xxxxxx"""xxx xxwwxxx..<..xx
- xxxxx xxxxx xwwwx xx...xx
+xxwwxxxxxxxxxxxwwxxx'xxxxxxx"xxxxxxxx.......xxx
+x""xxxxxxxxxxxxxwxx''xxxxx"""xxxxxxxxx....2...xx
+xx""xxxxxxxxxxxxxx''xxxxxx"""""..xxxxxxx2......x
+ xx""xxxxxxxxxxxx'x'xxxx"""xxx.......xxx.......x
+ x"x"xxxxxxxxxxx''xxxxx"xx'''xx......21x.....xx
+ xx"""xxxxxxxxxxx''xxx""x''x'''x....1..2....xx
+ xxx""""xxxxxxxxx''xx"xx''xxwwxx.1......1.xx
+ xxx"x"xxxxxxxxx'xx""xx''xxwwxx.x....x.xx
+ xxx"xxxxxxxxx''x""xxxx''xxwwxxxx..xxxx
+ xx"""xxxxxxxx'x'x"x"xxxx''xxwwxxx..x
+ xx""xxxxxxxxxx''xxx"x"xxxx''xwwxx..xx
+ xx""x"xxxxxxxxxx''xxx""xxx''xxwxx..xx
+ xx""x"xxxxxxxxxxxx'xxxx""x''xxxwwx...xx
+ x""xxxxxxxxxxxxxx'x'xxxx""'xxxxwwxx...xx
+ x"x"xxxxxxxxxxxxxx'''xxxx2'xxxxwwxxx44.x
+ xx""xxxxxxxxxxxxxxxx'x..x.'xxxxwwxxxx4.4x
+xx""xxxxxxxxxxxxxxxxxx.hx.xxxxxxwwxxx...xx
+x""xxxxxxxxxxxxxxxx.1xhxhx.xxxxwwwxxx...xx
+x"x"xxxxxxxxxxxxxxx.xhxhxh.xxxwwwxxx.....xx
+xx"x"xxxx""x"xxxxxx"1.....xx xxwwxx...A...x
+ xx""""x""""x""x""""xxxxxxx xwwxx.......x
+ xxxx"""xxx"x""""xxx xxwwxxx..<..xx
+ xxxxx xxxxxxxx xwwwx xx...xx
xxwxx xxxxx
xxx
ENDMAP
@@ -395,37 +395,37 @@ ITEM: any jewellery good_item / gold w:5 / nothing w:5
MAP
xxxxxxxx
xxxx......xxxx
- xx.....xxx....xxx
- x..xxxxxxx...2..xxx
- xxxx.xxxx$$.2....dexx
- xx..xx.xx$$$$....deddx
- xx.xx..xx$$$$$$..deddxx
- xx..xxxxxxxx$$$$$$$xxx'x
- xxxx11xxxxwwwxxxxxxxxxxwx'x
- xxxx...1xxwwwwwwwwwwwwwwwwwwxxx
+ xx......x.....xxx
+ x...xx.xxx...2..xxx
+ xxxxx..xxx$$.2....dexx
+ xx...xx.xx$$$$....deddx
+ xx.x....x$$$$$$..deddxx
+ xx..xxx.xxxx$$$$$$$xx''x
+ xxxx11xxxxxxwxxxxxxxxxxwx'x
+ xxxx...1xxwwwwwwwwwwwwwwwwwwwxx
xxx......xxwwwwwwwwwwwwwwwwwwwwwxx
xx...xxxxxxxxwwwwwwwwwxxwwwwwwwwwwx
xx..xxxxxxxxxxxxwwwwwxxxxxxxx'xwwxxx
- xxx..xxxxxxxxxxxxxxxxxxxxxxxxx.xxwwwx
- xxx....xxxxxxxxxxxxxxxxxxx"""x..$$xxwxx
- xx........xxxxxxxx""xxxxx""xxx.xxx$xxxx
- xx...........xxxxx"xx""x""xxxxxx'xxx"xx
-xx..............x""xxxxx"xxxxxxxxx'xxx"x
-x................xxxxxxxxxxxxxxxxxx'xx"xx
-x.................xxxxxxxxxxxxxxxxxx'xx"x
-xx...1.111.1....xx'xxxxxxxxxxxxxxxxx'xx"x
- xx...1.1.1.....xxx'xxx''xxxxx''x'x'xx"xx
- xx..........xxxxxx'''xx'xxx'xx'x'xx"xx
- xx4x....x4xxxxxxxxxxxxx''$xxxxxxx"xx
- xxxx..xxxxxxxxxxxxxxxxx$$$xxxx""xx
- xx..xxxxxxxxxxxxxx"xx$$$$xx"xxx
- xx..xxxxxxxxxxxxxx"x""x$$"xxx"x
- x..xxxxxxxxxxxxxxx"xxxxxxx"x"xx
- x...x""x"xxxxxxxxxx"xx xx"xx
- xx...xx"x""xxxxxxxxx"x xxx
- xx33.xxxxx""xxxxx""xx
- xx3.3x xxx"""x"xxx
- x...xx xxxx"xx
+ xxx..xxxxxxxxxxxxxxxxxxxxxxxxx..xwwwx
+ xxx....xxxxxxxxxxx"xxxxxx""""x..$$xxwxx
+ xx........xxxxxxxx"""x"x"""x"x.'xx$xxxx
+ xx...........xxxx"""x""x""xxxx"x''xx""xx
+xx..............x""xxxxx"xxxxxxxxx''xx""xx
+x................xxxxxxxxxxxxxxxxxx''x"x"x
+x.................xxxxxxxxxxxxxxxxxx'xx"xx
+xx...1.111.1....x'''xxxxxxxxxxxxxx'''x""x
+ xx...1.1.1.....xxx''xx''xxxx'''x'x'xx"xx
+ xx..........xxxxxx''''x''x''x''''xx""x
+ xx4x....x4xxxxxxxx'xxxx''$xxxxxx"""xx
+ xxxx..xxxxxxxxxxxxxxxxx$$$xxx""""xx
+ xx..xxxxxxxxxxxxx"""x$$$$xx"x"xx
+ xx..xxxxxxxxxxxxxx"x""x$$""xx"xx
+ x..xxxx"xxxxxxxxx""xxxxxxx""""x
+ x...x""x""xxxxxxxx"""x xx"xxx
+ xx..."x"x"""xxxxx"xx"x xxx
+ xx33.xxxxx"""x"xx""xx
+ xx3.3x xxx""""""xx
+ x...xx xxxx"xxx
xx...xx xxx
xx.....xx
x...A...x
@@ -504,12 +504,12 @@ x...xxffxx...xxxxx*%....3.3..xwwwwwxx6.6x
x....xxxx...xxxxxxxxx.......xxxwwwxx...xx
xxx.........xxxxxxxxxxx...xxxxwwwxxx...xx
x...7....xxxxxxxxxxxxx..xxxwwwxxx.....xx
- xx------xxxxxxxxxxxxxxxx..xxwwxx...A...x
- xx----xxxxxx...xxxxxxxx...xwwxx.......x
- x---xxxx...xx...xx.....xxxwwxxx..<..xx
+ xx------xxxxx.xxxxxxxxxx..xxwwxx...A...x
+ xx----xxxxx....xxxxx..x...xwwxx.......x
+ x---xx.x...xx....x.....xxxwwxxx..<..xx
xx.......xxxxxx....xxxxxxwwwwxxx...xx
- xxxxxxxxx xxxxxx xxwwwxxxxxxx
- xwwxx
+ xxx.xx.xx xxxxxx xxwwwxxxxxxx
+ xxxxxxx xwwxx
xxxx
ENDMAP
@@ -605,21 +605,21 @@ NAME: ice_cave_tombish
# This is an ice cave which is also a tomb of a necromancer who likes staying
# alive and simulacrums, or just a chillout of an ice fiend. By Zaba.
# Weighted as a small cave, although this is pretty tough. --Eino
-TAGS: ice_cave no_item_gen no_monster_gen
+TAGS: ice_cave no_item_gen no_monster_gen
ORIENT: encompass
WEIGHT: 6
# S is either an ice statue or a granite statue.
-SUBST: S = GGS
-KMONS: S = ice statue
+SUBST: S = GGS
+KMONS: S = ice statue
# I is an ice statue with loot underneath.
-KITEM: I = any scroll q:3
-KMONS: I = ice statue
-MONS: ice devil / blue devil / nothing w:7
+KITEM: I = any scroll q:3
+KMONS: I = ice statue
+MONS: ice devil / blue devil / nothing w:7
# FIXME: I can't quite make up more simulacrums
-MONS: grizzly bear simulacrum / bear simulacrum / dragon simulacrum /\
- human simulacrum / golden dragon simulacrum w:1
-MONS: Ice Fiend w:2 / necromancer
-ITEM: any potion / any scroll / any weapon good_item / any armour good_item
+MONS: grizzly bear simulacrum / bear simulacrum / dragon simulacrum /\
+ human simulacrum / golden dragon simulacrum w:1
+MONS: ice fiend w:2 / necromancer
+ITEM: any potion / any scroll / any weapon good_item / any armour good_item
KFEAT: ' = alarm trap / net trap / arrow trap / bolt trap w:5 / floor w:5
: ice_cave_colours(_G)
: ice_cave_milestone(_G)
diff --git a/crawl-ref/source/dat/mini.des b/crawl-ref/source/dat/mini.des
index e08d81b994..b27857e9fc 100644
--- a/crawl-ref/source/dat/mini.des
+++ b/crawl-ref/source/dat/mini.des
@@ -774,6 +774,27 @@ cccccccccc
ENDMAP
###################################
+# This wizard likes to experiment!
+#
+NAME: laboratory_2
+MONS: col:lightred wizard spells:polymorph_other;paralyse;blink\
+ ;bolt_of_fire;bolt_of_fire;teleport_self
+DEPTH: D:10-26, Vault
+MONS: col:red name:altered name_adjective rat spells:fire_breath
+MAP
+ccccccc+cc
+c........c
+c........c
+c..1.....c
+c........c
+cc+ccccccc
+c***c2222c
+c|**+2222c
+c||*c2222c
+cccccccccc
+ENDMAP
+
+###################################
# Beehive minivault
#
NAME: minivault_7
@@ -2627,3 +2648,15 @@ MAP
.............
.............
ENDMAP
+
+##############################################################################
+# Hunter's Booth (1KB)
+#
+NAME: hunters_booth
+DEPTH: D:5-15
+MONS: centaur, bush
+MAP
+.....xxx
+@....21=@
+.....xxx
+ENDMAP
diff --git a/crawl-ref/source/dat/pan.des b/crawl-ref/source/dat/pan.des
index 64503836f3..8ccf336169 100644
--- a/crawl-ref/source/dat/pan.des
+++ b/crawl-ref/source/dat/pan.des
@@ -548,9 +548,13 @@ ENDMAP
NAME: pan_disco_hall
TAGS: pan no_rotate
ORIENT: float
-COLOUR: . = random
-COLOUR: x = random
-MONS: col:random plant
+SUBST: - = 0:1 / .:10
+COLOUR: .x = random
+COLOUR: 0123456789 = random
+MONS: col:random name:demonic name_adjective plant
+MONS: red devil ; demon trident good_item ego:distortion
+MONS: red devil ; lajatang good_item ego:distortion
+MONS: red devil ; katana good_item ego:distortion
RTILE: x = wall_zot_blue / wall_zot_green / wall_zot_cyan / wall_zot_red /\
wall_zot_magenta / wall_zot_yellow
# alas, floor tiles are not distinguished from walls enough, commenting out:
@@ -563,19 +567,19 @@ MAP
x1.1x
x...x
xxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxx
- x........................x...............x
- x.x.x.x.x.x.x.x.x.x.x.x..x...............x
- x........................x...............xxxxxx
- x.x.x.x.x.x.x.x.x.x.x.x..x..............._....x
-xxxx........................................_....x
-x1.x........................................_....x
-@..........................................._....x
-x1.x........................................_....x
-xxxx........................................_....x
- x.xxxxxxxxxxxxxxxxxxxxx..x..............._....x
- x.x...x...x...x...x...x..x...............xxxxxx
- x.x...x...x...x...x...x..x...............x
- x........................x...............x
+ x........................x---------------x
+ x.x.x.x.x.x.x.x.x.x.x.x..x---------------x
+ x........................x---------------xxxxxx
+ x.x.x.x.x.x.x.x.x.x.x.x..x---------------_....x
+xxxx.........................---------------_..2.x
+x1.x.........................---------------_....x
+@............................---------------_..3.x
+x1.x.........................---------------_....x
+xxxx.........................---------------_..4.x
+ x.xxxxxxxxxxxxxxxxxxxxx..x---------------_....x
+ x.x0.0x..0x0.0x0.0x..0x..x---------------xxxxxx
+ x.x0..x0..x...x0..x...x..x---------------x
+ x........................x---------------x
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ENDMAP
diff --git a/crawl-ref/source/dat/shrine.des b/crawl-ref/source/dat/shrine.des
deleted file mode 100644
index c1e6d8b402..0000000000
--- a/crawl-ref/source/dat/shrine.des
+++ /dev/null
@@ -1,406 +0,0 @@
-###############################################################################
-# Shrines.des:
-# The shrines are thematic portal vaults which offer early religion in
-# exchange for one's safety.
-###############################################################################
-# Setup functions:
-{{
-function shrine_portal_setup (e)
- e.lua_marker("O", one_way_stair { desc = "An entrance to a Shrine",
- dst = "shrine" })
- e.kfeat("O = enter_portal_vault")
-end
-
-function shrine_setup(e)
- e.kfeat("> = exit_portal_vault")
- crawl.mark_milestone("br.enter", "entered a Shrine.")
-end
-}}
-###############################################################################
-# Entry vaults:
-default-depth: D:2-6
-
-NAME: shrine_entry_a
-TAGS: luniq_shrine
-ORIENT: float
-: shrine_portal_setup(_G)
-MAP
-x x
-x.T.x
-x...x
-@.O.@
-x...x
-x.T.x
-x x
-ENDMAP
-
-NAME: shrine_entry_b
-TAGS: luniq_shrine
-ORIENT: float
-: shrine_portal_setup (_G)
-MAP
- x x
- xx.xx
-xx...xx
- ..O..@
-xx...xx
- xx.xx
- x x
-ENDMAP
-
-NAME: shrine_entry_c
-TAGS: uniq_shrine
-ORIENT: float
-: shrine_portal_setup (_G)
-MAP
-.......
-.x...x.
-......@
-...O..@
-......@
-.x...x.
-.......
-ENDMAP
-
-###############################################################################
-# The portals themselves.
-default-depth:
-
-NAME: shrine_yred_kiku_a
-WEIGHT: 5
-TAGS: shrine no_item_gen no_monster_gen no_pool_fixup
-ORIENT: encompass
-SHUFFLE: XY
-KFEAT: X = altar_yredelemnul
-KFEAT: Y = altar_kikubaaqudgha
-NSUBST: M = 2:. / *:M
-SUBST: M = 1 2 3:5 4:5
-NSUBST: N = 4:. / *:N
-SUBST: N = 1 2 3:15 4:15
-SUBST: . = ZZ.
-COLOUR: Z = darkgrey
-SUBST: Z = .
-COLOUR: x = darkgrey
-MONS: place:D:4 zombie, place:D:5 skeleton, place:D:6 zombie, \
- place:D:7 skeleton
-ITEM: any wand w:5 / wand of enslavement / q:1-3 any scroll w:2 \
- / scroll of torment w:2
-: shrine_setup(_G)
-MAP
- xxxxxxx
- xx.....xx
- x..NYN..x
- x..NNN..x
-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..T..xxxxx
-xwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwW...Wwwwwx
-xwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwW.d.Wwwwwx
-xwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwW...Wwwwwx
-xwwww.......................................wwwwx
-xwwww..A.>.G.M.G.M.G.M.G.M.G.M.G.M.G.M.M....wwwwx
-xwwww.......................................wwwwx
-xwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwW...Wwwwwx
-xwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwW.d.Wwwwwx
-xwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwW...Wwwwwx
-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..T..xxxxx
- x..NNN..x
- x..NXN..x
- xx.....xx
- xxxxxxx
-ENDMAP
-
-NAME: shrine_yred_kiku_b
-WEIGHT: 5
-TAGS: shrine no_item_gen no_monster_gen no_pool_fixup
-ORIENT: encompass
-SHUFFLE: XY
-SHUFFLE: A>
-KFEAT: X = altar_yredelemnul
-KFEAT: Y = altar_kikubaaqudgha
-NSUBST: . = 8:M / *:.
-SUBST: M = 12
-NSUBST: H = 2:N / 3:M / *:.
-SUBST: N = 34
-MONS: place:D:4 zombie, place:D:5 skeleton
-MONS: place:D:6 zombie, place:D:6 skeleton
-SUBST: S = .
-SUBST: . = .ZZ
-COLOUR: Z = darkgrey
-SUBST: Z = .
-COLOUR: x = darkgrey
-ITEM: any wand w:5 / wand of enslavement / q:1-3 any scroll w:2 / \
- scroll of torment w:2
-: shrine_setup(_G)
-MAP
-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-x.............SSSx............x
-x............SSSSx............x
-x...........SSSSSx............x
-x...xxxxxxxxxxSSSx...xxxxxx...x
-x...xHHH.....xS>Sx.....HHHx...x
-x...xHXH.d...xSSSx...d.HYHx...x
-x...xHHH.....xSASx.....HHHx...x
-x...xxxxxx...xSSSxxxxxxxxxx...x
-x............xSSSSS...........x
-x............xSSSS............x
-x............xSSS.............x
-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-ENDMAP
-
-NAME: shrine_makh_vehu_a
-WEIGHT: 5
-TAGS: shrine no_item_gen no_monster_gen no_pool_fixup
-ORIENT: encompass
-SHUFFLE: YZ
-KFEAT: Y = altar_vehumet
-KFEAT: Z = altar_makhleb
-MONS: imp / shadow imp / white imp
-NSUBST: M = 5:1 / *:.
-ITEM: tome of destruction / q:1-3 scroll of summoning / q:2-3 \
- scroll of immolation / q:1-3 any scroll / wand of flame w:5 / \
- wand of frost w:5 / wand of lightning w:5 / any wand w:3
-: shrine_setup(_G)
-MAP
-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-x.........www.........www...x
-x........Mwww..M......www.Z.x
-x...www...www...www...www...x
-x...www...www...www...wwwMY.x
-x...www...www...www...www...x
-x...www...www...wwwM..www.d.x
-x.A.www...www...www...www...x
-x...www...www.M.www...www...x
-x.>.www...M.....www....M....x
-x...www.........www.........x
-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-ENDMAP
-
-NAME: shrine_makh_vehu_b
-WEIGHT: 5
-TAGS: shrine no_item_gen no_monster_gen no_pool_fixup
-ORIENT: encompass
-SHUFFLE: XY
-KFEAT: X = altar_makhleb
-KFEAT: Y = altar_vehumet
-MONS: neqoxec
-ITEM: tome of destruction / q:1-3 scroll of summoning / q:2-3 \
- scroll of immolation / q:1-3 any scroll / wand of flame w:5 / \
- wand of frost w:5 / wand of lightning w:5 / any wand w:3
-: shrine_setup(_G)
-MAP
- xxxxx
- xx...xx
- xx.....xx
- xx...w...xx
-xx.Y.www.A.xx
-x...wcncw...x
-xd.wwn1nww..x
-x...wcncw...x
-xx.X.www.>.xx
- xx...w...xx
- xx.....xx
- xx...xx
- xxxxx
-ENDMAP
-
-NAME: shrine_good
-TAGS: shrine no_item_gen no_monster_gen
-ORIENT: encompass
-SHUFFLE: XYZ
-KFEAT: X = altar_shining_one
-KFEAT: Y = altar_elyvilon
-KFEAT: Z = altar_zin
-COLOUR: a = darkgrey / red / blue w:3 / lightred w:2
-COLOUR: b = darkgrey / red w:5 / lightgrey w:1 / blue w:3 / cyan w:1 / \
- lightred w:1
-COLOUR: c = darkgrey w:7 / red w:2 / lightgrey w:4 / blue w:4 / cyan w:2
-COLOUR: d = darkgrey w:4 / lightgrey w:4 / blue / cyan w:4
-COLOUR: e = blue / cyan w:4
-COLOUR: f = blue / cyan w:7
-SUBST: abcdef = w
-SUBST: G = ...BBC
-NSUBST: H = 2:C / *:H
-SUBST: H = .BBCCC
-COLOUR: B = white
-COLOUR: C = yellow
-SUBST: B = .
-NSUBST: C = 3:M / 3:d / *:.
-ITEM: any scroll / scroll of holy word
-MONS: human; falchion / human; falchion ego:holy_wrath w:1 \
- / human; quarterstaff / human; quarterstaff ego:holy_wrath w:1 \
- / human
-MONS: gnoll; falchion / gnoll; falchion ego:holy_wrath w:1 / gnoll; \
- quarterstaff / gnoll; quarterstaff ego:holy_wrath w:1 / gnoll
-MONS: orc; falchion / orc; falchion ego:holy_wrath w:1 \
- / orc; quarterstaff / orc; quarterstaff ego:holy_wrath w:1 / orc
-SUBST: M = 1222333
-: shrine_setup(_G)
-MAP
- xxxxxxxxxxxxx
- xxaaaaaaaaaaaxx
- xxbbbbbbbbbbbbbxx
- xxcccccccccccccccxx
- xxdddddddddddddddddxx
- xxeeeeeeeeeeeeeeeeeeexx
-xxxxxxxxxxxxfffffffffffffffffffffxx
-x..........GGGGGGHHHHHHHHHHHGGGGGGxx
-x.>.A.....GGGGGGHHHXHHYHHZHHHGGGGGGx
-x..........GGGGGGHHHHHHHHHHHGGGGGGxx
-xxxxxxxxxxxxfffffffffffffffffffffxx
- xxeeeeeeeeeeeeeeeeeeexx
- xxdddddddddddddddddxx
- xxcccccccccccccccxx
- xxbbbbbbbbbbbbbxx
- xxaaaaaaaaaaaxx
- xxxxxxxxxxxxx
-ENDMAP
-
-NAME: shrine_trog_oka
-TAGS: shrine no_item_gen no_monster_gen
-ORIENT: encompass
-SHUFFLE: YZ
-KFEAT: Y = altar_okawaru
-KFEAT: Z = altar_trog
-MONS: moth of wrath
-MONS: orc warrior; nothing w:15 / orc warrior / orc; nothing
-ITEM: any weapon
-NSUBST: M = 8:d / *:.
-: shrine_setup(_G)
-MAP
- xxxxxxx
- xxxMMMxxx
- xxMMM2MMMxx
- xxMMY...ZMMxx
- xx.........xx
- x....ooo....x
- x...oo1oo...x
- x....ooo....x
- x...........x
- xx...A.>...xx
- xx.......xx
- xxx...xxx
- xxxxx
-ENDMAP
-
-NAME: shrine_xom_nemelex
-TAGS: shrine no_item_gen no_monster gen
-ORIENT: encompass
-SHUFFLE: XY
-KFEAT: X = altar_xom
-KFEAT: Y = altar_nemelex_xobeh
-MONS: orc; club ego:chaos / orc; dagger ego:chaos / orc; spear ego:chaos
-MONS: gnoll; club ego:chaos / gnoll; dagger ego:chaos \
- / gnoll; spear ego:chaos
-MONS: place:D:1-8
-NSUBST: . = 1:X / 1:Y / *:.
-SUBST: . = ....................~~~~~~~WWWWWWwwwwwxxxxxxxxvnnnnnnnnbvlZTUMM
-SUBST: Z = **%%%|
-SUBST: M = 123333.
-SUBST: S = ...W
-SUBST: R = ....................~~~~~~~WWWWWWwwwwwxxxxxxxxvnnnnnnnnbvlTU
-COLOUR: . = random
-: shrine_setup(_G)
-MAP
- xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- xx...........................xx
- xx.............................xx
-xx...............................xx
-x.................................x
-x.................................x
-x.................................x
-x...............RRR...............x
-x..............RRARR..............x
-x..............RRSRR..............x
-x...............RSR...............x
-x..............RRSRR..............x
-x..............RR>RR..............x
-x...............RRR...............x
-x.................................x
-x.................................x
-x.................................x
-xx...............................xx
- xx.............................xx
- xx...........................xx
- xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-ENDMAP
-
-NAME: shrine_sif
-TAGS: shrine no_item_gen no_monster_gen no_pool_fixup
-ORIENT: encompass
-KFEAT: X = altar_sif_muna
-MONS: orc wizard w:15 / Jessica / Blork the Orc
-NSUBST: M = 2:1 / *:.
-SUBST: . = ..Z
-COLOUR: Z = blue
-SUBST: Z = .
-ITEM: potion of gain intelligence / q:2 potion of gain intelligence w:5 \
- / q:2 potion of magic / any book w:2 / nothing
-: shrine_setup(_G)
-MAP
- xxxxx
- x...x
- x.A.x
- xxx...xxx
- xx...>...xx
- xx.........xx
- x....www....x
- xx...wwwww...xx
- x...wwM.Mww...x
- x...WWMMMWW...x
- x...wwMMMww...x
- xx...wwwww...xx
- x....www....x
- xx.........xx
- xx..d.d..xx
- xxx...xxx
- x.X.x
- x...x
- xxxxx
-ENDMAP
-
-NAME: shrine_fedhas
-TAGS: shrine no_item_gen no_monster_gen
-ORIENT: encompass
-KFEAT: X = altar_fedhas
-MONS: plant, fungus, oklob plant
-SUBST: . = .F
-COLOUR: F = green
-SUBST: F = .
-NSUBST: w = 2:Z / *:w
-KFEAT: Z = w
-KMONS: Z = big fish
-SUBST: x = xxxV
-COLOUR: V = green
-SUBST: V = x
-SUBST: x = xx11122.
-SUBST: y = x
-SUBST: d = dd.
-SHUFFLE: A>
-SUBST: 6 = 112
-ITEM: apple / apricot / orange / pear / grape / sultana \
- / strawberry / nothing w:30
-: shrine_setup(_G)
-MAP
-yyyyyyyyyyyyyyyyyyyyyyy
-yxxxxxxxxxxxxxxxxxxxxxy
-yxxxxxxxxxxxxxx6xxd3xxy
-yxxxxxxxxxxxxxx6ddddxxy
-yxxxxxxxxxxxxxx666x.dxy
-yxxxxxxx.......xx66xxxy
-yxxxxxx..wwdww..xx66xxy
-yxxxxx..wwwdwww..xxx6xy
-yxxxx..wwwwdwwww..xxxxy
-yxxxx.wwwwwdwwwww.xxxxy
-yxxxx.wwwwFFFwwww.xxxxy
-yxxxx.wwwwFXFwwww.xxxxy
-yxxxx.wwwwFFFwwww.xxxxy
-yxxxx.wwwwwwwwwww.xxxxy
-yxxxx..wwwwwwwww..xxxxy
-yxxxxx..wwwwwww..xxxxxy
-yxxxxxx..wwwww..xxxxxxy
-yxxxxxxx..A.>..xxxxxxxy
-yxxxxxxxxxxxxxxxxxxxxxy
-yxxxxxxxxxxxxxxxxxxxxxy
-yxxxxxxxxxxxxxxxxxxxxxy
-yxxxxxxxxxxxxxxxxxxxxxy
-yyyyyyyyyyyyyyyyyyyyyyy
-ENDMAP
diff --git a/crawl-ref/source/dat/temple.des b/crawl-ref/source/dat/temple.des
index 840a89dea7..64a59bcf4b 100644
--- a/crawl-ref/source/dat/temple.des
+++ b/crawl-ref/source/dat/temple.des
@@ -382,6 +382,12 @@ ENDMAP
# Temple maps
##############################################################################
+# To make a main temple (Ecumenical Temple branch) vault with an
+# arbitrary number of altars, give it the tag "temple_main_N", where
+# N is the number of altars. If no vaults are found for the specific
+# number of altars, then the game will pick a random vault for
+# "PLACE: Temple".
+
##########################################################################
# Circular temple (David Ploog). 12 = 1 x 12
@@ -461,6 +467,7 @@ NAME: twelve_chambers_temple
PLACE: Temple
TAGS: no_rotate
ORIENT: encompass
+WEIGHT: 5
MAP
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvxx
@@ -491,6 +498,44 @@ xvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ENDMAP
+##############################################################################
+# Fourteen chambers temple (David Ploog). 14 = 14 x 1
+
+NAME: fourteen_chambers_temple
+PLACE: Temple
+TAGS: no_rotate
+ORIENT: encompass
+WEIGHT: 5
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvxx
+xvvvvvvvvvvv..........................................vvvvvvvvvxx
+xvvvvvvv.....vvv.vvvvvvv.vvvvvvv.vvvvvvv.vvvvvvv.vvvv.....vvvvvxx
+xvvvvv...vvvvv.....vvv.....vvv.....vvv.....vvv.....vvvvvv...vvvxx
+xvvvvv.vvvvvv...B...v...B...v...B...v...B...v...B...vvvvvvv.vvvxx
+xvv.....vvvvv.......v.......v.......v.......v.......vvvvv.....vvx
+xv.......vvvvv.....vvv.....vvv.....vvv.....vvv.....vvvvv.......vx
+xv..B....vvvvvvv.vvvvvvv.vvvvvvv.vvvvvvv.vvvvvvv.vvvvvvv....B..vx
+xv........vvvvvv.vvvvvvv.vvvvvvv.vvvvvvv.vvvvvvv.vvvvvv........vx
+xvv.....v..vvvvv.vvvvvvv.vvvvvvv.vvvvvvv.vvvvvvv.vvvvv..v.....vvx
+xvvvv.vvvv.............................................vvvv.vvvvx
+xvvv..vvvv.............................................vvvv..vvvx
+xvvv.vvvvv........T.........(...{...[.........T........vvvvv.vvvx
+xvvv..vvvv.............................................vvvv..vvvx
+xvvvv.vvvv.............................................vvvv.vvvvx
+xvv.....v..vvvvv.vvvvvvv.vvvvvvv.vvvvvvv.vvvvvvv.vvvvv..v.....vvx
+xv........vvvvvv.vvvvvvv.vvvvvvv.vvvvvvv.vvvvvvv.vvvvvv........vx
+xv..B....vvvvvvv.vvvvvvv.vvvvvvv.vvvvvvv.vvvvvvv.vvvvvvv....B..vx
+xv.......vvvvv.....vvv.....vvv.....vvv.....vvv.....vvvvv.......vx
+xvv.....vvvvv.......v.......v.......v.......v.......vvvvv.....vvx
+xvvvvv.vvvvvv...B...v...B...v...B...v...B...v...B...vvvvvv.vvvvxx
+xvvvvv...vvvvv.....vvv.....vvv.....vvv.....vvv.....vvvvv...vvvvxx
+xvvvvvvv.....vvv.vvvvvvv.vvvvvvv.vvvvvvv.vvvvvvv.vvv.....vvvvvvxx
+xvvvvvvvvvvv.........................................vvvvvvvvvvxx
+xvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
##########################################################################
# Another temple (David Ploog). 12 + 3 = 1 + 2 + 3 + 4 + 5
@@ -558,7 +603,7 @@ xcwww......B.............................B......wwwcx
xcwww.............B...............B.............wwwcx
xcww......................(......................wwcx
xcww.............................................wwcx
-xcww...B..................T..................B...wwcx
+xcww...B......B...........T...........B......B...wwcx
xcww.............................................wwcx
xcww...................[.....{...................wwcx
xcwww.............B...............B.............wwwcx
@@ -660,65 +705,66 @@ ENDMAP
##########################################################################
# Five rooms temple (David Ploog). 12 + 3 = 5 x 3
-NAME: five_temple
-PLACE: Temple
-TAGS: no_rotate
-ORIENT: encompass
-SHUFFLE: ABC/DEF/GHI/JKL/MNO
-SHUFFLE: ABC, DEF, GHI, JKL, MNO
-SUBST: A=[, B=(, C={
-KFEAT: D = altar_trog
-KFEAT: E = altar_makhleb
-KFEAT: F = altar_okawaru
-KFEAT: G = altar_shining_one
-KFEAT: H = altar_zin
-KFEAT: I = altar_elyvilon
-KFEAT: J = altar_sif_muna
-KFEAT: K = altar_vehumet
-KFEAT: L = altar_kikubaaqudgha
-KFEAT: M = altar_yredelemnul
-KFEAT: N = altar_xom
-KFEAT: O = altar_nemelex_xobeh
-KFEAT: X : G / U / T
-MAP
-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-xxxxxxxxxxxxxxxxxxxx.......xxxxxxxxxxxxxxxxxxxx
-xxxxxxxxxxxxxxx........x........xxxxxxxxxxxxxxx
-xxxxxxxxxx........xxxxx+xxxxx........xxxxxxxxxx
-xxxxxxx.....xxxxxxxxx.....xxxxxxxxx.....xxxxxxx
-xxxxxx...xxxxxxxxxx.........xxxxxxxxxx...xxxxxx
-xxxxx..xxxxxxxxxxx..A.....C..xxxxxxxxxxx..xxxxx
-xxxx..xxxxxxxxxxxx.....X.....xxxxxxxxxxxx..xxxx
-xxx..xxxxxxxxxxxxx...........xxxxxxxxxxxxx..xxx
-xxx..xxx.....xxxxxx....B....xxxxxx.....xxx..xxx
-xx..+x..O......xxxxxx.....xxxxxx......F..x+..xx
-xx..x...........xxxxxxxxxxxxxxx...........x..xx
-x..xx.....X..N..xxxxxxxxxxxxxxx..D..X.....xx..x
-x..xx...........xxxxxxxxxxxxxxx...........xx..x
-x..xxx..M......xxxxxxxxxxxxxxxxx......E..xxx..x
-x..xxxxx.....xxxxxxxxxxxxxxxxxxxxx.....xxxxx..x
-x..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..x
-x..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..x
-x..xxxxxxxxxx.....xxxxxxxxxxx.....xxxxxxxxxx..x
-xx..xxxxxxx......K..xxxxxxx..G......xxxxxxx..xx
-xx..xxxxxx.L.........xxxxx.........H.xxxxxx..xx
-xxx..xxxxx.....X.....xxxxx.....X.....xxxxx..xxx
-xxx..xxxxx...........xxxxx...........xxxxx..xxx
-xxxx..xxxxx......J..xxxxxxx..I......xxxxx..xxxx
-xxxxx..xxxxxx.....xxxxxxxxxxx.....xxxxxx..xxxxx
-xxxxxx...xxx+xxxxxxxxxxxxxxxxxxxxx+xxx...xxxxxx
-xxxxxxxx....xxxxxxxxxxxxxxxxxxxxxxx....xxxxxxxx
-xxxxxxxxxx........xxxxxxxxxxx........xxxxxxxxxx
-xxxxxxxxxxxxxxx........x........xxxxxxxxxxxxxxx
-xxxxxxxxxxxxxxxxxxxx.......xxxxxxxxxxxxxxxxxxxx
-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-ENDMAP
+#NAME: five_temple
+#PLACE: Temple
+#TAGS: no_rotate
+#ORIENT: encompass
+#SHUFFLE: ABC/DEF/GHI/JKL/MNO
+#SHUFFLE: ABC, DEF, GHI, JKL, MNO
+#SUBST: A=[, B=(, C={
+#KFEAT: D = altar_trog
+#KFEAT: E = altar_makhleb
+#KFEAT: F = altar_okawaru
+#KFEAT: G = altar_shining_one
+#KFEAT: H = altar_zin
+#KFEAT: I = altar_elyvilon
+#KFEAT: J = altar_sif_muna
+#KFEAT: K = altar_vehumet
+#KFEAT: L = altar_kikubaaqudgha
+#KFEAT: M = altar_yredelemnul
+#KFEAT: N = altar_xom
+#KFEAT: O = altar_nemelex_xobeh
+#KFEAT: X : G / U / T
+#MAP
+#xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+#xxxxxxxxxxxxxxxxxxxx.......xxxxxxxxxxxxxxxxxxxx
+#xxxxxxxxxxxxxxx........x........xxxxxxxxxxxxxxx
+#xxxxxxxxxx........xxxxx+xxxxx........xxxxxxxxxx
+#xxxxxxx.....xxxxxxxxx.....xxxxxxxxx.....xxxxxxx
+#xxxxxx...xxxxxxxxxx.........xxxxxxxxxx...xxxxxx
+#xxxxx..xxxxxxxxxxx..A.....C..xxxxxxxxxxx..xxxxx
+#xxxx..xxxxxxxxxxxx.....X.....xxxxxxxxxxxx..xxxx
+#xxx..xxxxxxxxxxxxx...........xxxxxxxxxxxxx..xxx
+#xxx..xxx.....xxxxxx....B....xxxxxx.....xxx..xxx
+#xx..+x..O......xxxxxx.....xxxxxx......F..x+..xx
+#xx..x...........xxxxxxxxxxxxxxx...........x..xx
+#x..xx.....X..N..xxxxxxxxxxxxxxx..D..X.....xx..x
+#x..xx...........xxxxxxxxxxxxxxx...........xx..x
+#x..xxx..M......xxxxxxxxxxxxxxxxx......E..xxx..x
+#x..xxxxx.....xxxxxxxxxxxxxxxxxxxxx.....xxxxx..x
+#x..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..x
+#x..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..x
+#x..xxxxxxxxxx.....xxxxxxxxxxx.....xxxxxxxxxx..x
+#xx..xxxxxxx......K..xxxxxxx..G......xxxxxxx..xx
+#xx..xxxxxx.L.........xxxxx.........H.xxxxxx..xx
+#xxx..xxxxx.....X.....xxxxx.....X.....xxxxx..xxx
+#xxx..xxxxx...........xxxxx...........xxxxx..xxx
+#xxxx..xxxxx......J..xxxxxxx..I......xxxxx..xxxx
+#xxxxx..xxxxxx.....xxxxxxxxxxx.....xxxxxx..xxxxx
+#xxxxxx...xxx+xxxxxxxxxxxxxxxxxxxxx+xxx...xxxxxx
+#xxxxxxxx....xxxxxxxxxxxxxxxxxxxxxxx....xxxxxxxx
+#xxxxxxxxxx........xxxxxxxxxxx........xxxxxxxxxx
+#xxxxxxxxxxxxxxx........x........xxxxxxxxxxxxxxx
+#xxxxxxxxxxxxxxxxxxxx.......xxxxxxxxxxxxxxxxxxxx
+#xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+#ENDMAP
##########################################################################
# Eino's temples
-NAME: temple_eino_001
+NAME: temple_eino_001a
PLACE: Temple
ORIENT: encompass
+WEIGHT: 5
SHUFFLE: {([
COLOUR: c = red
MAP
@@ -749,6 +795,34 @@ cccccccclccccccclcccccccc
ccccccccccccccccccccccccc
ENDMAP
+NAME: temple_eino_001b
+PLACE: Temple
+ORIENT: encompass
+WEIGHT: 5
+SHUFFLE: {([
+COLOUR: c = red
+MAP
+ccccccccccccccccccccccccc
+cccccccclccccccclcccccccc
+cccccccl.lcclccl.lccccccc
+cccclll...c...c...lllcccc
+ccclll..B.G...G.B..lllccc
+cccll.......B.......llccc
+cccl.................lccc
+ccccG...............Gcccc
+ccc...................ccc
+ccl..B....{.(.[....B..lcc
+ccc...................ccc
+ccccG...............Gcccc
+cccl.................lccc
+cccll.......B.......llccc
+ccclll..B.G...G.B..lllccc
+cccclll...c...c...lllcccc
+cccccccl.lcclccl.lccccccc
+cccccccclccccccclcccccccc
+ccccccccccccccccccccccccc
+ENDMAP
+
NAME: temple_eino_002
PLACE: Temple
TAGS: no_pool_fixup
@@ -893,3 +967,152 @@ bbbbbbbbbbbbbbb.B.bbbbbbbbbbbbbbb
bbbbbbbbbbbbbbb...bbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
ENDMAP
+
+NAME: temple_eino_005a
+PLACE: Temple
+ORIENT: encompass
+WEIGHT: 5
+SHUFFLE: {([
+MAP
+ bbbbb
+ bbb...bbb
+ b...(...b
+ bbbbbbb.b...b.bbbbbbb
+ b...b...........b...b
+bbbbb.{.....b.T.b.....[.bbbbb
+b...b.....B.......B.....b...b
+b.B....bb...b...b...bb....B.b
+b...b...b.....B.....b...b...b
+bbbbb.B....bb...bb....B.bbbbb
+ b...b...b...b...b...b
+ bbbbb.B.......B.bbbbb
+ b...b...b...b
+ bbbbb.B.bbbbb
+ b...b
+ bbbbb
+ENDMAP
+
+NAME: temple_eino_005b
+PLACE: Temple
+ORIENT: encompass
+WEIGHT: 5
+SHUFFLE: {([
+MAP
+ bbbbb
+ bbbbb...bbbbb
+ b...b.(.b...b
+ b.B.......B.b
+ bbbbb...bbbbb...bbbbb
+ b...bb.bbbbbbbbbb...b
+bbbbb.{.b...bbbbb.....[.bbbbb
+b...b...b.B.......B.b...b...b
+b.B....bb...b...b...bb....B.b
+b...b...bbbbb.B.bbbbb...b...b
+bbbbb.B....bb...bb....B.bbbbb
+ b...b...bbbbb...b...b
+ bbbbb.B.......B.bbbbb
+ b...b...b...b
+ bbbbb.B.bbbbb
+ b...b
+ bbbbb
+ENDMAP
+
+NAME: temple_eino_006a
+PLACE: Temple
+ORIENT: encompass
+SHUFFLE: {([
+WEIGHT: 5
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+x..x...xxx....xxxxxxx....xxx...x..x
+x.x.....x.......xxx.......x.....x.x
+xx...B..x..B.....x.....B..x..B...xx
+x.......x.................x.......x
+xx.....xxx.......{.......xxx.....xx
+xxx...xxxxx...xx...xx...xxxxx...xxx
+xx.....xxx.....xx.xx.....xxx.....xx
+x.......x.......x.x.......x.......x
+x..B.........B..x(x..B.........B..x
+x.......x.......x.x.......x.......x
+xx.....xxx.....xx.xx.....xxx.....xx
+xxx...xxxxx...xx...xx...xxxxx...xxx
+xx.....xxx.......[.......xxx.....xx
+x.......x.................x.......x
+xx...B..x..B.....x.....B..x..B...xx
+x.x.....x.......xxx.......x.....x.x
+x..x...xxx....xxxxxxx....xxx...x..x
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+NAME: temple_eino_006b
+PLACE: Temple
+ORIENT: encompass
+SHUFFLE: {([
+WEIGHT: 5
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+x..x...xxx....xxxxxxx....xxx...x..x
+x.x.....x.......xxx.......x.....x.x
+xx...B..x..B.....x.....B..x..B...xx
+x.......x.................x.......x
+xx.....xxx.......{.......xxx.....xx
+xxx...xxxxx...xx...xx...xxxxx...xxx
+xx.....xxx...xxxx.xxxx...xxx.....xx
+x.......x...xxxx...xxxx...x.......x
+x..B.......xxxx..(..xxxx.......B..x
+x.......x...xxxx...xxxx...x.......x
+xx.....xxx...xxxx.xxxx...xxx.....xx
+xxx...xxxxx...xx...xx...xxxxx...xxx
+xx.....xxx.......[.......xxx.....xx
+x.......x.................x.......x
+xx...B..x..B.....x.....B..x..B...xx
+x.x.....x.......xxx.......x.....x.x
+x..x...xxx....xxxxxxx....xxx...x..x
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+NAME: mini_greek_temple
+PLACE: Temple
+ORIENT: encompass
+SHUFFLE: {([
+MONS: plant, bush
+MAP
+tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
+tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
+tttttttttttt....1111tttttttttttttttttttttttttttttttttttttttt
+tttttttt.........1111....tttttttttttt.........tttttttttttttt
+tttt.......................1tttttt.......t.........ttttttttt
+tt.........2........t...............................2222tttt
+tt.....{..21...t.................ccccccccccccccc.....22.tttt
+ttt...........ttt.......(........G.c...........ctt..t..ttttt
+tttt......2........................c.B.B.B.B.B.ctt......tttt
+tttttt.....................t.....G.c...........cttt.....tttt
+ttttttttt..1.....2...t.............+...B.B.B.B.ctt...t....tt
+tttttttt.....[...................G.c...........ct...ttt..ttt
+ttttttttt...................1......c.B.B.B.B.B.ct..tttt.tttt
+ttttttttttttttt....2....t........G.c...........ct....t..tttt
+ttttttttttttttttt................ccccccccccccccct.......2ttt
+tttttttttttttttttt..........t.........t......ttt......2ttttt
+ttttttttttttttttttttt...............................22tttttt
+ttttttttttttttttttttttt............t..........t....ttttttttt
+tttttttttttttttttttttttttttt...........t.........ttttttttttt
+ttttttttttttttttttttttttttttttt..............ttttttttttttttt
+tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
+tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
+ENDMAP
+
+#############################################################################
+# Overflow temples
+##############################################################################
+
+# To make an overflow temple for N altars, give it the tag
+# "temple_overflow_N".
+
+##############################################################################
+# Overflow temples with one altar, must have tag "temple_overflow_1"
+#
+NAME: overflow_temple_1_a
+TAGS: temple_overflow_1 allow_dup
+MAP
+B
+ENDMAP
diff --git a/crawl-ref/source/dat/uniques.des b/crawl-ref/source/dat/uniques.des
index 42e680646e..5934928d9d 100644
--- a/crawl-ref/source/dat/uniques.des
+++ b/crawl-ref/source/dat/uniques.des
@@ -129,9 +129,19 @@ MAP
1
ENDMAP
-NAME: uniq_gastronok
-DEPTH: 8-9, 10-13, Lair:4-8
-TAGS: place_unique
+NAME: uniq_gastronok_1
+DEPTH: 8-9, 10-13, !Lair
+TAGS: place_unique uniq_gastronok
+WEIGHT: 5
+MONS: Gastronok
+MAP
+1
+ENDMAP
+
+NAME: uniq_gastronok_2
+DEPTH: Lair:4-8
+TAGS: place_unique uniq_gastronok
+WEIGHT: 15
MONS: Gastronok
MAP
1
@@ -170,7 +180,7 @@ MAP
ENDMAP
NAME: uniq_urug
-DEPTH: 10-13, 14-16, !Lair, !Tomb, !Lair
+DEPTH: 10-13, 14-16, !Lair, !Lair
TAGS: place_unique
MONS: Urug
MAP
@@ -178,7 +188,7 @@ MAP
ENDMAP
NAME: uniq_michael
-DEPTH: 10-13, 14-16, !Lair, !Tomb, !Lair
+DEPTH: 10-13, 14-16, !Lair, !Lair
TAGS: place_unique
MONS: Michael
MAP
@@ -186,7 +196,7 @@ MAP
ENDMAP
NAME: uniq_eustachio
-DEPTH: 10-13, 14-16, !Lair, !Tomb, !Lair
+DEPTH: 10-13, 14-16, !Lair, !Lair
TAGS: place_unique
MONS: Eustachio
MAP
@@ -194,7 +204,7 @@ MAP
ENDMAP
NAME: uniq_sonja
-DEPTH: 10-13, 14-16, !Lair, !Tomb, !Lair
+DEPTH: 10-13, 14-16, !Lair, !Lair
TAGS: place_unique
MONS: Sonja
MAP
@@ -210,7 +220,7 @@ MAP
ENDMAP
NAME: uniq_erica
-DEPTH: 10-13, 14-16, !Lair, !Tomb, !Lair
+DEPTH: 10-13, 14-16, !Lair, !Lair
TAGS: place_unique
MONS: Erica
MAP
@@ -218,7 +228,7 @@ MAP
ENDMAP
NAME: uniq_josephine
-DEPTH: 10-13, 14-16, !Lair, !Tomb, !Lair
+DEPTH: 10-13, 14-16, !Lair, !Lair
TAGS: place_unique
MONS: Josephine band
MAP
@@ -226,7 +236,7 @@ MAP
ENDMAP
NAME: uniq_jozef
-DEPTH: 10-13, 14-16, !Lair, !Tomb, !Lair
+DEPTH: 10-13, 14-16, !Lair, !Lair
TAGS: place_unique
MONS: Jozef
MAP
@@ -234,7 +244,7 @@ MAP
ENDMAP
NAME: uniq_harold
-DEPTH: 10-13, 14-16, !Lair, !Tomb, !Lair
+DEPTH: 10-13, 14-16, !Lair, !Lair
TAGS: place_unique
MONS: Harold
MAP
@@ -242,7 +252,7 @@ MAP
ENDMAP
NAME: uniq_norbert
-DEPTH: 10-13, 14-16, !Lair, !Tomb, !Lair
+DEPTH: 10-13, 14-16, !Lair, !Lair
TAGS: place_unique
MONS: Norbert
MAP
@@ -250,7 +260,7 @@ MAP
ENDMAP
NAME: uniq_snorg
-DEPTH: 14-16, 17-19, !Tomb, !Lair
+DEPTH: 14-16, 17-19, !Lair
TAGS: place_unique
MONS: Snorg
MAP
@@ -258,7 +268,7 @@ MAP
ENDMAP
NAME: uniq_roxanne
-DEPTH: 14-16, 17-19, !Tomb, !Lair
+DEPTH: 14-16, 17-19, !Lair
TAGS: place_unique
MONS: Roxanne
MAP
@@ -266,7 +276,7 @@ MAP
ENDMAP
NAME: uniq_rupert
-DEPTH: 14-16, 17-19, !Tomb, !Lair
+DEPTH: 14-16, 17-19, !Lair
TAGS: place_unique
MONS: Rupert
MAP
@@ -274,7 +284,7 @@ MAP
ENDMAP
NAME: uniq_azrael
-DEPTH: 14-16, 17-19, !Tomb, !Lair, !Swamp, !Shoal
+DEPTH: 14-16, 17-19, !Lair, !Swamp, !Shoal
TAGS: place_unique
MONS: Azrael band
MAP
@@ -282,7 +292,7 @@ MAP
ENDMAP
NAME: uniq_nessos
-DEPTH: 14-16, 17-19, !Tomb, !Lair
+DEPTH: 14-16, 17-19, !Lair
TAGS: place_unique
MONS: Nessos
MAP
@@ -290,7 +300,7 @@ MAP
ENDMAP
NAME: uniq_agnes
-DEPTH: 14-16, !Tomb, !Lair
+DEPTH: 14-16, !Lair
TAGS: place_unique
MONS: Agnes
MAP
@@ -298,7 +308,7 @@ MAP
ENDMAP
NAME: uniq_nikola
-DEPTH: 14-16, 17-19, !Tomb, !Lair
+DEPTH: 14-16, 17-19, !Lair
TAGS: place_unique
MONS: Nikola
MAP
@@ -306,7 +316,7 @@ MAP
ENDMAP
NAME: uniq_maud
-DEPTH: 14-16, !Tomb, !Lair
+DEPTH: 14-16, !Lair
TAGS: place_unique
MONS: Maud
MAP
@@ -314,7 +324,7 @@ MAP
ENDMAP
NAME: uniq_louise
-DEPTH: 14-16, 17-19, !Tomb, !Lair
+DEPTH: 14-16, 17-19, !Lair
TAGS: place_unique
MONS: Louise
MAP
@@ -322,7 +332,7 @@ MAP
ENDMAP
NAME: uniq_nergalle
-DEPTH: 14-16, 17-19, !Tomb, !Lair
+DEPTH: 14-16, 17-19, !Lair
TAGS: place_unique
MONS: Nergalle
MAP
@@ -330,7 +340,7 @@ MAP
ENDMAP
NAME: uniq_kirke
-DEPTH: 14-16, 17-19, !Tomb, !Lair
+DEPTH: 14-16, 17-19, !Lair
TAGS: place_unique
MONS: Kirke band
MAP
@@ -338,7 +348,7 @@ MAP
ENDMAP
NAME: uniq_francis
-DEPTH: 17-19, 20-27, !Tomb, !Lair
+DEPTH: 17-19, 20-27, !Lair
TAGS: place_unique
MONS: Francis
MAP
@@ -346,7 +356,7 @@ MAP
ENDMAP
NAME: uniq_frances
-DEPTH: 17-19, 20-27, !Tomb, !Lair
+DEPTH: 17-19, 20-27, !Lair
TAGS: place_unique
MONS: Frances
MAP
@@ -354,7 +364,7 @@ MAP
ENDMAP
NAME: uniq_wayne
-DEPTH: 17-19, 20-27, !Tomb, !Lair
+DEPTH: 17-19, 20-27, !Lair
TAGS: place_unique
MONS: Wayne
MAP
@@ -362,7 +372,7 @@ MAP
ENDMAP
NAME: uniq_duane
-DEPTH: 17-19, 20-27, !Tomb, !Lair
+DEPTH: 17-19, 20-27, !Lair
TAGS: place_unique
MONS: Duane
MAP
@@ -370,7 +380,7 @@ MAP
ENDMAP
NAME: uniq_norris
-DEPTH: 17-19, !Tomb, !Lair
+DEPTH: 17-19, !Lair
TAGS: place_unique
MONS: Norris
MAP
@@ -378,7 +388,7 @@ MAP
ENDMAP
NAME: uniq_saint_roka
-DEPTH: 17-19, 20-27, !Tomb, !Lair
+DEPTH: 17-19, 20-27, !Lair
TAGS: place_unique
MONS: Saint Roka band
MAP
@@ -386,7 +396,7 @@ MAP
ENDMAP
NAME: uniq_xtahua
-DEPTH: 20-27, !Tomb, !Lair
+DEPTH: 20-27, !Lair
TAGS: place_unique
MONS: Xtahua
MAP
@@ -394,7 +404,7 @@ MAP
ENDMAP
NAME: uniq_frederick
-DEPTH: 20-27, !Tomb, !Lair
+DEPTH: 20-27, !Lair
TAGS: place_unique
MONS: Frederick
MAP
@@ -402,7 +412,7 @@ MAP
ENDMAP
NAME: uniq_margery
-DEPTH: 20-27, !Tomb, !Lair
+DEPTH: 20-27, !Lair
TAGS: place_unique
MONS: Margery band
MAP
@@ -423,7 +433,7 @@ MAP
ENDMAP
NAME: uniq_aizul
-DEPTH: 20-27, !Tomb, !Lair
+DEPTH: 20-27, !Lair
TAGS: place_unique
MONS: Aizul
MAP
diff --git a/crawl-ref/source/dat/volcano.des b/crawl-ref/source/dat/volcano.des
index f986ea9641..db0a8bb924 100644
--- a/crawl-ref/source/dat/volcano.des
+++ b/crawl-ref/source/dat/volcano.des
@@ -223,7 +223,10 @@ end
function make_fiery_weapon (e, weapon)
local weapon_string = ""
for _, wt in ipairs(weapon) do
- weapon_string = weapon_string .. " / " .. wt .. " ego:flaming good_item"
+ if string.find(wt, "bow") == nil
+ then weapon_string = weapon_string .. " / " .. wt .. " ego:flaming good_item"
+ else weapon_string = weapon_string .. " / " .. wt .. " ego:flame good_item"
+ end
end
local n_weapon = string.gsub(weapon_string, "%s*\/$", "")
e.item(n_weapon)
diff --git a/crawl-ref/source/dbg-util.cc b/crawl-ref/source/dbg-util.cc
index 1ccabe928d..12b2bf7931 100644
--- a/crawl-ref/source/dbg-util.cc
+++ b/crawl-ref/source/dbg-util.cc
@@ -12,7 +12,7 @@
#include "cio.h"
#include "coord.h"
#include "dungeon.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "religion.h"
#include "shopping.h"
diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc
index e82ba90e70..b57989a745 100644
--- a/crawl-ref/source/decks.cc
+++ b/crawl-ref/source/decks.cc
@@ -31,8 +31,9 @@
#include "maps.h"
#include "message.h"
#include "misc.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-iter.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mutation.h"
#include "ouch.h"
#include "player.h"
@@ -2372,7 +2373,7 @@ static bool _trowel_card(int power, deck_rarity_type rarity)
if (create_monster(
mgen_data::hostile_at(
- RANDOM_ELEMENT(statues),
+ RANDOM_ELEMENT(statues), "the Trowel card",
true, 0, 0, you.pos())) != -1)
{
mpr("A menacing statue appears!");
@@ -2386,7 +2387,7 @@ static bool _trowel_card(int power, deck_rarity_type rarity)
if (create_monster(
mgen_data(RANDOM_ELEMENT(golems),
- BEH_FRIENDLY, 5, 0,
+ BEH_FRIENDLY, &you, 5, 0,
you.pos(), MHITYOU)) != -1)
{
mpr("You construct a golem!");
@@ -2513,16 +2514,13 @@ static void _crusade_card(int power, deck_rarity_type rarity)
if (power_level >= 1)
{
// A chance to convert opponents.
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi(&you.get_los()); mi; ++mi)
{
- monsters* const monster = &menv[i];
- if (!monster->alive()
- || !mons_near(monster)
- || monster->friendly()
- || monster->holiness() != MH_NATURAL
- || mons_is_unique(monster->type)
- || mons_immune_magic(monster)
- || player_will_anger_monster(monster))
+ if (mi->friendly()
+ || mi->holiness() != MH_NATURAL
+ || mons_is_unique(mi->type)
+ || mons_immune_magic(*mi)
+ || player_will_anger_monster(*mi))
{
continue;
}
@@ -2531,35 +2529,35 @@ static void _crusade_card(int power, deck_rarity_type rarity)
// (though not immunity) check. Specifically,
// you can convert Killer Klowns this way.
// Might be too good.
- if (monster->hit_dice * 35 < random2(power))
+ if (mi->hit_dice * 35 < random2(power))
{
- simple_monster_message(monster, " is converted.");
+ simple_monster_message(*mi, " is converted.");
if (one_chance_in(5 - power_level))
{
- monster->attitude = ATT_FRIENDLY;
+ mi->attitude = ATT_FRIENDLY;
// If you worship a god that lets you recruit
// permanent followers, or a god allied with one,
// count this as a recruitment.
if (is_good_god(you.religion)
|| you.religion == GOD_BEOGH
- && mons_species(monster->type) == MONS_ORC
- && !monster->is_summoned()
- && !monster->is_shapeshifter())
+ && mons_species(mi->type) == MONS_ORC
+ && !mi->is_summoned()
+ && !mi->is_shapeshifter())
{
// Prevent assertion if the monster was
// previously worshipping a different god,
// rather than already worshipping your god or
// being an atheist.
- monster->god = GOD_NO_GOD;
+ mi->god = GOD_NO_GOD;
- mons_make_god_gift(monster, is_good_god(you.religion) ?
+ mons_make_god_gift(*mi, is_good_god(you.religion) ?
GOD_SHINING_ONE : GOD_BEOGH);
}
}
else
- monster->add_ench(ENCH_CHARM);
+ mi->add_ench(ENCH_CHARM);
}
}
}
@@ -2584,7 +2582,7 @@ static void _summon_demon_card(int power, deck_rarity_type rarity)
// and thus not print the message.
// This hack appears later in this file as well.
if (create_monster(
- mgen_data(summon_any_demon(dct), BEH_FRIENDLY,
+ mgen_data(summon_any_demon(dct), BEH_FRIENDLY, &you,
std::min(power/50 + 1, 6), 0,
you.pos(), MHITYOU),
false) == -1)
@@ -2640,7 +2638,7 @@ static void _summon_any_monster(int power, deck_rarity_type rarity)
const bool friendly = (power_level > 0 || !one_chance_in(4));
if (create_monster(mgen_data(mon_chosen,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
3, 0, chosen_spot, MHITYOU),
false) == -1)
{
@@ -2656,7 +2654,7 @@ static void _summon_dancing_weapon(int power, deck_rarity_type rarity)
const int mon =
create_monster(
mgen_data(MONS_DANCING_WEAPON,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
power_level + 3, 0, you.pos(), MHITYOU),
false);
@@ -2742,7 +2740,7 @@ static void _summon_flying(int power, deck_rarity_type rarity)
{
create_monster(
mgen_data(result,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
std::min(power/50 + 1, 6), 0,
you.pos(), MHITYOU));
}
@@ -2757,7 +2755,7 @@ static void _summon_skeleton(int power, deck_rarity_type rarity)
};
if (create_monster(mgen_data(skeltypes[power_level],
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
std::min(power/50 + 1, 6), 0,
you.pos(), MHITYOU),
false) == -1)
@@ -2780,6 +2778,7 @@ static void _summon_ugly(int power, deck_rarity_type rarity)
if (create_monster(mgen_data(ugly,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ &you,
std::min(power/50 + 1, 6), 0,
you.pos(), MHITYOU),
false) == -1)
diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc
index 0ef9aa6aca..b05ca85380 100644
--- a/crawl-ref/source/delay.cc
+++ b/crawl-ref/source/delay.cc
@@ -34,7 +34,7 @@
#include "message.h"
#include "misc.h"
#include "mon-behv.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "notes.h"
#include "ouch.h"
@@ -165,7 +165,7 @@ static int _recite_to_monsters(coord_def where, int pow, int, actor *)
case 6:
case 7:
case 8:
- mon->put_to_sleep();
+ mon->hibernate();
simple_monster_message(mon, " falls asleep!");
break;
case 9:
diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc
index 933bd6886d..426cba067f 100644
--- a/crawl-ref/source/describe.cc
+++ b/crawl-ref/source/describe.cc
@@ -40,7 +40,7 @@
#include "macro.h"
#include "menu.h"
#include "message.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "newgame.h"
#include "jobs.h"
@@ -689,14 +689,14 @@ static std::string _describe_demon(const monsters &mons)
void append_weapon_stats(std::string &description, const item_def &item)
{
- description += "$Damage rating: ";
- _append_value(description, property( item, PWPN_DAMAGE ), false);
- description += " ";
-
- description += "Accuracy rating: ";
+ description += "$Accuracy rating: ";
_append_value(description, property( item, PWPN_HIT ), true);
description += " ";
+ description += "Damage rating: ";
+ _append_value(description, property( item, PWPN_DAMAGE ), false);
+ description += " ";
+
description += "Base attack delay: ";
_append_value(description, property( item, PWPN_SPEED ) * 10, false);
description += "%";
@@ -748,9 +748,14 @@ static std::string _describe_weapon(const item_def &item, bool verbose)
"cause great damage to the undead and demons.";
break;
case SPWPN_ELECTROCUTION:
- description += "Occasionally, upon striking a foe, it will "
- "discharge some electrical energy and cause terrible "
- "harm.";
+ if (is_range_weapon(item))
+ description += "It charges the ammunition it shoots with "
+ "electricity; occasionally upon a hit, such missiles "
+ "may discharge and cause terrible harm.";
+ else
+ description += "Occasionally, upon striking a foe, it will "
+ "discharge some electrical energy and cause terrible "
+ "harm.";
break;
case SPWPN_ORC_SLAYING:
description += "It is especially effective against all of "
@@ -763,7 +768,7 @@ static std::string _describe_weapon(const item_def &item, bool verbose)
break;
case SPWPN_VENOM:
if (is_range_weapon(item))
- description += "It poisons the unbranded ammo it fires.";
+ description += "It poisons the ammo it fires.";
else
description += "It poisons the flesh of those it strikes.";
break;
@@ -1992,10 +1997,17 @@ std::string get_item_description( const item_def &item, bool verbose,
}
}
- if (good_god_hates_item_handling(item))
+ if (conduct_type ct = good_god_hates_item_handling(item))
{
description << "$$" << god_name(you.religion) << " opposes the use of "
- << "such an evil item.";
+ << "such an ";
+
+ if (ct == DID_NECROMANCY)
+ description << "evil";
+ else
+ description << "unholy";
+
+ description << " item.";
}
else if (god_hates_item_handling(item))
{
@@ -2940,6 +2952,19 @@ void get_monster_db_desc(const monsters& mons, describe_info &inf,
<< mitm[mons.inv[i]].name(DESC_NOCAP_A, false, true);
}
}
+
+ if (mons.props.exists("blame"))
+ {
+ inf.body << "$$Monster blame chain:$";
+
+ const CrawlVector& blame = mons.props["blame"].get_vector();
+
+ for (CrawlVector::const_iterator it = blame.begin();
+ it != blame.end(); ++it)
+ {
+ inf.body << " " << it->get_string() << "$";
+ }
+ }
#endif
}
diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc
index 50fdc78af6..3d225bfd6c 100644
--- a/crawl-ref/source/directn.cc
+++ b/crawl-ref/source/directn.cc
@@ -44,7 +44,7 @@
#include "message.h"
#include "menu.h"
#include "misc.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "mon-info.h"
#include "mon-util.h"
#include "output.h"
@@ -695,7 +695,7 @@ void full_describe_view()
const coord_def c = list_features[i];
std::string desc = "";
#ifndef USE_TILE
- const coord_def e = c - you.pos() + coord_def(9,9);
+ const coord_def e = c - you.pos() + coord_def(8,8);
show_type object = env.show(e);
unsigned short col = object.colour;
unsigned ch;
@@ -2902,6 +2902,13 @@ std::string feature_description(const coord_def& where, bool bloody,
if (grid == DNGN_OPEN_DOOR || feat_is_closed_door(grid))
{
+ const std::string door_desc_prefix =
+ env.markers.property_at(where, MAT_ANY,
+ "door_description_prefix");
+ const std::string door_desc_suffix =
+ env.markers.property_at(where, MAT_ANY,
+ "door_description_suffix");
+
std::set<coord_def> all_door;
find_connected_identical(where, grd(where), all_door);
const char *adj, *noun;
@@ -2911,12 +2918,8 @@ std::string feature_description(const coord_def& where, bool bloody,
desc += (grid == DNGN_OPEN_DOOR) ? "open " : "closed ";
if (grid == DNGN_DETECTED_SECRET_DOOR)
desc += "detected secret ";
- desc += noun;
- const std::string door_desc_suffix =
- env.markers.property_at(where, MAT_ANY,
- "door_description_suffix");
- desc += door_desc_suffix;
+ desc += door_desc_prefix + noun + door_desc_suffix;
if (bloody)
desc += ", spattered with blood";
@@ -2965,6 +2968,7 @@ static std::string _describe_mons_enchantment(const monsters &mons,
// Suppress silly-looking combinations, even if they're
// internally valid.
if (paralysed && (ench.ench == ENCH_SLOW || ench.ench == ENCH_HASTE
+ || ench.ench == ENCH_SWIFT
|| ench.ench == ENCH_PETRIFIED
|| ench.ench == ENCH_PETRIFYING))
{
@@ -2992,7 +2996,7 @@ static std::string _describe_mons_enchantment(const monsters &mons,
case ENCH_POISON: return "poisoned";
case ENCH_SICK: return "sick";
case ENCH_ROT: return "rotting away"; //jmf: "covered in sores"?
- case ENCH_BACKLIGHT: return "softly glowing";
+ case ENCH_CORONA: return "softly glowing";
case ENCH_SLOW: return "moving slowly";
case ENCH_BERSERK: return "berserk";
case ENCH_BATTLE_FRENZY: return "consumed by blood-lust";
@@ -3006,6 +3010,7 @@ static std::string _describe_mons_enchantment(const monsters &mons,
case ENCH_PETRIFIED: return "petrified";
case ENCH_PETRIFYING: return "slowly petrifying";
case ENCH_LOWERED_MR: return "susceptible to magic";
+ case ENCH_SWIFT: return "moving somewhat quickly";
default: return "";
}
}
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index 9b9998584e..401c53ab1d 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -41,7 +41,7 @@
#include "message.h"
#include "misc.h"
#include "mon-util.h"
-#include "monplace.h"
+#include "mon-place.h"
#include "notes.h"
#include "place.h"
#include "player.h"
@@ -55,6 +55,10 @@
#include "traps.h"
#include "travel.h"
+#ifdef DEBUG_DIAGNOSTICS
+#define DEBUG_TEMPLES 1
+#endif
+
#ifdef WIZARD
#include "cio.h" // for cancelable_get_line()
#endif
@@ -211,10 +215,15 @@ static void _dgn_load_colour_grid();
static void _dgn_map_colour_fixup();
// ALTAR FUNCTIONS
+static int _setup_temple_altars(CrawlHashTable &temple);
+static dungeon_feature_type _pick_temple_altar(vault_placement &place);
static dungeon_feature_type _pick_an_altar();
static void _place_altar();
static void _place_altars();
+static std::vector<god_type> _temple_altar_list;
+static CrawlHashTable* _current_temple_hash = NULL; // XXX: hack!
+
typedef std::list<coord_def> coord_list;
// MISC FUNCTIONS
@@ -295,6 +304,9 @@ bool builder(int level_number, int level_type)
dgn_reset_level();
+ if (player_in_branch(BRANCH_ECUMENICAL_TEMPLE))
+ _setup_temple_altars(you.props);
+
// If we're getting low on available retries, disable random vaults
// and minivaults (special levels will still be placed).
if (tries < 5)
@@ -948,6 +960,9 @@ void dgn_reset_level()
dgn_check_connectivity = false;
dgn_zones = 0;
+ _temple_altar_list.clear();
+ _current_temple_hash = NULL;
+
// Forget level properties.
env.properties.clear();
@@ -1617,6 +1632,142 @@ static void _dgn_verify_connectivity(unsigned nvaults)
}
}
+// Structure of OVERFLOW_TEMPLES:
+//
+// * A vector, with one cell per dungeon level (unset if there's no
+// overflow temples on that level).
+//
+// * The cell of the previous vector is a vector, with one overlfow
+// temple definition per cell.
+//
+// * The cell of the previous vector is a hash table, containing the
+// list of gods for the overflow temple and (optionally) the name of
+// the vault to use for the temple. If no map name is supplied,
+// it will randomly pick from vaults tagged "temple_overflow_num",
+// where "num" is the number of gods in the temple. Gods are listed
+// in the order their altars are placed.
+static void _build_overflow_temples(int level_number)
+{
+ if (!you.props.exists(OVERFLOW_TEMPLES_KEY))
+ // Levels built while in testing mode.
+ return;
+
+ CrawlVector &levels = you.props[OVERFLOW_TEMPLES_KEY].get_vector();
+
+ // Are we deeper than the last overflow temple?
+ if (level_number >= levels.size())
+ return;
+
+ CrawlStoreValue &val = levels[level_number];
+
+ // Does this level have an overflow temple?
+ if (val.get_flags() & SFLAG_UNSET)
+ return;
+
+ CrawlVector &temples = val.get_vector();
+
+ if (temples.size() == 0)
+ return;
+
+ if (!can_create_vault)
+ {
+ mpr("WARNING: Overriding can_create_vault",
+ MSGCH_DIAGNOSTICS);
+ can_create_vault = true;
+ }
+
+ for (unsigned int i = 0; i < temples.size(); i++)
+ {
+ CrawlHashTable &temple = temples[i].get_table();
+
+ const int num_gods = _setup_temple_altars(temple);
+
+ const map_def *vault = NULL;
+
+ if (temple.exists(TEMPLE_MAP_KEY))
+ {
+ std::string name = temple[TEMPLE_MAP_KEY].get_string();
+
+ vault = find_map_by_name(name);
+ if (vault == NULL)
+ {
+ mprf(MSGCH_ERROR,
+ "Couldn't find overflow temple map '%s'!",
+ name.c_str());
+ }
+ }
+ else
+ {
+ std::string vault_tag;
+
+ // For a single-altar temple, first try to find a temple specialized
+ // for that god.
+ if (num_gods == 1)
+ {
+ CrawlVector &god_vec = temple[TEMPLE_GODS_KEY];
+ god_type god = (god_type) god_vec[0].get_byte();
+
+ std::string name = god_name(god);
+ name = replace_all(name, " ", "_");
+ lowercase(name);
+
+ if (you.uniq_map_tags.find("uniq_altar_" + name)
+ != you.uniq_map_tags.end())
+ {
+ // We've already placed a specialized temple for this
+ // god, so do nothing.
+#ifdef DEBUG_TEMPLES
+ mprf(MSGCH_DIAGNOSTICS, "Already placed specialized "
+ "single-altar temple for %s", name.c_str());
+#endif
+ continue;
+ }
+
+ vault_tag = make_stringf("temple_overflow_%s", name.c_str());
+
+ vault = random_map_for_tag(vault_tag, true);
+#ifdef DEBUG_TEMPLES
+ if (vault == NULL)
+ mprf(MSGCH_DIAGNOSTICS, "Couldn't find overflow temple "
+ "for god %s", name.c_str());
+#endif
+ }
+
+ if (vault == NULL)
+ {
+ vault_tag = make_stringf("temple_overflow_%d", num_gods);
+
+ vault = random_map_for_tag(vault_tag, true);
+ if (vault == NULL)
+ {
+ mprf(MSGCH_ERROR,
+ "Couldn't find overflow temple tag '%s'!",
+ vault_tag.c_str());
+ }
+ }
+ }
+
+ if (vault == NULL)
+ // Might as well build the rest of the level if we couldn't
+ // find the overflow temple map, so don't veto the level.
+ return;
+
+ if (!_ensure_vault_placed(_build_vaults(level_number, vault), false))
+ {
+#ifdef DEBUG_TEMPLES
+ mprf(MSGCH_DIAGNOSTICS, "Couldn't place overlfow temple '%s', "
+ "vetoing level.", vault->name.c_str());
+#endif
+ return;
+ }
+#ifdef DEBUG_TEMPLES
+ mprf(MSGCH_DIAGNOSTICS, "Placed overflow temple %s",
+ vault->name.c_str());
+#endif
+ }
+ _current_temple_hash = NULL; // XXX: hack!
+}
+
static void _build_dungeon_level(int level_number, int level_type)
{
spec_room sr;
@@ -1663,9 +1814,16 @@ static void _build_dungeon_level(int level_number, int level_type)
// Any further vaults must make sure not to disrupt level layout.
dgn_check_connectivity = !player_in_branch(BRANCH_SHOALS);
+ if (you.where_are_you == BRANCH_MAIN_DUNGEON)
+ {
+ _build_overflow_temples(level_number);
+
+ if (dgn_level_vetoed)
+ return;
+ }
+
// Try to place minivaults that really badly want to be placed. Still
// no guarantees, seeing this is a minivault.
-
_place_minivaults();
_place_branch_entrances( level_number, level_type );
_place_extra_vaults();
@@ -2503,7 +2661,27 @@ static bool _place_portal_vault(int stair, const std::string &tag, int dlevel)
static const map_def *_dgn_random_map_for_place(bool minivault)
{
- const level_id lid = level_id::current();
+ if (!minivault && player_in_branch(BRANCH_ECUMENICAL_TEMPLE))
+ {
+ // Temple vault determined at new game tiem.
+ std::string name = you.props[TEMPLE_MAP_KEY];
+
+ // Tolerate this for a little while, for old games.
+ if (!name.empty())
+ {
+ const map_def *vault = find_map_by_name(name);
+
+ if (vault == NULL)
+ {
+ end(1, false, "Unable to place Temple vault '%s'",
+ name.c_str());
+ }
+ return (vault);
+ }
+ }
+
+ const level_id lid = level_id::current();
+
const map_def *vault = random_map_for_place(lid, minivault);
// Disallow entry vaults for tutorial (only complicates things).
@@ -2517,6 +2695,20 @@ static const map_def *_dgn_random_map_for_place(bool minivault)
return (vault);
}
+static int _setup_temple_altars(CrawlHashTable &temple)
+{
+ _current_temple_hash = &temple; // XXX: hack!
+
+ CrawlVector god_list = temple[TEMPLE_GODS_KEY].get_vector();
+
+ _temple_altar_list.clear();
+
+ for (unsigned int i = 0; i < god_list.size(); i++)
+ _temple_altar_list.push_back( (god_type) god_list[i].get_byte() );
+
+ return ( (int) god_list.size() );
+}
+
// Returns BUILD_SKIP if we should skip further generation,
// BUILD_QUIT if we should immediately quit, and BUILD_CONTINUE
// otherwise.
@@ -4796,9 +4988,6 @@ dungeon_feature_type map_feature_at(map_def *map, const coord_def &c, int rawfea
: DNGN_FLOOR); // includes everything else
}
-// Returns altar_count - seems rather odd to me to force such a return
-// when I believe the value is only used in the case of the ecumenical
-// temple - oh, well... {dlb} (XXX)
static void _vault_grid( vault_placement &place,
int vgrid,
const coord_def& where,
@@ -4871,9 +5060,7 @@ static void _vault_grid( vault_placement &place,
(vgrid == ']') ? DNGN_STONE_STAIRS_DOWN_III :
(vgrid == '[') ? DNGN_STONE_STAIRS_UP_III :
(vgrid == 'A') ? DNGN_STONE_ARCH :
- (vgrid == 'B') ?
- static_cast<dungeon_feature_type>(
- DNGN_ALTAR_FIRST_GOD + place.altar_count) :// see below
+ (vgrid == 'B') ? _pick_temple_altar(place) :
(vgrid == 'C') ? _pick_an_altar() : // f(x) elsewhere {dlb}
(vgrid == 'I') ? DNGN_ORCISH_IDOL :
(vgrid == 'G') ? DNGN_GRANITE_STATUE :
@@ -4890,9 +5077,6 @@ static void _vault_grid( vault_placement &place,
// then, handle oddball grids {dlb}:
switch (vgrid)
{
- case 'B':
- place.altar_count++;
- break;
case '@':
place.exits.push_back( where );
break;
@@ -5311,6 +5495,27 @@ static void _many_pools(dungeon_feature_type pool_type)
}
} // end many_pools()
+static dungeon_feature_type _pick_temple_altar(vault_placement &place)
+{
+ if (_temple_altar_list.empty())
+ {
+ if (_current_temple_hash != NULL)
+ {
+ mprf("Ran out of altars for temple!", MSGCH_ERROR);
+ return (DNGN_FLOOR);
+ }
+ // Randomized altar list for mini-temples.
+ _temple_altar_list = temple_god_list();
+ std::random_shuffle(_temple_altar_list.begin(), _temple_altar_list.end());
+ }
+
+ const god_type god = _temple_altar_list.back();
+
+ _temple_altar_list.pop_back();
+
+ return altar_for_god(god);
+}
+
//jmf: Generate altar based on where you are, or possibly randomly.
static dungeon_feature_type _pick_an_altar()
{
@@ -8231,7 +8436,10 @@ static bool _fixup_interlevel_connectivity()
void vault_placement::reset()
{
- altar_count = 0;
+ if (_current_temple_hash != NULL)
+ _setup_temple_altars(*_current_temple_hash);
+ else
+ _temple_altar_list.clear();
}
void vault_placement::apply_grid()
@@ -8286,10 +8494,10 @@ void remember_vault_placement(std::string key, vault_placement &place)
table.size() + 1);
std::string place_str
- = make_stringf("(%d,%d) (%d,%d) orient: %d lev: %d alt: %d rune: %d "
+ = make_stringf("(%d,%d) (%d,%d) orient: %d lev: %d rune: %d "
"subst: %d",
place.pos.x, place.pos.y, place.size.x, place.size.y,
- place.orient, place.level_number, place.altar_count,
+ place.orient, place.level_number,
place.num_runes, place.rune_subst);
table[name] = place_str;
diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h
index f6932d1cb6..c9c236cb9b 100644
--- a/crawl-ref/source/dungeon.h
+++ b/crawl-ref/source/dungeon.h
@@ -29,6 +29,12 @@
#define YOU_PORTAL_VAULT_NAMES_KEY "you_portal_vault_names_key"
+// See _build_overflow_temples() in dungeon.cc for details on overflow
+// temples.
+#define TEMPLE_GODS_KEY "temple_gods_key"
+#define OVERFLOW_TEMPLES_KEY "overflow_temples_key"
+#define TEMPLE_MAP_KEY "temple_map_key"
+
enum portal_type
{
PORTAL_NONE = 0,
@@ -140,7 +146,7 @@ public:
map_def map;
std::vector<coord_def> exits;
- int level_number, altar_count, num_runes;
+ int level_number, num_runes;
// If we're not placing runes, this is the substitute feature.
int rune_subst;
@@ -148,8 +154,7 @@ public:
public:
vault_placement()
: pos(-1, -1), size(0, 0), orient(0), map(),
- exits(), level_number(0), altar_count(0), num_runes(0),
- rune_subst(-1)
+ exits(), level_number(0), num_runes(0), rune_subst(-1)
{
}
diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc
index 195aaa9792..f74729b323 100644
--- a/crawl-ref/source/effects.cc
+++ b/crawl-ref/source/effects.cc
@@ -43,8 +43,9 @@
#include "misc.h"
#include "mon-behv.h"
#include "mon-cast.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-iter.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "mutation.h"
#include "notes.h"
@@ -2449,44 +2450,35 @@ bool recharge_wand(int item_slot)
return (false);
}
+// Berserking monsters cannot be ordered around.
+static bool _follows_orders(monsters* mon)
+{
+ return (mon->friendly() && mon->type != MONS_GIANT_SPORE
+ && !mon->berserk());
+}
+
// Sets foe target of friendly monsters.
// If allow_patrol is true, patrolling monsters get MHITNOT instead.
static void _set_friendly_foes(bool allow_patrol = false)
{
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi(&you.get_los()); mi; ++mi)
{
- monsters *mon(&menv[i]);
- if (!mon->alive() || !mons_near(mon) || !mon->friendly()
- || mon->type == MONS_GIANT_SPORE)
- {
+ if (!_follows_orders(*mi))
continue;
- }
-
- // Berserking monsters cannot be ordered around.
- if (mon->berserk())
- continue;
-
- mon->foe = (allow_patrol && mon->is_patrolling() ? MHITNOT
+ mi->foe = (allow_patrol && mi->is_patrolling() ? MHITNOT
: you.pet_target);
}
}
static void _set_allies_patrol_point(bool clear = false)
{
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi(&you.get_los()); mi; ++mi)
{
- monsters *mon(&menv[i]);
- if (!mon->alive() || !mons_near(mon) || !mon->friendly())
+ if (!_follows_orders(*mi))
continue;
-
- // Berserking monsters cannot be ordered around.
- if (mon->berserk() || mon->type == MONS_GIANT_SPORE)
- continue;
-
- mon->patrol_point = (clear ? coord_def(0, 0) : mon->pos());
-
+ mi->patrol_point = (clear ? coord_def(0, 0) : mi->pos());
if (!clear)
- mon->behaviour = BEH_WANDER;
+ mi->behaviour = BEH_WANDER;
}
}
@@ -2868,7 +2860,7 @@ static void _hell_effects()
if (summon_instead)
{
create_monster(
- mgen_data::hostile_at(which_beastie,
+ mgen_data::hostile_at(which_beastie, "the effects of Hell",
true, 0, 0, you.pos()));
}
else
@@ -2890,6 +2882,7 @@ static void _hell_effects()
mgen_data mg;
mg.pos = you.pos();
mg.foe = MHITYOU;
+ mg.non_actor_summoner = "the effects of Hell";
create_monster(mg);
for (int i = 0; i < 4; ++i)
@@ -3944,8 +3937,9 @@ void handle_time(long time_delta)
|| monster_at(newpos)
|| env.cgrid(newpos) != EMPTY_CLOUD);
- mgen_data mg(MONS_JELLY, BEH_STRICT_NEUTRAL, 0, 0, newpos,
+ mgen_data mg(MONS_JELLY, BEH_STRICT_NEUTRAL, 0, 0, 0, newpos,
MHITNOT, 0, GOD_JIYVA);
+ mg.non_actor_summoner = "Jiyva";
if (create_monster(mg) != -1)
success = true;
@@ -4166,57 +4160,52 @@ void update_level(double elapsedTime)
dungeon_events.fire_event(
dgn_event(DET_TURN_ELAPSED, coord_def(0, 0), turns * 10));
- for (int m = 0; m < MAX_MONSTERS; m++)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *mon = &menv[m];
-
- if (!mon->alive())
- continue;
-
#if DEBUG_DIAGNOSTICS
mons_total++;
#endif
// Pacified monsters often leave the level now.
- if (mon->pacified() && turns > random2(40) + 21)
+ if (mi->pacified() && turns > random2(40) + 21)
{
- make_mons_leave_level(mon);
+ make_mons_leave_level(*mi);
continue;
}
// Following monsters don't get movement.
- if (mon->flags & MF_JUST_SUMMONED)
+ if (mi->flags & MF_JUST_SUMMONED)
continue;
// XXX: Allow some spellcasting (like Healing and Teleport)? - bwr
- // const bool healthy = (mon->hit_points * 2 > mon->max_hit_points);
+ // const bool healthy = (mi->hit_points * 2 > mi->max_hit_points);
// This is the monster healing code, moved here from tag.cc:
- if (mons_can_regenerate(mon))
+ if (mons_can_regenerate(*mi))
{
- if (monster_descriptor(mon->type, MDSC_REGENERATES)
- || mon->type == MONS_PLAYER_GHOST)
+ if (monster_descriptor(mi->type, MDSC_REGENERATES)
+ || mi->type == MONS_PLAYER_GHOST)
{
- mon->heal(turns);
+ mi->heal(turns);
}
else
{
// Set a lower ceiling of 0.1 on the regen rate.
const int regen_rate =
- std::max(mons_natural_regen_rate(mon) * 2, 5);
+ std::max(mons_natural_regen_rate(*mi) * 2, 5);
- mon->heal(div_rand_round(turns * regen_rate, 50));
+ mi->heal(div_rand_round(turns * regen_rate, 50));
}
}
// Handle nets specially to remove the trapping property of the net.
- if (mon->caught())
- mon->del_ench(ENCH_HELD, true);
+ if (mi->caught())
+ mi->del_ench(ENCH_HELD, true);
- _catchup_monster_moves(mon, turns);
+ _catchup_monster_moves(*mi, turns);
- if (turns >= 10 && mon->alive())
- mon->timeout_enchantments(turns / 10);
+ if (turns >= 10 && mi->alive())
+ mi->timeout_enchantments(turns / 10);
}
#if DEBUG_DIAGNOSTICS
@@ -4458,7 +4447,7 @@ static int _mushroom_ring(item_def &corpse, int & seen_count,
return (0);
mgen_data temp(MONS_TOADSTOOL,
- toadstool_behavior, 0, 0,
+ toadstool_behavior, 0, 0, 0,
coord_def(),
MHITNOT,
MG_FORCE_PLACE,
@@ -4554,6 +4543,7 @@ int spawn_corpse_mushrooms(item_def &corpse,
toadstool_behavior,
0,
0,
+ 0,
current,
MHITNOT,
MG_FORCE_PLACE,
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index f452a9523c..d33a2ec149 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -243,24 +243,25 @@ enum beam_type // beam[].flavour
BEAM_ENSLAVE_DEMON,
BEAM_BLINK,
BEAM_PETRIFY,
- BEAM_BACKLIGHT, // 45
+ BEAM_CORONA, // 45
BEAM_PORKALATOR,
- BEAM_SLEEP,
+ BEAM_HIBERNATION,
BEAM_BERSERK,
- BEAM_LAST_ENCHANTMENT = BEAM_BERSERK,
+ BEAM_SLEEP,
+ BEAM_LAST_ENCHANTMENT = BEAM_SLEEP,
// new beams for evaporate
- BEAM_POTION_STINKING_CLOUD, // 50
+ BEAM_POTION_STINKING_CLOUD,
BEAM_POTION_POISON,
BEAM_POTION_MIASMA,
BEAM_POTION_STEAM,
BEAM_POTION_FIRE,
- BEAM_POTION_COLD, // 55
+ BEAM_POTION_COLD,
BEAM_POTION_BLACK_SMOKE,
BEAM_POTION_GREY_SMOKE,
BEAM_POTION_MUTAGENIC,
BEAM_POTION_BLUE_SMOKE,
- BEAM_POTION_RAIN, // 60
+ BEAM_POTION_RAIN,
BEAM_POTION_RANDOM,
BEAM_LAST_REAL = BEAM_POTION_RANDOM,
@@ -579,6 +580,7 @@ enum command_type
CMD_MAP_ADD_WAYPOINT,
CMD_MAP_EXCLUDE_AREA,
CMD_MAP_CLEAR_EXCLUDES,
+ CMD_MAP_EXCLUDE_RADIUS,
CMD_MAP_MOVE_LEFT,
CMD_MAP_MOVE_DOWN,
@@ -1147,7 +1149,7 @@ enum duration_type
DUR_CONFUSING_TOUCH,
DUR_SURE_BLADE,
- DUR_BACKLIGHT,
+ DUR_CORONA,
DUR_DEATHS_DOOR,
DUR_FIRE_SHIELD,
@@ -1221,7 +1223,7 @@ enum enchant_type
ENCH_ROT, // 10
ENCH_SUMMON,
ENCH_ABJ,
- ENCH_BACKLIGHT,
+ ENCH_CORONA,
ENCH_CHARM,
ENCH_STICKY_FLAME, // 15
ENCH_GLOWING_SHAPESHIFTER,
@@ -1245,6 +1247,7 @@ enum enchant_type
ENCH_AQUATIC_LAND, // Water monsters lose hp while on land.
ENCH_SPORE_PRODUCTION, // 35
ENCH_SLOUCH,
+ ENCH_SWIFT,
// Update enchantment names in mon-util.cc when adding or removing
// enchantments.
@@ -1921,7 +1924,7 @@ enum monster_type // (int) menv[].type
MONS_WHITE_DRACONIAN,
MONS_PALE_DRACONIAN, // 320 Should always be last colour.
- // Sync up with monplace.cc's draconian selection if adding more.
+ // Sync up with mon-place.cc's draconian selection if adding more.
MONS_DRACONIAN_CALLER,
MONS_DRACONIAN_MONK,
MONS_DRACONIAN_ZEALOT,
@@ -2092,7 +2095,8 @@ enum beh_type
BEH_STRICT_NEUTRAL,
BEH_NEUTRAL, // creation only
BEH_HOSTILE, // creation only
- BEH_GUARD // creation only - monster is guard
+ BEH_GUARD, // creation only - monster is guard
+ BEH_COPY // creation only - copy from summoner
};
enum mon_attitude_type
@@ -2151,8 +2155,10 @@ enum monster_flag_type
MF_SPELLCASTER = 0x200000,
MF_ACTUAL_SPELLS = 0x400000, // Can use spells and is a spellcaster for
// Trog purposes.
- MF_PRIEST = 0x800000 // Is a priest (divine spells)
+ MF_PRIEST = 0x800000, // Is a priest (divine spells)
// for the conduct.
+
+ MF_GOING_BERSERK = 0x1000000 // Is about to go berserk!
};
// Adding slots breaks saves. YHBW.
@@ -2821,8 +2827,8 @@ enum spell_type
SPELL_CALL_CANINE_FAMILIAR,
SPELL_SUMMON_DRAGON,
SPELL_TAME_BEASTS,
- SPELL_SLEEP,
- SPELL_MASS_SLEEP,
+ SPELL_HIBERNATION,
+ SPELL_ENGLACIATION,
SPELL_DETECT_SECRET_DOORS,
SPELL_SEE_INVISIBLE,
SPELL_PHASE_SHIFT,
@@ -2832,7 +2838,7 @@ enum spell_type
SPELL_SHATTER,
SPELL_DISPERSAL,
SPELL_DISCHARGE,
- SPELL_BACKLIGHT,
+ SPELL_CORONA,
SPELL_INTOXICATE,
SPELL_EVAPORATE,
SPELL_FRAGMENTATION,
@@ -2880,6 +2886,7 @@ enum spell_type
SPELL_FIRE_ELEMENTALS,
SPELL_EARTH_ELEMENTALS,
SPELL_AIR_ELEMENTALS,
+ SPELL_SLEEP,
NUM_SPELLS
};
@@ -3120,8 +3127,8 @@ enum zap_type
ZAP_ORB_OF_FRAGMENTATION,
ZAP_THROW_ICICLE,
ZAP_ICE_STORM,
- ZAP_BACKLIGHT,
- ZAP_SLEEP,
+ ZAP_CORONA,
+ ZAP_HIBERNATION,
ZAP_FLAME_TONGUE,
ZAP_SANDBLAST,
ZAP_SMALL_SANDBLAST,
@@ -3134,6 +3141,7 @@ enum zap_type
ZAP_CHAOS,
ZAP_SLIME,
ZAP_PORKALATOR,
+ ZAP_SLEEP,
NUM_ZAPS
};
diff --git a/crawl-ref/source/exclude.cc b/crawl-ref/source/exclude.cc
index 6ddbcd9c2b..6b7e3a9ae7 100644
--- a/crawl-ref/source/exclude.cc
+++ b/crawl-ref/source/exclude.cc
@@ -19,6 +19,9 @@
#include "tutorial.h"
#include "view.h"
+typedef std::map<coord_def, travel_exclude*> exclmap;
+static exclmap _curr_excludes_map;
+
static bool _mon_needs_auto_exclude(const monsters *mon, bool sleepy = false)
{
if (mons_is_stationary(mon))
@@ -111,8 +114,7 @@ static opacity_excl opc_excl;
// Note: circle_def(r, C_ROUND) gives a circle with square radius r*r+1;
// this doesn't work well for radius 0, but then we want to
// skip LOS calculation in that case anyway since it doesn't
-// currently short-cut for small bounds. So radius 0 is special-cased.
-
+// currently short-cut for small bounds. So radius 0, 1 are special-cased.
travel_exclude::travel_exclude(const coord_def &p, int r,
bool autoexcl, monster_type mons, bool vaultexcl)
: pos(p), radius(r),
@@ -125,7 +127,7 @@ travel_exclude::travel_exclude(const coord_def &p, int r,
void travel_exclude::set_los()
{
uptodate = true;
- if (radius > 0)
+ if (radius > 1)
{
// Radius might have been changed, and this is cheap.
los.set_bounds(circle_def(radius, C_ROUND));
@@ -140,31 +142,42 @@ bool travel_exclude::affects(const coord_def& p) const
pos.x, pos.y, p.x, p.y);
if (radius == 0)
return (p == pos);
- return (los.see_cell(p));
+ else if (radius == 1)
+ return ((p - pos).rdist() <= 1);
+ else
+ return (los.see_cell(p));
}
bool travel_exclude::in_bounds(const coord_def &p) const
{
return (radius == 0 && p == pos
+ || radius == 1 && (p - pos).rdist() <= 1
|| los.in_bounds(p));
}
void _mark_excludes_non_updated(const coord_def &p)
{
- for (exclvec::iterator it = curr_excludes.begin();
+ _curr_excludes_map.clear();
+
+ for (exclvec::iterator it = curr_excludes.begin();
it != curr_excludes.end(); ++it)
{
it->uptodate = it->uptodate && it->in_bounds(p);
- }
+ _curr_excludes_map[it->pos] = &(*it);
+ }
}
-void _update_exclusion_los(bool all=false)
+static void _update_exclusion_los(bool all=false)
{
+ _curr_excludes_map.clear();
+
for (exclvec::iterator it = curr_excludes.begin();
it != curr_excludes.end(); ++it)
{
if (all || !it->uptodate)
it->set_los();
+
+ _curr_excludes_map[it->pos] = &(*it);
}
}
@@ -199,9 +212,11 @@ bool is_excluded(const coord_def &p, const exclvec &exc)
static travel_exclude *_find_exclude_root(const coord_def &p)
{
- for (unsigned int i = 0; i < curr_excludes.size(); ++i)
- if (curr_excludes[i].pos == p)
- return (&curr_excludes[i]);
+ exclmap::iterator it = _curr_excludes_map.find(p);
+
+ if (it !=_curr_excludes_map.end())
+ return it->second;
+
return (NULL);
}
@@ -256,12 +271,14 @@ void clear_excludes()
#endif
curr_excludes.clear();
+ _curr_excludes_map.clear();
clear_level_exclusion_annotation();
_exclude_update();
}
-// Cycles the radius of an exclusion, including "off" state.
+// Cycles the radius of an exclusion, including "off" state;
+// may start at 0 < radius < LOS_RADIUS, but won't cycle there.
void cycle_exclude_radius(const coord_def &p)
{
// XXX: scanning through curr_excludes twice
@@ -270,10 +287,7 @@ void cycle_exclude_radius(const coord_def &p)
if (exc->radius == LOS_RADIUS)
set_exclude(p, 0);
else
- {
- ASSERT(exc->radius == 0);
del_exclude(p);
- }
}
else
set_exclude(p, LOS_RADIUS);
@@ -286,6 +300,7 @@ void del_exclude(const coord_def &p)
if (curr_excludes[i].pos == p)
{
curr_excludes.erase(curr_excludes.begin() + i);
+ _curr_excludes_map.erase(p);
break;
}
_exclude_update(p);
@@ -316,6 +331,7 @@ void set_exclude(const coord_def &p, int radius, bool autoexcl, bool vaultexcl)
curr_excludes.push_back(travel_exclude(p, radius, autoexcl,
montype, vaultexcl));
+ _curr_excludes_map[p] = &curr_excludes.back();
}
_exclude_update(p);
@@ -390,6 +406,7 @@ void marshallExcludes(writer& outf, const exclvec& excludes)
void unmarshallExcludes(reader& inf, char minorVersion, exclvec &excludes)
{
excludes.clear();
+ _curr_excludes_map.clear();
int nexcludes = unmarshallShort(inf);
if (nexcludes)
{
@@ -406,6 +423,7 @@ void unmarshallExcludes(reader& inf, char minorVersion, exclvec &excludes)
mon = static_cast<monster_type>(unmarshallShort(inf));
}
excludes.push_back(travel_exclude(c, radius, autoexcl, mon));
+ _curr_excludes_map[c] = &curr_excludes.back();
}
}
}
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 7bd0f6d512..ada19b5efc 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -44,8 +44,8 @@
#include "misc.h"
#include "mon-behv.h"
#include "mon-cast.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "mutation.h"
#include "ouch.h"
@@ -2854,7 +2854,8 @@ static bool _make_zombie(monsters* mon, int corpse_class, int corpse_index,
mitm[last_item].link = idx;
animate_remains(mon->pos(), CORPSE_BODY, mon->behaviour,
- mon->foe, mon->god, true, true, true, &zombie_index);
+ mon->foe, 0, "a chaos effect", mon->god,
+ true, true, true, &zombie_index);
}
// No equipment to get, or couldn't get it for some reason.
@@ -2862,10 +2863,11 @@ static bool _make_zombie(monsters* mon, int corpse_class, int corpse_index,
{
monster_type type = (mons_zombie_size(mon->type) == Z_SMALL) ?
MONS_ZOMBIE_SMALL : MONS_ZOMBIE_LARGE;
- zombie_index = create_monster(
- mgen_data(type, mon->behaviour, 0, 0, mon->pos(),
- mon->foe, MG_FORCE_PLACE, mon->god,
- mon->type, mon->number));
+ mgen_data mg(type, mon->behaviour, 0, 0, 0, mon->pos(),
+ mon->foe, MG_FORCE_PLACE, mon->god,
+ mon->type, mon->number);
+ mg.non_actor_summoner = "a chaos effect";
+ zombie_index = create_monster(mg);
}
if (zombie_index == -1)
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index cd63e9cd15..9bfb072dc3 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -8,7 +8,7 @@
#include "delay.h"
#include "files.h"
-#include "monplace.h"
+#include "mon-place.h"
#include <errno.h>
#include <string.h>
@@ -59,7 +59,7 @@
#include "message.h"
#include "misc.h"
#include "mon-act.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "mtransit.h"
#include "newgame.h"
diff --git a/crawl-ref/source/fixary.h b/crawl-ref/source/fixary.h
index 8743e4573a..faf35b7c38 100644
--- a/crawl-ref/source/fixary.h
+++ b/crawl-ref/source/fixary.h
@@ -78,56 +78,6 @@ protected:
FixedVector<Column, WIDTH> mData;
};
-template <typename Z>
-class Matrix {
-public:
- Matrix(int width, int height, const Z &initial);
- Matrix(int width, int height);
- ~Matrix();
-
- void init(const Z &initial);
- Z &operator () (int x, int y)
- {
- return data[x + y * width];
- }
- const Z &operator () (int x, int y) const
- {
- return data[x + y * width];
- }
-
-private:
- Z *data;
- int width, height, size;
-};
-
-template <typename Z>
-Matrix<Z>::Matrix(int _width, int _height, const Z &initial)
- : data(NULL), width(_width), height(_height), size(_width * _height)
-{
- data = new Z [ size ];
- init(initial);
-}
-
-template <typename Z>
-Matrix<Z>::Matrix(int _width, int _height)
- : data(NULL), width(_width), height(_height), size(_width * _height)
-{
- data = new Z [ size ];
-}
-
-template <typename Z>
-Matrix<Z>::~Matrix()
-{
- delete [] data;
-}
-
-template <typename Z>
-void Matrix<Z>::init(const Z &initial)
-{
- for (int i = 0; i < size; ++i)
- data[i] = initial;
-}
-
// A fixed array centered around the origin.
template <class TYPE, int RADIUS> class SquareArray {
//-----------------------------------
diff --git a/crawl-ref/source/fixvec.h b/crawl-ref/source/fixvec.h
index 94ea8b5315..476eded773 100644
--- a/crawl-ref/source/fixvec.h
+++ b/crawl-ref/source/fixvec.h
@@ -7,11 +7,6 @@
#ifndef FIXVEC_H
#define FIXVEC_H
-#ifdef TARGET_COMPILER_VC
-// Benign: FixedVector has an array in member init list
-# pragma warning(disable : 4351)
-#endif
-
#include <cstdarg>
#include <cstring>
diff --git a/crawl-ref/source/ghost.cc b/crawl-ref/source/ghost.cc
index 901a4b92d4..6cb75f44d0 100644
--- a/crawl-ref/source/ghost.cc
+++ b/crawl-ref/source/ghost.cc
@@ -16,6 +16,7 @@
#include "externs.h"
#include "itemname.h"
#include "itemprop.h"
+#include "mon-iter.h"
#include "ng-input.h"
#include "random.h"
#include "skills2.h"
@@ -67,8 +68,8 @@ static spell_type search_order_conj[] = {
SPELL_SHOCK,
SPELL_SANDBLAST,
SPELL_MAGIC_DART,
- SPELL_SLEEP,
- SPELL_BACKLIGHT,
+ SPELL_HIBERNATION,
+ SPELL_CORONA,
SPELL_NO_SPELL, // end search
};
@@ -84,6 +85,7 @@ static spell_type search_order_third[] = {
SPELL_DEMONIC_HORDE,
SPELL_HASTE,
SPELL_SUMMON_UGLY_THING,
+ SPELL_SWIFTNESS,
SPELL_SUMMON_ICE_BEAST,
SPELL_ANIMATE_DEAD,
// 10
@@ -113,7 +115,7 @@ static spell_type search_order_misc[] = {
SPELL_TELEPORT_OTHER,
// 10
SPELL_DIG,
- SPELL_BACKLIGHT,
+ SPELL_CORONA,
SPELL_NO_SPELL, // end search
};
@@ -846,16 +848,13 @@ void ghost_demon::announce_ghost(const ghost_demon &g)
void ghost_demon::find_extra_ghosts( std::vector<ghost_demon> &gs, int n )
{
- for (int i = 0; n > 0 && i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- if (!menv[i].alive())
- continue;
-
- if (menv[i].type == MONS_PLAYER_GHOST && menv[i].ghost.get())
+ if (mi->type == MONS_PLAYER_GHOST && mi->ghost.get())
{
// Bingo!
- announce_ghost(*menv[i].ghost);
- gs.push_back(*menv[i].ghost);
+ announce_ghost(*(mi->ghost));
+ gs.push_back(*(mi->ghost));
--n;
}
}
diff --git a/crawl-ref/source/godabil.cc b/crawl-ref/source/godabil.cc
index 8bac2d4ee0..69986ec4be 100644
--- a/crawl-ref/source/godabil.cc
+++ b/crawl-ref/source/godabil.cc
@@ -23,8 +23,9 @@
#include "misc.h"
#include "mon-act.h"
#include "mon-behv.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-iter.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "mutation.h"
#include "options.h"
@@ -203,22 +204,21 @@ static bool _yred_enslaved_souls_on_level_disappear()
{
bool success = false;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
- if (_is_yred_enslaved_soul(monster))
+ if (_is_yred_enslaved_soul(*mi))
{
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Undead soul disappearing: %s on level %d, branch %d",
- monster->name(DESC_PLAIN).c_str(),
+ mi->name(DESC_PLAIN).c_str(),
static_cast<int>(you.your_level),
static_cast<int>(you.where_are_you));
#endif
- simple_monster_message(monster, " is freed.");
+ simple_monster_message(*mi, " is freed.");
// The monster disappears.
- monster_die(monster, KILL_DISMISSED, NON_MONSTER);
+ monster_die(*mi, KILL_DISMISSED, NON_MONSTER);
success = true;
}
@@ -386,6 +386,7 @@ int fungal_bloom()
const int mushroom = create_monster(
mgen_data(MONS_TOADSTOOL,
BEH_FRIENDLY,
+ &you,
0,
0,
pos,
@@ -458,6 +459,7 @@ static int _create_plant(coord_def & target)
const int plant = create_monster(mgen_data
(MONS_PLANT,
BEH_FRIENDLY,
+ &you,
0,
0,
target,
@@ -560,6 +562,7 @@ bool sunlight()
// Create a plant.
const int plant = create_monster(mgen_data(MONS_PLANT,
BEH_HOSTILE,
+ &you,
0,
0,
target,
@@ -876,6 +879,7 @@ int rain(const coord_def &target)
const int plant = create_monster(mgen_data
(coinflip() ? MONS_PLANT : MONS_FUNGUS,
BEH_GOOD_NEUTRAL,
+ &you,
0,
0,
*rad,
@@ -953,6 +957,7 @@ int corpse_spores(beh_type behavior)
int rc = create_monster(mgen_data(MONS_GIANT_SPORE,
behavior,
+ &you,
0,
0,
*rad,
diff --git a/crawl-ref/source/goditem.cc b/crawl-ref/source/goditem.cc
index f5c6e8976b..cfe29fcd8f 100644
--- a/crawl-ref/source/goditem.cc
+++ b/crawl-ref/source/goditem.cc
@@ -429,15 +429,23 @@ bool god_hates_rod(const item_def& item)
conduct_type good_god_hates_item_handling(const item_def &item)
{
- if (!is_good_god(you.religion) || !is_evil_item(item))
+ if (!is_good_god(you.religion)
+ || (!is_unholy_item(item) && !is_evil_item(item)))
+ {
return (DID_NOTHING);
+ }
+
+ if (item_type_known(item))
+ {
+ if (is_evil_item(item))
+ return (DID_NECROMANCY);
+ else
+ return (DID_UNHOLY);
+ }
if (is_demonic(item))
return (DID_UNHOLY);
- if (item_type_known(item))
- return (DID_NECROMANCY);
-
return (DID_NOTHING);
}
@@ -590,7 +598,7 @@ bool god_dislikes_spell_type(spell_type spell, god_type god)
// into a state where attacking them would be unchivalrous.
if (spell == SPELL_CAUSE_FEAR || spell == SPELL_PARALYSE
|| spell == SPELL_CONFUSE || spell == SPELL_MASS_CONFUSION
- || spell == SPELL_SLEEP || spell == SPELL_MASS_SLEEP)
+ || spell == SPELL_HIBERNATION || spell == SPELL_ENGLACIATION)
{
return (true);
}
diff --git a/crawl-ref/source/goditem.h b/crawl-ref/source/goditem.h
index e08c09b43b..f6e9e3caf0 100644
--- a/crawl-ref/source/goditem.h
+++ b/crawl-ref/source/goditem.h
@@ -16,6 +16,7 @@ bool is_unholy_item(const item_def& item);
bool is_potentially_evil_item(const item_def& item);
bool is_evil_item(const item_def& item);
bool is_chaotic_item(const item_def& item);
+bool is_hasty_item(const item_def& item);
bool is_holy_discipline(int discipline);
bool is_evil_discipline(int discipline);
bool is_holy_spell(spell_type spell, god_type god = GOD_NO_GOD);
diff --git a/crawl-ref/source/godwrath.cc b/crawl-ref/source/godwrath.cc
index d896de98c3..0408bb228c 100644
--- a/crawl-ref/source/godwrath.cc
+++ b/crawl-ref/source/godwrath.cc
@@ -22,8 +22,8 @@
#include "message.h"
#include "misc.h"
#include "mon-util.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mutation.h"
#include "ouch.h"
#include "quiver.h"
@@ -61,7 +61,8 @@ static bool _yred_random_zombified_hostile()
else
z_type = skel ? MONS_SKELETON_SMALL : MONS_ZOMBIE_SMALL;
- return (create_monster(mgen_data::hostile_at(z_type, true,
+ return (create_monster(mgen_data::hostile_at(z_type,
+ "the anger of Yredelemnul", true,
0, 0, you.pos(), 0, GOD_YREDELEMNUL, z_base)) != -1);
}
@@ -83,7 +84,7 @@ static bool _okawaru_random_servant()
: MONS_TITAN); // 5%
return (create_monster(
- mgen_data::hostile_at(mon_type,
+ mgen_data::hostile_at(mon_type, "the fury of Okawaru",
true, 0, 0, you.pos(), 0, GOD_OKAWARU)) != -1);
}
@@ -202,7 +203,7 @@ static bool _zin_retribution()
mon_pos = you.pos();
if (mons_place(
- mgen_data::hostile_at(mon,
+ mgen_data::hostile_at(mon, "the power of Zin",
true, 0, 0, mon_pos, 0, god)) != -1)
{
success = true;
@@ -234,7 +235,7 @@ static bool _zin_retribution()
confuse_player(3 + random2(10), false);
break;
case 1:
- you.put_to_sleep();
+ you.hibernate();
break;
case 2:
you.paralyse(NULL, 3 + random2(10));
@@ -372,7 +373,7 @@ static bool _cheibriados_retribution()
case 2:
case 3:
mpr("You lose track of time.");
- you.put_to_sleep();
+ you.hibernate();
break;
case 4:
@@ -400,6 +401,7 @@ static bool _makhleb_retribution()
mgen_data::hostile_at(
static_cast<monster_type>(
MONS_EXECUTIONER + random2(5)),
+ "the fury of Makhleb",
true, 0, 0, you.pos(), 0, god)) != -1);
simple_god_message(success ? " sends a greater servant after you!"
@@ -417,6 +419,7 @@ static bool _makhleb_retribution()
mgen_data::hostile_at(
static_cast<monster_type>(
MONS_NEQOXEC + random2(5)),
+ "the fury of Makhleb",
true, 0, 0, you.pos(), 0, god)) != -1)
{
count++;
@@ -445,6 +448,7 @@ static bool _kikubaaqudgha_retribution()
{
if (create_monster(
mgen_data::hostile_at(MONS_REAPER,
+ "the malice of Kikubaaqudgha",
true, 0, 0, you.pos(), 0, god)) != -1)
{
success = true;
@@ -646,6 +650,7 @@ static bool _beogh_retribution()
const int mon =
create_monster(
mgen_data::hostile_at(MONS_DANCING_WEAPON,
+ "the wrath of Beogh",
true, 0, 0, you.pos(), 0, god));
if (mon != -1)
@@ -724,6 +729,7 @@ static bool _beogh_retribution()
int mons = create_monster(
mgen_data::hostile_at(punisher,
+ "the wrath of Beogh",
true, 0, 0, you.pos(), MG_PERMIT_BANDS, god));
// sometimes name band leader
@@ -835,6 +841,7 @@ static bool _lugonu_retribution()
mgen_data::hostile_at(
static_cast<monster_type>(
MONS_GREEN_DEATH + random2(3)),
+ "the touch of Lugonu",
true, 0, 0, you.pos(), 0, god)) != -1);
simple_god_message(success ? " sends a demon after you!"
@@ -851,6 +858,7 @@ static bool _lugonu_retribution()
mgen_data::hostile_at(
static_cast<monster_type>(
MONS_NEQOXEC + random2(5)),
+ "the touch of Lugonu",
true, 0, 0, you.pos(), 0, god)) != -1)
{
success = true;
@@ -977,6 +985,7 @@ static bool _jiyva_retribution()
if (create_monster(
mgen_data::hostile_at(static_cast<monster_type>(slime),
+ "the vengence of Jiyva",
true, 0, 0, you.pos(), 0, god)) != -1)
{
success = true;
@@ -1043,12 +1052,14 @@ static bool _fedhas_retribution()
unsigned free_thresh = 30;
mgen_data temp(MONS_OKLOB_PLANT,
- BEH_HOSTILE, 0, 0,
+ BEH_HOSTILE, 0, 0, 0,
coord_def(),
MHITNOT,
MG_FORCE_PLACE,
GOD_FEDHAS);
+ temp.non_actor_summoner = "the enmity of Fedhas Madash";
+
// If we have a lot of space to work with (the circle with
// radius 6 is substantially unoccupied), we can do something
// flashy.
diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc
index 73b19f57a8..8c87b7bc41 100644
--- a/crawl-ref/source/hiscores.cc
+++ b/crawl-ref/source/hiscores.cc
@@ -499,6 +499,8 @@ void scorefile_entry::init_from(const scorefile_entry &se)
mon_num = se.mon_num;
death_source_name = se.death_source_name;
auxkilldata = se.auxkilldata;
+ indirectkiller = se.indirectkiller;
+ killerpath = se.killerpath;
dlvl = se.dlvl;
level_type = se.level_type;
branch = se.branch;
@@ -594,6 +596,8 @@ void scorefile_entry::init_with_fields()
death_type = str_to_kill_method(fields->str_field("ktyp"));
death_source_name = fields->str_field("killer");
auxkilldata = fields->str_field("kaux");
+ indirectkiller = fields->str_field("ikiller");
+ killerpath = fields->str_field("kpath");
branch = str_to_branch(fields->str_field("br"), BRANCH_MAIN_DUNGEON);
dlvl = fields->int_field("lvl");
@@ -713,6 +717,8 @@ void scorefile_entry::set_score_fields() const
fields->add_field("dam", "%d", damage);
fields->add_field("kaux", "%s", auxkilldata.c_str());
+ fields->add_field("ikiller", "%s", indirectkiller.c_str());
+ fields->add_field("kpath", "%s", killerpath.c_str());
if (piety > 0)
fields->add_field("piety", "%d", piety);
@@ -837,11 +843,33 @@ void scorefile_entry::init_death_cause(int dam, int dsrc,
death_source_name += " (shapeshifter)";
else if (monster->has_ench(ENCH_GLOWING_SHAPESHIFTER))
death_source_name += " (glowing shapeshifter)";
+
+ if (monster->props.exists("blame"))
+ {
+ const CrawlVector& blame = monster->props["blame"].get_vector();
+
+ indirectkiller = blame[blame.size() - 1].get_string();
+ killerpath = "";
+
+ for (CrawlVector::const_iterator it = blame.begin();
+ it != blame.end(); ++it)
+ {
+ killerpath = killerpath + ":" + xlog_escape(it->get_string());
+ }
+
+ killerpath.erase(killerpath.begin());
+ }
+ else
+ {
+ indirectkiller = death_source_name;
+ killerpath = "";
+ }
}
else
{
mon_num = 0;
death_source_name.clear();
+ indirectkiller = killerpath = "";
}
if (death_type == KILLED_BY_WEAKNESS
@@ -871,6 +899,8 @@ void scorefile_entry::reset()
mon_num = 0;
death_source_name.clear();
auxkilldata.clear();
+ indirectkiller.clear();
+ killerpath.clear();
dlvl = 0;
level_type = LEVEL_DUNGEON;
branch = BRANCH_MAIN_DUNGEON;
@@ -1850,6 +1880,9 @@ std::string scorefile_entry::death_description(death_desc_verbosity verbosity)
else if (needs_called_by_monster_line)
desc += death_source_name;
+ if (!killerpath.empty())
+ desc += "[" + indirectkiller + "]";
+
if (needs_damage && damage > 0)
desc += " " + damage_string(true);
}
@@ -1932,6 +1965,31 @@ std::string scorefile_entry::death_description(death_desc_verbosity verbosity)
needs_damage = true;
}
+ if (!killerpath.empty())
+ {
+ std::vector<std::string> summoners
+ = xlog_split_fields(killerpath);
+
+ for (std::vector<std::string>::iterator it = summoners.begin();
+ it != summoners.end(); ++it)
+ {
+ if (!semiverbose)
+ {
+ desc += "... summoned by " + *it;
+ desc += _hiscore_newline_string();
+ }
+ else
+ {
+ desc += " (summoned by " + *it;
+ }
+ }
+
+ if (semiverbose)
+ {
+ desc += std::string(summoners.size(), ')');
+ }
+ }
+
if (!semiverbose)
{
if (needs_damage && !done_damage && damage > 0)
@@ -1989,23 +2047,23 @@ xlog_fields::xlog_fields(const std::string &line) : fields(), fieldmap()
init(line);
}
-std::string::size_type
-xlog_fields::next_separator(const std::string &s,
- std::string::size_type start) const
+static std::string::size_type
+_xlog_next_separator(const std::string &s,
+ std::string::size_type start)
{
std::string::size_type p = s.find(':', start);
if (p != std::string::npos && p < s.length() - 1 && s[p + 1] == ':')
- return next_separator(s, p + 2);
+ return _xlog_next_separator(s, p + 2);
return (p);
}
-std::vector<std::string> xlog_fields::split_fields(const std::string &s) const
+std::vector<std::string> xlog_split_fields(const std::string &s)
{
std::string::size_type start = 0, end = 0;
std::vector<std::string> fs;
- for ( ; (end = next_separator(s, start)) != std::string::npos;
+ for ( ; (end = _xlog_next_separator(s, start)) != std::string::npos;
start = end + 1 )
{
fs.push_back( s.substr(start, end - start) );
@@ -2019,7 +2077,7 @@ std::vector<std::string> xlog_fields::split_fields(const std::string &s) const
void xlog_fields::init(const std::string &line)
{
- std::vector<std::string> rawfields = split_fields(line);
+ std::vector<std::string> rawfields = xlog_split_fields(line);
for (int i = 0, size = rawfields.size(); i < size; ++i)
{
const std::string field = rawfields[i];
@@ -2037,13 +2095,13 @@ void xlog_fields::init(const std::string &line)
}
// xlogfile escape: s/:/::/g
-std::string xlog_fields::xlog_escape(const std::string &s) const
+std::string xlog_escape(const std::string &s)
{
return replace_all(s, ":", "::");
}
// xlogfile unescape: s/::/:/g
-std::string xlog_fields::xlog_unescape(const std::string &s) const
+std::string xlog_unescape(const std::string &s)
{
return replace_all(s, "::", ":");
}
diff --git a/crawl-ref/source/hiscores.h b/crawl-ref/source/hiscores.h
index f2b4fd53a4..2fc108c37d 100644
--- a/crawl-ref/source/hiscores.h
+++ b/crawl-ref/source/hiscores.h
@@ -29,6 +29,11 @@ void mark_milestone(const std::string &type, const std::string &milestone);
std::string xlog_status_line();
#endif
+std::string xlog_unescape(const std::string &);
+std::string xlog_escape(const std::string &);
+
+std::vector<std::string> xlog_split_fields(const std::string &s);
+
class xlog_fields
{
public:
@@ -46,12 +51,7 @@ public:
long long_field(const std::string &) const;
private:
- std::string xlog_unescape(const std::string &) const;
- std::string xlog_escape(const std::string &) const;
void map_fields() const;
- std::string::size_type next_separator(const std::string &s,
- std::string::size_type start) const;
- std::vector<std::string> split_fields(const std::string &s) const;
private:
typedef std::vector< std::pair<std::string, std::string> > xl_fields;
@@ -79,6 +79,8 @@ public:
int mon_num; // sigh...
std::string death_source_name; // overrides death_source
std::string auxkilldata; // weapon wielded, spell cast, etc
+ std::string indirectkiller; // the effect or real monster that summoned
+ std::string killerpath; // colon-separated intermediate killers
char dlvl; // dungeon level (relative)
level_area_type level_type; // what kind of level died on..
branch_type branch; // dungeon branch
diff --git a/crawl-ref/source/it_use2.cc b/crawl-ref/source/it_use2.cc
index b8cee7b101..bbe84c93e7 100644
--- a/crawl-ref/source/it_use2.cc
+++ b/crawl-ref/source/it_use2.cc
@@ -304,7 +304,7 @@ bool potion_effect(potion_type pot_eff, int pow, bool drank_it, bool was_known)
// And also cancel backlight (for whatever good that will
// do).
- you.duration[DUR_BACKLIGHT] = 0;
+ you.duration[DUR_CORONA] = 0;
return (true);
}
@@ -324,7 +324,7 @@ bool potion_effect(potion_type pot_eff, int pow, bool drank_it, bool was_known)
}
// Invisibility cancels backlight.
- you.duration[DUR_BACKLIGHT] = 0;
+ you.duration[DUR_CORONA] = 0;
// Now multiple invisiblity casts aren't as good. -- bwr
if (!you.duration[DUR_INVIS])
diff --git a/crawl-ref/source/it_use3.cc b/crawl-ref/source/it_use3.cc
index f36bae0148..d1bfd030c6 100644
--- a/crawl-ref/source/it_use3.cc
+++ b/crawl-ref/source/it_use3.cc
@@ -30,7 +30,7 @@
#include "itemprop.h"
#include "mapmark.h"
#include "message.h"
-#include "monplace.h"
+#include "mon-place.h"
#include "misc.h"
#include "player.h"
#include "religion.h"
@@ -145,8 +145,8 @@ void shadow_lantern_effect()
{
if (x_chance_in_y(player_spec_death() + 1, 8))
{
- create_monster(mgen_data(MONS_SHADOW, BEH_FRIENDLY, 2, 0, you.pos(),
- MHITYOU));
+ create_monster(mgen_data(MONS_SHADOW, BEH_FRIENDLY, &you, 2, 0,
+ you.pos(), MHITYOU));
item_def *lantern = you.weapon();
@@ -336,7 +336,7 @@ static bool evoke_horn_of_geryon()
{
mpr("You produce a hideous howling noise!", MSGCH_SOUND);
create_monster(
- mgen_data::hostile_at(MONS_BEAST,
+ mgen_data::hostile_at(MONS_BEAST, "the horn of Geryon",
true, 4, 0, you.pos()));
}
return (rc);
@@ -352,7 +352,7 @@ static bool _efreet_flask(int slot)
create_monster(
mgen_data(MONS_EFREET,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
- 0, 0, you.pos(),
+ &you, 0, 0, you.pos(),
MHITYOU, MG_FORCE_BEH));
if (monster != -1)
@@ -530,6 +530,7 @@ void tome_of_power(int slot)
{
if (create_monster(
mgen_data::hostile_at(MONS_ABOMINATION_SMALL,
+ "a tome of Destruction",
true, 6, 0, you.pos())) != -1)
{
mpr("A horrible Thing appears!");
@@ -630,7 +631,7 @@ static bool _box_of_beasts(item_def &box)
beha = BEH_HOSTILE;
if (create_monster(
- mgen_data(beasty, beha, 2 + random2(4), 0,
+ mgen_data(beasty, beha, &you, 2 + random2(4), 0,
you.pos(), MHITYOU)) != -1)
{
success = true;
diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc
index 8214497c93..e9a0160bea 100644
--- a/crawl-ref/source/item_use.cc
+++ b/crawl-ref/source/item_use.cc
@@ -45,8 +45,8 @@
#include "misc.h"
#include "mon-behv.h"
#include "mon-util.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "notes.h"
#include "options.h"
#include "ouch.h"
@@ -519,10 +519,14 @@ void wield_effects(int item_wield_2, bool showMsgs)
{
if (is_holy_item(item) && you.religion == GOD_YREDELEMNUL)
mpr("You really shouldn't be using a holy item like this.");
+ else if (is_unholy_item(item) && is_good_god(you.religion))
+ mpr("You really shouldn't be using an unholy item like this.");
else if (is_evil_item(item) && is_good_god(you.religion))
mpr("You really shouldn't be using an evil item like this.");
else if (is_chaotic_item(item) && you.religion == GOD_ZIN)
mpr("You really shouldn't be using a chaotic item like this.");
+ else if (is_hasty_item(item) && you.religion == GOD_CHEIBRIADOS)
+ mpr("You really shouldn't be using a fast item like this.");
}
// Call unrandrt equip func before item is identified.
@@ -1790,8 +1794,8 @@ static bool _reaping_hit_victim(bolt& beam, actor* victim, int dmg, int corpse)
}
int midx = NON_MONSTER;
- if (animate_remains(victim->pos(), CORPSE_BODY, beh, hitting, GOD_NO_GOD,
- true, true, true, &midx) <= 0)
+ if (animate_remains(victim->pos(), CORPSE_BODY, beh, hitting, agent, "",
+ GOD_NO_GOD, true, true, true, &midx) <= 0)
{
return (false);
}
@@ -1894,6 +1898,60 @@ static bool _dispersal_hit_victim(bolt& beam, actor* victim, int dmg,
return (true);
}
+static bool _electricity_water_explosion(const bolt &beam, const actor *victim,
+ int &used)
+{
+ used = 1000;
+
+ ASSERT(!beam.is_tracer);
+ if (you.can_see(victim))
+ mpr("Electricity arcs through the water!");
+ conduct_electricity(victim->pos(), beam.agent());
+
+ return (true);
+}
+
+static bool _charged_hit_victim(bolt &beam, actor* victim, int &dmg,
+ std::string &dmg_msg)
+{
+ if (victim->airborne() || victim->res_elec() > 0 || !one_chance_in(3))
+ return (false);
+
+ dmg += 10 + random2(15);
+
+ if (beam.is_tracer)
+ return (false);
+
+ if (you.can_see(victim))
+ if (victim->atype() == ACT_PLAYER)
+ dmg_msg = "You are electrocuted!";
+ else
+ dmg_msg = "There is a sudden explosion of sparks!";
+
+ if (feat_is_water(grd(victim->pos())))
+ {
+ beam.range_funcs.insert(beam.range_funcs.begin(),
+ _electricity_water_explosion);
+ }
+
+ return (false);
+}
+
+static bool _blessed_hit_victim(bolt &beam, actor* victim, int &dmg,
+ std::string &dmg_msg)
+{
+ if (victim->undead_or_demonic())
+ {
+ dmg += 1 + (random2(dmg * 15) / 10);
+
+ if (!beam.is_tracer && you.can_see(victim))
+ dmg_msg = victim->name(DESC_CAP_THE) + " "
+ + victim->conj_verb("convulse") + "!";
+ }
+
+ return (false);
+}
+
bool setup_missile_beam(const actor *agent, bolt &beam, item_def &item,
std::string &ammo_name, bool &returning)
{
@@ -1992,7 +2050,11 @@ bool setup_missile_beam(const actor *agent, bolt &beam, item_def &item,
const bool silver = (ammo_brand == SPMSL_SILVER);
const bool disperses = (ammo_brand == SPMSL_DISPERSAL);
const bool reaping = (bow_brand == SPWPN_REAPING
- || ammo_brand == SPMSL_REAPING);
+ || ammo_brand == SPMSL_REAPING)
+ && bow_brand != SPWPN_HOLY_WRATH;
+ const bool charged = bow_brand == SPWPN_ELECTROCUTION;
+ const bool blessed = bow_brand == SPWPN_HOLY_WRATH
+ && ammo_brand != SPMSL_REAPING;
ASSERT(!exploding || !is_artefact(item));
@@ -2061,6 +2123,10 @@ bool setup_missile_beam(const actor *agent, bolt &beam, item_def &item,
beam.hit_funcs.push_back(_reaping_hit_victim);
if (disperses)
beam.hit_funcs.push_back(_dispersal_hit_victim);
+ if (charged)
+ beam.damage_funcs.push_back(_charged_hit_victim);
+ if (blessed)
+ beam.damage_funcs.push_back(_blessed_hit_victim);
if (reaping && ammo.special != SPMSL_REAPING)
{
@@ -2092,6 +2158,18 @@ bool setup_missile_beam(const actor *agent, bolt &beam, item_def &item,
ammo_name = "silvery " + ammo_name;
}
+ if (charged)
+ {
+ beam.name = "charged " + beam.name;
+ ammo_name = "charged " + ammo_name;
+ }
+
+ if (blessed)
+ {
+ beam.name = "blessed " + beam.name;
+ ammo_name = "blessed " + ammo_name;
+ }
+
// Do this here so that we get all the name mods except for a
// redundant "exploding".
if (exploding)
@@ -4987,11 +5065,12 @@ static void _vulnerability_scroll()
const enchant_type lost_enchantments[] = {
ENCH_SLOW,
ENCH_HASTE,
+ ENCH_SWIFT,
ENCH_MIGHT,
ENCH_FEAR,
ENCH_CONFUSION,
ENCH_INVIS,
- ENCH_BACKLIGHT,
+ ENCH_CORONA,
ENCH_CHARM,
ENCH_PARALYSIS,
ENCH_PETRIFYING,
@@ -5183,7 +5262,7 @@ void read_scroll(int slot)
{
const int monster = create_monster(
mgen_data(MONS_ABOMINATION_SMALL, BEH_FRIENDLY,
- 0, 0, you.pos(), MHITYOU,
+ &you, 0, 0, you.pos(), MHITYOU,
MG_FORCE_BEH));
if (monster != -1)
{
diff --git a/crawl-ref/source/itemname.cc b/crawl-ref/source/itemname.cc
index 16adb7a234..5de5f16256 100644
--- a/crawl-ref/source/itemname.cc
+++ b/crawl-ref/source/itemname.cc
@@ -1637,9 +1637,14 @@ std::string item_def::name_aux(description_level_type desc,
if (food_is_rotten(*this) && !dbname)
buff << "rotting ";
- const std::string _name = get_corpse_name(*this);
+ unsigned long name_type;
+
+ const std::string _name = get_corpse_name(*this, &name_type);
const bool shaped = starts_with(_name, "shaped ");
+ if (!_name.empty() && name_type == MF_NAME_ADJECTIVE)
+ buff << _name << " ";
+
if (!dbname && !starts_with(_name, "the "))
{
buff << mons_type_name(it_plus, DESC_PLAIN) << ' ';
@@ -1655,8 +1660,13 @@ std::string item_def::name_aux(description_level_type desc,
else
buff << "corpse bug";
- if (!_name.empty() && !shaped)
- buff << " of " << _name;
+ if (!_name.empty() && !shaped && name_type != MF_NAME_ADJECTIVE)
+ {
+ if (name_type == MF_NAME_SUFFIX)
+ buff << " " << _name;
+ else
+ buff << " of " << _name;
+ }
break;
}
@@ -3065,12 +3075,18 @@ bool is_named_corpse(const item_def &corpse)
return (corpse.props.exists(CORPSE_NAME_KEY));
}
-std::string get_corpse_name(const item_def &corpse)
+std::string get_corpse_name(const item_def &corpse, unsigned long *name_type)
{
ASSERT(corpse.base_type == OBJ_CORPSES);
if (!corpse.props.exists(CORPSE_NAME_KEY))
return ("");
+ if (name_type != NULL)
+ {
+ *name_type
+ = (unsigned long) corpse.props[CORPSE_NAME_TYPE_KEY].get_long();
+ }
+
return (corpse.props[CORPSE_NAME_KEY].get_string());
}
diff --git a/crawl-ref/source/itemname.h b/crawl-ref/source/itemname.h
index 731c7b7443..271bf2d340 100644
--- a/crawl-ref/source/itemname.h
+++ b/crawl-ref/source/itemname.h
@@ -10,7 +10,8 @@
#include "externs.h"
-#define CORPSE_NAME_KEY "corpse_name_key"
+#define CORPSE_NAME_KEY "corpse_name_key"
+#define CORPSE_NAME_TYPE_KEY "corpse_name_type_key"
struct item_types_pair
{
@@ -126,6 +127,7 @@ std::vector<std::string> item_name_list_for_glyph(unsigned glyph);
const char* wand_type_name(int wandtype);
bool is_named_corpse(const item_def &corpse);
-std::string get_corpse_name(const item_def &corpse);
+std::string get_corpse_name(const item_def &corpse,
+ unsigned long *name_type = NULL);
#endif
diff --git a/crawl-ref/source/itemprop.cc b/crawl-ref/source/itemprop.cc
index 565827c41c..20acaf45aa 100644
--- a/crawl-ref/source/itemprop.cc
+++ b/crawl-ref/source/itemprop.cc
@@ -27,7 +27,7 @@
#include "itemprop.h"
#include "macro.h"
#include "mon-util.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "notes.h"
#include "player.h"
#include "quiver.h"
@@ -485,7 +485,7 @@ void do_curse_item( item_def &item, bool quiet )
{
if (!quiet)
{
- mprf("Your %s glows black briefly, but repels the curse",
+ mprf("Your %s glows black briefly, but repels the curse.",
item.name(DESC_PLAIN).c_str());
}
return;
diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc
index 625dafd11d..2e366841c7 100644
--- a/crawl-ref/source/items.cc
+++ b/crawl-ref/source/items.cc
@@ -43,8 +43,8 @@
#include "libutil.h"
#include "message.h"
#include "misc.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "mutation.h"
#include "notes.h"
diff --git a/crawl-ref/source/kills.cc b/crawl-ref/source/kills.cc
index 589a9b3972..6857c3d82c 100644
--- a/crawl-ref/source/kills.cc
+++ b/crawl-ref/source/kills.cc
@@ -10,7 +10,7 @@
#include "describe.h"
#include "mon-util.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "files.h"
#include "ghost.h"
#include "place.h"
diff --git a/crawl-ref/source/l_defs.h b/crawl-ref/source/l_defs.h
index 641af4a117..8d0974a918 100644
--- a/crawl-ref/source/l_defs.h
+++ b/crawl-ref/source/l_defs.h
@@ -14,6 +14,7 @@ const char *dungeon_feature_name(dungeon_feature_type feat);
std::string dgn_set_default_depth(const std::string &s);
void dgn_reset_default_depth();
bool in_show_bounds(const coord_def &c);
+coord_def player2grid(const coord_def &p);
#endif
diff --git a/crawl-ref/source/l_dgnmon.cc b/crawl-ref/source/l_dgnmon.cc
index 4b8a7bc5ba..7c37b6bdb0 100644
--- a/crawl-ref/source/l_dgnmon.cc
+++ b/crawl-ref/source/l_dgnmon.cc
@@ -11,8 +11,8 @@
#include "dungeon.h"
#include "mapdef.h"
#include "mon-util.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#define MONSLIST_METATABLE "crawldgn.monster_list"
diff --git a/crawl-ref/source/l_libs.h b/crawl-ref/source/l_libs.h
index ecbecd12ba..a97eb7dc75 100644
--- a/crawl-ref/source/l_libs.h
+++ b/crawl-ref/source/l_libs.h
@@ -19,6 +19,7 @@ void cluaopen_item(lua_State *ls);
void cluaopen_kills(lua_State *ls); // defined in kills.cc
void cluaopen_moninf(lua_State *ls);
void cluaopen_options(lua_State *ls);
+void cluaopen_travel(lua_State *ls);
void cluaopen_view(lua_State *ls);
void cluaopen_you(lua_State *ls);
diff --git a/crawl-ref/source/l_mons.cc b/crawl-ref/source/l_mons.cc
index 8ace3eb119..5f9defaf6c 100644
--- a/crawl-ref/source/l_mons.cc
+++ b/crawl-ref/source/l_mons.cc
@@ -5,7 +5,7 @@
#include "delay.h"
#include "mon-util.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
/////////////////////////////////////////////////////////////////////
// Monster handling
@@ -39,6 +39,26 @@ void push_monster(lua_State *ls, monsters *mons)
MDEF(name)
{
+ PLUARET(string, mons->name(DESC_PLAIN, true).c_str());
+}
+
+MDEF(base_name)
+{
+ PLUARET(string, mons->base_name(DESC_PLAIN, true).c_str());
+}
+
+MDEF(full_name)
+{
+ PLUARET(string, mons->full_name(DESC_PLAIN, true).c_str());
+}
+
+MDEF(db_name)
+{
+ PLUARET(string, mons->name(DESC_DBNAME, true).c_str());
+}
+
+MDEF(type_name)
+{
PLUARET(string, mons_type_name(mons->type, DESC_PLAIN).c_str());
}
@@ -145,14 +165,20 @@ struct MonsAccessor
static MonsAccessor mons_attrs[] =
{
- { "name", l_mons_name },
+ { "name", l_mons_name },
+ { "base_name", l_mons_base_name },
+ { "full_name", l_mons_full_name },
+ { "db_name", l_mons_db_name },
+ { "type_name", l_mons_type_name },
+
{ "x" , l_mons_x },
{ "y" , l_mons_y },
{ "hd" , l_mons_hd },
{ "muse", l_mons_muse },
{ "meat", l_mons_meat },
- { "dismiss", l_mons_dismiss },
- { "experience", l_mons_experience },
+
+ { "dismiss", l_mons_dismiss },
+ { "experience", l_mons_experience },
{ "random_teleport", l_mons_random_teleport }
};
diff --git a/crawl-ref/source/l_travel.cc b/crawl-ref/source/l_travel.cc
new file mode 100644
index 0000000000..8c32d65812
--- /dev/null
+++ b/crawl-ref/source/l_travel.cc
@@ -0,0 +1,54 @@
+/*
+ * File: l_travel.cc
+ * Summary: Travel and exclusions.
+ */
+
+#include "AppHdr.h"
+
+#include "l_libs.h"
+#include "l_defs.h"
+
+#include "cluautil.h"
+#include "coord.h"
+#include "exclude.h"
+#include "player.h"
+
+LUAFN(l_set_exclude)
+{
+ coord_def s;
+ s.x = luaL_checkint(ls, 1);
+ s.y = luaL_checkint(ls, 2);
+ const coord_def p = player2grid(s);
+ if (!in_bounds(p))
+ return (0);
+ int r = LOS_MAX_RADIUS;
+ if (lua_gettop(ls) > 2)
+ r = luaL_checkint(ls, 3);
+ set_exclude(p, r);
+ return (0);
+}
+
+LUAFN(l_del_exclude)
+{
+ coord_def s;
+ s.x = luaL_checkint(ls, 1);
+ s.y = luaL_checkint(ls, 2);
+ const coord_def p = player2grid(s);
+ if (!in_bounds(p))
+ return (0);
+ del_exclude(p);
+ return (0);
+}
+
+static const struct luaL_reg travel_lib[] =
+{
+ { "set_exclude", l_set_exclude },
+ { "del_exclude", l_del_exclude },
+
+ { NULL, NULL }
+};
+
+void cluaopen_travel(lua_State *ls)
+{
+ luaL_openlib(ls, "travel", travel_lib, 0);
+}
diff --git a/crawl-ref/source/lev-pand.cc b/crawl-ref/source/lev-pand.cc
index 827e753cd1..a772d6e3d6 100644
--- a/crawl-ref/source/lev-pand.cc
+++ b/crawl-ref/source/lev-pand.cc
@@ -12,7 +12,7 @@
#include "externs.h"
#include "dungeon.h"
-#include "monplace.h"
+#include "mon-place.h"
#include "mon-pick.h"
#include "random.h"
diff --git a/crawl-ref/source/makefile b/crawl-ref/source/makefile
index 2adc7a79ae..7f2819dd74 100644
--- a/crawl-ref/source/makefile
+++ b/crawl-ref/source/makefile
@@ -663,15 +663,11 @@ LIBS += $(CONTRIB_LIBS) $(EXTRA_LIBS)
GAME_DEPENDS := $(DESTTILEFILES) $(OBJECTS) $(EXTRA_OBJECTS) $(CONTRIB_LIBS)
SRC_PKG_BASE := stone_soup
SRC_VERSION := $(shell git describe --tags --long)
-PKG_SRC_DIR := $(SRC_PKG_BASE)-$(SRC_VERSION)-src
-SRC_PKG_TAR := $(PKG_SRC_DIR).tbz2
+PKG_SRC_DIR := $(SRC_PKG_BASE)-$(SRC_VERSION)
+SRC_PKG_TAR := $(PKG_SRC_DIR).tar.bz2
SRC_PKG_ZIP := $(PKG_SRC_DIR).zip
-PKG_TIDY_LIST := $(UTIL)*.o $(LEVCOMP) *.o \
- $(UTIL)*.tab.cc $(UTIL)*.tab.h $(UTIL)*.lex.cc *.ixx
-PKG_EXCLUDES := $(PWD)/misc/src-pkg-excludes.lst
-
-.PHONY: all test install clean clean-contrib distclean debug profile wizard
+.PHONY: all test install clean clean-contrib distclean debug profile wizard package-source
all: $(GAME)
@@ -707,7 +703,7 @@ DEPS := $(OBJECTS:.o=.d)
ifeq ($(shell which fastdep 2> /dev/null),)
DEPEND := $(CXX) -MM $(ALL_CFLAGS)
else
-DEPEND := fastdep $(DEFINES) $(INCLUDES)
+DEPEND := fastdep $(DEFINES) $(DEFINES_L) $(INCLUDES) $(INCLUDES_L)
endif
%.d: %.cc .cflags
@@ -901,32 +897,26 @@ clean-rltiles:
#
# To package, you *must* have lex and yacc to generate the intermediates.
-package-source:
- +$(MAKE) distclean
- +$(MAKE) prebuildyacc
- +$(MAKE) pkgtidy
- +$(MAKE) depend
- +$(MAKE) removeold
- +$(MAKE) vlink
- +$(MAKE) pkgtarbz2
- +$(MAKE) pkgzip
-
-pkgtidy:
- $(RM) $(PKG_TIDY_LIST)
+BSRC = build/crawl-ref/source/
+package-source: prebuildyacc depend removeold
+ rm -rf build
+ mkdir build
+ (cd ../..;git ls-files| \
+ grep -v -f crawl-ref/source/misc/src-pkg-excludes.lst| \
+ tar cf - -T -)|tar xf - -C build
+ cp -p *.d $(BSRC)
+ for x in lua pcre sqlite; \
+ do \
+ mkdir -p $(BSRC)contrib/$$x; \
+ (cd contrib/$$x;git ls-files|tar cf - -T -)| \
+ tar xf - -C $(BSRC)contrib/$$x; \
+ done
+ find build -name .gitignore -execdir rm -f '{}' +
+ cd build && mv crawl-ref $(PKG_SRC_DIR)
+ cd build && tar cfj ../../../$(SRC_PKG_TAR) $(PKG_SRC_DIR)
+ cd build && zip -rq ../../../$(SRC_PKG_ZIP) $(PKG_SRC_DIR)
+ rm -rf build
removeold:
if [ -f ../../$(SRC_PKG_TAR) ]; then $(RM) ../../$(SRC_PKG_TAR); fi
if [ -f ../../$(SRC_PKG_ZIP) ]; then $(RM) ../../$(SRC_PKG_ZIP); fi
-
-# [ds] Existing directory names could produce a bad package!
-vlink:
- cd .. && WHERE=$$PWD && cd .. && \
- ( [ -e $(PKG_SRC_DIR) ] || ln -sf $$WHERE $(PKG_SRC_DIR) )
-
-pkgtarbz2:
- cd ../.. && tar -ch --bzip2 -f $(SRC_PKG_TAR) \
- -X $(PKG_EXCLUDES) $(PKG_SRC_DIR)
-
-pkgzip:
- cd ../.. && zip -rq $(SRC_PKG_ZIP) $(PKG_SRC_DIR) \
- -x@$(PKG_EXCLUDES)
diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj
index c85450cd5f..03fe8f2bd3 100644
--- a/crawl-ref/source/makefile.obj
+++ b/crawl-ref/source/makefile.obj
@@ -79,6 +79,7 @@ l_mapmrk.o \
l_moninf.o \
l_mons.o \
l_option.o \
+l_travel.o \
l_view.o \
l_you.o \
lev-pand.o \
@@ -103,12 +104,13 @@ mon-behv.o \
mon-cast.o \
mon-gear.o \
mon-info.o \
+mon-iter.o \
mon-pick.o \
mon-util.o \
-monplace.o \
-monspeak.o \
+mon-place.o \
+mon-speak.o \
monster.o \
-monstuff.o \
+mon-stuff.o \
mt19937ar.o \
mtransit.o \
mutation.o \
diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc
index 332187dd4e..645685ac06 100644
--- a/crawl-ref/source/makeitem.cc
+++ b/crawl-ref/source/makeitem.cc
@@ -1437,6 +1437,9 @@ static brand_type _determine_weapon_brand(const item_def& item, int item_level)
rc = SPWPN_VORPAL;
else
rc = SPWPN_SPEED;
+ if (item.sub_type == WPN_HAND_CROSSBOW || item.sub_type == WPN_CROSSBOW)
+ if (one_chance_in(5))
+ rc = SPWPN_ELECTROCUTION;
break;
}
@@ -1552,12 +1555,12 @@ bool is_weapon_brand_ok(int type, int brand)
case SPWPN_VORPAL:
case SPWPN_CHAOS:
case SPWPN_REAPING:
+ case SPWPN_HOLY_WRATH:
+ case SPWPN_ELECTROCUTION:
break;
// Melee-only brands.
case SPWPN_FLAMING:
case SPWPN_FREEZING:
- case SPWPN_HOLY_WRATH:
- case SPWPN_ELECTROCUTION:
case SPWPN_ORC_SLAYING:
case SPWPN_DRAGON_SLAYING:
case SPWPN_DRAINING:
@@ -2246,12 +2249,9 @@ bool is_armour_brand_ok(int type, int brand)
case SPARM_STEALTH:
return (slot == EQ_BOOTS);
- case SPARM_RESISTANCE:
- if (slot == EQ_SHIELD)
- return (true);
case SPARM_ARCHMAGI:
- if (type != ARM_ROBE)
- return (false);
+ return (type == ARM_ROBE);
+
case SPARM_PONDEROUSNESS:
return (slot == EQ_BODY_ARMOUR);
@@ -2269,25 +2269,20 @@ bool is_armour_brand_ok(int type, int brand)
return (slot == EQ_GLOVES);
case SPARM_SEE_INVISIBLE:
- if (type == ARM_WIZARD_HAT)
- return (false);
case SPARM_INTELLIGENCE:
return (slot == EQ_HELMET);
case SPARM_FIRE_RESISTANCE:
case SPARM_COLD_RESISTANCE:
- if (slot == EQ_BOOTS && type != ARM_BOOTS) // both bardings
+ case SPARM_RESISTANCE:
+ return (true); // in portal vaults, these can happen on every slot
+
+ case SPARM_MAGIC_RESISTANCE:
+ if (type == ARM_WIZARD_HAT)
return (true);
case SPARM_POISON_RESISTANCE:
- case SPARM_MAGIC_RESISTANCE:
case SPARM_POSITIVE_ENERGY:
- if (brand == SPARM_POISON_RESISTANCE && slot == EQ_CLOAK)
- return (true);
- if (brand == SPARM_MAGIC_RESISTANCE && slot == EQ_CLOAK)
- return (true);
- if (brand == SPARM_MAGIC_RESISTANCE && type == ARM_WIZARD_HAT)
- return (true);
- return (slot == EQ_BODY_ARMOUR || slot == EQ_SHIELD);
+ return (slot == EQ_BODY_ARMOUR || slot == EQ_SHIELD || slot == EQ_CLOAK);
case SPARM_SPIRIT_SHIELD:
return (type == ARM_CAP || slot == EQ_SHIELD);
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index a9bff3cf52..ebafae76e2 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -31,7 +31,7 @@
#include "maps.h"
#include "misc.h"
#include "mon-cast.h"
-#include "monplace.h"
+#include "mon-place.h"
#include "mon-util.h"
#include "place.h"
#include "random.h"
@@ -1784,6 +1784,78 @@ std::string map_def::rewrite_chunk_errors(const std::string &s) const
return (res);
}
+std::string map_def::validate_temple_map()
+{
+ std::vector<coord_def> altars = find_glyph('B');
+
+ if (has_tag_prefix("temple_overflow_"))
+ {
+ std::vector<std::string> tag_list = get_tags();
+ std::string temple_tag;
+
+ for (unsigned int i = 0; i < tag_list.size(); i++)
+ {
+ if (starts_with(tag_list[i], "temple_overflow_"))
+ {
+ temple_tag = tag_list[i];
+ break;
+ }
+ }
+
+ if (temple_tag.empty())
+ return make_stringf("Unkown temple tag.");
+
+ temple_tag = strip_tag_prefix(temple_tag, "temple_overflow_");
+
+ if (temple_tag.empty())
+ return ("Malformed temple_overflow_ tag");
+
+ int num = atoi(temple_tag.c_str());
+
+ if (num == 0)
+ {
+ temple_tag = replace_all(temple_tag, "_", " ");
+
+ god_type god = string_to_god(temple_tag.c_str(), true);
+
+ if (god == GOD_NO_GOD)
+ {
+ return make_stringf("Invalid god name '%s'",
+ temple_tag.c_str());
+ }
+
+ // Assume that specialized single-god temples are set up
+ // properly.
+ return("");
+ }
+ else
+ {
+ if ( ( (unsigned long) num ) != altars.size() )
+ {
+ return make_stringf("Temple should contain %lu altars, but "
+ "has %d.", altars.size(), num);
+ }
+ }
+ }
+
+ if (altars.empty())
+ return ("Temple vault must contain at least one altar.");
+
+ // TODO: check for substitutions and shuffles
+
+ keyed_mapspec *spec = mapspec_for_key('B');
+
+ if (spec != NULL && spec->feat.feats.size() > 0)
+ return ("Can't change feat 'B' in temple (KFEAT)");
+
+ std::vector<god_type> god_list = temple_god_list();
+
+ if (altars.size() > god_list.size())
+ return ("Temple vault has too many altars");
+
+ return ("");
+}
+
std::string map_def::validate_map_def()
{
std::string err = run_lua(true);
@@ -1794,6 +1866,15 @@ std::string map_def::validate_map_def()
resolve();
test_lua_validate(true);
+ if ((place.branch == BRANCH_ECUMENICAL_TEMPLE
+ && place.level_type == LEVEL_DUNGEON)
+ || has_tag_prefix("temple_overflow_"))
+ {
+ err = validate_temple_map();
+ if (!err.empty())
+ return err;
+ }
+
if (orient == MAP_FLOAT || is_minivault())
{
if (map.width() > GXM - MAPGEN_BORDER * 2
@@ -2991,6 +3072,8 @@ static int str_to_ego(item_spec &spec, std::string ego_str)
"archmagi",
"preservation",
"reflection",
+ "spirit shield",
+ "archery",
NULL
};
@@ -3015,6 +3098,8 @@ static int str_to_ego(item_spec &spec, std::string ego_str)
"returning",
"chaos",
"confuse", // 20
+ "penetration",
+ "reaping",
NULL
};
@@ -3293,6 +3378,20 @@ item_spec item_list::parse_single_spec(std::string s)
}
else if (ego == -1)
{
+ error = make_stringf("Ego '%s' is invalid for item '%s'.",
+ ego_str.c_str(), s.c_str());
+ return (result);
+ }
+ else if (result.sub_type == OBJ_RANDOM)
+ {
+ // it will be assigned among appropriate ones later
+ }
+ else if (result.base_type == OBJ_WEAPONS
+ && !is_weapon_brand_ok(result.sub_type, ego)
+ || result.base_type == OBJ_ARMOUR
+ && !is_armour_brand_ok(result.sub_type, ego))
+ // no missile brands are disallowed yet
+ {
error = make_stringf("Ego '%s' is incompatible with item '%s'.",
ego_str.c_str(), s.c_str());
return (result);
diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h
index c70c16cece..791a929b10 100644
--- a/crawl-ref/source/mapdef.h
+++ b/crawl-ref/source/mapdef.h
@@ -19,7 +19,7 @@
#include "dlua.h"
#include "enum.h"
#include "externs.h"
-#include "fixary.h"
+#include "matrix.h"
#include "fprop.h"
#include "makeitem.h"
#include "stuff.h"
@@ -759,6 +759,7 @@ public:
bool test_lua_veto();
std::string validate_map_def();
+ std::string validate_temple_map();
void add_prelude_line(int line, const std::string &s);
void add_main_line(int line, const std::string &s);
diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc
index 06a47f6100..cbe4922382 100644
--- a/crawl-ref/source/maps.cc
+++ b/crawl-ref/source/maps.cc
@@ -24,7 +24,7 @@
#include "message.h"
#include "mapdef.h"
#include "mon-util.h"
-#include "monplace.h"
+#include "mon-place.h"
#include "random.h"
#include "state.h"
#include "terrain.h"
@@ -507,6 +507,8 @@ bool map_selector::accept(const map_def &mapdef) const
&& mapdef.place == place
&& !mapdef.has_tag("layout")
&& !mapdef.has_tag("place_unique")
+ && (!mapdef.has_tag_prefix("temple_")
+ || mapdef.has_tag_prefix("uniq_altar_"))
&& map_matches_layout_type(mapdef)
&& vault_unforbidden(mapdef));
case DEPTH:
@@ -522,6 +524,8 @@ bool map_selector::accept(const map_def &mapdef) const
&& !mapdef.has_tag("bazaar")
&& !mapdef.has_tag("layout")
&& !mapdef.has_tag("place_unique")
+ && (!mapdef.has_tag_prefix("temple_")
+ || mapdef.has_tag_prefix("uniq_altar_"))
&& (!check_layout || map_matches_layout_type(mapdef))
&& vault_unforbidden(mapdef));
case TAG:
diff --git a/crawl-ref/source/matrix.h b/crawl-ref/source/matrix.h
new file mode 100644
index 0000000000..520711ca88
--- /dev/null
+++ b/crawl-ref/source/matrix.h
@@ -0,0 +1,59 @@
+/*
+ * File: matrix.h
+ * Summary: Two-dimensional array class.
+ */
+
+#ifndef MATRIX_H
+#define MATRIX_H
+
+template <typename Z>
+class Matrix {
+public:
+ Matrix(int width, int height, const Z &initial);
+ Matrix(int width, int height);
+ ~Matrix();
+
+ void init(const Z &initial);
+ Z &operator () (int x, int y)
+ {
+ return data[x + y * width];
+ }
+ const Z &operator () (int x, int y) const
+ {
+ return data[x + y * width];
+ }
+
+private:
+ Z *data;
+ int width, height, size;
+};
+
+template <typename Z>
+Matrix<Z>::Matrix(int _width, int _height, const Z &initial)
+ : data(NULL), width(_width), height(_height), size(_width * _height)
+{
+ data = new Z [ size ];
+ init(initial);
+}
+
+template <typename Z>
+Matrix<Z>::Matrix(int _width, int _height)
+ : data(NULL), width(_width), height(_height), size(_width * _height)
+{
+ data = new Z [ size ];
+}
+
+template <typename Z>
+Matrix<Z>::~Matrix()
+{
+ delete [] data;
+}
+
+template <typename Z>
+void Matrix<Z>::init(const Z &initial)
+{
+ for (int i = 0; i < size; ++i)
+ data[i] = initial;
+}
+
+#endif // MATRIX_H
diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc
index 8cb98b8680..af1454f22f 100644
--- a/crawl-ref/source/menu.cc
+++ b/crawl-ref/source/menu.cc
@@ -20,7 +20,7 @@
#ifdef USE_TILE
#include "coord.h"
- #include "monstuff.h"
+ #include "mon-stuff.h"
#include "mon-util.h"
#include "newgame.h"
#include "terrain.h"
diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc
index e87a988682..77fb18d697 100644
--- a/crawl-ref/source/message.cc
+++ b/crawl-ref/source/message.cc
@@ -27,7 +27,7 @@
#include "libutil.h"
#include "macro.h"
#include "message.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "notes.h"
#include "random.h"
#include "religion.h"
diff --git a/crawl-ref/source/mgrow.cc b/crawl-ref/source/mgrow.cc
index 3693e43dd4..7be571d541 100644
--- a/crawl-ref/source/mgrow.cc
+++ b/crawl-ref/source/mgrow.cc
@@ -9,8 +9,8 @@
#include "enum.h"
#include "mgrow.h"
#include "mon-util.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "random.h"
// Base experience required by a monster to reach HD 1.
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index 0c4d997d89..944cf6aa98 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -55,9 +55,10 @@
#include "makeitem.h"
#include "mapmark.h"
#include "message.h"
-#include "monplace.h"
+#include "mon-place.h"
+#include "mon-iter.h"
#include "mon-util.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "ouch.h"
#include "output.h"
#include "overmap.h"
@@ -2968,14 +2969,11 @@ static void monster_threat_values(double *general, double *highest,
double sum = 0;
int highest_xp = -1;
- monsters *monster = NULL;
- for (int it = 0; it < MAX_MONSTERS; it++)
+ for (monster_iterator mi(&you.get_los()); mi; ++mi)
{
- monster = &menv[it];
-
- if (monster->alive() && mons_near(monster) && !monster->friendly())
+ if (!mi->friendly())
{
- const int xp = exper_value(monster);
+ const int xp = exper_value(*mi);
const double log_xp = log((double)xp);
sum += log_xp;
if (xp > highest_xp)
@@ -2983,7 +2981,7 @@ static void monster_threat_values(double *general, double *highest,
highest_xp = xp;
*highest = log_xp;
}
- if (!you.can_see(monster))
+ if (!you.can_see(*mi))
*invis = true;
}
}
@@ -3128,6 +3126,27 @@ void reveal_secret_door(const coord_def& p)
: DNGN_OPEN_DOOR;
viewwindow(false);
learned_something_new(TUT_SEEN_SECRET_DOOR, p);
+
+ // If a transparent secret door was forced open to preserve LOS,
+ // check if it had an opening prompt.
+ if (grd(p) == DNGN_OPEN_DOOR)
+ {
+ std::string door_open_prompt =
+ env.markers.property_at(p, MAT_ANY, "door_open_prompt");
+
+ if (!door_open_prompt.empty())
+ {
+ mprf("That secret door had a prompt on it:", MSGCH_PROMPT);
+ mprf(MSGCH_PROMPT, "%s", door_open_prompt.c_str());
+
+ if (!is_exclude_root(p))
+ {
+ if (yesno("Put travel exclusion on door? (Y/n)", true, 'y'))
+ // Zero radius exclusion right on top of door.
+ set_exclude(p, 0);
+ }
+ }
+ }
}
// A feeble attempt at Nethack-like completeness for cute messages.
diff --git a/crawl-ref/source/misc/src-pkg-excludes.lst b/crawl-ref/source/misc/src-pkg-excludes.lst
index 1d28c6f19f..95b38dac4e 100644
--- a/crawl-ref/source/misc/src-pkg-excludes.lst
+++ b/crawl-ref/source/misc/src-pkg-excludes.lst
@@ -1,3 +1,11 @@
-,svn
-**/.svn/*
-.*
+^\.
+/\.
+git-hooks
+contrib/freetype
+contrib/libpng
+contrib/lua
+contrib/pcre
+contrib/sdl
+contrib/sdl-image
+contrib/sqlite
+contrib/zlib
diff --git a/crawl-ref/source/mon-abil.cc b/crawl-ref/source/mon-abil.cc
index 16bde8d4f4..9d53edc726 100644
--- a/crawl-ref/source/mon-abil.cc
+++ b/crawl-ref/source/mon-abil.cc
@@ -24,9 +24,10 @@
#include "mon-act.h"
#include "mon-behv.h"
#include "mon-cast.h"
-#include "monplace.h"
-#include "monspeak.h"
-#include "monstuff.h"
+#include "mon-iter.h"
+#include "mon-place.h"
+#include "mon-speak.h"
+#include "mon-stuff.h"
#include "random.h"
#include "spl-mis.h"
#include "spl-util.h"
@@ -192,6 +193,7 @@ static bool _do_split(monsters *thing, coord_def & target)
thing->behaviour,
0,
0,
+ 0,
target,
thing->foe,
MG_FORCE_PLACE));
@@ -208,6 +210,8 @@ static bool _do_split(monsters *thing, coord_def & target)
_split_ench_durations(thing, new_slime);
new_slime->attitude = thing->attitude;
new_slime->flags = thing->flags;
+ new_slime->props = thing->props;
+ // XXX copy summoner info
if (you.can_see(thing))
mprf("%s splits.", thing->name(DESC_CAP_A).c_str());
@@ -546,7 +550,7 @@ static bool _silver_statue_effects(monsters *mons)
mgen_data(
summon_any_demon((coinflip() ? DEMON_COMMON
: DEMON_LESSER)),
- SAME_ATTITUDE(mons), 5, 0, foe->pos(), mons->foe));
+ SAME_ATTITUDE(mons), mons, 5, 0, foe->pos(), mons->foe));
return (true);
}
return (false);
@@ -591,44 +595,41 @@ static bool _orc_battle_cry(monsters *chief)
const int boss_index = monster_index(chief);
const int level = chief->hit_dice > 12? 2 : 1;
std::vector<monsters*> seen_affected;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi(chief); mi; ++mi)
{
- monsters *mon = &menv[i];
- if (mon != chief
- && mon->alive()
- && mons_species(mon->type) == MONS_ORC
- && mons_aligned(boss_index, i)
- && mon->hit_dice < chief->hit_dice
- && !mon->berserk()
- && !mon->has_ench(ENCH_MIGHT)
- && !mon->cannot_move()
- && !mon->confused()
- && chief->can_see(mon))
+ if (*mi != chief
+ && mons_species(mi->type) == MONS_ORC
+ && mons_aligned(boss_index, mi->mindex())
+ && mi->hit_dice < chief->hit_dice
+ && !mi->berserk()
+ && !mi->has_ench(ENCH_MIGHT)
+ && !mi->cannot_move()
+ && !mi->confused())
{
- mon_enchant ench = mon->get_ench(ENCH_BATTLE_FRENZY);
+ mon_enchant ench = mi->get_ench(ENCH_BATTLE_FRENZY);
if (ench.ench == ENCH_NONE || ench.degree < level)
{
const int dur =
- random_range(12, 20) * speed_to_duration(mon->speed);
+ random_range(12, 20) * speed_to_duration(mi->speed);
if (ench.ench != ENCH_NONE)
{
ench.degree = level;
ench.duration = std::max(ench.duration, dur);
- mon->update_ench(ench);
+ mi->update_ench(ench);
}
else
{
- mon->add_ench(mon_enchant(ENCH_BATTLE_FRENZY, level,
+ mi->add_ench(mon_enchant(ENCH_BATTLE_FRENZY, level,
KC_OTHER, dur));
}
affected++;
- if (you.can_see(mon))
- seen_affected.push_back(mon);
+ if (you.can_see(*mi))
+ seen_affected.push_back(*mi);
- if (mon->asleep())
- behaviour_event(mon, ME_DISTURB, MHITNOT, chief->pos());
+ if (mi->asleep())
+ behaviour_event(*mi, ME_DISTURB, MHITNOT, chief->pos());
}
}
}
@@ -729,23 +730,20 @@ static bool _moth_incite_monsters(const monsters *mon)
return false;
int goaded = 0;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ circle_def c(mon->pos(), 3, C_SQUARE);
+ for (monster_iterator mi(&c); mi; ++mi)
{
- monsters *targ = &menv[i];
- if (targ == mon || !targ->alive() || !targ->needs_berserk())
- continue;
-
- if (mon->pos().distance_from(targ->pos()) > 3)
+ if (*mi == mon || !mi->needs_berserk())
continue;
- if (is_sanctuary(targ->pos()))
+ if (is_sanctuary(mi->pos()))
continue;
// Cannot goad other moths of wrath!
- if (targ->type == MONS_MOTH_OF_WRATH)
+ if (mi->type == MONS_MOTH_OF_WRATH)
continue;
- if (_make_monster_angry(mon, targ) && !one_chance_in(3 * ++goaded))
+ if (_make_monster_angry(mon, *mi) && !one_chance_in(3 * ++goaded))
return (true);
}
@@ -779,6 +777,7 @@ bool mon_special_ability(monsters *monster, bolt & beem)
spell_type spell = SPELL_NO_SPELL;
+ circle_def c;
switch (mclass)
{
case MONS_UGLY_THING:
@@ -832,16 +831,9 @@ bool mon_special_ability(monsters *monster, bolt & beem)
break;
}
- for (int i = 0; i < MAX_MONSTERS; i++)
+ c = circle_def(monster->pos(), 4, C_CIRCLE);
+ for (monster_iterator targ(&c); targ; ++targ)
{
- monsters *targ = &menv[i];
-
- if (targ->type == MONS_NO_MONSTER)
- continue;
-
- if (distance(monster->pos(), targ->pos()) >= 5)
- continue;
-
if (mons_atts_aligned(monster->attitude, targ->attitude))
continue;
@@ -1306,46 +1298,7 @@ void mon_nearby_ability(monsters *monster)
return;
}
-#define MON_SPEAK_CHANCE 21
-
- if (monster->is_patrolling() || mons_is_wandering(monster)
- || monster->attitude == ATT_NEUTRAL)
- {
- // Very fast wandering/patrolling monsters might, in one monster turn,
- // move into the player's LOS and then back out (or the player
- // might move into their LOS and the monster move back out before
- // the player's view has a chance to update) so prevent them
- // from speaking.
- ;
- }
- else if ((mons_class_flag(monster->type, M_SPEAKS)
- || !monster->mname.empty())
- && one_chance_in(MON_SPEAK_CHANCE))
- {
- mons_speaks(monster);
- }
- else if (get_mon_shape(monster) >= MON_SHAPE_QUADRUPED)
- {
- // Non-humanoid-ish monsters have a low chance of speaking
- // without the M_SPEAKS flag, to give the dungeon some
- // atmosphere/flavour.
- int chance = MON_SPEAK_CHANCE * 4;
-
- // Band members are a lot less likely to speak, since there's
- // a lot of them.
- if (testbits(monster->flags, MF_BAND_MEMBER))
- chance *= 10;
-
- // However, confused and fleeing monsters are more interesting.
- if (mons_is_fleeing(monster))
- chance /= 2;
- if (monster->has_ench(ENCH_CONFUSION))
- chance /= 2;
-
- if (one_chance_in(chance))
- mons_speaks(monster);
- }
- // Okay then, don't speak.
+ maybe_mons_speaks(monster);
if (monster_can_submerge(monster, grd(monster->pos()))
&& !monster->caught() // No submerging while caught.
diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc
index 3c57266252..f699d7578e 100644
--- a/crawl-ref/source/mon-act.cc
+++ b/crawl-ref/source/mon-act.cc
@@ -31,8 +31,9 @@
#include "mon-abil.h"
#include "mon-behv.h"
#include "mon-cast.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-iter.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mutation.h"
#include "notes.h"
#include "options.h"
@@ -856,7 +857,8 @@ static bool _handle_scroll(monsters *monster)
simple_monster_message(monster, " reads a scroll.");
const int mon = create_monster(
mgen_data(MONS_ABOMINATION_SMALL, SAME_ATTITUDE(monster),
- 0, 0, monster->pos(), monster->foe, MG_FORCE_BEH));
+ monster, 0, 0, monster->pos(), monster->foe,
+ MG_FORCE_BEH));
read = true;
if (mon != -1)
@@ -2077,20 +2079,18 @@ void handle_monsters()
// them to move again.
memset(immobile_monster, 0, sizeof immobile_monster);
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
-
- if (!monster->alive() || immobile_monster[i])
+ if (immobile_monster[mi->mindex()])
continue;
- const coord_def oldpos = monster->pos();
+ const coord_def oldpos = mi->pos();
- monster->update_los();
- _handle_monster_move(monster);
+ mi->update_los();
+ _handle_monster_move(*mi);
- if (!invalid_monster(monster) && monster->pos() != oldpos)
- immobile_monster[i] = true;
+ if (!invalid_monster(*mi) && mi->pos() != oldpos)
+ immobile_monster[mi->mindex()] = true;
// If the player got banished, discard pending monster actions.
if (you.banished)
@@ -2129,18 +2129,10 @@ static bool _jelly_divide(monsters *parent)
if ( num_spots == 0 )
return (false);
- int k = 0;
-
// Now that we have a spot, find a monster slot {dlb}:
- for (k = 0; k < MAX_MONSTERS; k++)
- {
- child = &menv[k];
-
- if (child->type == -1)
- break;
- else if (k == MAX_MONSTERS - 1)
- return (false);
- }
+ child = get_free_monster();
+ if (!child)
+ return (false);
// Handle impact of split on parent {dlb}:
parent->max_hit_points /= 2;
@@ -2159,7 +2151,7 @@ static bool _jelly_divide(monsters *parent)
child->speed_increment = 70 + random2(5);
child->moveto(child_spot);
- mgrd(child->pos()) = k;
+ mgrd(child->pos()) = child->mindex();
if (!simple_monster_message(parent, " splits in two!"))
if (player_can_hear(parent->pos()) || player_can_hear(child->pos()))
diff --git a/crawl-ref/source/mon-behv.cc b/crawl-ref/source/mon-behv.cc
index 2954e65065..03ae622bb9 100644
--- a/crawl-ref/source/mon-behv.cc
+++ b/crawl-ref/source/mon-behv.cc
@@ -15,8 +15,9 @@
#include "fprop.h"
#include "exclude.h"
#include "los.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-iter.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "random.h"
#include "state.h"
@@ -914,13 +915,13 @@ static void _arena_set_foe(monsters *mons)
int nearest_unseen = -1;
int best_unseen_distance = -1;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator other; other; ++other)
{
+ int i = other->mindex();
if (mind == i)
continue;
- const monsters *other(&menv[i]);
- if (!other->alive() || mons_aligned(mind, i))
+ if (mons_aligned(mind, i))
continue;
// Don't fight test spawners, since they're only pseudo-monsters
@@ -934,7 +935,7 @@ static void _arena_set_foe(monsters *mons)
}
const int distance = grid_distance(mons->pos(), other->pos());
- const bool seen = mons->can_see(other);
+ const bool seen = mons->can_see(*other);
if (seen)
{
@@ -954,7 +955,7 @@ static void _arena_set_foe(monsters *mons)
}
if ((best_distance == -1 || distance < best_distance)
- && mons->can_see(other))
+ && mons->can_see(*other))
{
best_distance = distance;
diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc
index 3464517da8..daf8520ac1 100644
--- a/crawl-ref/source/mon-cast.cc
+++ b/crawl-ref/source/mon-cast.cc
@@ -21,9 +21,10 @@
#include "los.h"
#include "misc.h"
#include "mon-behv.h"
-#include "monplace.h"
-#include "monspeak.h"
-#include "monstuff.h"
+#include "mon-iter.h"
+#include "mon-place.h"
+#include "mon-speak.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "random.h"
#include "religion.h"
@@ -148,22 +149,19 @@ static bool _set_allied_target(monsters * caster, bolt & pbolt)
monster_type caster_genus = mons_genus(caster->type);
- for (int i = 0; i < MAX_MONSTERS; i++)
+ for (monster_iterator targ(caster); targ; ++targ)
{
- monsters * targ = &menv[i];
- if (i != caster->mindex()
- && targ->alive()
- && caster->can_see(targ)
+ if (*targ != caster
&& mons_genus(targ->type) == caster_genus
&& mons_atts_aligned(targ->attitude, caster->attitude)
&& !targ->has_ench(ENCH_CHARM)
- && _flavour_benefits_monster(pbolt.flavour, *targ))
+ && _flavour_benefits_monster(pbolt.flavour, **targ))
{
int targ_distance = grid_distance(targ->pos(), caster->pos());
if (targ_distance < min_distance && targ_distance < pbolt.range)
{
min_distance = targ_distance;
- selected_target = targ;
+ selected_target = *targ;
}
}
}
@@ -273,8 +271,8 @@ bolt mons_spells( monsters *mons, spell_type spell_cast, int power,
beam.flavour = BEAM_HASTE;
break;
- case SPELL_BACKLIGHT:
- beam.flavour = BEAM_BACKLIGHT;
+ case SPELL_CORONA:
+ beam.flavour = BEAM_CORONA;
beam.is_beam = true;
break;
@@ -283,6 +281,11 @@ bolt mons_spells( monsters *mons, spell_type spell_cast, int power,
beam.is_beam = true;
break;
+ case SPELL_HIBERNATION:
+ beam.flavour = BEAM_HIBERNATION;
+ beam.is_beam = true;
+ break;
+
case SPELL_SLEEP:
beam.flavour = BEAM_SLEEP;
beam.is_beam = true;
@@ -732,6 +735,8 @@ bool setup_mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
if (spell_cast == SPELL_TELEPORT_SELF)
pbolt.ench_power = 2000;
+ else if (spell_cast == SPELL_SLEEP)
+ pbolt.ench_power = 6 * monster->hit_dice;
pbolt.beam_source = monster_index(monster);
@@ -786,6 +791,7 @@ bool setup_mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
case SPELL_SUMMON_GREATER_DEMON:
case SPELL_CANTRIP:
case SPELL_BERSERKER_RAGE:
+ case SPELL_SWIFTNESS:
case SPELL_WATER_ELEMENTALS:
case SPELL_FIRE_ELEMENTALS:
case SPELL_AIR_ELEMENTALS:
@@ -846,35 +852,29 @@ bool setup_mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
}
else if (spell_cast == SPELL_PORKALATOR && one_chance_in(3))
{
- int target = -1;
- int count = 0;
+ monsters* targ = NULL;
+ int count = 0;
monster_type hog_type = MONS_HOG;
- for (int i = 0; i < MAX_MONSTERS; i++)
+ for (monster_iterator mi(monster); mi; ++mi)
{
- monsters *targ = &menv[i];
-
- if (!monster->can_see(targ))
- continue;
-
hog_type = MONS_HOG;
- if (targ->holiness() == MH_DEMONIC)
+ if (mi->holiness() == MH_DEMONIC)
hog_type = MONS_HELL_HOG;
- else if (targ->holiness() != MH_NATURAL)
+ else if (mi->holiness() != MH_NATURAL)
continue;
- if (targ->type != hog_type
- && mons_atts_aligned(monster->attitude, targ->attitude)
- && mons_power(hog_type) + random2(4) >= mons_power(targ->type)
- && (!targ->can_use_spells() || coinflip())
+ if (mi->type != hog_type
+ && mons_atts_aligned(monster->attitude, mi->attitude)
+ && mons_power(hog_type) + random2(4) >= mons_power(mi->type)
+ && (!mi->can_use_spells() || coinflip())
&& one_chance_in(++count))
{
- target = i;
+ targ = *mi;
}
}
- if (target != -1)
+ if (targ)
{
- monsters *targ = &menv[target];
pbolt.target = targ->pos();
#if DEBUG_DIAGNOSTICS
mprf("Porkalator: targetting %s instead",
@@ -1265,7 +1265,7 @@ bool handle_mon_spell(monsters *monster, bolt &beem)
// Try to animate dead: if nothing rises, pretend we didn't cast it.
if (spell_cast == SPELL_ANIMATE_DEAD
&& !animate_dead(monster, 100, SAME_ATTITUDE(monster),
- monster->foe, god, false))
+ monster->foe, monster, "", god, false))
{
return (false);
}
@@ -1493,7 +1493,7 @@ static void _do_high_level_summon(monsters *monster, bool monsterNearby,
continue;
create_monster(
- mgen_data(which_mons, SAME_ATTITUDE(monster),
+ mgen_data(which_mons, SAME_ATTITUDE(monster), monster,
duration, spell_cast, target ? *target : monster->pos(),
monster->foe, 0, god));
}
@@ -1608,6 +1608,11 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
monster->go_berserk(true);
return;
+ case SPELL_SWIFTNESS:
+ monster->add_ench(ENCH_SWIFT);
+ simple_monster_message(monster, " seems to move somewhat quicker.");
+ return;
+
case SPELL_SUMMON_SMALL_MAMMALS:
case SPELL_VAMPIRE_SUMMON:
if (spell_cast == SPELL_SUMMON_SMALL_MAMMALS)
@@ -1626,7 +1631,7 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
const monster_type mon = (one_chance_in(3) ? MONS_GIANT_BAT
: RANDOM_ELEMENT(rats));
create_monster(
- mgen_data(mon, SAME_ATTITUDE(monster),
+ mgen_data(mon, SAME_ATTITUDE(monster), monster,
5, spell_cast, monster->pos(), monster->foe, 0, god));
}
return;
@@ -1640,7 +1645,7 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
for (sumcount = 0; sumcount < sumcount2; ++sumcount)
{
create_monster(
- mgen_data(RANDOM_MONSTER, SAME_ATTITUDE(monster),
+ mgen_data(RANDOM_MONSTER, SAME_ATTITUDE(monster), monster,
5, spell_cast, monster->pos(), monster->foe, 0, god));
}
return;
@@ -1669,7 +1674,7 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
for (sumcount = 0; sumcount < sumcount2; sumcount++)
{
create_monster(
- mgen_data(el_summon_type, SAME_ATTITUDE(monster),
+ mgen_data(el_summon_type, SAME_ATTITUDE(monster), monster,
3, spell_cast, monster->pos(), monster->foe, 0, god));
}
return;
@@ -1701,7 +1706,7 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
// being passed to summon_type), so I'm not sure what the
// abjuration value (3) is doing there. (jpeg)
if (create_monster(
- mgen_data(MONS_KRAKEN_TENTACLE, SAME_ATTITUDE(monster),
+ mgen_data(MONS_KRAKEN_TENTACLE, SAME_ATTITUDE(monster), monster,
3, spell_cast, monster->pos(), monster->foe, 0, god,
MONS_NO_MONSTER, kraken_index, monster->colour,
you.your_level, PROX_CLOSE_TO_PLAYER,
@@ -1722,7 +1727,7 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
for (sumcount = 0; sumcount < sumcount2; sumcount++)
{
create_monster(
- mgen_data(MONS_RAKSHASA_FAKE, SAME_ATTITUDE(monster),
+ mgen_data(MONS_RAKSHASA_FAKE, SAME_ATTITUDE(monster), monster,
3, spell_cast, monster->pos(), monster->foe, 0, god));
}
return;
@@ -1738,7 +1743,7 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
{
create_monster(
mgen_data(summon_any_demon(DEMON_COMMON),
- SAME_ATTITUDE(monster), duration, spell_cast,
+ SAME_ATTITUDE(monster), monster, duration, spell_cast,
monster->pos(), monster->foe, 0, god));
}
return;
@@ -1757,16 +1762,16 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
: MONS_UGLY_THING);
create_monster(
- mgen_data(mon, SAME_ATTITUDE(monster),
+ mgen_data(mon, SAME_ATTITUDE(monster), monster,
duration, spell_cast, monster->pos(), monster->foe, 0,
god));
}
return;
case SPELL_ANIMATE_DEAD:
- // see special handling in monstuff::handle_spell() {dlb}
+ // see special handling in mon-stuff::handle_spell() {dlb}
animate_dead(monster, 5 + random2(5), SAME_ATTITUDE(monster),
- monster->foe, god);
+ monster->foe, monster, "", god);
return;
case SPELL_CALL_IMP: // class 5 demons
@@ -1777,7 +1782,7 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
{
create_monster(
mgen_data(summon_any_demon(DEMON_LESSER),
- SAME_ATTITUDE(monster),
+ SAME_ATTITUDE(monster), monster,
duration, spell_cast, monster->pos(), monster->foe, 0,
god));
}
@@ -1793,7 +1798,7 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
for (sumcount = 0; sumcount < sumcount2; ++sumcount)
{
create_monster(
- mgen_data(MONS_SCORPION, SAME_ATTITUDE(monster),
+ mgen_data(MONS_SCORPION, SAME_ATTITUDE(monster), monster,
duration, spell_cast, monster->pos(), monster->foe, 0,
god));
}
@@ -1807,7 +1812,7 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
for (sumcount = 0; sumcount < sumcount2; ++sumcount)
{
create_monster(
- mgen_data(MONS_UFETUBUS, SAME_ATTITUDE(monster),
+ mgen_data(MONS_UFETUBUS, SAME_ATTITUDE(monster), monster,
duration, spell_cast, monster->pos(), monster->foe, 0,
god));
}
@@ -1815,13 +1820,13 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
case SPELL_SUMMON_BEAST: // Geryon
create_monster(
- mgen_data(MONS_BEAST, SAME_ATTITUDE(monster),
+ mgen_data(MONS_BEAST, SAME_ATTITUDE(monster), monster,
4, spell_cast, monster->pos(), monster->foe, 0, god));
return;
case SPELL_SUMMON_ICE_BEAST:
create_monster(
- mgen_data(MONS_ICE_BEAST, SAME_ATTITUDE(monster),
+ mgen_data(MONS_ICE_BEAST, SAME_ATTITUDE(monster), monster,
5, spell_cast, monster->pos(), monster->foe, 0, god));
return;
@@ -1836,8 +1841,8 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
{
create_monster(
mgen_data(MONS_WANDERING_MUSHROOM, SAME_ATTITUDE(monster),
- duration, spell_cast, monster->pos(), monster->foe, 0,
- god));
+ monster, duration, spell_cast, monster->pos(),
+ monster->foe, 0, god));
}
return;
@@ -1853,7 +1858,8 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
{
create_monster(
mgen_data(MONS_BALL_LIGHTNING, SAME_ATTITUDE(monster),
- 2, spell_cast, monster->pos(), monster->foe, 0, god));
+ monster, 2, spell_cast, monster->pos(), monster->foe,
+ 0, god));
}
return;
}
@@ -1883,7 +1889,7 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
{
create_monster(
mgen_data(summon_any_demon(DEMON_GREATER),
- SAME_ATTITUDE(monster),
+ SAME_ATTITUDE(monster), monster,
duration, spell_cast, monster->pos(), monster->foe,
0, god));
}
@@ -1921,7 +1927,7 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
for (int i = 0, size = monsters.size(); i < size; ++i)
{
create_monster(
- mgen_data(monsters[i], SAME_ATTITUDE(monster),
+ mgen_data(monsters[i], SAME_ATTITUDE(monster), monster,
duration, spell_cast,
monster->pos(), monster->foe, 0, god));
}
@@ -2108,7 +2114,7 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast,
0));
create_monster(
- mgen_data(mon, SAME_ATTITUDE(monster), duration,
+ mgen_data(mon, SAME_ATTITUDE(monster), monster, duration,
spell_cast, monster->pos(), monster->foe, 0, god));
}
return;
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index 1360ed5987..dc677f3413 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -50,7 +50,7 @@
MH_NONLIVING - golems and other constructs
MH_PLANT - plants
- exp_mod: see give_adjusted_experience() in monstuff.cc
+ exp_mod: see give_adjusted_experience() in mon-stuff.cc
- the experience given for killing this monster is calculated something
like this:
@@ -2725,7 +2725,7 @@ static monsterentry mondata[] = {
{
MONS_OKLOB_PLANT, 'P', LIGHTGREEN, "oklob plant",
M_SPECIAL_ABILITY | M_STATIONARY,
- MR_RES_POISON,
+ MR_RES_POISON | MR_RES_ACID,
0, 10, MONS_PLANT, MONS_OKLOB_PLANT, MH_PLANT, -3,
{ AT_NO_ATK, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
{ 10, 3, 5, 0 },
@@ -4443,11 +4443,11 @@ static monsterentry mondata[] = {
MONS_GASTRONOK, 'j', LIGHTRED, "Gastronok",
M_NO_SKELETON | M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS
| M_SPEAKS | M_NO_WAND,
- MR_RES_FIRE | MR_RES_COLD,
- 700, 10, MONS_GIANT_SLUG, MONS_GIANT_SLUG, MH_NATURAL, -4,
- { {AT_BITE, AF_PLAIN, 15}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
- { 12, 0, 0, 150 },
- 1, 2, MST_GASTRONOK, CE_POISONOUS, Z_NOZOMBIE, S_GURGLE,
+ MR_NO_FLAGS,
+ 1500, 10, MONS_GIANT_SLUG, MONS_ELEPHANT_SLUG, MH_NATURAL, -3,
+ { {AT_BITE, AF_PLAIN, 40}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
+ { 20, 0, 0, 150 },
+ 2, 1, MST_GASTRONOK, CE_POISONOUS, Z_NOZOMBIE, S_GURGLE,
I_NORMAL, HT_AMPHIBIOUS_LAND, FL_NONE, 5, DEFAULT_ENERGY,
MONUSE_STARTING_EQUIPMENT, MONEAT_FOOD, SIZE_LARGE
},
diff --git a/crawl-ref/source/mon-gear.cc b/crawl-ref/source/mon-gear.cc
index b1573d11a7..6680e3a27a 100644
--- a/crawl-ref/source/mon-gear.cc
+++ b/crawl-ref/source/mon-gear.cc
@@ -324,8 +324,8 @@ static item_make_species_type _give_weapon(monsters *mon, int level,
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_QUARTERSTAFF;
set_item_ego_type(item, OBJ_WEAPONS, SPWPN_CHAOS);
- item.plus += random2(5);
- item.plus2 += random2(4);
+ item.plus += 2 + random2(3);
+ item.plus2 += 2 + random2(3);
break;
case MONS_ORC:
diff --git a/crawl-ref/source/mon-info.cc b/crawl-ref/source/mon-info.cc
index 12f64499dc..d32b8466d1 100644
--- a/crawl-ref/source/mon-info.cc
+++ b/crawl-ref/source/mon-info.cc
@@ -169,7 +169,7 @@ static std::string _verbose_info(const monsters* m)
return (" (fleeing)");
if (m->asleep())
{
- if (!m->can_sleep(true))
+ if (!m->can_hibernate(true))
return (" (dormant)");
else
return (" (sleeping)");
diff --git a/crawl-ref/source/mon-info.h b/crawl-ref/source/mon-info.h
index c5d559d4e9..20618caf1a 100644
--- a/crawl-ref/source/mon-info.h
+++ b/crawl-ref/source/mon-info.h
@@ -1,7 +1,7 @@
#ifndef MON_INFO_H
#define MON_INFO_H
-#include "monstuff.h"
+#include "mon-stuff.h"
// Monster info used by the pane; precomputes some data
// to help with sorting and rendering.
diff --git a/crawl-ref/source/mon-iter.cc b/crawl-ref/source/mon-iter.cc
new file mode 100644
index 0000000000..1158a9028d
--- /dev/null
+++ b/crawl-ref/source/mon-iter.cc
@@ -0,0 +1,87 @@
+#include "AppHdr.h"
+
+#include "mon-iter.h"
+
+#include "actor.h"
+#include "coord-circle.h"
+#include "env.h"
+#include "monster.h"
+
+monster_iterator::monster_iterator()
+ : restr(R_NONE), curr_mid(0)
+{
+ advance(true);
+}
+
+monster_iterator::monster_iterator(const circle_def* circle_)
+ : restr(R_CIRC), curr_mid(0), circle(circle_)
+{
+ advance(true);
+}
+
+monster_iterator::monster_iterator(const los_def* los_)
+ : restr(R_LOS), curr_mid(0), los(los_)
+{
+ advance(true);
+}
+
+monster_iterator::monster_iterator(const actor* act_)
+ : restr(R_ACT), curr_mid(0), act(act_)
+{
+ advance(true);
+}
+
+monster_iterator::operator bool() const
+{
+ return (curr_mid < MAX_MONSTERS);
+}
+
+monsters* monster_iterator::operator*() const
+{
+ return (&env.mons[curr_mid]);
+}
+
+monsters* monster_iterator::operator->() const
+{
+ return (&env.mons[curr_mid]);
+}
+
+monster_iterator& monster_iterator::operator++()
+{
+ advance();
+ return (*this);
+}
+
+monster_iterator monster_iterator::operator++(int)
+{
+ monster_iterator copy = *this;
+ ++(*this);
+ return (copy);
+}
+
+bool monster_iterator::valid(int mid) const
+{
+ monsters* mon = &env.mons[mid];
+ if (!mon->alive())
+ return (false);
+ switch (restr)
+ {
+ case R_CIRC:
+ return (circle->contains(mon->pos()));
+ case R_LOS:
+ return (los->see_cell(mon->pos()));
+ case R_ACT:
+ return (act->can_see(mon));
+ default:
+ return (true);
+ }
+}
+
+void monster_iterator::advance(bool may_stay)
+{
+ if (!may_stay)
+ ++curr_mid;
+ while (curr_mid < MAX_MONSTERS && !valid(curr_mid))
+ ++curr_mid;
+}
+
diff --git a/crawl-ref/source/mon-iter.h b/crawl-ref/source/mon-iter.h
new file mode 100644
index 0000000000..7f31831c64
--- /dev/null
+++ b/crawl-ref/source/mon-iter.h
@@ -0,0 +1,49 @@
+/*
+ * Provide a way to iterator over all monsters,
+ * subject to a few common restrictions.
+ *
+ * TODO:
+ * - Iterate over actors?
+ */
+
+#ifndef MON_ITER_H
+#define MON_ITER_H
+
+enum restr_type
+{
+ R_NONE,
+ R_CIRC,
+ R_LOS,
+ R_ACT
+};
+
+class circle_def;
+class los_def;
+class actor;
+
+class monster_iterator
+{
+public:
+ monster_iterator();
+ monster_iterator(const circle_def* circle_);
+ monster_iterator(const los_def* los_);
+ monster_iterator(const actor* act_);
+
+ operator bool() const;
+ monsters* operator*() const;
+ monsters* operator->() const;
+ monster_iterator& operator++();
+ monster_iterator operator++(int);
+
+protected:
+ restr_type restr;
+ int curr_mid;
+ const circle_def* circle;
+ const los_def* los;
+ const actor* act;
+
+ bool valid(int mid) const;
+ void advance(bool may_stay=false);
+};
+
+#endif
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/mon-place.cc
index b0282aeaf1..dbf488e6a5 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/mon-place.cc
@@ -8,7 +8,7 @@
#include <algorithm>
-#include "monplace.h"
+#include "mon-place.h"
#include "arena.h"
#include "branch.h"
@@ -23,9 +23,10 @@
#include "message.h"
#include "mon-behv.h"
#include "mon-gear.h"
+#include "mon-iter.h"
#include "mon-pick.h"
#include "mon-util.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "player.h"
#include "random.h"
#include "religion.h"
@@ -1000,23 +1001,26 @@ int place_monster(mgen_data mg, bool force_pos)
return (id);
}
+monsters* get_free_monster()
+{
+ for (int i = 0; i < MAX_MONSTERS; ++i)
+ if (env.mons[i].type == MONS_NO_MONSTER)
+ {
+ env.mons[i].reset();
+ return (&env.mons[i]);
+ }
+ return (NULL);
+}
+
static int _place_monster_aux(const mgen_data &mg,
bool first_band_member, bool force_pos)
{
- int id = -1;
coord_def fpos;
- // Gotta be able to pick an ID.
- for (id = 0; id < MAX_MONSTERS; id++)
- if (menv[id].type == MONS_NO_MONSTER)
- break;
-
- // Too many monsters on level?
- if (id == MAX_MONSTERS)
+ monsters* mon = get_free_monster();
+ if (!mon)
return (-1);
- menv[id].reset();
-
const monster_type montype = (mons_class_is_zombified(mg.cls) ? mg.base_type
: mg.cls);
@@ -1035,8 +1039,8 @@ static int _place_monster_aux(const mgen_data &mg,
// We'll try 1000 times for a good spot.
for (i = 0; i < 1000; ++i)
{
- fpos = mg.pos + coord_def( random_range(-3, 3),
- random_range(-3, 3) );
+ fpos = mg.pos + coord_def(random_range(-3, 3),
+ random_range(-3, 3));
if (_valid_monster_generation_location(mg, fpos))
break;
@@ -1055,16 +1059,16 @@ static int _place_monster_aux(const mgen_data &mg,
return (-1);
}
- monsters &mons(menv[id]);
// Now, actually create the monster. (Wheeee!)
- mons.type = mg.cls;
- mons.base_monster = mg.base_type;
- mons.number = mg.number;
+ mon->type = mg.cls;
+ mon->base_monster = mg.base_type;
+ mon->number = mg.number;
- mons.moveto(fpos);
+ mon->moveto(fpos);
// Link monster into monster grid.
- mgrd(fpos) = id;
+ int id = mon->mindex();
+ env.mgrid(fpos) = id;
// Generate a brand shiny new monster, or zombie.
if (mons_class_is_zombified(mg.cls))
@@ -1075,8 +1079,8 @@ static int _place_monster_aux(const mgen_data &mg,
// Is it a god gift?
if (mg.god != GOD_NO_GOD)
{
- mons.god = mg.god;
- mons.flags |= MF_GOD_GIFT;
+ mon->god = mg.god;
+ mon->flags |= MF_GOD_GIFT;
}
// Not a god gift, give priestly monsters a god.
else if (mons_class_flag(mg.cls, M_PRIEST))
@@ -1084,17 +1088,17 @@ static int _place_monster_aux(const mgen_data &mg,
switch (mons_genus(mg.cls))
{
case MONS_ORC:
- mons.god = GOD_BEOGH;
+ mon->god = GOD_BEOGH;
break;
case MONS_JELLY:
- mons.god = GOD_JIYVA;
+ mon->god = GOD_JIYVA;
break;
case MONS_MUMMY:
case MONS_DRACONIAN:
case MONS_ELF:
// [ds] Vault defs can request priest monsters of unusual types.
default:
- mons.god = GOD_NAMELESS;
+ mon->god = GOD_NAMELESS;
break;
}
}
@@ -1102,34 +1106,34 @@ static int _place_monster_aux(const mgen_data &mg,
else if (mons_genus(mg.cls) == MONS_ORC)
{
if (!one_chance_in(7))
- mons.god = GOD_BEOGH;
+ mon->god = GOD_BEOGH;
}
// The royal jelly belongs to Jiyva.
else if (mg.cls == MONS_ROYAL_JELLY)
- mons.god = GOD_JIYVA;
+ mon->god = GOD_JIYVA;
// Angels and Daevas belong to TSO, but 1 out of 7 in the Abyss are
// adopted by Xom.
else if (mons_class_holiness(mg.cls) == MH_HOLY)
{
if (mg.level_type != LEVEL_ABYSS || !one_chance_in(7))
- mons.god = GOD_SHINING_ONE;
+ mon->god = GOD_SHINING_ONE;
else
- mons.god = GOD_XOM;
+ mon->god = GOD_XOM;
}
// 6 out of 7 demons in the Abyss belong to Lugonu.
else if (mons_class_holiness(mg.cls) == MH_DEMONIC)
{
if (mg.level_type == LEVEL_ABYSS && !one_chance_in(7))
- mons.god = GOD_LUGONU;
+ mon->god = GOD_LUGONU;
}
// If the caller requested a specific colour for this monster, apply
// it now.
if (mg.colour != BLACK)
- mons.colour = mg.colour;
+ mon->colour = mg.colour;
if (mg.mname != "")
- mons.mname = mg.mname;
+ mon->mname = mg.mname;
// The return of Boris is now handled in monster_die(). Not setting
// this for Boris here allows for multiple Borises in the dungeon at
@@ -1138,16 +1142,16 @@ static int _place_monster_aux(const mgen_data &mg,
you.unique_creatures[mg.cls] = true;
if (mons_class_flag(mg.cls, M_INVIS))
- mons.add_ench(ENCH_INVIS);
+ mon->add_ench(ENCH_INVIS);
if (mons_class_flag(mg.cls, M_CONFUSED))
- mons.add_ench(ENCH_CONFUSION);
+ mon->add_ench(ENCH_CONFUSION);
if (mg.cls == MONS_SHAPESHIFTER)
- mons.add_ench(ENCH_SHAPESHIFTER);
+ mon->add_ench(ENCH_SHAPESHIFTER);
if (mg.cls == MONS_GLOWING_SHAPESHIFTER)
- mons.add_ench(ENCH_GLOWING_SHAPESHIFTER);
+ mon->add_ench(ENCH_GLOWING_SHAPESHIFTER);
if (mg.cls == MONS_TOADSTOOL)
{
@@ -1156,23 +1160,23 @@ static int _place_monster_aux(const mgen_data &mg,
// spawning mushrooms in the same place over and over. Aside
// from that, the value is slightly randomised to avoid
// simultaneous die-offs of mushroom rings.
- mons.add_ench(ENCH_SLOWLY_DYING);
+ mon->add_ench(ENCH_SLOWLY_DYING);
}
- if (monster_can_submerge(&mons, grd(fpos)) && !one_chance_in(5))
- mons.add_ench(ENCH_SUBMERGED);
+ if (monster_can_submerge(mon, grd(fpos)) && !one_chance_in(5))
+ mon->add_ench(ENCH_SUBMERGED);
- mons.flags |= MF_JUST_SUMMONED;
+ mon->flags |= MF_JUST_SUMMONED;
// Don't leave shifters in their starting shape.
if (mg.cls == MONS_SHAPESHIFTER || mg.cls == MONS_GLOWING_SHAPESHIFTER)
{
no_messages nm;
- monster_polymorph(&mons, RANDOM_MONSTER);
+ monster_polymorph(mon, RANDOM_MONSTER);
// It's not actually a known shapeshifter if it happened to be
// placed in LOS of the player.
- mons.flags &= ~MF_KNOWN_MIMIC;
+ mon->flags &= ~MF_KNOWN_MIMIC;
}
// dur should always be 1-6 for monsters that can be abjured.
@@ -1185,16 +1189,16 @@ static int _place_monster_aux(const mgen_data &mg,
// Dancing weapons *always* have a weapon. Fail to create them
// otherwise.
- const item_def* wpn = mons.mslot_item(MSLOT_WEAPON);
+ const item_def* wpn = mon->mslot_item(MSLOT_WEAPON);
if (!wpn)
{
- mons.destroy_inventory();
- mons.reset();
+ mon->destroy_inventory();
+ mon->reset();
mgrd(fpos) = NON_MONSTER;
return (-1);
}
else
- mons.colour = wpn->colour;
+ mon->colour = wpn->colour;
}
else if (mons_class_itemuse(mg.cls) >= MONUSE_STARTING_EQUIPMENT)
{
@@ -1203,13 +1207,13 @@ static int _place_monster_aux(const mgen_data &mg,
if (mons_class_wields_two_weapons(mg.cls))
give_item(id, mg.power, summoned);
- unwind_var<int> save_speedinc(mons.speed_increment);
- mons.wield_melee_weapon(false);
+ unwind_var<int> save_speedinc(mon->speed_increment);
+ mon->wield_melee_weapon(false);
}
// Give manticores 8 to 16 spike volleys.
if (mg.cls == MONS_MANTICORE)
- mons.number = 8 + random2(9);
+ mon->number = 8 + random2(9);
if (mg.cls == MONS_SLIME_CREATURE)
{
@@ -1217,21 +1221,21 @@ static int _place_monster_aux(const mgen_data &mg,
{
// Boost HP to what it would have been if it had grown this
// big by merging.
- mons.hit_points *= mg.number;
- mons.max_hit_points *= mg.number;
+ mon->hit_points *= mg.number;
+ mon->max_hit_points *= mg.number;
}
}
// Set attitude, behaviour and target.
- mons.attitude = ATT_HOSTILE;
- mons.behaviour = mg.behaviour;
+ mon->attitude = ATT_HOSTILE;
+ mon->behaviour = mg.behaviour;
// Statues cannot sleep (nor wander but it means they are a bit
// more aware of the player than they'd be otherwise).
if (mons_is_statue(mg.cls))
- mons.behaviour = BEH_WANDER;
+ mon->behaviour = BEH_WANDER;
- mons.foe_memory = 0;
+ mon->foe_memory = 0;
// Setting attitude will always make the monster wander...
// If you want sleeping hostiles, use BEH_SLEEP since the default
@@ -1239,66 +1243,102 @@ static int _place_monster_aux(const mgen_data &mg,
if (mg.behaviour > NUM_BEHAVIOURS)
{
if (mg.behaviour == BEH_FRIENDLY)
- mons.attitude = ATT_FRIENDLY;
+ mon->attitude = ATT_FRIENDLY;
if (mg.behaviour == BEH_GOOD_NEUTRAL)
- mons.attitude = ATT_GOOD_NEUTRAL;
+ mon->attitude = ATT_GOOD_NEUTRAL;
if (mg.behaviour == BEH_NEUTRAL)
- mons.attitude = ATT_NEUTRAL;
+ mon->attitude = ATT_NEUTRAL;
if (mg.behaviour == BEH_STRICT_NEUTRAL)
- mons.attitude = ATT_STRICT_NEUTRAL;
+ mon->attitude = ATT_STRICT_NEUTRAL;
- mons.behaviour = BEH_WANDER;
+ mon->behaviour = BEH_WANDER;
}
if (summoned)
{
- mons.mark_summoned(mg.abjuration_duration, true,
- mg.summon_type);
+ mon->mark_summoned(mg.abjuration_duration, true,
+ mg.summon_type);
+ }
+ mon->foe = mg.foe;
+
+ if (!mg.non_actor_summoner.empty())
+ {
+ CrawlStoreValue& blame = mon->props["blame"];
+
+ blame.new_vector(SV_STR, SFLAG_CONST_TYPE);
+ blame.get_vector().push_back(mg.non_actor_summoner);
+ }
+ else if (mg.summoner != NULL)
+ {
+ CrawlStoreValue& blame = mon->props["blame"];
+
+ blame.new_vector(SV_STR, SFLAG_CONST_TYPE);
+
+ if (mg.summoner->atype() == ACT_PLAYER)
+ {
+ blame.get_vector().push_back("themselves");
+ }
+ else
+ {
+ monsters* sum = &menv[mg.summoner->mindex()];
+
+ blame.get_vector().push_back(sum->full_name(DESC_NOCAP_A, true));
+
+ if (sum->props.exists("blame"))
+ {
+ CrawlVector& oldblame = sum->props["blame"].get_vector();
+
+ for (CrawlVector::iterator i = oldblame.begin();
+ i != oldblame.end(); ++i)
+ {
+ blame.get_vector().push_back(*i);
+ }
+ }
+ }
}
- mons.foe = mg.foe;
// Initialise (very) ugly things and pandemonium demons.
- if (mons.type == MONS_UGLY_THING
- || mons.type == MONS_VERY_UGLY_THING)
+ if (mon->type == MONS_UGLY_THING
+ || mon->type == MONS_VERY_UGLY_THING)
{
ghost_demon ghost;
- ghost.init_ugly_thing(mons.type == MONS_VERY_UGLY_THING, false,
+ ghost.init_ugly_thing(mon->type == MONS_VERY_UGLY_THING, false,
mg.colour);
- mons.set_ghost(ghost, false);
- mons.uglything_init();
+ mon->set_ghost(ghost, false);
+ mon->uglything_init();
}
- else if (mons.type == MONS_PANDEMONIUM_DEMON)
+ else if (mon->type == MONS_PANDEMONIUM_DEMON)
{
ghost_demon ghost;
ghost.init_random_demon();
- mons.set_ghost(ghost);
- mons.pandemon_init();
+ mon->set_ghost(ghost);
+ mon->pandemon_init();
}
- else if (mons.type == MONS_DANCING_WEAPON)
+ else if (mon->type == MONS_DANCING_WEAPON)
{
ghost_demon ghost;
// We can't use monsters::weapon here because it wants to look
// at attack types, which are in the ghost structure we're
// building.
- ASSERT( mons.mslot_item(MSLOT_WEAPON) );
+ ASSERT(mon->mslot_item(MSLOT_WEAPON));
// Dancing weapons are placed at pretty high power. Remember, the
// player is fighting them one-on-one, while he will often summon
// several.
- ghost.init_dancing_weapon(*(mons.mslot_item(MSLOT_WEAPON)), 180);
- mons.set_ghost(ghost);
- mons.dancing_weapon_init();
+ ghost.init_dancing_weapon(*(mon->mslot_item(MSLOT_WEAPON)), 180);
+ mon->set_ghost(ghost);
+ mon->dancing_weapon_init();
}
- mark_interesting_monst(&mons, mg.behaviour);
+ mark_interesting_monst(mon, mg.behaviour);
- if (you.can_see(&mons))
- handle_seen_interrupt(&mons);
+ if (you.can_see(mon))
+ handle_seen_interrupt(mon);
if (crawl_state.arena)
- arena_placed_monster(&mons);
+ arena_placed_monster(mon);
return (id);
}
@@ -2398,6 +2438,11 @@ int mons_place(mgen_data mg)
break;
}
+ if (mg.behaviour == BEH_COPY)
+ mg.behaviour = mg.summoner == &you
+ ? BEH_FRIENDLY
+ : SAME_ATTITUDE((&menv[mg.summoner->mindex()]));
+
int mid = place_monster(mg);
if (mid == -1)
return (-1);
diff --git a/crawl-ref/source/monplace.h b/crawl-ref/source/mon-place.h
index 7e35108863..bf9cd64ec2 100644
--- a/crawl-ref/source/monplace.h
+++ b/crawl-ref/source/mon-place.h
@@ -1,5 +1,5 @@
/*
- * File: monplace.h
+ * File: mon-place.h
* Summary: Functions used when placing monsters in the dungeon.
* Written by: Linley Henzell
*/
@@ -126,6 +126,10 @@ struct mgen_data
// XXX: Could use splitting up these aspects.
beh_type behaviour;
+ // Who summoned this monster? Important to know for death accounting
+ // and the summon cap, if and when it goes in. NULL is no summoner.
+ actor* summoner;
+
// For summoned monsters, this is a measure of how long the summon will
// hang around, on a scale of 1-6, 6 being longest. Use 0 for monsters
// that aren't summoned.
@@ -190,8 +194,13 @@ struct mgen_data
// XXX: Rather hackish.
std::string mname;
+ // This is used to account for non-actor summoners. Blasted by an Ice
+ // Fiend ... summoned by the effects of Hell.
+ std::string non_actor_summoner;
+
mgen_data(monster_type mt = RANDOM_MONSTER,
beh_type beh = BEH_HOSTILE,
+ actor* sner = 0,
int abj = 0,
int st = 0,
const coord_def &p = coord_def(-1, -1),
@@ -204,13 +213,14 @@ struct mgen_data
int monpower = you.your_level,
proximity_type prox = PROX_ANYWHERE,
level_area_type ltype = you.level_type,
- std::string monname = "")
+ std::string monname = "",
+ std::string nas = "")
- : cls(mt), base_type(base), behaviour(beh),
+ : cls(mt), base_type(base), behaviour(beh), summoner(sner),
abjuration_duration(abj), summon_type(st), pos(p), foe(mfoe),
flags(monflags), god(which_god), number(monnumber), colour(moncolour),
power(monpower), proximity(prox), level_type(ltype), map_mask(0),
- mname(monname)
+ mname(monname), non_actor_summoner(nas)
{
ASSERT(summon_type == 0 || (abj >= 1 && abj <= 6)
|| mt == MONS_BALL_LIGHTNING);
@@ -230,10 +240,11 @@ struct mgen_data
const coord_def &where,
unsigned flags = 0)
{
- return mgen_data(what, BEH_SLEEP, 0, 0, where, MHITNOT, flags);
+ return mgen_data(what, BEH_SLEEP, 0, 0, 0, where, MHITNOT, flags);
}
static mgen_data hostile_at(monster_type mt,
+ std::string summoner,
bool alert = false,
int abj = 0,
int st = 0,
@@ -243,9 +254,10 @@ struct mgen_data
monster_type base = MONS_NO_MONSTER)
{
- return mgen_data(mt, BEH_HOSTILE, abj, st, p,
+ return mgen_data(mt, BEH_HOSTILE, 0, abj, st, p,
alert ? MHITYOU : MHITNOT,
- monflags, god, base);
+ monflags, god, base, 0, BLACK, you.your_level,
+ PROX_ANYWHERE, you.level_type, "", summoner);
}
};
@@ -335,6 +347,8 @@ void setup_vault_mon_list();
int mons_tracking_range(const monsters *mon);
+monsters* get_free_monster();
+
class monster_pathfind
{
public:
diff --git a/crawl-ref/source/monspeak.cc b/crawl-ref/source/mon-speak.cc
index 8f66ebb025..3f21434520 100644
--- a/crawl-ref/source/monspeak.cc
+++ b/crawl-ref/source/mon-speak.cc
@@ -1,11 +1,11 @@
/*
- * File: monspeak.cc
+ * File: mon-speak.cc
* Summary: Functions to handle speaking monsters
*/
#include "AppHdr.h"
-#include "monspeak.h"
+#include "mon-speak.h"
#include <stdlib.h>
#include <string.h>
@@ -23,7 +23,7 @@
#include "debug.h"
#include "ghost.h"
#include "message.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "jobs.h"
#include "player.h"
@@ -355,6 +355,60 @@ static bool _polyd_can_speak(const monsters* monster)
return (shape >= MON_SHAPE_HUMANOID && shape <= MON_SHAPE_NAGA);
}
+// Returns true if the monster did speak, false otherwise.
+// Maybe monsters will speak!
+void maybe_mons_speaks (monsters *monster)
+{
+#define MON_SPEAK_CHANCE 21
+
+ if (monster->is_patrolling() || mons_is_wandering(monster)
+ || monster->attitude == ATT_NEUTRAL)
+ {
+ // Very fast wandering/patrolling monsters might, in one monster turn,
+ // move into the player's LOS and then back out (or the player
+ // might move into their LOS and the monster move back out before
+ // the player's view has a chance to update) so prevent them
+ // from speaking.
+ ;
+ }
+ else if ((mons_class_flag(monster->type, M_SPEAKS)
+ || !monster->mname.empty())
+ && one_chance_in(MON_SPEAK_CHANCE))
+ {
+ mons_speaks(monster);
+ }
+ else if (monster->type == MONS_CRAZY_YIUF
+ && one_chance_in(MON_SPEAK_CHANCE / 3))
+ {
+ // Yiuf gets an extra chance to speak!
+ mons_speaks(monster);
+ }
+ else if (get_mon_shape(monster) >= MON_SHAPE_QUADRUPED)
+ {
+ // Non-humanoid-ish monsters have a low chance of speaking
+ // without the M_SPEAKS flag, to give the dungeon some
+ // atmosphere/flavour.
+ int chance = MON_SPEAK_CHANCE * 4;
+
+ // Band members are a lot less likely to speak, since there's
+ // a lot of them. Except for uniques.
+ if (testbits(monster->flags, MF_BAND_MEMBER)
+ && !mons_is_unique(monster->type))
+ chance *= 10;
+
+ // However, confused and fleeing monsters are more interesting.
+ if (mons_is_fleeing(monster))
+ chance /= 2;
+ if (monster->has_ench(ENCH_CONFUSION))
+ chance /= 2;
+
+ if (one_chance_in(chance))
+ mons_speaks(monster);
+ }
+ // Okay then, don't speak.
+}
+
+
// Returns true if something is said.
bool mons_speaks(monsters *monster)
{
diff --git a/crawl-ref/source/monspeak.h b/crawl-ref/source/mon-speak.h
index 674aaa1257..e0e65b24ff 100644
--- a/crawl-ref/source/monspeak.h
+++ b/crawl-ref/source/mon-speak.h
@@ -1,5 +1,5 @@
/*
- * File: monspeak.h
+ * File: mon-speak.h
* Summary: Functions to handle speaking monsters
*/
@@ -8,6 +8,7 @@
#include "externs.h"
+void maybe_mons_speaks(monsters *monster);
bool mons_speaks(monsters *monster);
bool mons_speaks_msg(monsters *monster, const std::string &msg,
const msg_channel_type def_chan = MSGCH_TALK,
diff --git a/crawl-ref/source/mon-spll.h b/crawl-ref/source/mon-spll.h
index 52d6f152a7..9989ddcd21 100644
--- a/crawl-ref/source/mon-spll.h
+++ b/crawl-ref/source/mon-spll.h
@@ -1080,7 +1080,7 @@
SPELL_SLOW,
SPELL_SUMMON_UGLY_THING,
SPELL_PORKALATOR,
- SPELL_BACKLIGHT,
+ SPELL_CORONA,
SPELL_INVISIBILITY
}
},
@@ -1088,7 +1088,7 @@
{ MST_DOWAN,
{
SPELL_THROW_FROST,
- SPELL_BACKLIGHT,
+ SPELL_CORONA,
SPELL_BLINK,
SPELL_THROW_FLAME,
SPELL_HASTE_OTHER,
@@ -1100,7 +1100,7 @@
{
SPELL_AIRSTRIKE,
SPELL_SLOW,
- SPELL_AIRSTRIKE,
+ SPELL_SWIFTNESS,
SPELL_SUMMON_SMALL_MAMMALS,
SPELL_CANTRIP,
SPELL_AIRSTRIKE,
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/mon-stuff.cc
index d94598974c..0e8a3b436f 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/mon-stuff.cc
@@ -1,11 +1,11 @@
/*
- * File: monstuff.cc
+ * File: mon-stuff.cc
* Summary: Misc monster related functions.
* Written by: Linley Henzell
*/
#include "AppHdr.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
//#include <stdlib.h>
//#include <string.h>
@@ -35,8 +35,9 @@
#include "misc.h"
#include "mon-abil.h"
#include "mon-behv.h"
-#include "monplace.h"
-#include "monspeak.h"
+#include "mon-iter.h"
+#include "mon-place.h"
+#include "mon-speak.h"
#include "notes.h"
#include "options.h"
#include "player.h"
@@ -334,11 +335,16 @@ monster_type fill_out_corpse(const monsters* monster, item_def& corpse,
corpse.colour = monster->colour;
if (!monster->mname.empty())
+ {
corpse.props[CORPSE_NAME_KEY] = monster->mname;
+ corpse.props[CORPSE_NAME_TYPE_KEY]
+ = (long) (monster->flags & MF_NAME_MASK);
+ }
else if (mons_is_unique(monster->type))
{
corpse.props[CORPSE_NAME_KEY] = mons_type_name(monster->type,
DESC_PLAIN);
+ corpse.props[CORPSE_NAME_TYPE_KEY] = (long) 0;
}
return (corpse_class);
@@ -1213,44 +1219,57 @@ static void _elven_twin_died(monsters* twin)
bool found_dowan = false;
monsters *monster;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monster = &menv[i];
- if (monster->alive() && monster->type == MONS_DUVESSA)
+ if (mi->type == MONS_DUVESSA)
{
+ monster = *mi;
found_duvessa = true;
break;
}
- else if (monster->alive() && monster->type == MONS_DOWAN)
+ else if (mi->type == MONS_DOWAN)
{
+ monster = *mi;
found_dowan = true;
break;
}
}
- if ((found_duvessa || found_dowan) && mons_near(monster))
- {
- // Will generate strings such as 'Duvessa_Duvessa_dies' or, alternately
- // 'Dowan_Dowan_dies', but as neither will match, these can safely be
- // ignored.
- std::string key = "_" + monster->name(DESC_CAP_THE, true) + "_"
- + twin->name(DESC_CAP_THE) + "_dies_";
+ if (!found_duvessa && !found_dowan)
+ return;
- if (!monster->observable())
- key += "invisible_";
+ // If you've stabbed one of them, the other one is likely asleep still.
+ if (monster->asleep())
+ behaviour_event(monster, ME_DISTURB, MHITNOT, monster->pos());
- std::string death_message = getSpeakString(key);
+ // Will generate strings such as 'Duvessa_Duvessa_dies' or, alternately
+ // 'Dowan_Dowan_dies', but as neither will match, these can safely be
+ // ignored.
+ std::string key = "_" + monster->name(DESC_CAP_THE, true) + "_"
+ + twin->name(DESC_CAP_THE) + "_dies_";
- if (!death_message.empty())
- mons_speaks_msg(monster, death_message, MSGCH_TALK, silenced(you.pos()));
- }
+ if (mons_near(monster) && !monster->observable())
+ key += "invisible_";
+ else if (!mons_near(monster))
+ key += "distance_";
- if (found_duvessa && mons_near(monster))
+ std::string death_message = getSpeakString(key);
+
+ if (mons_near(monster) && !death_message.empty())
+ mons_speaks_msg(monster, death_message, MSGCH_TALK, silenced(you.pos()));
+ else
+ mprf("%s", death_message.c_str());
+
+ if (found_duvessa)
{
- // Provides its own flavour message.
- monster->go_berserk(true);
+ if (mons_near(monster))
+ // Provides its own flavour message.
+ monster->go_berserk(true);
+ else
+ // She'll go berserk the next time she sees you
+ monster->flags |= MF_GOING_BERSERK;
}
- else if (found_dowan && mons_near(monster))
+ else if (found_dowan)
{
// Doesn't provide any message, so needs one, but only if visible.
if (monster->observable())
@@ -1267,18 +1286,17 @@ void pikel_band_neutralise ()
// with MF_BAND_MEMBER are Pikel's band members.
bool message_made = false;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
- if (monster->alive() && monster->type == MONS_HUMAN
- && testbits(monster->flags, MF_BAND_MEMBER))
+ if (mi->type == MONS_HUMAN
+ && testbits(mi->flags, MF_BAND_MEMBER))
{
- if (monster->observable() && !message_made)
+ if (mi->observable() && !message_made)
{
mpr("Pikel's slaves thank you for their freedom.");
message_made = true;
}
- mons_pacify(monster);
+ mons_pacify(*mi);
}
}
}
@@ -1294,60 +1312,87 @@ static void _hogs_to_humans()
// porkalator spell, they should be handled specially...
int any = 0, human = 0;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
- if (monster->alive() && monster->type == MONS_HOG)
+ if (mi->type != MONS_HOG)
+ continue;
+
+ // Shapeshifters will stop being a hog when they feel like it.
+ if (mi->is_shapeshifter())
+ continue;
+
+ const bool could_see = you.can_see(*mi);
+
+ monsters _orig;
+ monsters* orig;
+
+ if (mi->props.exists(ORIG_MONSTER_KEY))
{
- const bool could_see = you.can_see(monster);
+ orig = &(mi->props[ORIG_MONSTER_KEY].get_monster());
+ }
+ else
+ {
+ orig = &_orig;
+ orig->type = MONS_HUMAN;
+ define_monster(*orig);
+ }
- // XXX: This resets the size of slime creatures, the number
- // of heads a hydra has, and the number of spikes a manticore
- // has. Plus it also changes the colour of a draconian which
- // has a sub-type. And it re-rolls the spellbook the monster
- // has.
- if (monster->number == 0)
- monster->type = MONS_HUMAN;
- else
- monster->type = (monster_type) (monster->number - 1);
+ // Preserve relative HP.
+ const float hp
+ = (float) mi->hit_points / (float) mi->max_hit_points;
+ // Preserve some flags.
+ const unsigned long preserve_flags =
+ mi->flags & ~(MF_JUST_SUMMONED | MF_WAS_IN_VIEW);
- monster->number = 0;
- define_monster(*monster);
+ // Preserve enchantments.
+ mon_enchant_list enchantments = mi->enchantments;
- const bool can_see = you.can_see(monster);
+ // Restore original monster.
+ **mi = *orig;
- // A monster changing factions while in the arena messes up
- // arena book-keeping.
- if (!crawl_state.arena)
+ mi->enchantments = enchantments;
+ mi->hit_points = std::max(1, (int) (mi->max_hit_points * hp));
+ mi->flags = mi->flags | preserve_flags;
+
+ // Allow ORIG_MONSTER_KEY to be chained.
+ if (orig->props.exists(ORIG_MONSTER_KEY))
+ mi->props[ORIG_MONSTER_KEY] = orig->props[ORIG_MONSTER_KEY];
+ else
+ mi->props.erase(ORIG_MONSTER_KEY);
+
+ const bool can_see = you.can_see(*mi);
+
+ // A monster changing factions while in the arena messes up
+ // arena book-keeping.
+ if (!crawl_state.arena)
+ {
+ // * A monster's attitude shouldn't downgrade from friendly
+ // or good-neutral because you helped it. It'd suck to
+ // lose a permanent ally that way.
+ //
+ // * A monster has to be smart enough to realize that you
+ // helped it.
+ if (mi->attitude == ATT_HOSTILE
+ && mons_intel(*mi) >= I_NORMAL)
{
- // * A monster's attitude shouldn't downgrade from friendly
- // or good-neutral because you helped it. It'd suck to
- // lose a permanent ally that way.
- //
- // * A monster has to be smart enough to realize that you
- // helped it.
- if (monster->attitude == ATT_HOSTILE
- && mons_intel(monster) >= I_NORMAL)
- {
- monster->attitude = ATT_GOOD_NEUTRAL;
- monster->flags |= MF_WAS_NEUTRAL;
- }
+ mi->attitude = ATT_GOOD_NEUTRAL;
+ mi->flags |= MF_WAS_NEUTRAL;
}
+ }
- behaviour_event(monster, ME_EVAL);
+ behaviour_event(*mi, ME_EVAL);
- if (could_see && can_see)
- {
- any++;
- if (monster->type == MONS_HUMAN)
- human++;
- }
- else if (could_see && !can_see)
- mpr("The hog vanishes!");
- else if (!could_see && can_see)
- mprf("%s appears from out of thin air!",
- monster->name(DESC_CAP_A).c_str());
+ if (could_see && can_see)
+ {
+ any++;
+ if (mi->type == MONS_HUMAN)
+ human++;
}
+ else if (could_see && !can_see)
+ mpr("The hog vanishes!");
+ else if (!could_see && can_see)
+ mprf("%s appears from out of thin air!",
+ mi->name(DESC_CAP_A).c_str());
}
if (any == 1)
@@ -1391,14 +1436,13 @@ void mons_relocated(monsters *monster)
if (invalid_monster_index(headnum))
return;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *tentacle = &menv[i];
- if (tentacle->type == MONS_KRAKEN_TENTACLE
- && (int)tentacle->number == headnum
- && _tentacle_too_far(monster, tentacle))
+ if (mi->type == MONS_KRAKEN_TENTACLE
+ && (int)mi->number == headnum
+ && _tentacle_too_far(monster, *mi))
{
- monster_die(tentacle, KILL_RESET, -1, true, false);
+ monster_die(*mi, KILL_RESET, -1, true, false);
}
}
}
@@ -1421,15 +1465,14 @@ static int _destroy_tentacles(monsters *head)
if (invalid_monster_index(headnum))
return 0;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
- if (monster->type == MONS_KRAKEN_TENTACLE
- && (int)monster->number == headnum)
+ if (mi->type == MONS_KRAKEN_TENTACLE
+ && (int)mi->number == headnum)
{
- if (mons_near(monster))
+ if (mons_near(*mi))
tent++;
- monster->hurt(monster, INSTANT_DEATH);
+ mi->hurt(*mi, INSTANT_DEATH);
}
}
return tent;
@@ -1793,7 +1836,7 @@ int monster_die(monsters *monster, killer_type killer,
{
const int spectre =
create_monster(
- mgen_data(MONS_SPECTRAL_THING, BEH_FRIENDLY,
+ mgen_data(MONS_SPECTRAL_THING, BEH_FRIENDLY, &you,
0, 0, monster->pos(), MHITYOU,
0, static_cast<god_type>(you.attribute[ATTR_DIVINE_DEATH_CHANNEL]),
spectre_type, monster->number));
@@ -2200,9 +2243,9 @@ void monster_cleanup(monsters *monster)
unsigned int monster_killed = monster_index(monster);
monster->reset();
- for (int dmi = 0; dmi < MAX_MONSTERS; dmi++)
- if (menv[dmi].foe == monster_killed)
- menv[dmi].foe = MHITNOT;
+ for (monster_iterator mi; mi; ++mi)
+ if (mi->foe == monster_killed)
+ mi->foe = MHITNOT;
if (you.pet_target == monster_killed)
you.pet_target = MHITNOT;
@@ -2211,24 +2254,14 @@ void monster_cleanup(monsters *monster)
// If you're invis and throw/zap whatever, alerts menv to your position.
void alert_nearby_monsters(void)
{
- monsters *monster = 0; // NULL {dlb}
-
- for (int it = 0; it < MAX_MONSTERS; it++)
- {
- monster = &menv[it];
-
- // Judging from the above comment, this function isn't
- // intended to wake up monsters, so we're only going to
- // alert monsters that aren't sleeping. For cases where an
- // event should wake up monsters and alert them, I'd suggest
- // calling noisy() before calling this function. -- bwr
- if (monster->alive()
- && mons_near(monster)
- && !monster->asleep())
- {
- behaviour_event(monster, ME_ALERT, MHITYOU);
- }
- }
+ // Judging from the above comment, this function isn't
+ // intended to wake up monsters, so we're only going to
+ // alert monsters that aren't sleeping. For cases where an
+ // event should wake up monsters and alert them, I'd suggest
+ // calling noisy() before calling this function. -- bwr
+ for (monster_iterator mi(&you.get_los()); mi; ++mi)
+ if (!mi->asleep())
+ behaviour_event(*mi, ME_ALERT, MHITYOU);
}
static bool _valid_morph(monsters *monster, monster_type new_mclass)
@@ -3621,15 +3654,14 @@ int dismiss_monsters(std::string pattern) {
// Dismiss by regex
text_pattern tpat(pattern);
int ndismissed = 0;
- for (int mon = 0; mon < MAX_MONSTERS; mon++)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[mon];
- if (monster->alive() &&
- (tpat.empty() || tpat.matches(monster->name(DESC_PLAIN, true))))
+ if (mi->alive() &&
+ (tpat.empty() || tpat.matches(mi->name(DESC_PLAIN, true))))
{
if (!keep_item)
- _vanish_orig_eq(monster);
- monster_die(monster, KILL_DISMISSED, NON_MONSTER, false, true);
+ _vanish_orig_eq(*mi);
+ monster_die(*mi, KILL_DISMISSED, NON_MONSTER, false, true);
++ndismissed;
}
}
@@ -3846,15 +3878,9 @@ int clone_mons(const monsters* orig, bool quiet, bool* obvious,
coord_def pos)
{
// Is there an open slot in menv?
- int midx = NON_MONSTER;
- for (int i = 0; i < MAX_MONSTERS; i++)
- if (menv[i].type == MONS_NO_MONSTER)
- {
- midx = i;
- break;
- }
+ monsters* mons = get_free_monster();
- if (midx == NON_MONSTER)
+ if (!mons)
return (NON_MONSTER);
if (!in_bounds(pos))
@@ -3880,11 +3906,9 @@ int clone_mons(const monsters* orig, bool quiet, bool* obvious,
ASSERT( !actor_at(pos) );
- monsters &mon(menv[midx]);
-
- mon = *orig;
- mon.set_position(pos);
- mgrd(pos) = midx;
+ *mons = *orig;
+ mons->set_position(pos);
+ mgrd(pos) = mons->mindex();
// Duplicate objects, or unequip them if they can't be duplicated.
for (int i = 0; i < NUM_MONSTER_SLOTS; i++)
@@ -3897,14 +3921,14 @@ int clone_mons(const monsters* orig, bool quiet, bool* obvious,
const int new_index = get_item_slot(0);
if (new_index == NON_ITEM)
{
- mon.unequip(mitm[old_index], i, 0, true);
- mon.inv[i] = NON_ITEM;
+ mons->unequip(mitm[old_index], i, 0, true);
+ mons->inv[i] = NON_ITEM;
continue;
}
- mon.inv[i] = new_index;
+ mons->inv[i] = new_index;
mitm[new_index] = mitm[old_index];
- mitm[new_index].set_holding_monster(midx);
+ mitm[new_index].set_holding_monster(mons->mindex());
}
bool _obvious;
@@ -3912,24 +3936,24 @@ int clone_mons(const monsters* orig, bool quiet, bool* obvious,
obvious = &_obvious;
*obvious = false;
- if (you.can_see(orig) && you.can_see(&mon))
+ if (you.can_see(orig) && you.can_see(mons))
{
if (!quiet)
simple_monster_message(orig, " is duplicated!");
*obvious = true;
}
- mark_interesting_monst(&mon, mon.behaviour);
- if (you.can_see(&mon))
+ mark_interesting_monst(mons, mons->behaviour);
+ if (you.can_see(mons))
{
- handle_seen_interrupt(&mon);
+ handle_seen_interrupt(mons);
viewwindow(false);
}
if (crawl_state.arena)
- arena_placed_monster(&mon);
+ arena_placed_monster(mons);
- return (midx);
+ return (mons->mindex());
}
std::string summoned_poof_msg(const monsters* monster, bool plural)
diff --git a/crawl-ref/source/monstuff.h b/crawl-ref/source/mon-stuff.h
index 75656c73a1..4f1bb73a78 100644
--- a/crawl-ref/source/monstuff.h
+++ b/crawl-ref/source/mon-stuff.h
@@ -1,5 +1,5 @@
/*
- * File: monstuff.h
+ * File: mon-stuff.h
* Summary: Misc monster related functions.
* Written by: Linley Henzell
*/
@@ -10,6 +10,8 @@
#include "mon-util.h"
+#define ORIG_MONSTER_KEY "orig_monster_key"
+
enum mon_dam_level_type
{
MDAM_OKAY,
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index b0a831e167..d891ed2b50 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -23,8 +23,8 @@
#include "kills.h"
#include "los.h"
#include "mon-behv.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "options.h"
#include "random.h"
#include "religion.h"
@@ -1360,8 +1360,8 @@ monster_type random_draconian_monster_species()
// Note: For consistent behavior in player_will_anger_monster(), all
// spellbooks a given monster can get here should produce the same
-// return values in is_holy_spell(), is_evil_spell(), and
-// is_chaotic_spell().
+// return values in is_holy_spell(), (is_unholy_spell() ||
+// is_evil_spell()), and is_chaotic_spell().
//
// FIXME: This is not true for one set of spellbooks; MST_WIZARD_IV
// contains the evil Banishment spell, but the other MST_WIZARD-type
@@ -2209,6 +2209,7 @@ bool ms_useful_fleeing_out_of_sight( const monsters *mon, spell_type monspell )
switch (monspell)
{
case SPELL_HASTE:
+ case SPELL_SWIFTNESS:
case SPELL_INVISIBILITY:
case SPELL_MINOR_HEALING:
case SPELL_MAJOR_HEALING:
@@ -2355,7 +2356,7 @@ bool ms_waste_of_time( const monsters *mon, spell_type monspell )
ret = (!foe || foe->holiness() != MH_UNDEAD);
break;
- case SPELL_BACKLIGHT:
+ case SPELL_CORONA:
ret = (!foe || foe->backlit());
break;
@@ -2369,6 +2370,11 @@ bool ms_waste_of_time( const monsters *mon, spell_type monspell )
ret = true;
break;
+ case SPELL_SWIFTNESS:
+ if (mon->has_ench(ENCH_SWIFT))
+ ret = true;
+ break;
+
case SPELL_INVISIBILITY:
if (mon->has_ench(ENCH_INVIS)
|| mon->friendly() && !you.can_see_invisible(false))
@@ -2410,8 +2416,9 @@ bool ms_waste_of_time( const monsters *mon, spell_type monspell )
case SPELL_DISINTEGRATE:
case SPELL_PARALYSE:
case SPELL_SLEEP:
+ case SPELL_HIBERNATION:
{
- if (monspell == SPELL_SLEEP && (!foe || foe->asleep()))
+ if (monspell == SPELL_HIBERNATION && (!foe || foe->asleep()))
{
ret = true;
break;
@@ -2522,6 +2529,7 @@ static bool _ms_ranged_spell(spell_type monspell, bool attack_only = false,
case SPELL_INVISIBILITY:
case SPELL_BLINK:
case SPELL_BERSERKER_RAGE:
+ case SPELL_SWIFTNESS:
return (false);
// The animation spells don't work through transparent walls and thus
@@ -2533,6 +2541,7 @@ static bool _ms_ranged_spell(spell_type monspell, bool attack_only = false,
case SPELL_CONFUSE:
case SPELL_SLOW:
case SPELL_PARALYSE:
+ case SPELL_SLEEP:
case SPELL_TELEPORT_OTHER:
return (ench_too);
diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc
index 4b706d8a47..869e65ce68 100644
--- a/crawl-ref/source/monster.cc
+++ b/crawl-ref/source/monster.cc
@@ -19,8 +19,8 @@
#include "misc.h"
#include "mon-abil.h"
#include "mon-behv.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mtransit.h"
#include "random.h"
#include "religion.h"
@@ -52,7 +52,7 @@ monsters::monsters()
inv(NON_ITEM), spells(), attitude(ATT_HOSTILE), behaviour(BEH_WANDER),
foe(MHITYOU), enchantments(), flags(0L), experience(0), number(0),
colour(BLACK), foe_memory(0), shield_blocks(0), god(GOD_NO_GOD), ghost(),
- seen_context("")
+ seen_context(""), props()
{
travel_path.clear();
}
@@ -105,6 +105,7 @@ void monsters::reset()
travel_path.clear();
ghost.reset(NULL);
seen_context = "";
+ props.clear();
}
void monsters::init_with(const monsters &mon)
@@ -136,6 +137,7 @@ void monsters::init_with(const monsters &mon)
colour = mon.colour;
foe_memory = mon.foe_memory;
god = mon.god;
+ props = mon.props;
if (mon.ghost.get())
ghost.reset(new ghost_demon(*mon.ghost));
@@ -1199,6 +1201,8 @@ static bool _compatible_launcher_ammo_brands(item_def *launcher,
return (bow_brand != SPWPN_FLAME && bow_brand != SPWPN_FROST);
case SPMSL_CHAOS:
return (bow_brand != SPWPN_CHAOS);
+ case SPMSL_REAPING:
+ return (bow_brand != SPWPN_HOLY_WRATH);
default:
return (true);
}
@@ -1758,7 +1762,7 @@ bool monsters::pickup_misc(item_def &item, int near)
return (pickup(item, MSLOT_MISCELLANY, near));
}
-// Eaten items are handled elsewhere, in _handle_pickup() in monstuff.cc.
+// Eaten items are handled elsewhere, in _handle_pickup() in mon-stuff.cc.
bool monsters::pickup_item(item_def &item, int near, bool force)
{
// Equipping stuff can be forced when initially equipping monsters.
@@ -2850,7 +2854,7 @@ bool monsters::asleep() const
bool monsters::backlit(bool check_haloed) const
{
- return (has_ench(ENCH_BACKLIGHT)
+ return (has_ench(ENCH_CORONA)
|| ((check_haloed) ? haloed() : false));
}
@@ -3508,7 +3512,7 @@ bool monsters::rot(actor *agent, int amount, int immediate, bool quiet)
int monsters::hurt(const actor *agent, int amount, beam_type flavour,
bool cleanup_dead)
{
- if (hit_points > 0 && type != -1)
+ if (alive())
{
if (amount == INSTANT_DEATH)
amount = hit_points;
@@ -4208,6 +4212,11 @@ void monsters::remove_enchantment_effect(const mon_enchant &me, bool quiet)
simple_monster_message(this, " is no longer moving quickly.");
break;
+ case ENCH_SWIFT:
+ if (!quiet)
+ simple_monster_message(this, " is no longer moving somewhat quickly.");
+ break;
+
case ENCH_MIGHT:
if (!quiet)
simple_monster_message(this, " no longer looks unusually strong.");
@@ -4322,7 +4331,7 @@ void monsters::remove_enchantment_effect(const mon_enchant &me, bool quiet)
behaviour_event(this, ME_EVAL);
break;
- case ENCH_BACKLIGHT:
+ case ENCH_CORONA:
if (!quiet)
{
if (visible_to(&you))
@@ -4515,12 +4524,12 @@ void monsters::timeout_enchantments(int levels)
{
switch (i->first)
{
- case ENCH_POISON: case ENCH_ROT: case ENCH_BACKLIGHT:
+ case ENCH_POISON: case ENCH_ROT: case ENCH_CORONA:
case ENCH_STICKY_FLAME: case ENCH_ABJ: case ENCH_SHORT_LIVED:
case ENCH_SLOW: case ENCH_HASTE: case ENCH_MIGHT: case ENCH_FEAR:
case ENCH_INVIS: case ENCH_CHARM: case ENCH_SLEEP_WARY:
case ENCH_SICK: case ENCH_SLEEPY: case ENCH_PARALYSIS:
- case ENCH_PETRIFYING: case ENCH_PETRIFIED:
+ case ENCH_PETRIFYING: case ENCH_PETRIFIED: case ENCH_SWIFT:
case ENCH_BATTLE_FRENZY: case ENCH_NEUTRAL:
case ENCH_LOWERED_MR: case ENCH_SOUL_RIPE:
lose_ench_levels(i->second, levels);
@@ -4654,6 +4663,7 @@ void monsters::apply_enchantment(const mon_enchant &me)
case ENCH_SLOW:
case ENCH_HASTE:
+ case ENCH_SWIFT:
case ENCH_MIGHT:
case ENCH_FEAR:
case ENCH_PARALYSIS:
@@ -4661,7 +4671,7 @@ void monsters::apply_enchantment(const mon_enchant &me)
case ENCH_PETRIFYING:
case ENCH_PETRIFIED:
case ENCH_SICK:
- case ENCH_BACKLIGHT:
+ case ENCH_CORONA:
case ENCH_ABJ:
case ENCH_CHARM:
case ENCH_SLEEP_WARY:
@@ -5001,6 +5011,7 @@ void monsters::apply_enchantment(const mon_enchant &me)
int rc = create_monster(mgen_data(MONS_GIANT_SPORE,
created_behavior,
+ this,
0,
0,
adjacent,
@@ -5576,7 +5587,7 @@ bool monsters::do_shaft()
return (reveal);
}
-bool monsters::can_sleep(bool holi_only) const
+bool monsters::can_hibernate(bool holi_only) const
{
// Undead, nonliving, and plants don't sleep.
const mon_holy_type holi = holiness();
@@ -5601,9 +5612,9 @@ bool monsters::can_sleep(bool holi_only) const
return (true);
}
-void monsters::put_to_sleep(int)
+void monsters::hibernate(int)
{
- if (!can_sleep())
+ if (!can_hibernate())
return;
behaviour = BEH_SLEEP;
@@ -5624,12 +5635,14 @@ const monsterentry *monsters::find_monsterentry() const
int monsters::action_energy(energy_use_type et) const
{
+ bool swift = has_ench(ENCH_SWIFT);
+
if (const monsterentry *me = find_monsterentry())
{
const mon_energy_usage &mu = me->energy_usage;
switch (et)
{
- case EUT_MOVE: return mu.move;
+ case EUT_MOVE: return mu.move - (swift ? 2 : 0);
case EUT_SWIM:
// [ds] Amphibious monsters get a significant speed boost
// when swimming, as discussed with dpeg. We do not
@@ -5638,9 +5651,9 @@ int monsters::action_energy(energy_use_type et) const
// favour water (HT_AMPHIBIOUS_WATER, such as merfolk), but
// that's something we can think about.
if (mons_amphibious(this))
- return div_rand_round(mu.swim * 7, 10);
+ return div_rand_round(mu.swim * 7, 10) - (swift ? 2 : 0);
else
- return mu.swim;
+ return mu.swim - (swift ? 2 : 0);
case EUT_MISSILE: return mu.missile;
case EUT_ITEM: return mu.item;
case EUT_SPECIAL: return mu.special;
@@ -5835,7 +5848,7 @@ void monsters::react_to_damage(int damage, beam_type flavour, kill_category whos
continue;
const int nmons = mons_place(
- mgen_data(jelly, beha, 0, 0,
+ mgen_data(jelly, beha, this, 0, 0,
jpos, foe, 0, god));
if (nmons != -1 && nmons != NON_MONSTER)
@@ -5893,7 +5906,7 @@ static const char *enchant_names[] =
"short-lived", "paralysis", "sick", "sleep", "fatigue", "held",
"blood-lust", "neutral", "petrifying", "petrified", "magic-vulnerable",
"soul-ripe", "decay", "hungry", "flopping", "spore-producing",
- "downtrodden", "bug"
+ "downtrodden", "swift", "bug"
};
static const char *_mons_enchantment_name(enchant_type ench)
@@ -5994,6 +6007,7 @@ int mon_enchant::calc_duration(const monsters *mons,
switch (ench)
{
case ENCH_HASTE:
+ case ENCH_SWIFT:
case ENCH_MIGHT:
case ENCH_INVIS:
cturn = 1000 / _mod_speed(25, mons->speed);
@@ -6030,7 +6044,7 @@ int mon_enchant::calc_duration(const monsters *mons,
cturn = 1000 * (deg - 1) / _mod_speed(333, mons->speed);
cturn += 1000 / _mod_speed(250, mons->speed);
break;
- case ENCH_BACKLIGHT:
+ case ENCH_CORONA:
if (deg > 1)
cturn = 1000 * (deg - 1) / _mod_speed(200, mons->speed);
cturn += 1000 / _mod_speed(100, mons->speed);
diff --git a/crawl-ref/source/monster.h b/crawl-ref/source/monster.h
index 26b266ee37..8725688d01 100644
--- a/crawl-ref/source/monster.h
+++ b/crawl-ref/source/monster.h
@@ -60,6 +60,7 @@ public:
void reset();
public:
+ // Possibly some of these should be moved into the hash table
std::string mname;
monster_type type;
@@ -102,6 +103,8 @@ public:
std::string seen_context; // Non-standard context for
// AI_SEE_MONSTER
+ CrawlHashTable props;
+
public:
mon_attitude_type temp_attitude() const;
@@ -377,8 +380,8 @@ public:
void blink(bool allow_partial_control = true);
void teleport(bool right_now = false, bool abyss_shift = false);
- bool can_sleep(bool holi_only = false) const;
- void put_to_sleep(int power = 0);
+ bool can_hibernate(bool holi_only = false) const;
+ void hibernate(int power = 0);
void check_awaken(int disturbance);
int stat_hp() const { return hit_points; }
diff --git a/crawl-ref/source/mtransit.cc b/crawl-ref/source/mtransit.cc
index a743278398..e9bf292df2 100644
--- a/crawl-ref/source/mtransit.cc
+++ b/crawl-ref/source/mtransit.cc
@@ -13,7 +13,7 @@
#include "artefact.h"
#include "dungeon.h"
#include "items.h"
-#include "monplace.h"
+#include "mon-place.h"
#include "mon-util.h"
#include "random.h"
diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc
index 4223ef6c0e..b0760bc6de 100644
--- a/crawl-ref/source/newgame.cc
+++ b/crawl-ref/source/newgame.cc
@@ -893,6 +893,7 @@ game_start:
Generated_Levels.clear();
initialise_branch_depths();
+ initialise_temples();
init_level_connectivity();
// Generate the second name of Jiyva
@@ -1645,7 +1646,7 @@ static void _give_basic_spells(job_type which_job)
which_spell = SPELL_PAIN;
break;
case JOB_ENCHANTER:
- which_spell = SPELL_BACKLIGHT;
+ which_spell = SPELL_CORONA;
break;
case JOB_FIRE_ELEMENTALIST:
which_spell = SPELL_FLAME_TONGUE;
@@ -2426,7 +2427,7 @@ static void _give_wanderer_spell(skill_type skill)
break;
case SK_ENCHANTMENTS:
- spell = SPELL_BACKLIGHT;
+ spell = SPELL_CORONA;
break;
}
diff --git a/crawl-ref/source/ng-init.cc b/crawl-ref/source/ng-init.cc
index 446c95af1a..588d42b505 100644
--- a/crawl-ref/source/ng-init.cc
+++ b/crawl-ref/source/ng-init.cc
@@ -10,9 +10,17 @@
#include "branch.h"
#include "describe.h"
+#include "dungeon.h"
#include "itemname.h"
+#include "maps.h"
#include "player.h"
#include "random.h"
+#include "religion.h"
+#include "store.h"
+
+#ifdef DEBUG_DIAGNOSTICS
+#define DEBUG_TEMPLES 1
+#endif
static unsigned char _random_potion_description()
{
@@ -64,6 +72,125 @@ void initialise_branch_depths()
branches[BRANCH_TOMB].startdepth = random_range(2, 3);
}
+#define MAX_OVERFLOW_LEVEL 9
+
+// Determine which altars go into the Ecumenical Temple, which go into
+// overflow temples, and on what level the overflow temples are.
+void initialise_temples()
+{
+ //////////////////////////////////////////
+ // First determine main temple map to use.
+ level_id ecumenical(BRANCH_ECUMENICAL_TEMPLE, 1);
+
+ map_def *main_temple = NULL;
+ for (int i = 0; i < 10; i++)
+ {
+ main_temple
+ = const_cast<map_def*>(random_map_for_place(ecumenical, false));
+
+ if (main_temple == NULL)
+ end (1, false, "No temples?!");
+
+ // Without all this find_glyph() returns 0.
+ std::string err;
+ main_temple->load();
+ main_temple->reinit();
+ err = main_temple->run_lua(true);
+
+ if (!err.empty())
+ {
+ mprf(MSGCH_ERROR, "Temple %s: %s", main_temple->name.c_str(),
+ err.c_str());
+ main_temple = NULL;
+ continue;
+ }
+
+ main_temple->fixup();
+ err = main_temple->resolve();
+
+ if (!err.empty())
+ {
+ mprf(MSGCH_ERROR, "Temple %s: %s", main_temple->name.c_str(),
+ err.c_str());
+ main_temple = NULL;
+ continue;
+ }
+ break;
+ }
+
+ if (main_temple == NULL)
+ end(1, false, "No valid temples.");
+
+ you.props[TEMPLE_MAP_KEY] = main_temple->name;
+
+ const std::vector<coord_def> altar_coords
+ = main_temple->find_glyph('B');
+ const unsigned int main_temple_size = altar_coords.size();
+
+ if (main_temple_size == 0)
+ {
+ end(1, false, "Main temple '%s' has no altars",
+ main_temple->name.c_str());
+ }
+
+#ifdef DEBUG_TEMPLES
+ mprf(MSGCH_DIAGNOSTICS, "Chose main temple %s, size %lu",
+ main_temple->name.c_str(), main_temple_size);
+#endif
+
+ ///////////////////////////////////
+ // Now set up the overflow temples.
+
+ std::vector<god_type> god_list = temple_god_list();
+
+ std::random_shuffle(god_list.begin(), god_list.end());
+
+ std::vector<god_type> overflow_gods;
+
+ while (god_list.size() > main_temple_size)
+ {
+ overflow_gods.push_back(god_list.back());
+ god_list.pop_back();
+ }
+
+#ifdef DEBUG_TEMPLES
+ mprf(MSGCH_DIAGNOSTICS, "%lu overflow altars", overflow_gods.size());
+#endif
+
+ CrawlVector &temple_gods
+ = you.props[TEMPLE_GODS_KEY].new_vector(SV_BYTE);
+
+ for (unsigned int i = 0; i < god_list.size(); i++)
+ temple_gods.push_back( (char) god_list[i] );
+
+ CrawlVector &overflow_temples
+ = you.props[OVERFLOW_TEMPLES_KEY].new_vector(SV_VEC);
+ overflow_temples.resize(MAX_OVERFLOW_LEVEL);
+
+ // NOTE: The overflow temples don't have to contain only one
+ // altar; they can contain any number of altars, so long as there's
+ // at least one vault definition with the tag "overflow_temple_num"
+ // (where "num" is the number of altars).
+ for (unsigned int i = 0; i < overflow_gods.size(); i++)
+ {
+ const unsigned int level = random_range(2, MAX_OVERFLOW_LEVEL);
+
+ // List of overflow temples on this level.
+ CrawlVector &level_temples
+ = overflow_temples[level - 1].get_vector();
+
+ CrawlHashTable temple;
+
+ CrawlVector &gods
+ = temple[TEMPLE_GODS_KEY].new_vector(SV_BYTE);
+
+ // Only single-altar overflow temples for now.
+ gods.push_back( (char) overflow_gods[i] );
+
+ level_temples.push_back(temple);
+ }
+}
+
static int _get_random_porridge_desc()
{
return PDESCQ(PDQ_GLUGGY, one_chance_in(3) ? PDC_BROWN
diff --git a/crawl-ref/source/ng-init.h b/crawl-ref/source/ng-init.h
index 58fdce4514..dc41e8168d 100644
--- a/crawl-ref/source/ng-init.h
+++ b/crawl-ref/source/ng-init.h
@@ -3,6 +3,7 @@
void fix_up_jiyva_name();
void initialise_branch_depths();
+void initialise_temples();
void initialise_item_descriptions();
#endif
diff --git a/crawl-ref/source/ouch.cc b/crawl-ref/source/ouch.cc
index e4230464af..b3912a3e1f 100644
--- a/crawl-ref/source/ouch.cc
+++ b/crawl-ref/source/ouch.cc
@@ -51,8 +51,8 @@
#include "message.h"
#include "misc.h"
#include "mon-util.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "notes.h"
#include "output.h"
#include "player.h"
@@ -947,7 +947,7 @@ static void _maybe_spawn_jellies(int dam, const char* aux,
int count_created = 0;
for (int i = 0; i < how_many; ++i)
{
- mgen_data mg(mon, BEH_STRICT_NEUTRAL, 0, 0, you.pos(),
+ mgen_data mg(mon, BEH_STRICT_NEUTRAL, &you, 0, 0, you.pos(),
MHITNOT, 0, GOD_JIYVA);
if (create_monster(mg) != -1)
@@ -1218,34 +1218,9 @@ static std::string morgue_name(time_t when_crawl_got_even)
#endif // SHORT_FILE_NAMES
}
-void end_game( scorefile_entry &se )
+// Delete save files on game end.
+static void delete_files()
{
- bool dead = true;
-
- for (int i = 0; i < ENDOFPACK; i++)
- set_ident_flags( you.inv[i], ISFLAG_IDENT_MASK );
-
- for (int i = 0; i < ENDOFPACK; i++)
- {
- if (you.inv[i].base_type != 0)
- set_ident_type( you.inv[i], ID_KNOWN_TYPE );
- }
-
- if (!dump_char( morgue_name(se.death_time), !dead, true, &se ))
- {
- mpr("Char dump unsuccessful! Sorry about that.");
- if (!crawl_state.seen_hups)
- more();
- clrscr();
- }
-
- if (se.death_type == KILLED_BY_LEAVING
- || se.death_type == KILLED_BY_QUITTING
- || se.death_type == KILLED_BY_WINNING)
- {
- dead = false;
- }
-
// clean all levels that we think we have ever visited
for (level_id_set::const_iterator i = Generated_Levels.begin();
i != Generated_Levels.end(); ++i)
@@ -1289,6 +1264,37 @@ void end_game( scorefile_entry &se )
std::string tmpname = basename + suffixes[i];
unlink( tmpname.c_str() );
}
+}
+
+void end_game(scorefile_entry &se)
+{
+ bool dead = true;
+
+ for (int i = 0; i < ENDOFPACK; i++)
+ set_ident_flags( you.inv[i], ISFLAG_IDENT_MASK );
+
+ for (int i = 0; i < ENDOFPACK; i++)
+ {
+ if (you.inv[i].base_type != 0)
+ set_ident_type( you.inv[i], ID_KNOWN_TYPE );
+ }
+
+ delete_files();
+
+ if (!dump_char( morgue_name(se.death_time), !dead, true, &se ))
+ {
+ mpr("Char dump unsuccessful! Sorry about that.");
+ if (!crawl_state.seen_hups)
+ more();
+ clrscr();
+ }
+
+ if (se.death_type == KILLED_BY_LEAVING
+ || se.death_type == KILLED_BY_QUITTING
+ || se.death_type == KILLED_BY_WINNING)
+ {
+ dead = false;
+ }
// death message
if (dead)
diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc
index 9e6978bb87..a1494fe726 100644
--- a/crawl-ref/source/output.cc
+++ b/crawl-ref/source/output.cc
@@ -34,7 +34,7 @@
#include "item_use.h"
#include "menu.h"
#include "message.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "mon-info.h"
#include "mon-util.h"
#include "newgame.h"
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index b3d7218db1..19b8758dd2 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -6895,7 +6895,7 @@ bool player::visible_to(const actor *looker) const
bool player::backlit(bool check_haloed) const
{
- return (get_contamination_level() > 0 || duration[DUR_BACKLIGHT]
+ return (get_contamination_level() > 0 || duration[DUR_CORONA]
|| (check_haloed ? haloed() : false));
}
@@ -6904,22 +6904,22 @@ void player::backlight()
{
if (!this->duration[DUR_INVIS])
{
- if (this->duration[DUR_BACKLIGHT])
+ if (this->duration[DUR_CORONA])
mpr("You glow brighter.");
else
mpr("You are outlined in light.");
- this->duration[DUR_BACKLIGHT] += random_range(15, 35);
- if (this->duration[DUR_BACKLIGHT] > 250)
- this->duration[DUR_BACKLIGHT] = 250;
+ this->duration[DUR_CORONA] += random_range(15, 35);
+ if (this->duration[DUR_CORONA] > 250)
+ this->duration[DUR_CORONA] = 250;
}
else
{
mpr("You feel strangely conspicuous.");
- this->duration[DUR_BACKLIGHT] += random_range(3, 5);
- if (this->duration[DUR_BACKLIGHT] > 250)
- this->duration[DUR_BACKLIGHT] = 250;
+ this->duration[DUR_CORONA] += random_range(3, 5);
+ if (this->duration[DUR_CORONA] > 250)
+ this->duration[DUR_CORONA] = 250;
}
}
@@ -7038,7 +7038,7 @@ bool player::can_throw_large_rocks() const
return (player_genus(GENPC_OGRE) || species == SP_TROLL);
}
-bool player::can_sleep(bool holi_only) const
+bool player::can_hibernate(bool holi_only) const
{
// Undead, nonliving, and plants don't sleep.
const mon_holy_type holi = holiness();
@@ -7059,11 +7059,11 @@ bool player::can_sleep(bool holi_only) const
return (true);
}
-void player::put_to_sleep(int)
+void player::hibernate(int)
{
ASSERT(!crawl_state.arena);
- if (!can_sleep())
+ if (!can_hibernate())
{
mpr("You feel weary for a moment.");
return;
@@ -7079,6 +7079,23 @@ void player::put_to_sleep(int)
duration[DUR_SLEEP] = 3 + random2avg(5, 2);
}
+void player::put_to_sleep(int power)
+{
+ ASSERT(!crawl_state.arena);
+
+ if (duration[DUR_SLEEP])
+ return;
+
+ mpr("You fall asleep!");
+
+ stop_delay();
+ flash_colour = DARKGREY;
+ viewwindow(false);
+
+ // As above, do this after redraw.
+ duration[DUR_SLEEP] = 5 + random2avg(power / 10, 5);
+}
+
void player::awake()
{
ASSERT(!crawl_state.arena);
diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h
index 900d6bb52f..430307a982 100644
--- a/crawl-ref/source/player.h
+++ b/crawl-ref/source/player.h
@@ -473,7 +473,8 @@ public:
bool petrified() const;
bool asleep() const;
- bool can_sleep(bool holi_only = false) const;
+ bool can_hibernate(bool holi_only = false) const;
+ void hibernate(int power = 0);
void put_to_sleep(int power = 0);
void awake();
void check_awaken(int disturbance);
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index 6a4c05fee1..76a4c5af79 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -52,9 +52,10 @@
#include "message.h"
#include "misc.h"
#include "mon-behv.h"
+#include "mon-iter.h"
#include "mon-util.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mutation.h"
#include "newgame.h"
#include "notes.h"
@@ -1120,7 +1121,11 @@ int yred_random_servants(int threshold, bool force_hostile)
how_many = 2 + random2(4);
mgen_data mg(mon_type, !force_hostile ? BEH_FRIENDLY : BEH_HOSTILE,
- 0, 0, you.pos(), MHITYOU, 0, GOD_YREDELEMNUL);
+ !force_hostile ? &you : 0, 0, 0, you.pos(), MHITYOU, 0,
+ GOD_YREDELEMNUL);
+
+ if (force_hostile)
+ mg.non_actor_summoner = "the anger of Yredelemnul";
int created = 0;
if (force_hostile)
@@ -1421,13 +1426,9 @@ bool _has_jelly()
{
ASSERT(you.religion == GOD_JIYVA);
- for (int i = 0; i < MAX_MONSTERS; ++i)
- {
- monsters *monster = &menv[i];
- if (mons_is_god_gift(monster, GOD_JIYVA))
+ for (monster_iterator mi; mi; ++mi)
+ if (mons_is_god_gift(*mi, GOD_JIYVA))
return (true);
- }
-
return (false);
}
@@ -1579,8 +1580,8 @@ static bool _tso_blessing_holy_wpn(monsters* mon)
const int wpn_brand = get_weapon_brand(wpn);
- // Only brand melee weapons, and only override certain brands.
- if (is_artefact(wpn) || is_range_weapon(wpn)
+ // Only brand weapons, and only override certain brands.
+ if (is_artefact(wpn)
|| (wpn_brand != SPWPN_NORMAL && wpn_brand != SPWPN_DRAINING
&& wpn_brand != SPWPN_PAIN && wpn_brand != SPWPN_VAMPIRICISM
&& wpn_brand != SPWPN_REAPING && wpn_brand != SPWPN_CHAOS
@@ -1733,7 +1734,7 @@ static void _beogh_blessing_reinforcements()
follower_type = RANDOM_ELEMENT(followers);
_delayed_monster(
- mgen_data(follower_type, BEH_FRIENDLY, 0, 0,
+ mgen_data(follower_type, BEH_FRIENDLY, &you, 0, 0,
you.pos(), MHITYOU, 0, GOD_BEOGH),
_beogh_reinf_callback);
}
@@ -2140,9 +2141,11 @@ static void _do_god_gift(bool prayed_for)
int count_created = 0;
for (; jelly_count > 0; --jelly_count)
{
- mgen_data mg(MONS_JELLY, BEH_STRICT_NEUTRAL, 0, 0,
+ mgen_data mg(MONS_JELLY, BEH_STRICT_NEUTRAL, 0, 0, 0,
you.pos(), MHITNOT, 0, GOD_JIYVA);
+ mg.non_actor_summoner = "Jiyva";
+
if (create_monster(mg) != -1)
count_created++;
@@ -4212,7 +4215,7 @@ static bool _bless_weapon(god_type god, brand_type brand, int colour)
item_def& wpn = *you.weapon();
// Only bless non-artefact melee weapons.
- if (is_artefact(wpn) || is_range_weapon(wpn))
+ if (is_artefact(wpn) || (is_range_weapon(wpn) && brand != SPWPN_HOLY_WRATH))
return (false);
std::string prompt = "Do you wish to have your weapon ";
@@ -5049,8 +5052,8 @@ void god_pitch(god_type which_god)
if (!_has_jelly())
{
monster_type mon = MONS_JELLY;
- mgen_data mg(mon, BEH_STRICT_NEUTRAL, 0, 0, you.pos(), MHITNOT, 0,
- GOD_JIYVA);
+ mgen_data mg(mon, BEH_STRICT_NEUTRAL, &you, 0, 0, you.pos(),
+ MHITNOT, 0, GOD_JIYVA);
_delayed_monster(mg);
simple_god_message(" grants you a jelly!");
@@ -5446,10 +5449,8 @@ int get_tension(god_type god, bool count_travelling)
int total = 0;
bool nearby_monster = false;
- for (int midx = 0; midx < MAX_MONSTERS; ++midx)
+ for (monster_iterator mons; mons; ++mons)
{
- const monsters* mons = &menv[midx];
-
if (!mons->alive())
continue;
@@ -5479,14 +5480,14 @@ int get_tension(god_type god, bool count_travelling)
continue;
}
- const mon_attitude_type att = mons_attitude(mons);
+ const mon_attitude_type att = mons_attitude(*mons);
if (att == ATT_GOOD_NEUTRAL || att == ATT_NEUTRAL)
continue;
- if (mons->cannot_act() || mons->asleep() || mons_is_fleeing(mons))
+ if (mons->cannot_act() || mons->asleep() || mons_is_fleeing(*mons))
continue;
- int exper = exper_value(mons);
+ int exper = exper_value(*mons);
if (exper <= 0)
continue;
@@ -5494,7 +5495,7 @@ int get_tension(god_type god, bool count_travelling)
exper *= mons->hit_points;
exper /= mons->max_hit_points;
- const bool gift = mons_is_god_gift(mons, god);
+ const bool gift = mons_is_god_gift(*mons, god);
if (att == ATT_HOSTILE)
{
@@ -5517,7 +5518,7 @@ int get_tension(god_type god, bool count_travelling)
if (att != ATT_FRIENDLY)
{
- if (!you.visible_to(mons))
+ if (!you.visible_to(*mons))
exper /= 2;
if (!mons->visible_to(&you))
exper *= 2;
@@ -5719,3 +5720,29 @@ static void _place_delayed_monsters()
_delayed_success.clear();
_delayed_failure.clear();
}
+
+std::vector<god_type> temple_god_list()
+{
+ std::vector<god_type> god_list;
+
+ for (int i = 0; i < NUM_GODS; i++)
+ {
+ god_type god = (god_type) i;
+
+ // These never appear in any temples.
+ switch(god)
+ {
+ case GOD_NO_GOD:
+ case GOD_LUGONU:
+ case GOD_BEOGH:
+ case GOD_JIYVA:
+ continue;
+
+ default:
+ break;
+ }
+
+ god_list.push_back(god);
+ }
+ return god_list;
+}
diff --git a/crawl-ref/source/religion.h b/crawl-ref/source/religion.h
index 82b1a5f731..5ecc6ce34c 100644
--- a/crawl-ref/source/religion.h
+++ b/crawl-ref/source/religion.h
@@ -134,4 +134,6 @@ void religion_turn_start();
void religion_turn_end();
int get_tension(god_type god = you.religion, bool count_travelling = true);
+
+std::vector<god_type> temple_god_list();
#endif
diff --git a/crawl-ref/source/rltiles/dc-player.txt b/crawl-ref/source/rltiles/dc-player.txt
index 06fa9a62bd..98c4e62156 100644
--- a/crawl-ref/source/rltiles/dc-player.txt
+++ b/crawl-ref/source/rltiles/dc-player.txt
@@ -418,6 +418,7 @@ knife_of_accuracy KNIFE_OF_ACCURACY
vampires_tooth VAMPIRES_TOOTH
dire_lajatang DIRE_LAJATANG
spriggans_knife SPRIGGANS_KNIFE
+cutlass CUTLASS
## blunt
wucad_mu WUCAD_MU
mace_of_variability MACE_OF_VARIABILITY
diff --git a/crawl-ref/source/rltiles/dc-unrand.txt b/crawl-ref/source/rltiles/dc-unrand.txt
index 69d9cc4c54..356a53ad39 100644
--- a/crawl-ref/source/rltiles/dc-unrand.txt
+++ b/crawl-ref/source/rltiles/dc-unrand.txt
@@ -2,13 +2,6 @@
# util/art-data.pl. Do not directly edit this file, but rather change
# art-data.txt.
-%sdir item/amulet/artefact
-urand_air UNRAND_AIR
-urand_cekugob UNRAND_CEKUGOB
-urand_four_winds UNRAND_FOUR_WINDS
-urand_bloodlust UNRAND_BLOODLUST
-urand_brooch_of_shielding UNRAND_SHIELDING
-
%sdir item/armour/artefact
urand_ignorance UNRAND_IGNORANCE
urand_augmentation UNRAND_AUGMENTATION
@@ -34,12 +27,6 @@ urand_fencer UNRAND_FENCERS_GLOVES
urand_starlight UNRAND_STARLIGHT
urand_ratskin_cloak UNRAND_RATSKIN_CLOAK
-%sdir item/ring/artefact
-urand_shadows UNRAND_SHADOWS
-urand_shaolin UNRAND_SHAOLIN
-urand_robustness UNRAND_ROBUSTNESS
-urand_mage UNRAND_MAGE
-
%sdir item/weapon/artefact
spwpn_singing_sword UNRAND_SINGING_SWORD
spwpn_wrath_of_trog UNRAND_TROG
@@ -73,6 +60,8 @@ urand_piercer UNRAND_PIERCER
urand_plutonium UNRAND_PLUTONIUM_SWORD
urand_undeadhunter UNRAND_UNDEADHUNTER
urand_crystal_spear UNRAND_CRYSTAL_SPEAR
+urand_cutlass UNRAND_CAPTAINS_CUTLASS
+urand_storm_bow UNRAND_STORM_BOW
%rim 1
spwpn_sword_of_power UNRAND_POWER
spwpn_sceptre_of_torment UNRAND_TORMENT
@@ -87,3 +76,16 @@ urand_serpent_scourge UNRAND_SERPENT_SCOURGE
urand_knife_of_accuracy UNRAND_ACCURACY
%rim 0
+%sdir item/amulet/artefact
+urand_air UNRAND_AIR
+urand_cekugob UNRAND_CEKUGOB
+urand_four_winds UNRAND_FOUR_WINDS
+urand_bloodlust UNRAND_BLOODLUST
+urand_brooch_of_shielding UNRAND_SHIELDING
+
+%sdir item/ring/artefact
+urand_shadows UNRAND_SHADOWS
+urand_shaolin UNRAND_SHAOLIN
+urand_robustness UNRAND_ROBUSTNESS
+urand_mage UNRAND_MAGE
+
diff --git a/crawl-ref/source/rltiles/item/weapon/artefact/urand_cutlass.png b/crawl-ref/source/rltiles/item/weapon/artefact/urand_cutlass.png
new file mode 100644
index 0000000000..cbaab9e3af
--- /dev/null
+++ b/crawl-ref/source/rltiles/item/weapon/artefact/urand_cutlass.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/item/weapon/artefact/urand_storm_bow.png b/crawl-ref/source/rltiles/item/weapon/artefact/urand_storm_bow.png
new file mode 100644
index 0000000000..a1ee1e2e7d
--- /dev/null
+++ b/crawl-ref/source/rltiles/item/weapon/artefact/urand_storm_bow.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/player/hand1/artefact/cutlass.png b/crawl-ref/source/rltiles/player/hand1/artefact/cutlass.png
new file mode 100644
index 0000000000..73cb6cc1d3
--- /dev/null
+++ b/crawl-ref/source/rltiles/player/hand1/artefact/cutlass.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/tiledef-unrand.cc b/crawl-ref/source/rltiles/tiledef-unrand.cc
index 077d23577f..558e0fa69f 100644
--- a/crawl-ref/source/rltiles/tiledef-unrand.cc
+++ b/crawl-ref/source/rltiles/tiledef-unrand.cc
@@ -58,6 +58,8 @@ int unrandart_to_tile(int unrand)
case UNRAND_SERPENT_SCOURGE: return TILE_UNRAND_SERPENT_SCOURGE;
case UNRAND_ACCURACY: return TILE_UNRAND_ACCURACY;
case UNRAND_CRYSTAL_SPEAR: return TILE_UNRAND_CRYSTAL_SPEAR;
+ case UNRAND_CAPTAINS_CUTLASS: return TILE_UNRAND_CAPTAINS_CUTLASS;
+ case UNRAND_STORM_BOW: return TILE_UNRAND_STORM_BOW;
case UNRAND_IGNORANCE: return TILE_UNRAND_IGNORANCE;
case UNRAND_AUGMENTATION: return TILE_UNRAND_AUGMENTATION;
case UNRAND_THIEF: return TILE_UNRAND_THIEF;
@@ -162,6 +164,8 @@ int unrandart_to_doll_tile(int unrand)
case UNRAND_SERPENT_SCOURGE: return TILEP_HAND1_SERPENT_SCOURGE;
case UNRAND_ACCURACY: return TILEP_HAND1_KNIFE_OF_ACCURACY;
case UNRAND_CRYSTAL_SPEAR: return TILEP_HAND1_CRYSTAL_SPEAR;
+ case UNRAND_CAPTAINS_CUTLASS: return TILEP_HAND1_CUTLASS;
+ case UNRAND_STORM_BOW: return TILEP_HAND1_BOW_BLUE;
// HAND2
case UNRAND_IGNORANCE: return TILEP_HAND2_SHIELD_OF_IGNORANCE;
case UNRAND_BULLSEYE: return TILEP_HAND2_BULLSEYE;
diff --git a/crawl-ref/source/rng.cc b/crawl-ref/source/rng.cc
index 409f0975c9..8c856e7229 100644
--- a/crawl-ref/source/rng.cc
+++ b/crawl-ref/source/rng.cc
@@ -28,12 +28,18 @@ void seed_rng(unsigned long* seed_key, size_t num_keys)
{
// MT19937 -- see mt19937ar.cc for details/licence
init_by_array(seed_key, num_keys);
+
+ // for std::random_shuffle()
+ srand(seed_key[0]);
}
void seed_rng(long seed)
{
// MT19937 -- see mt19937ar.cc for details/licence
init_genrand(seed);
+
+ // for std::random_shuffle()
+ srand(seed);
}
void seed_rng()
diff --git a/crawl-ref/source/shout.cc b/crawl-ref/source/shout.cc
index 1ecc0600f5..d9dea1473c 100644
--- a/crawl-ref/source/shout.cc
+++ b/crawl-ref/source/shout.cc
@@ -15,9 +15,10 @@
#include "message.h"
#include "misc.h"
#include "mon-behv.h"
-#include "monplace.h"
+#include "mon-iter.h"
+#include "mon-place.h"
#include "monster.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "options.h"
#include "player.h"
#include "random.h"
@@ -378,34 +379,32 @@ bool noisy(int loudness, const coord_def& where, const char *msg, int who,
ret = true;
}
- for (int p = 0; p < MAX_MONSTERS; p++)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters* monster = &menv[p];
-
- if (!monster->alive())
+ if (!mi->alive())
continue;
// Monsters arent' affected by their own noise. We don't check
- // where == monster->pos() since it might be caused by the
+ // where == mi->pos() since it might be caused by the
// Projected Noise spell.
- if (p == who)
+ if (mi->mindex() == who)
continue;
- if (distance(monster->pos(), where) <= dist
- && !silenced(monster->pos()))
+ if (distance(mi->pos(), where) <= dist
+ && !silenced(mi->pos()))
{
// If the noise came from the character, any nearby monster
// will be jumping on top of them.
if (where == you.pos())
- behaviour_event( monster, ME_ALERT, MHITYOU, you.pos() );
- else if (mermaid && mons_primary_habitat(monster) == HT_WATER
- && !monster->friendly())
+ behaviour_event(*mi, ME_ALERT, MHITYOU, you.pos());
+ else if (mermaid && mons_primary_habitat(*mi) == HT_WATER
+ && !mi->friendly())
{
// Mermaids/sirens call (hostile) aquatic monsters.
- behaviour_event( monster, ME_ALERT, MHITNOT, where );
+ behaviour_event(*mi, ME_ALERT, MHITNOT, where);
}
else
- behaviour_event( monster, ME_DISTURB, MHITNOT, where );
+ behaviour_event(*mi, ME_DISTURB, MHITNOT, where);
}
}
@@ -434,10 +433,8 @@ static const char* _player_vampire_smells_blood(int dist)
return "";
}
-void blood_smell( int strength, const coord_def& where )
+void blood_smell(int strength, const coord_def& where)
{
- monsters *monster = NULL;
-
const int range = strength * strength;
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS,
@@ -454,7 +451,7 @@ void blood_smell( int strength, const coord_def& where )
{
int vamp_range = vamp_strength * vamp_strength;
- const int player_distance = distance( you.pos(), where );
+ const int player_distance = distance(you.pos(), where);
if (player_distance <= vamp_range)
{
@@ -474,73 +471,66 @@ void blood_smell( int strength, const coord_def& where )
}
}
- for (int p = 0; p < MAX_MONSTERS; p++)
+ circle_def c(where, range, C_CIRCLE);
+ for (monster_iterator mi(&c); mi; ++mi)
{
- monster = &menv[p];
-
- if (monster->type < 0)
+ if (!mons_class_flag(mi->type, M_BLOOD_SCENT))
continue;
- if (!mons_class_flag(monster->type, M_BLOOD_SCENT))
- continue;
-
- if (distance(monster->pos(), where) <= range)
+ // Let sleeping hounds lie.
+ if (mi->asleep()
+ && mons_species(mi->type) != MONS_VAMPIRE
+ && mi->type != MONS_SHARK)
{
- // Let sleeping hounds lie.
- if (monster->asleep()
- && mons_species(monster->type) != MONS_VAMPIRE
- && monster->type != MONS_SHARK)
+ // 33% chance of sleeping on
+ // 33% of being disturbed (start BEH_WANDER)
+ // 33% of being alerted (start BEH_SEEK)
+ if (!one_chance_in(3))
{
- // 33% chance of sleeping on
- // 33% of being disturbed (start BEH_WANDER)
- // 33% of being alerted (start BEH_SEEK)
- if (!one_chance_in(3))
+ if (coinflip())
{
- if (coinflip())
- {
#ifdef DEBUG_DIAGNOSTICS
- mprf(MSGCH_DIAGNOSTICS, "disturbing %s (%d, %d)",
- monster->name(DESC_PLAIN).c_str(),
- monster->pos().x, monster->pos().y);
+ mprf(MSGCH_DIAGNOSTICS, "disturbing %s (%d, %d)",
+ mi->name(DESC_PLAIN).c_str(),
+ mi->pos().x, mi->pos().y);
#endif
- behaviour_event(monster, ME_DISTURB, MHITNOT, where);
- }
- continue;
+ behaviour_event(*mi, ME_DISTURB, MHITNOT, where);
}
+ continue;
}
+ }
#ifdef DEBUG_DIAGNOSTICS
- mprf(MSGCH_DIAGNOSTICS, "alerting %s (%d, %d)",
- monster->name(DESC_PLAIN).c_str(),
- monster->pos().x, monster->pos().y);
+ mprf(MSGCH_DIAGNOSTICS, "alerting %s (%d, %d)",
+ mi->name(DESC_PLAIN).c_str(),
+ mi->pos().x, mi->pos().y);
#endif
- behaviour_event( monster, ME_ALERT, MHITNOT, where );
+ behaviour_event(*mi, ME_ALERT, MHITNOT, where);
- if (monster->type == MONS_SHARK)
+ if (mi->type == MONS_SHARK)
+ {
+ // Sharks go into a battle frenzy if they smell blood.
+ monster_pathfind mp;
+ if (mp.init_pathfind(*mi, where))
{
- // Sharks go into a battle frenzy if they smell blood.
- monster_pathfind mp;
- if (mp.init_pathfind(monster, where))
+ mon_enchant ench = mi->get_ench(ENCH_BATTLE_FRENZY);
+ const int dist = 15 - (mi->pos() - where).rdist();
+ const int dur = random_range(dist, dist*2)
+ * speed_to_duration(mi->speed);
+
+ if (ench.ench != ENCH_NONE)
+ {
+ int level = ench.degree;
+ if (level < 4 && one_chance_in(2*level))
+ ench.degree++;
+ ench.duration = std::max(ench.duration, dur);
+ mi->update_ench(ench);
+ }
+ else
{
- mon_enchant ench = monster->get_ench(ENCH_BATTLE_FRENZY);
- const int dist = 15 - (monster->pos() - where).rdist();
- const int dur = random_range(dist, dist*2)
- * speed_to_duration(monster->speed);
-
- if (ench.ench != ENCH_NONE)
- {
- int level = ench.degree;
- if (level < 4 && one_chance_in(2*level))
- ench.degree++;
- ench.duration = std::max(ench.duration, dur);
- monster->update_ench(ench);
- }
- else
- {
- monster->add_ench(mon_enchant(ENCH_BATTLE_FRENZY, 1,
- KC_OTHER, dur));
- simple_monster_message(monster, " is consumed with "
- "blood-lust!");
- }
+ mi->add_ench(mon_enchant(ENCH_BATTLE_FRENZY, 1,
+ KC_OTHER, dur));
+ simple_monster_message(*mi, " is consumed with "
+ "blood-lust!");
}
}
}
diff --git a/crawl-ref/source/spells1.cc b/crawl-ref/source/spells1.cc
index 1b2e1b14df..9ba939477d 100644
--- a/crawl-ref/source/spells1.cc
+++ b/crawl-ref/source/spells1.cc
@@ -33,7 +33,8 @@
#include "los.h"
#include "message.h"
#include "misc.h"
-#include "monstuff.h"
+#include "mon-iter.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "options.h"
#include "player.h"
@@ -372,14 +373,12 @@ void cast_chain_lightning(int pow, const actor *caster)
target.x = -1;
target.y = -1;
- for (int i = 0; i < MAX_MONSTERS; i++)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[i];
-
- if (invalid_monster(monster))
+ if (invalid_monster(*mi))
continue;
- dist = grid_distance(source, monster->pos());
+ dist = grid_distance(source, mi->pos());
// check for the source of this arc
if (!dist)
@@ -392,7 +391,7 @@ void cast_chain_lightning(int pow, const actor *caster)
if (dist > min_dist)
continue;
- if (!_lightning_los(source, monster->pos()))
+ if (!_lightning_los(source, mi->pos()))
continue;
count++;
@@ -403,14 +402,14 @@ void cast_chain_lightning(int pow, const actor *caster)
if (!one_chance_in(10))
{
min_dist = dist;
- target = monster->pos();
+ target = mi->pos();
count = 0;
}
}
else if (target.x == -1 || one_chance_in(count))
{
// either first target, or new selected target at min_dist
- target = monster->pos();
+ target = mi->pos();
// need to set min_dist for first target case
dist = std::max(dist, min_dist);
@@ -1132,30 +1131,25 @@ void abjuration(int pow)
// Scale power into something comparable to summon lifetime.
const int abjdur = pow * 12;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mon(&you.get_los()); mon; ++mon)
{
- monsters* const monster = &menv[i];
-
- if (monster->type == MONS_NO_MONSTER || !mons_near(monster))
- continue;
-
- if (monster->wont_attack())
+ if (mon->wont_attack())
continue;
int duration;
- if (monster->is_summoned(&duration))
+ if (mon->is_summoned(&duration))
{
int sockage = std::max(fuzz_value(abjdur, 60, 30), 40);
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "%s abj: dur: %d, abj: %d",
- monster->name(DESC_PLAIN).c_str(), duration, sockage);
+ mon->name(DESC_PLAIN).c_str(), duration, sockage);
#endif
bool shielded = false;
// TSO and Trog's abjuration protection.
- if (mons_is_god_gift(monster, GOD_SHINING_ONE))
+ if (mons_is_god_gift(*mon, GOD_SHINING_ONE))
{
- sockage = sockage * (30 - monster->hit_dice) / 45;
+ sockage = sockage * (30 - mon->hit_dice) / 45;
if (sockage < duration)
{
simple_god_message(" protects a fellow warrior from your evil magic!",
@@ -1163,7 +1157,7 @@ void abjuration(int pow)
shielded = true;
}
}
- else if (mons_is_god_gift(monster, GOD_TROG))
+ else if (mons_is_god_gift(*mon, GOD_TROG))
{
sockage = sockage * 8 / 15;
if (sockage < duration)
@@ -1174,9 +1168,9 @@ void abjuration(int pow)
}
}
- mon_enchant abj = monster->get_ench(ENCH_ABJ);
- if (!monster->lose_ench_duration(abj, sockage) && !shielded)
- simple_monster_message(monster, " shudders.");
+ mon_enchant abj = mon->get_ench(ENCH_ABJ);
+ if (!mon->lose_ench_duration(abj, sockage) && !shielded)
+ simple_monster_message(*mon, " shudders.");
}
}
}
diff --git a/crawl-ref/source/spells2.cc b/crawl-ref/source/spells2.cc
index 57293bf40d..e0378e81f4 100644
--- a/crawl-ref/source/spells2.cc
+++ b/crawl-ref/source/spells2.cc
@@ -33,8 +33,9 @@
#include "message.h"
#include "misc.h"
#include "mon-behv.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-iter.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "ouch.h"
#include "player.h"
@@ -531,31 +532,29 @@ void cast_toxic_radiance()
counted_monster_list affected_monsters;
// determine which monsters are hit by the radiance: {dlb}
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi(&you.get_los()); mi; ++mi)
{
- monsters* const monster = &menv[i];
-
- if (monster->alive() && mons_near(monster) && !monster->submerged())
+ if (!mi->submerged())
{
// Monsters affected by corona are still invisible in that
// radiation passes through them without affecting them. Therefore,
// this check should not be !monster->invisible().
- if (!monster->has_ench(ENCH_INVIS))
+ if (!mi->has_ench(ENCH_INVIS))
{
bool affected =
- poison_monster(monster, KC_YOU, 1, false, false);
+ poison_monster(*mi, KC_YOU, 1, false, false);
- if (coinflip() && poison_monster(monster, KC_YOU, false, false))
+ if (coinflip() && poison_monster(*mi, KC_YOU, false, false))
affected = true;
if (affected)
- _record_monster_by_name(affected_monsters, monster);
+ _record_monster_by_name(affected_monsters, *mi);
}
else if (you.can_see_invisible())
{
// message player re:"miss" where appropriate {dlb}
mprf("The light passes through %s.",
- monster->name(DESC_NOCAP_THE).c_str());
+ mi->name(DESC_NOCAP_THE).c_str());
}
}
}
@@ -606,12 +605,8 @@ void cast_refrigeration(int pow)
// First build the message.
counted_monster_list affected_monsters;
- for (int i = 0; i < MAX_MONSTERS; i++)
- {
- const monsters* const monster = &menv[i];
- if (monster->alive() && you.can_see(monster))
- _record_monster_by_name(affected_monsters, monster);
- }
+ for (monster_iterator mi(&you); mi; ++mi)
+ _record_monster_by_name(affected_monsters, *mi);
if (!affected_monsters.empty())
{
@@ -636,25 +631,22 @@ void cast_refrigeration(int pow)
beam.flavour = BEAM_COLD;
beam.thrower = KILL_YOU;
- for (int i = 0; i < MAX_MONSTERS; i++)
+ for (monster_iterator mi(&you.get_los()); mi; ++mi)
{
- monsters* const monster = &menv[i];
// Note that we *do* hurt monsters which you can't see
// (submerged, invisible) even though you get no information
// about it.
- if (monster->alive() && mons_near(monster))
+
+ // Calculate damage and apply.
+ int hurt = mons_adjust_flavoured(*mi, beam, dam_dice.roll());
+ mi->hurt(&you, hurt, BEAM_COLD);
+
+ // Cold-blooded creatures can be slowed.
+ if (mi->alive()
+ && mons_class_flag(mi->type, M_COLD_BLOOD)
+ && coinflip())
{
- // Calculate damage and apply.
- int hurt = mons_adjust_flavoured(monster, beam, dam_dice.roll());
- monster->hurt(&you, hurt, BEAM_COLD);
-
- // Cold-blooded creatures can be slowed.
- if (monster->alive()
- && mons_class_flag(monster->type, M_COLD_BLOOD)
- && coinflip())
- {
- monster->add_ench(ENCH_SLOW);
- }
+ mi->add_ench(ENCH_SLOW);
}
}
}
@@ -675,32 +667,26 @@ void drain_life(int pow)
int hp_gain = 0;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi(&you.get_los()); mi; ++mi)
{
- monsters* monster = &menv[i];
-
- if (!monster->alive()
- || monster->holiness() != MH_NATURAL
- || monster->res_negative_energy())
+ if (mi->holiness() != MH_NATURAL
+ || mi->res_negative_energy())
{
continue;
}
- if (mons_near(monster))
- {
- mprf("You draw life from %s.",
- monster->name(DESC_NOCAP_THE).c_str());
+ mprf("You draw life from %s.",
+ mi->name(DESC_NOCAP_THE).c_str());
- const int hurted = 3 + random2(7) + random2(pow);
- behaviour_event(monster, ME_WHACK, MHITYOU, you.pos());
- if (!monster->is_summoned())
- hp_gain += hurted;
+ const int hurted = 3 + random2(7) + random2(pow);
+ behaviour_event(*mi, ME_WHACK, MHITYOU, you.pos());
+ if (!mi->is_summoned())
+ hp_gain += hurted;
- monster->hurt(&you, hurted);
+ mi->hurt(&you, hurted);
- if (monster->alive())
- print_wounds(monster);
- }
+ if (mi->alive())
+ print_wounds(*mi);
}
hp_gain /= 2;
@@ -898,7 +884,7 @@ bool summon_animals(int pow)
if (create_monster(
mgen_data(mon,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
4, 0, you.pos(), MHITYOU)) != -1)
{
success = true;
@@ -917,7 +903,7 @@ bool cast_summon_butterflies(int pow, god_type god)
for (int i = 0; i < how_many; ++i)
{
if (create_monster(
- mgen_data(MONS_BUTTERFLY, BEH_FRIENDLY,
+ mgen_data(MONS_BUTTERFLY, BEH_FRIENDLY, &you,
3, SPELL_SUMMON_BUTTERFLIES,
you.pos(), MHITYOU,
0, god)) != -1)
@@ -952,7 +938,7 @@ bool cast_summon_small_mammals(int pow, god_type god)
}
if (create_monster(
- mgen_data(mon, BEH_FRIENDLY,
+ mgen_data(mon, BEH_FRIENDLY, &you,
3, SPELL_SUMMON_SMALL_MAMMALS,
you.pos(), MHITYOU,
0, god)) != -1)
@@ -1010,7 +996,7 @@ bool cast_sticks_to_snakes(int pow, god_type god)
mon = MONS_SMALL_SNAKE;
if (create_monster(
- mgen_data(mon, beha,
+ mgen_data(mon, beha, &you,
dur, SPELL_STICKS_TO_SNAKES,
you.pos(), MHITYOU,
0, god)) != -1)
@@ -1057,7 +1043,7 @@ bool cast_sticks_to_snakes(int pow, god_type god)
mon = MONS_GREY_SNAKE;
if (create_monster(
- mgen_data(mon, beha,
+ mgen_data(mon, beha, &you,
dur, SPELL_STICKS_TO_SNAKES,
you.pos(), MHITYOU,
0, god)) != -1)
@@ -1096,7 +1082,7 @@ bool cast_summon_scorpions(int pow, god_type god)
if (create_monster(
mgen_data(MONS_SCORPION,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
3, SPELL_SUMMON_SCORPIONS,
you.pos(), MHITYOU,
0, god)) != -1)
@@ -1137,7 +1123,7 @@ bool cast_summon_swarm(int pow, god_type god,
if (create_monster(
mgen_data(mon,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
dur, !permanent ? SPELL_SUMMON_SWARM : 0,
you.pos(),
MHITYOU,
@@ -1194,7 +1180,7 @@ bool cast_call_canine_familiar(int pow, god_type god)
const int dur = std::min(2 + (random2(pow) / 4), 6);
if (create_monster(
- mgen_data(mon, BEH_FRIENDLY,
+ mgen_data(mon, BEH_FRIENDLY, &you,
dur, SPELL_CALL_CANINE_FAMILIAR,
you.pos(),
MHITYOU,
@@ -1331,7 +1317,7 @@ bool cast_summon_elemental(int pow, god_type god,
if (create_monster(
mgen_data(mon,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
dur, SPELL_SUMMON_ELEMENTAL,
targ,
MHITYOU,
@@ -1356,7 +1342,7 @@ bool cast_summon_ice_beast(int pow, god_type god)
const int dur = std::min(2 + (random2(pow) / 4), 6);
if (create_monster(
- mgen_data(mon, BEH_FRIENDLY,
+ mgen_data(mon, BEH_FRIENDLY, &you,
dur, SPELL_SUMMON_ICE_BEAST,
you.pos(), MHITYOU,
0, god)) != -1)
@@ -1381,7 +1367,7 @@ bool cast_summon_ugly_thing(int pow, god_type god)
if (create_monster(
mgen_data(mon,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
dur, SPELL_SUMMON_UGLY_THING,
you.pos(),
MHITYOU,
@@ -1411,7 +1397,7 @@ bool cast_summon_dragon(int pow, god_type god)
if (create_monster(
mgen_data(MONS_DRAGON,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
3, SPELL_SUMMON_DRAGON,
you.pos(),
MHITYOU,
@@ -1476,11 +1462,15 @@ bool summon_berserker(int pow, god_type god, int spell,
mon = (coinflip()) ? MONS_HILL_GIANT : MONS_STONE_GIANT;
}
+ mgen_data mg(mon, !force_hostile ? BEH_FRIENDLY : BEH_HOSTILE,
+ !force_hostile ? &you : 0, dur, spell, you.pos(),
+ MHITYOU, 0, god);
+
+ if (force_hostile)
+ mg.non_actor_summoner = "the rage of " + god_name(god, false);
+
int monster =
- create_monster(
- mgen_data(mon,
- !force_hostile ? BEH_FRIENDLY : BEH_HOSTILE,
- dur, spell, you.pos(), MHITYOU, 0, god));
+ create_monster(mg);
if (monster == -1)
return (false);
@@ -1510,14 +1500,18 @@ static bool _summon_holy_being_wrapper(int pow, god_type god, int spell,
{
UNUSED(pow);
- const int monster =
- create_monster(
- mgen_data(mon,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
- dur, spell,
- you.pos(),
- MHITYOU,
- MG_FORCE_BEH, god));
+ mgen_data mg(mon,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ friendly ? &you : 0,
+ dur, spell,
+ you.pos(),
+ MHITYOU,
+ MG_FORCE_BEH, god);
+
+ if (!friendly)
+ mg.non_actor_summoner = god_name(god, false);
+
+ const int monster = create_monster(mg);
if (monster == -1)
return (false);
@@ -1598,14 +1592,18 @@ bool cast_tukimas_dance(int pow, god_type god, bool force_hostile)
// Cursed weapons become hostile.
const bool friendly = (!force_hostile && !item_cursed(you.inv[wpn]));
- monster =
- create_monster(
- mgen_data(MONS_DANCING_WEAPON,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
- dur, SPELL_TUKIMAS_DANCE,
- you.pos(),
- MHITYOU,
- 0, god));
+ mgen_data mg(MONS_DANCING_WEAPON,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ force_hostile ? 0 : &you,
+ dur, SPELL_TUKIMAS_DANCE,
+ you.pos(),
+ MHITYOU,
+ 0, god);
+
+ if (force_hostile)
+ mg.non_actor_summoner = god_name(god, false);
+
+ monster = create_monster(mg);
if (monster == -1)
{
@@ -1694,7 +1692,7 @@ bool cast_conjure_ball_lightning(int pow, god_type god)
int monster =
mons_place(
- mgen_data(MONS_BALL_LIGHTNING, BEH_FRIENDLY,
+ mgen_data(MONS_BALL_LIGHTNING, BEH_FRIENDLY, &you,
0, SPELL_CONJURE_BALL_LIGHTNING,
target, MHITNOT, 0, god));
diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc
index f235c04520..17b33ead54 100644
--- a/crawl-ref/source/spells3.cc
+++ b/crawl-ref/source/spells3.cc
@@ -35,8 +35,9 @@
#include "message.h"
#include "misc.h"
#include "mon-behv.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-iter.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "player.h"
#include "quiver.h"
@@ -426,7 +427,7 @@ bool cast_call_imp(int pow, god_type god)
const int monster =
create_monster(
- mgen_data(mon, BEH_FRIENDLY, dur, SPELL_CALL_IMP,
+ mgen_data(mon, BEH_FRIENDLY, &you, dur, SPELL_CALL_IMP,
you.pos(), MHITYOU, MG_FORCE_BEH, god));
if (monster != -1)
@@ -455,7 +456,7 @@ static bool _summon_demon_wrapper(int pow, god_type god, int spell,
create_monster(
mgen_data(mon,
friendly ? BEH_FRIENDLY :
- charmed ? BEH_CHARMED : BEH_HOSTILE,
+ charmed ? BEH_CHARMED : BEH_HOSTILE, &you,
dur, spell, you.pos(), MHITYOU, MG_FORCE_BEH, god));
if (monster != -1)
@@ -565,7 +566,7 @@ bool cast_shadow_creatures(god_type god)
const int monster =
create_monster(
- mgen_data(RANDOM_MONSTER, BEH_FRIENDLY,
+ mgen_data(RANDOM_MONSTER, BEH_FRIENDLY, &you,
2, SPELL_SHADOW_CREATURES,
you.pos(), MHITYOU,
MG_FORCE_BEH, god), false);
@@ -612,7 +613,7 @@ bool cast_summon_horrible_things(int pow, god_type god)
{
const int monster =
create_monster(
- mgen_data(MONS_TENTACLED_MONSTROSITY, BEH_FRIENDLY,
+ mgen_data(MONS_TENTACLED_MONSTROSITY, BEH_FRIENDLY, &you,
6, SPELL_SUMMON_HORRIBLE_THINGS,
you.pos(), MHITYOU,
MG_FORCE_BEH, god));
@@ -628,7 +629,7 @@ bool cast_summon_horrible_things(int pow, god_type god)
{
const int monster =
create_monster(
- mgen_data(MONS_ABOMINATION_LARGE, BEH_FRIENDLY,
+ mgen_data(MONS_ABOMINATION_LARGE, BEH_FRIENDLY, &you,
6, SPELL_SUMMON_HORRIBLE_THINGS,
you.pos(), MHITYOU,
MG_FORCE_BEH, god));
@@ -925,8 +926,9 @@ void equip_undead(const coord_def &a, int corps, int monster, int monnum)
}
static bool _raise_remains(const coord_def &pos, int corps, beh_type beha,
- unsigned short hitting, god_type god, bool actual,
- bool force_beh, int* mon_index)
+ unsigned short hitting, actor *as, std::string nas,
+ god_type god, bool actual, bool force_beh,
+ int* mon_index)
{
if (mon_index != NULL)
*mon_index = -1;
@@ -969,11 +971,12 @@ static bool _raise_remains(const coord_def &pos, int corps, beh_type beha,
: MONS_SKELETON_LARGE;
}
- int monster = create_monster(
- mgen_data(mon, beha,
- 0, 0, pos, hitting,
- MG_FORCE_BEH, god,
- zombie_type, number));
+ mgen_data mg(mon, beha, as, 0, 0, pos, hitting, MG_FORCE_BEH, god,
+ zombie_type, number);
+
+ mg.non_actor_summoner = nas;
+
+ int monster = create_monster(mg);
if (mon_index != NULL)
*mon_index = monster;
@@ -984,7 +987,13 @@ static bool _raise_remains(const coord_def &pos, int corps, beh_type beha,
const int monnum = item.orig_monnum - 1;
if (is_named_corpse(item))
- name_zombie(&menv[monster], monnum, get_corpse_name(item));
+ {
+ unsigned long name_type;
+ std::string name = get_corpse_name(item, &name_type);
+
+ if (name_type == 0 || name_type == MF_NAME_REPLACE)
+ name_zombie(&menv[monster], monnum, name);
+ }
equip_undead(pos, corps, monster, monnum);
@@ -1000,6 +1009,7 @@ static bool _raise_remains(const coord_def &pos, int corps, beh_type beha,
// you are butchering being animated.
int animate_remains(const coord_def &a, corpse_type class_allowed,
beh_type beha, unsigned short hitting,
+ actor *as, std::string nas,
god_type god, bool actual,
bool quiet, bool force_beh,
int* mon_index)
@@ -1024,8 +1034,8 @@ int animate_remains(const coord_def &a, corpse_type class_allowed,
const bool was_butchering = is_being_butchered(*si);
- success = _raise_remains(a, si.link(), beha, hitting, god, actual,
- force_beh, mon_index);
+ success = _raise_remains(a, si.link(), beha, hitting, as, nas,
+ god, actual, force_beh, mon_index);
if (actual && success)
{
@@ -1058,7 +1068,7 @@ int animate_remains(const coord_def &a, corpse_type class_allowed,
}
int animate_dead(actor *caster, int pow, beh_type beha, unsigned short hitting,
- god_type god, bool actual)
+ actor *as, std::string nas, god_type god, bool actual)
{
UNUSED(pow);
@@ -1073,7 +1083,7 @@ int animate_dead(actor *caster, int pow, beh_type beha, unsigned short hitting,
{
// This will produce a message if the corpse you are butchering
// is raised.
- if (animate_remains(*ri, CORPSE_BODY, beha, hitting, god,
+ if (animate_remains(*ri, CORPSE_BODY, beha, hitting, as, nas, god,
actual, true) > 0)
{
number_raised++;
@@ -1126,7 +1136,7 @@ bool cast_simulacrum(int pow, god_type god)
{
const int monster =
create_monster(
- mgen_data(sim_type, BEH_FRIENDLY,
+ mgen_data(sim_type, BEH_FRIENDLY, &you,
6, SPELL_SIMULACRUM,
you.pos(), MHITYOU,
MG_FORCE_BEH, god, type));
@@ -1217,7 +1227,7 @@ bool cast_twisted_resurrection(int pow, god_type god)
const int monster =
create_monster(
- mgen_data(mon, BEH_FRIENDLY,
+ mgen_data(mon, BEH_FRIENDLY, &you,
0, 0,
you.pos(), MHITYOU,
MG_FORCE_BEH, god,
@@ -1299,7 +1309,7 @@ bool cast_haunt(int pow, const coord_def& where, god_type god)
const int monster =
create_monster(
mgen_data(mon,
- BEH_FRIENDLY,
+ BEH_FRIENDLY, &you,
5, SPELL_HAUNT,
where, mi, MG_FORCE_BEH, god));
@@ -1761,12 +1771,8 @@ bool remove_sanctuary(bool did_attack)
// Now that the sanctuary is gone, monsters aren't afraid of it
// anymore.
- for (int i = 0; i < MAX_MONSTERS; ++i)
- {
- monsters *mon = &menv[i];
- if (mon->alive())
- mons_stop_fleeing_from_sanctuary(mon);
- }
+ for (monster_iterator mi; mi; ++mi)
+ mons_stop_fleeing_from_sanctuary(*mi);
if (is_resting())
stop_running();
diff --git a/crawl-ref/source/spells3.h b/crawl-ref/source/spells3.h
index 0aac012c80..7656213bcb 100644
--- a/crawl-ref/source/spells3.h
+++ b/crawl-ref/source/spells3.h
@@ -51,11 +51,13 @@ bool receive_corpses(int pow, coord_def where);
void equip_undead(const coord_def &a, int corps, int monster, int monnum);
int animate_remains(const coord_def &a, corpse_type class_allowed,
beh_type beha, unsigned short hitting,
+ actor *as = NULL, std::string nas = "",
god_type god = GOD_NO_GOD, bool actual = true,
bool quiet = false, bool force_beh = false,
int* mon_index = NULL);
int animate_dead(actor *caster, int pow, beh_type beha, unsigned short hitting,
+ actor *as = NULL, std::string nas = "",
god_type god = GOD_NO_GOD, bool actual = true);
bool cast_simulacrum(int pow, god_type god = GOD_NO_GOD);
diff --git a/crawl-ref/source/spells4.cc b/crawl-ref/source/spells4.cc
index 027359417e..86d344f25d 100644
--- a/crawl-ref/source/spells4.cc
+++ b/crawl-ref/source/spells4.cc
@@ -33,8 +33,8 @@
#include "message.h"
#include "misc.h"
#include "mon-behv.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "ouch.h"
#include "player.h"
@@ -397,7 +397,7 @@ static int _sleep_monsters(coord_def where, int pow, int, actor *)
if (!monster)
return (0);
- if (!monster->can_sleep(true))
+ if (!monster->can_hibernate(true))
return (0);
if (monster->check_res_magic(pow))
@@ -410,7 +410,7 @@ static int _sleep_monsters(coord_def where, int pow, int, actor *)
if (monster->has_ench(ENCH_SLEEP_WARY) && !one_chance_in(3))
return (0);
- monster->put_to_sleep();
+ monster->hibernate();
monster->expose_to_element(BEAM_COLD, 2);
return (1);
}
@@ -1036,22 +1036,22 @@ bool backlight_monsters(coord_def where, int pow, int garbage)
if (mons_class_flag(monster->type, M_GLOWS))
return (false);
- mon_enchant bklt = monster->get_ench(ENCH_BACKLIGHT);
+ mon_enchant bklt = monster->get_ench(ENCH_CORONA);
const int lvl = bklt.degree;
// This enchantment overrides invisibility (neat).
if (monster->has_ench(ENCH_INVIS))
{
- if (!monster->has_ench(ENCH_BACKLIGHT))
+ if (!monster->has_ench(ENCH_CORONA))
{
monster->add_ench(
- mon_enchant(ENCH_BACKLIGHT, 1, KC_OTHER, random_range(30, 50)));
+ mon_enchant(ENCH_CORONA, 1, KC_OTHER, random_range(30, 50)));
simple_monster_message(monster, " is lined in light.");
}
return (true);
}
- monster->add_ench(mon_enchant(ENCH_BACKLIGHT, 1));
+ monster->add_ench(mon_enchant(ENCH_CORONA, 1));
if (lvl == 0)
simple_monster_message(monster, " is outlined in light.");
diff --git a/crawl-ref/source/spl-book.cc b/crawl-ref/source/spl-book.cc
index 8845464757..989e5db899 100644
--- a/crawl-ref/source/spl-book.cc
+++ b/crawl-ref/source/spl-book.cc
@@ -156,12 +156,12 @@ static spell_type spellbook_template_array[][SPELLBOOK_SIZE] =
// 9 - Book of Ice
{SPELL_FREEZING_AURA,
- SPELL_SLEEP,
+ SPELL_HIBERNATION,
SPELL_CONDENSATION_SHIELD,
SPELL_OZOCUBUS_REFRIGERATION,
SPELL_BOLT_OF_COLD,
SPELL_SIMULACRUM,
- SPELL_MASS_SLEEP,
+ SPELL_ENGLACIATION,
SPELL_NO_SPELL,
},
@@ -320,9 +320,9 @@ static spell_type spellbook_template_array[][SPELLBOOK_SIZE] =
},
// 24 - Book of Charms
- {SPELL_BACKLIGHT,
+ {SPELL_CORONA,
SPELL_REPEL_MISSILES,
- SPELL_SLEEP,
+ SPELL_HIBERNATION,
SPELL_CONFUSE,
SPELL_ENSLAVEMENT,
SPELL_SILENCE,
@@ -402,7 +402,7 @@ static spell_type spellbook_template_array[][SPELLBOOK_SIZE] =
SPELL_TAME_BEASTS,
SPELL_MASS_CONFUSION,
SPELL_CONTROL_UNDEAD,
- SPELL_MASS_SLEEP,
+ SPELL_ENGLACIATION,
SPELL_NO_SPELL,
SPELL_NO_SPELL,
},
diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc
index 9a48b2ad31..8d96fb7f82 100644
--- a/crawl-ref/source/spl-cast.cc
+++ b/crawl-ref/source/spl-cast.cc
@@ -34,7 +34,8 @@
#include "misc.h"
#include "message.h"
#include "mon-cast.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mutation.h"
#include "ouch.h"
#include "player.h"
@@ -1039,13 +1040,8 @@ static void _try_monster_cast(spell_type spell, int powc,
return;
}
- int midx;
-
- for (midx = 0; midx < MAX_MONSTERS; midx++)
- if (menv[midx].type == MONS_NO_MONSTER)
- break;
-
- if (midx == MAX_MONSTERS)
+ monsters* mon = get_free_monster();
+ if (!mon)
{
mpr("Couldn't try casting monster spell because there is "
"no empty monster slot.");
@@ -1054,8 +1050,6 @@ static void _try_monster_cast(spell_type spell, int powc,
mpr("Invalid player spell, attempting to cast it as monster spell.");
- monsters* mon = &menv[midx];
-
mon->mname = "Dummy Monster";
mon->type = MONS_HUMAN;
mon->behaviour = BEH_SEEK;
@@ -1079,7 +1073,7 @@ static void _try_monster_cast(spell_type spell, int powc,
else
mon->foe = mgrd(spd.target);
- mgrd(you.pos()) = midx;
+ mgrd(you.pos()) = mon->mindex();
mons_cast(mon, beam, spell);
@@ -1711,7 +1705,7 @@ spret_type your_spells(spell_type spell, int powc, bool allow_fail)
mpr("You attempt to give life to the dead...");
if (animate_remains(you.pos(), CORPSE_SKELETON, BEH_FRIENDLY,
- MHITYOU, god) < 0)
+ MHITYOU, &you, "", god) < 0)
{
mpr("There is no skeleton here to animate!");
}
@@ -1720,7 +1714,7 @@ spret_type your_spells(spell_type spell, int powc, bool allow_fail)
case SPELL_ANIMATE_DEAD:
mpr("You call on the dead to walk for you...");
- animate_dead(&you, powc + 1, BEH_FRIENDLY, MHITYOU, god);
+ animate_dead(&you, powc + 1, BEH_FRIENDLY, MHITYOU, &you, "", god);
break;
case SPELL_SIMULACRUM:
@@ -1744,8 +1738,8 @@ spret_type your_spells(spell_type spell, int powc, bool allow_fail)
cast_confusing_touch(powc);
break;
- case SPELL_BACKLIGHT:
- if (!zapping(ZAP_BACKLIGHT, powc + 10, beam, true))
+ case SPELL_CORONA:
+ if (!zapping(ZAP_CORONA, powc + 10, beam, true))
return (SPRET_ABORT);
break;
@@ -1772,7 +1766,7 @@ spret_type your_spells(spell_type spell, int powc, bool allow_fail)
cast_tame_beasts(powc);
break;
- case SPELL_SLEEP:
+ case SPELL_HIBERNATION:
{
const int sleep_power =
stepdown_value(powc * 9 / 10, 5, 35, 45, 50);
@@ -1780,11 +1774,16 @@ spret_type your_spells(spell_type spell, int powc, bool allow_fail)
mprf(MSGCH_DIAGNOSTICS, "Sleep power stepdown: %d -> %d",
powc, sleep_power);
#endif
- if (!zapping(ZAP_SLEEP, sleep_power, beam, true))
+ if (!zapping(ZAP_HIBERNATION, sleep_power, beam, true))
return (SPRET_ABORT);
break;
}
+ case SPELL_SLEEP:
+ if (!zapping(ZAP_SLEEP, powc, beam, true))
+ return (SPRET_ABORT);
+ break;
+
case SPELL_PARALYSE:
if (!zapping(ZAP_PARALYSIS, powc, beam, true))
return (SPRET_ABORT);
@@ -1813,7 +1812,7 @@ spret_type your_spells(spell_type spell, int powc, bool allow_fail)
mass_enchantment(ENCH_CONFUSION, powc, MHITYOU);
break;
- case SPELL_MASS_SLEEP:
+ case SPELL_ENGLACIATION:
cast_mass_sleep(powc);
break;
diff --git a/crawl-ref/source/spl-data.h b/crawl-ref/source/spl-data.h
index 724d627fd9..e8d212591e 100644
--- a/crawl-ref/source/spl-data.h
+++ b/crawl-ref/source/spl-data.h
@@ -1664,7 +1664,7 @@
},
{
- SPELL_SLEEP, "Ensorcelled Hibernation",
+ SPELL_HIBERNATION, "Ensorcelled Hibernation",
SPTYP_ENCHANTMENT | SPTYP_ICE,
SPFLAG_DIR_OR_TARGET | SPFLAG_NOT_SELF,
2,
@@ -1677,7 +1677,7 @@
},
{
- SPELL_MASS_SLEEP, "Metabolic Englaciation",
+ SPELL_ENGLACIATION, "Metabolic Englaciation",
SPTYP_ENCHANTMENT | SPTYP_ICE,
SPFLAG_AREA,
7,
@@ -1807,7 +1807,7 @@
},
{
- SPELL_BACKLIGHT, "Corona",
+ SPELL_CORONA, "Corona",
SPTYP_ENCHANTMENT,
SPFLAG_DIR_OR_TARGET | SPFLAG_NOT_SELF,
1,
@@ -2434,6 +2434,19 @@
},
{
+ SPELL_SLEEP, "Sleep",
+ SPTYP_ENCHANTMENT,
+ SPFLAG_DIR_OR_TARGET | SPFLAG_NOT_SELF,
+ 5,
+ 200,
+ LOS_RADIUS, LOS_RADIUS,
+ 0,
+ NULL,
+ true,
+ false
+},
+
+{
SPELL_NO_SPELL, "nonexistent spell",
0,
SPFLAG_TESTING,
diff --git a/crawl-ref/source/spl-mis.cc b/crawl-ref/source/spl-mis.cc
index bbab3c230a..511426ec09 100644
--- a/crawl-ref/source/spl-mis.cc
+++ b/crawl-ref/source/spl-mis.cc
@@ -18,8 +18,8 @@
#include "it_use2.h"
#include "kills.h"
#include "misc.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "mutation.h"
#include "player.h"
@@ -630,7 +630,7 @@ void MiscastEffect::_potion_effect(int pot_eff, int pot_pow)
// There's no levitation enchantment for monsters, and,
// anyway, it's not nearly as inconvenient for monsters as
// for the player, so backlight them instead.
- mon_target->add_ench(mon_enchant(ENCH_BACKLIGHT, pot_pow, kc));
+ mon_target->add_ench(mon_enchant(ENCH_CORONA, pot_pow, kc));
break;
case POT_BERSERK_RAGE:
if (target->can_go_berserk())
@@ -707,7 +707,9 @@ bool MiscastEffect::_create_monster(monster_type what, int abj_deg,
(crawl_state.is_god_acting()) ? crawl_state.which_god_acting()
: GOD_NO_GOD;
- mgen_data data = mgen_data::hostile_at(what, alert,
+ if (cause.empty())
+ cause = get_default_cause();
+ mgen_data data = mgen_data::hostile_at(what, cause, alert,
abj_deg, 0, target->pos(), 0, god);
// hostile_at() assumes the monster is hostile to the player,
diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc
index 283d022339..7b861de749 100644
--- a/crawl-ref/source/stash.cc
+++ b/crawl-ref/source/stash.cc
@@ -26,7 +26,7 @@
#include "message.h"
#include "misc.h"
#include "mon-util.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "notes.h"
#include "options.h"
#include "place.h"
diff --git a/crawl-ref/source/store.cc b/crawl-ref/source/store.cc
index 25c50ed763..f52a97d510 100644
--- a/crawl-ref/source/store.cc
+++ b/crawl-ref/source/store.cc
@@ -9,7 +9,9 @@
#include "store.h"
+#include "dlua.h"
#include "externs.h"
+#include "monster.h"
#include "tags.h"
#include "travel.h"
@@ -105,6 +107,22 @@ CrawlStoreValue::CrawlStoreValue(const CrawlStoreValue &other)
break;
}
+ case SV_MONST:
+ {
+ monsters* mon;
+ mon = new monsters(*static_cast<monsters*>(other.val.ptr));
+ val.ptr = static_cast<void*>(mon);
+ break;
+ }
+
+ case SV_LUA:
+ {
+ dlua_chunk* chunk;
+ chunk = new dlua_chunk(*static_cast<dlua_chunk*>(other.val.ptr));
+ val.ptr = static_cast<void*>(chunk);
+ break;
+ }
+
case NUM_STORE_VAL_TYPES:
ASSERT(false);
}
@@ -208,6 +226,20 @@ CrawlStoreValue::CrawlStoreValue(const level_pos &_val)
get_level_pos() = _val;
}
+CrawlStoreValue::CrawlStoreValue(const monsters &_val)
+ : type(SV_MONST), flags(SFLAG_UNSET)
+{
+ val.ptr = NULL;
+ get_monster() = _val;
+}
+
+CrawlStoreValue::CrawlStoreValue(const dlua_chunk &_val)
+ : type(SV_LUA), flags(SFLAG_UNSET)
+{
+ val.ptr = NULL;
+ get_lua() = _val;
+}
+
CrawlStoreValue::~CrawlStoreValue()
{
unset(true);
@@ -301,6 +333,22 @@ void CrawlStoreValue::unset(bool force)
break;
}
+ case SV_MONST:
+ {
+ monsters* mon = static_cast<monsters*>(val.ptr);
+ delete mon;
+ val.ptr = NULL;
+ break;
+ }
+
+ case SV_LUA:
+ {
+ dlua_chunk* chunk = static_cast<dlua_chunk*>(val.ptr);
+ delete chunk;
+ val.ptr = NULL;
+ break;
+ }
+
case SV_NONE:
DEBUGSTR("CrawlStoreValue::unset: unsetting nothing");
break;
@@ -413,7 +461,8 @@ store_val_type CrawlStoreValue::get_type() const
// Read/write from/to savefile
void CrawlStoreValue::write(writer &th) const
{
- ASSERT(!(flags & SFLAG_UNSET));
+ ASSERT(type != SV_NONE || (flags & SFLAG_UNSET));
+ ASSERT(!(flags & SFLAG_UNSET) || (type == SV_NONE));
marshallByte(th, (char) type);
marshallByte(th, (char) flags);
@@ -489,8 +538,22 @@ void CrawlStoreValue::write(writer &th) const
break;
}
+ case SV_MONST:
+ {
+ monsters* mon = static_cast<monsters*>(val.ptr);
+ marshallMonster(th, *mon);
+ break;
+ }
+
+ case SV_LUA:
+ {
+ dlua_chunk* chunk = static_cast<dlua_chunk*>(val.ptr);
+ chunk->write(th);
+ break;
+ }
+
case SV_NONE:
- ASSERT(false);
+ break;
case NUM_STORE_VAL_TYPES:
ASSERT(false);
@@ -502,7 +565,8 @@ void CrawlStoreValue::read(reader &th)
type = static_cast<store_val_type>(unmarshallByte(th));
flags = (store_flags) unmarshallByte(th);
- ASSERT(!(flags & SFLAG_UNSET));
+ ASSERT(type != SV_NONE || (flags & SFLAG_UNSET));
+ ASSERT(!(flags & SFLAG_UNSET) || (type == SV_NONE));
switch (type)
{
@@ -587,8 +651,26 @@ void CrawlStoreValue::read(reader &th)
break;
}
+ case SV_MONST:
+ {
+ monsters mon;
+ unmarshallMonster(th, mon);
+ val.ptr = (void*) new monsters(mon);
+
+ break;
+ }
+
+ case SV_LUA:
+ {
+ dlua_chunk chunk;
+ chunk.read(th);
+ val.ptr = (void*) new dlua_chunk(chunk);
+
+ break;
+ }
+
case SV_NONE:
- ASSERT(false);
+ break;
case NUM_STORE_VAL_TYPES:
ASSERT(false);
@@ -757,6 +839,15 @@ level_pos &CrawlStoreValue::get_level_pos()
GET_VAL_PTR(SV_LEV_POS, level_pos*, new level_pos());
}
+monsters &CrawlStoreValue::get_monster()
+{
+ GET_VAL_PTR(SV_MONST, monsters*, new monsters());
+}
+
+dlua_chunk &CrawlStoreValue::get_lua()
+{
+ GET_VAL_PTR(SV_LUA, dlua_chunk*, new dlua_chunk());
+}
CrawlStoreValue &CrawlStoreValue::operator [] (const std::string &key)
{
@@ -861,18 +952,20 @@ const CrawlStoreValue &CrawlStoreValue::operator
/////////////////////
// Typecast operators
#ifdef TARGET_COMPILER_VC
-CrawlStoreValue::operator bool&() { return get_bool(); }
-CrawlStoreValue::operator char&() { return get_byte(); }
-CrawlStoreValue::operator short&() { return get_short(); }
-CrawlStoreValue::operator float&() { return get_float(); }
-CrawlStoreValue::operator long&() { return get_long(); }
-CrawlStoreValue::operator std::string&() { return get_string(); }
-CrawlStoreValue::operator coord_def&() { return get_coord(); }
-CrawlStoreValue::operator CrawlHashTable&() { return get_table(); }
-CrawlStoreValue::operator CrawlVector&() { return get_vector(); }
-CrawlStoreValue::operator item_def&() { return get_item(); }
-CrawlStoreValue::operator level_id&() { return get_level_id(); }
-CrawlStoreValue::operator level_pos&() { return get_level_pos(); }
+CrawlStoreValue::operator bool&() { return get_bool(); }
+CrawlStoreValue::operator char&() { return get_byte(); }
+CrawlStoreValue::operator short&() { return get_short(); }
+CrawlStoreValue::operator float&() { return get_float(); }
+CrawlStoreValue::operator long&() { return get_long(); }
+CrawlStoreValue::operator std::string&() { return get_string(); }
+CrawlStoreValue::operator coord_def&() { return get_coord(); }
+CrawlStoreValue::operator CrawlHashTable&() { return get_table(); }
+CrawlStoreValue::operator CrawlVector&() { return get_vector(); }
+CrawlStoreValue::operator item_def&() { return get_item(); }
+CrawlStoreValue::operator level_id&() { return get_level_id(); }
+CrawlStoreValue::operator level_pos&() { return get_level_pos(); }
+CrawlStoreValue::operator monster&() { return get_monster(); }
+CrawlStoreValue::operator dlua_chunk&() { return get_dlua_chunk(); }
#else
&CrawlStoreValue::operator bool()
{
@@ -933,6 +1026,16 @@ CrawlStoreValue::operator level_pos&() { return get_level_pos(); }
{
return get_level_pos();
}
+
+&CrawlStoreValue::operator monsters()
+{
+ return get_monster();
+}
+
+&CrawlStoreValue::operator dlua_chunk()
+{
+ return get_lua();
+}
#endif
///////////////////////////
@@ -1076,6 +1179,18 @@ CrawlStoreValue &CrawlStoreValue::operator = (const level_pos &_val)
return (*this);
}
+CrawlStoreValue &CrawlStoreValue::operator = (const monsters &_val)
+{
+ get_monster() = _val;
+ return (*this);
+}
+
+CrawlStoreValue &CrawlStoreValue::operator = (const dlua_chunk &_val)
+{
+ get_lua() = _val;
+ return (*this);
+}
+
///////////////////////////////////////////////////
// Non-assignment operators which affect the lvalue
#define INT_OPERATOR_UNARY(op) \
@@ -1493,9 +1608,7 @@ void CrawlVector::write(writer &th) const
for (vec_size i = 0; i < size(); i++)
{
CrawlStoreValue val = vector[i];
- ASSERT(val.type != SV_NONE);
- ASSERT(!(val.flags & SFLAG_UNSET));
- val.write(th);
+ val.write(th);
}
assert_validity();
diff --git a/crawl-ref/source/store.h b/crawl-ref/source/store.h
index e23e6056be..79b9454c97 100644
--- a/crawl-ref/source/store.h
+++ b/crawl-ref/source/store.h
@@ -20,7 +20,9 @@ class CrawlVector;
struct item_def;
struct coord_def;
struct level_pos;
-class level_id;
+class level_id;
+class dlua_chunk;
+class monsters;
typedef unsigned char hash_size;
typedef unsigned char vec_size;
@@ -46,6 +48,8 @@ enum store_val_type
SV_VEC,
SV_LEV_ID,
SV_LEV_POS,
+ SV_MONST,
+ SV_LUA,
NUM_STORE_VAL_TYPES
};
@@ -94,8 +98,9 @@ public:
CrawlStoreValue(const CrawlVector &val);
CrawlStoreValue(const level_id &val);
CrawlStoreValue(const level_pos &val);
+ CrawlStoreValue(const monsters &val);
+ CrawlStoreValue(const dlua_chunk &val);
- // Only needed for doing some assertion checking.
CrawlStoreValue &operator = (const CrawlStoreValue &other);
protected:
@@ -128,6 +133,8 @@ public:
item_def &get_item();
level_id &get_level_id();
level_pos &get_level_pos();
+ monsters &get_monster();
+ dlua_chunk &get_lua();
bool get_bool() const;
char get_byte() const;
@@ -142,6 +149,8 @@ public:
const CrawlHashTable& get_table() const;
const CrawlVector& get_vector() const;
const item_def& get_item() const;
+ const monsters& get_monster() const;
+ const dlua_chunk& get_lua() const;
#if 0
// These don't actually exist
@@ -188,6 +197,8 @@ public:
operator item_def&();
operator level_id&();
operator level_pos&();
+ operator monsters&();
+ operator dlua_chunk&();
#else
&operator bool();
&operator char();
@@ -201,6 +212,8 @@ public:
&operator item_def();
&operator level_id();
&operator level_pos();
+ &operator monsters();
+ &operator dlua_chunk();
#endif
operator bool() const;
@@ -227,6 +240,8 @@ public:
CrawlStoreValue &operator = (const item_def &val);
CrawlStoreValue &operator = (const level_id &val);
CrawlStoreValue &operator = (const level_pos &val);
+ CrawlStoreValue &operator = (const monsters &val);
+ CrawlStoreValue &operator = (const dlua_chunk &val);
// Misc operators
std::string &operator += (const std::string &val);
diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc
index d7f211bdea..92e670a644 100644
--- a/crawl-ref/source/stuff.cc
+++ b/crawl-ref/source/stuff.cc
@@ -14,7 +14,7 @@
#include "los.h"
#include "message.h"
#include "misc.h"
-#include "monplace.h"
+#include "mon-place.h"
#include "state.h"
#include "stuff.h"
#include "view.h"
@@ -53,7 +53,7 @@
#include "items.h"
#include "macro.h"
#include "misc.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "notes.h"
#include "output.h"
@@ -885,27 +885,21 @@ bool is_trap_square(dungeon_feature_type grid)
// Does the equivalent of KILL_RESET on all monsters in LOS. Should only be
// applied to new games.
-void zap_los_monsters()
+void zap_los_monsters(bool items_also)
{
- calc_show_los();
+ // Not using player LOS since clouds might temporarily
+ // block monsters.
+ los_def los(you.pos(), opc_fullyopaque);
+ los.update();
- for (rectangle_iterator ri(crawl_view.vlos1, crawl_view.vlos2); ri; ++ri )
+ for (radius_iterator ri(you.pos(), LOS_RADIUS, true, false); ri; ++ri)
{
- if (!in_vlos(*ri))
+ if (!you.see_cell(*ri))
continue;
- const coord_def g = view2grid(*ri);
-
- if (!map_bounds(g))
- continue;
-
- if (g == you.pos())
- continue;
-
- // At tutorial beginning disallow items in line of sight.
- if (Options.tutorial_events[TUT_SEEN_FIRST_OBJECT])
+ if (items_also)
{
- int item = igrd(g);
+ int item = igrd(*ri);
if (item != NON_ITEM && mitm[item].is_valid() )
destroy_item(item);
@@ -913,11 +907,8 @@ void zap_los_monsters()
// If we ever allow starting with a friendly monster,
// we'll have to check here.
- monsters *mon = monster_at(g);
- if (mon == NULL)
- continue;
-
- if (mons_class_flag( mon->type, M_NO_EXP_GAIN ))
+ monsters *mon = monster_at(*ri);
+ if (mon == NULL || mons_class_flag(mon->type, M_NO_EXP_GAIN))
continue;
#ifdef DEBUG_DIAGNOSTICS
diff --git a/crawl-ref/source/stuff.h b/crawl-ref/source/stuff.h
index 4a7fab6c11..976bb8fddb 100644
--- a/crawl-ref/source/stuff.h
+++ b/crawl-ref/source/stuff.h
@@ -93,7 +93,7 @@ template <typename Z> inline Z sgn(Z x)
}
bool is_trap_square(dungeon_feature_type grid);
-void zap_los_monsters();
+void zap_los_monsters(bool items_also);
int integer_sqrt(int value);
diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc
index 4b5ab14ae8..fabf242086 100644
--- a/crawl-ref/source/tags.cc
+++ b/crawl-ref/source/tags.cc
@@ -202,9 +202,6 @@ static void unmarshallResists(reader &th, mon_resist_def &res,
static void marshallSpells(writer &, const monster_spells &);
static void unmarshallSpells(reader &, monster_spells &);
-static void marshall_monster(writer &th, const monsters &m);
-static void unmarshall_monster(reader &th, monsters &m);
-
template<typename T, typename T_iter, typename T_marshal>
static void marshall_iterator(writer &th, T_iter beg, T_iter end,
T_marshal marshal);
@@ -1161,14 +1158,14 @@ static void tag_construct_you_dungeon(writer &th)
static void marshall_follower(writer &th, const follower &f)
{
- marshall_monster(th, f.mons);
+ marshallMonster(th, f.mons);
for (int i = 0; i < NUM_MONSTER_SLOTS; ++i)
marshallItem(th, f.items[i]);
}
static void unmarshall_follower(reader &th, follower &f)
{
- unmarshall_monster(th, f.mons);
+ unmarshallMonster(th, f.mons);
for (int i = 0; i < NUM_MONSTER_SLOTS; ++i)
unmarshallItem(th, f.items[i]);
}
@@ -1876,7 +1873,7 @@ static mon_enchant unmarshall_mon_enchant(reader &th)
return (me);
}
-static void marshall_monster(writer &th, const monsters &m)
+void marshallMonster(writer &th, const monsters &m)
{
marshallString(th, m.mname);
marshallByte(th, m.ac);
@@ -1928,6 +1925,8 @@ static void marshall_monster(writer &th, const monsters &m)
ASSERT(m.ghost.get());
marshallGhost(th, *m.ghost);
}
+
+ m.props.write(th);
}
static void tag_construct_level_monsters(writer &th)
@@ -1963,7 +1962,7 @@ static void tag_construct_level_monsters(writer &th)
}
}
#endif
- marshall_monster(th, m);
+ marshallMonster(th, m);
}
}
@@ -2186,7 +2185,7 @@ static void tag_read_level_items(reader &th, char minorVersion)
#endif
}
-static void unmarshall_monster(reader &th, monsters &m)
+void unmarshallMonster(reader &th, monsters &m)
{
m.reset();
@@ -2246,6 +2245,12 @@ static void unmarshall_monster(reader &th, monsters &m)
if (mons_is_ghost_demon(m.type))
m.set_ghost(unmarshallGhost(th, _tag_minor_version));
+ if (_tag_minor_version >= TAG_MINOR_MON_PROP)
+ {
+ m.props.clear();
+ m.props.read(th);
+ }
+
m.check_speed();
}
@@ -2270,7 +2275,7 @@ static void tag_read_level_monsters(reader &th, char minorVersion)
for (i = 0; i < count; i++)
{
monsters &m = menv[i];
- unmarshall_monster(th, m);
+ unmarshallMonster(th, m);
// place monster
if (m.type != MONS_NO_MONSTER)
diff --git a/crawl-ref/source/tags.h b/crawl-ref/source/tags.h
index b843a55329..773c686b49 100644
--- a/crawl-ref/source/tags.h
+++ b/crawl-ref/source/tags.h
@@ -61,7 +61,8 @@ enum tag_minor_version
TAG_MINOR_DSTRAITS = 9, // Pre-calculate demonspawn mutations
TAG_MINOR_YOU_PROP = 10, // Player class has CrawlHashTable
TAG_MINOR_SMALL_HASH = 11, // Reduced RAM size of CrawlHashTable
- TAG_MINOR_VERSION = 11 // Current version. (Keep equal to max.)
+ TAG_MINOR_MON_PROP = 12, // Monster class has CrawlHashTable
+ TAG_MINOR_VERSION = 12 // Current version. (Keep equal to max.)
};
@@ -95,6 +96,7 @@ void marshallString (writer &, const std::string &, int maxSize = 0);
void marshallString4 (writer &, const std::string &);
void marshallCoord (writer &, const coord_def &);
void marshallItem (writer &, const item_def &);
+void marshallMonster (writer &, const monsters &);
void marshallShowtype (writer &, const show_type &);
/* ***********************************************************************
@@ -133,6 +135,7 @@ std::string unmarshallString (reader &, int maxSize = 1000);
void unmarshallString4 (reader &, std::string&);
void unmarshallCoord (reader &, coord_def &c);
void unmarshallItem (reader &, item_def &item);
+void unmarshallMonster (reader &, monsters &item);
show_type unmarshallShowtype (reader &);
/* ***********************************************************************
diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc
index 16b7db05b7..45ea54fafe 100644
--- a/crawl-ref/source/terrain.cc
+++ b/crawl-ref/source/terrain.cc
@@ -23,8 +23,8 @@
#include "los.h"
#include "message.h"
#include "misc.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "ouch.h"
#include "overmap.h"
diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc
index e0b76d4b87..561d790dd1 100644
--- a/crawl-ref/source/tilepick.cc
+++ b/crawl-ref/source/tilepick.cc
@@ -24,7 +24,7 @@
#include "kills.h"
#include "los.h"
#include "macro.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "player.h"
#include "shopping.h"
@@ -2794,14 +2794,14 @@ int tileidx_spell(spell_type spell)
case SPELL_FREEZE: return TILEG_FREEZE;
case SPELL_THROW_FROST: return TILEG_THROW_FROST;
case SPELL_FREEZING_AURA: return TILEG_FREEZING_AURA;
- case SPELL_SLEEP: return TILEG_ENSORCELLED_HIBERNATION;
+ case SPELL_HIBERNATION: return TILEG_ENSORCELLED_HIBERNATION;
case SPELL_OZOCUBUS_ARMOUR: return TILEG_OZOCUBUS_ARMOUR;
case SPELL_THROW_ICICLE: return TILEG_THROW_ICICLE;
case SPELL_CONDENSATION_SHIELD: return TILEG_CONDENSATION_SHIELD;
case SPELL_OZOCUBUS_REFRIGERATION: return TILEG_OZOCUBUS_REFRIGERATION;
case SPELL_BOLT_OF_COLD: return TILEG_BOLT_OF_COLD;
case SPELL_FREEZING_CLOUD: return TILEG_FREEZING_CLOUD;
- case SPELL_MASS_SLEEP: return TILEG_METABOLIC_ENGLACIATION;
+ case SPELL_ENGLACIATION: return TILEG_METABOLIC_ENGLACIATION;
case SPELL_SIMULACRUM: return TILEG_SIMULACRUM;
case SPELL_ICE_STORM: return TILEG_ICE_STORM;
@@ -2819,7 +2819,7 @@ int tileidx_spell(spell_type spell)
// Enchantment
case SPELL_CONFUSING_TOUCH: return TILEG_CONFUSING_TOUCH;
- case SPELL_BACKLIGHT: return TILEG_CORONA;
+ case SPELL_CORONA: return TILEG_CORONA;
case SPELL_PROJECTED_NOISE: return TILEG_PROJECTED_NOISE;
case SPELL_SURE_BLADE: return TILEG_SURE_BLADE;
case SPELL_TUKIMAS_VORPAL_BLADE: return TILEG_TUKIMAS_VORPAL_BLADE;
diff --git a/crawl-ref/source/tilereg.cc b/crawl-ref/source/tilereg.cc
index 14d53e03e1..4ddabc8b67 100644
--- a/crawl-ref/source/tilereg.cc
+++ b/crawl-ref/source/tilereg.cc
@@ -226,10 +226,9 @@ TileRegion::TileRegion(ImageManager* im, FTFont *tag_font, int tile_x, int tile_
dx = tile_x;
dy = tile_y;
m_tag_font = tag_font;
-#if 0
- // Not needed? (jpeg)
+
+ // To quite Valgrind
m_dirty = true;
-#endif
}
TileRegion::~TileRegion()
diff --git a/crawl-ref/source/tilereg.h b/crawl-ref/source/tilereg.h
index c157148c68..74fbb18f60 100644
--- a/crawl-ref/source/tilereg.h
+++ b/crawl-ref/source/tilereg.h
@@ -295,7 +295,6 @@ protected:
TileBuffer m_buf_dngn;
TileBuffer m_buf_doll;
TileBuffer m_buf_main;
- bool m_dirty;
struct tile_overlay
{
diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc
index 40410f8362..47b245f71d 100644
--- a/crawl-ref/source/traps.cc
+++ b/crawl-ref/source/traps.cc
@@ -27,7 +27,7 @@
#include "message.h"
#include "misc.h"
#include "mon-util.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "mtransit.h"
#include "ouch.h"
#include "player.h"
diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc
index 0046863591..51848b200e 100644
--- a/crawl-ref/source/travel.cc
+++ b/crawl-ref/source/travel.cc
@@ -32,7 +32,7 @@
#include "message.h"
#include "misc.h"
#include "mon-util.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "options.h"
#ifdef USE_TILE
#include "output.h"
diff --git a/crawl-ref/source/tutorial.cc b/crawl-ref/source/tutorial.cc
index 5585875576..a770cc1956 100644
--- a/crawl-ref/source/tutorial.cc
+++ b/crawl-ref/source/tutorial.cc
@@ -3256,7 +3256,6 @@ void learned_something_new(tutorial_event_type seen_what, coord_def gc)
text << "That ";
#ifdef USE_TILE
// need to highlight monster
- const coord_def gc = m->pos();
tiles.place_cursor(CURSOR_TUTORIAL, gc);
tiles.add_text_tag(TAG_TUTORIAL, m);
diff --git a/crawl-ref/source/util/art-data.pl b/crawl-ref/source/util/art-data.pl
index 05f6dcdf9b..67a4dfe476 100755
--- a/crawl-ref/source/util/art-data.pl
+++ b/crawl-ref/source/util/art-data.pl
@@ -589,12 +589,10 @@ sub write_data
ENDofTEXT
my $artefact;
- my $art_num = 1;
foreach $artefact (@all_artefacts)
{
- print HEADER "/* $art_num: UNRAND_$artefact->{_ENUM} */\n";
+ print HEADER "/* UNRAND_$artefact->{_ENUM} */\n";
print HEADER art_to_str($artefact);
- $art_num++;
}
close(HEADER);
diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc
index fc9c6cf271..648141b7a3 100644
--- a/crawl-ref/source/view.cc
+++ b/crawl-ref/source/view.cc
@@ -31,6 +31,7 @@
#include "attitude-change.h"
#include "branch.h"
#include "cio.h"
+#include "cloud.h"
#include "clua.h"
#include "colour.h"
#include "database.h"
@@ -48,8 +49,9 @@
#include "message.h"
#include "misc.h"
#include "mon-behv.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-iter.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "newgame.h"
#include "options.h"
@@ -122,34 +124,39 @@ void flush_comes_into_view()
void monster_grid_updates()
{
- for (int s = 0; s < MAX_MONSTERS; ++s)
+ for (monster_iterator mi(&you.get_los()); mi; ++mi)
{
- monsters *monster = &menv[s];
-
- if (monster->alive() && mons_near(monster))
+ if ((mi->asleep() || mons_is_wandering(*mi))
+ && check_awaken(*mi))
{
- if ((monster->asleep() || mons_is_wandering(monster))
- && check_awaken(monster))
- {
- behaviour_event(monster, ME_ALERT, MHITYOU, you.pos(), false);
- handle_monster_shouts(monster);
- }
+ behaviour_event(*mi, ME_ALERT, MHITYOU, you.pos(), false);
+ handle_monster_shouts(*mi);
+ }
fedhas_neutralise(monster);
- if (!monster->visible_to(&you))
- continue;
+ if (!mi->visible_to(&you))
+ continue;
good_god_follower_attitude_change(monster);
beogh_follower_convert(monster);
slime_convert(monster);
+ // XXX: Probably quite hackish. Allows for monsters going berserk when
+ // they see the player. Currently only used for Duvessa, see the
+ // function _elven_twin_dies in mon-stuff.cc.
+ if (mi->flags & MF_GOING_BERSERK)
+ {
+ mi->flags &= ~MF_GOING_BERSERK;
+ mi->go_berserk(true);
}
}
}
-static void _check_monster_pos(const monsters* monster, int s)
+static void _check_monster_pos(const monsters* monster)
{
+ int s = monster->mindex();
ASSERT(mgrd(monster->pos()) == s);
+ // [rob] The following in case asserts aren't enabled.
// [enne] - It's possible that mgrd and monster->x/y are out of
// sync because they are updated separately. If we can see this
// monster, then make sure that the mgrd is set correctly.
@@ -169,20 +176,15 @@ static void _check_monster_pos(const monsters* monster, int s)
void monster_grid()
{
- for (int s = 0; s < MAX_MONSTERS; ++s)
+ for (monster_iterator mi(&you.get_los()); mi; ++mi)
{
- monsters *monster = &menv[s];
-
- if (monster->alive() && mons_near(monster))
- {
- _check_monster_pos(monster, s);
- env.show.update_monster(monster);
+ _check_monster_pos(*mi);
+ env.show.update_monster(*mi);
#ifdef USE_TILE
- if (monster->visible_to(&you))
- tile_place_monster(monster->pos().x, monster->pos().y, s, true);
+ if (mi->visible_to(&you))
+ tile_place_monster(mi->pos().x, mi->pos().y, mi->mindex(), true);
#endif
- }
}
}
@@ -190,39 +192,34 @@ void update_monsters_in_view()
{
unsigned int num_hostile = 0;
- for (int s = 0; s < MAX_MONSTERS; s++)
+ for (monster_iterator mi; mi; ++mi)
{
- monsters *monster = &menv[s];
-
- if (!monster->alive())
- continue;
-
- if (mons_near(monster))
+ if (mons_near(*mi))
{
- if (monster->attitude == ATT_HOSTILE)
+ if (mi->attitude == ATT_HOSTILE)
num_hostile++;
- if (mons_is_unknown_mimic(monster))
+ if (mons_is_unknown_mimic(*mi))
{
// For unknown mimics, don't mark as seen,
// but do mark it as in view for later messaging.
// FIXME: is this correct?
- monster->flags |= MF_WAS_IN_VIEW;
+ mi->flags |= MF_WAS_IN_VIEW;
}
- else if (monster->visible_to(&you))
+ else if (mi->visible_to(&you))
{
- handle_seen_interrupt(monster);
- seen_monster(monster);
+ handle_seen_interrupt(*mi);
+ seen_monster(*mi);
}
else
- monster->flags &= ~MF_WAS_IN_VIEW;
+ mi->flags &= ~MF_WAS_IN_VIEW;
}
else
- monster->flags &= ~MF_WAS_IN_VIEW;
+ mi->flags &= ~MF_WAS_IN_VIEW;
// If the monster hasn't been seen by the time that the player
// gets control back then seen_context is out of date.
- monster->seen_context.clear();
+ mi->seen_context.clear();
}
// Xom thinks it's hilarious the way the player picks up an ever
@@ -767,8 +764,30 @@ void viewwindow(bool do_updates)
const coord_def ep = view2show(grid2view(gc));
if (in_bounds(gc) && you.see_cell(gc))
+ {
maybe_remove_autoexclusion(gc);
+ // Set excludes in a radius of 1 around harmful clouds genereated
+ // by neither monsters nor the player.
+ const int cloudidx = env.cgrid(gc);
+ if (cloudidx != EMPTY_CLOUD)
+ {
+ cloud_struct &cl = env.cloud[cloudidx];
+ cloud_type ctype = cl.type;
+
+ if (!is_harmless_cloud(ctype)
+ && cl.whose == KC_OTHER
+ && cl.killer == KILL_MISC)
+ {
+ for (adjacent_iterator ai(gc, false); ai; ++ai)
+ {
+ if (!cell_is_solid(*ai) && !is_exclude_root(*ai))
+ set_exclude(*ai, 0);
+ }
+ }
+ }
+ }
+
// Print tutorial messages for features in LOS.
if (Options.tutorial_left
&& in_bounds(gc)
diff --git a/crawl-ref/source/viewmap.cc b/crawl-ref/source/viewmap.cc
index 98603fc959..3369147e66 100644
--- a/crawl-ref/source/viewmap.cc
+++ b/crawl-ref/source/viewmap.cc
@@ -741,6 +741,17 @@ void show_map( level_pos &spec_place, bool travel_mode, bool allow_esc )
_reset_travel_colours(features, on_level);
break;
+#ifdef WIZARD
+ case CMD_MAP_EXCLUDE_RADIUS:
+ {
+ const coord_def p(start_x + curs_x - 1, start_y + curs_y - 1);
+ set_exclude(p, getchm() - '0');
+
+ _reset_travel_colours(features, on_level);
+ break;
+ }
+#endif
+
case CMD_MAP_MOVE_DOWN_LEFT:
move_x = -1;
move_y = 1;
diff --git a/crawl-ref/source/wiz-dgn.cc b/crawl-ref/source/wiz-dgn.cc
index 5d178d02c1..69f5e1ec2a 100644
--- a/crawl-ref/source/wiz-dgn.cc
+++ b/crawl-ref/source/wiz-dgn.cc
@@ -25,6 +25,7 @@
#include "options.h"
#include "place.h"
#include "player.h"
+#include "religion.h"
#include "stuff.h"
#include "terrain.h"
#include "traps.h"
@@ -366,6 +367,49 @@ void wizard_list_branches()
"this game", i, branches[i].longname);
}
}
+
+ if (!you.props.exists(OVERFLOW_TEMPLES_KEY))
+ return;
+
+ mpr("----", MSGCH_DIAGNOSTICS);
+ mpr("Overflow temples: ", MSGCH_DIAGNOSTICS);
+
+ CrawlVector &levels = you.props[OVERFLOW_TEMPLES_KEY].get_vector();
+
+ for (unsigned int i = 0; i < levels.size(); i++)
+ {
+ CrawlStoreValue &val = levels[i];
+
+ // Does this level have an overflow temple?
+ if (val.get_flags() & SFLAG_UNSET)
+ continue;
+
+ CrawlVector &temples = val.get_vector();
+
+ if (temples.size() == 0)
+ continue;
+
+ std::vector<std::string> god_names;
+
+ for (unsigned int j = 0; j < temples.size(); j++)
+ {
+ CrawlHashTable &temple_hash = temples[j];
+ CrawlVector &gods = temple_hash[TEMPLE_GODS_KEY];
+
+ for (unsigned int k = 0; k < gods.size(); k++)
+ {
+ god_type god = (god_type) gods[k].get_byte();
+
+ god_names.push_back(god_name(god));
+ }
+ }
+
+ mprf(MSGCH_DIAGNOSTICS, "%lu on D:%lu (%s)", temples.size(),
+ i + 1,
+ comma_separated_line( god_names.begin(),
+ god_names.end() ).c_str()
+ );
+ }
}
void wizard_map_level()
diff --git a/crawl-ref/source/wiz-fsim.cc b/crawl-ref/source/wiz-fsim.cc
index 4aa2b2bac7..31d052a268 100644
--- a/crawl-ref/source/wiz-fsim.cc
+++ b/crawl-ref/source/wiz-fsim.cc
@@ -17,9 +17,9 @@
#include "item_use.h"
#include "it_use2.h"
#include "message.h"
-#include "monplace.h"
+#include "mon-place.h"
#include "monster.h"
-#include "monstuff.h"
+#include "mon-stuff.h"
#include "options.h"
#include "player.h"
#include "quiver.h"
@@ -32,7 +32,8 @@ static int _create_fsim_monster(int mtype, int hp)
const int mi =
create_monster(
mgen_data::hostile_at(
- static_cast<monster_type>(mtype), false, 0, 0, you.pos()));
+ static_cast<monster_type>(mtype),
+ "the fight simulator", false, 0, 0, you.pos()));
if (mi == -1)
return (mi);
diff --git a/crawl-ref/source/wiz-item.cc b/crawl-ref/source/wiz-item.cc
index 8b11fb100a..bae01bc91a 100644
--- a/crawl-ref/source/wiz-item.cc
+++ b/crawl-ref/source/wiz-item.cc
@@ -22,7 +22,8 @@
#include "it_use2.h"
#include "invent.h"
#include "makeitem.h"
-#include "monstuff.h"
+#include "mon-iter.h"
+#include "mon-stuff.h"
#include "mon-util.h"
#include "options.h"
#include "religion.h"
@@ -729,25 +730,20 @@ void wizard_unidentify_pack()
// Forget things that nearby monsters are carrying, as well.
// (For use with the "give monster an item" wizard targetting
// command.)
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mon(&you.get_los()); mon; ++mon)
{
- monsters* mon = &menv[i];
-
- if (mon->alive() && mons_near(mon))
+ for (int j = 0; j < NUM_MONSTER_SLOTS; ++j)
{
- for (int j = 0; j < NUM_MONSTER_SLOTS; ++j)
- {
- if (mon->inv[j] == NON_ITEM)
- continue;
+ if (mon->inv[j] == NON_ITEM)
+ continue;
- item_def &item = mitm[mon->inv[j]];
+ item_def &item = mitm[mon->inv[j]];
- if (!item.is_valid())
- continue;
+ if (!item.is_valid())
+ continue;
- set_ident_type(item, ID_UNKNOWN_TYPE);
- unset_ident_flags(item, ISFLAG_IDENT_MASK);
- }
+ set_ident_type(item, ID_UNKNOWN_TYPE);
+ unset_ident_flags(item, ISFLAG_IDENT_MASK);
}
}
}
diff --git a/crawl-ref/source/wiz-mon.cc b/crawl-ref/source/wiz-mon.cc
index eaccf8346e..3701d344a0 100644
--- a/crawl-ref/source/wiz-mon.cc
+++ b/crawl-ref/source/wiz-mon.cc
@@ -20,9 +20,10 @@
#include "jobs.h"
#include "macro.h"
#include "message.h"
-#include "monplace.h"
-#include "monspeak.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-speak.h"
+#include "mon-stuff.h"
+#include "mon-iter.h"
#include "mon-util.h"
#include "output.h"
#include "religion.h"
@@ -253,13 +254,9 @@ void debug_list_monsters()
std::string prev_name = "";
int count = 0;
- for (int i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi; mi; ++mi)
{
- const monsters *m = &menv[mon_nums[i]];
- if (!m->alive())
- continue;
-
- std::string name = m->name(DESC_PLAIN, true);
+ std::string name = mi->name(DESC_PLAIN, true);
if (prev_name != name && count > 0)
{
@@ -276,15 +273,15 @@ void debug_list_monsters()
count++;
prev_name = name;
- int exp = exper_value(m);
+ int exp = exper_value(*mi);
total_exp += exp;
- if ((m->flags & (MF_WAS_NEUTRAL | MF_CREATED_FRIENDLY))
- || m->has_ench(ENCH_ABJ))
+ if ((mi->flags & (MF_WAS_NEUTRAL | MF_CREATED_FRIENDLY))
+ || mi->has_ench(ENCH_ABJ))
{
continue;
}
- if (m->flags & MF_GOT_HALF_XP)
+ if (mi->flags & MF_GOT_HALF_XP)
exp /= 2;
total_adj_exp += exp;
@@ -338,9 +335,8 @@ void wizard_spawn_control()
{
// 50 spots are reserved for non-wandering monsters.
int max_spawn = MAX_MONSTERS - 50;
- for (int i = 0; i < MAX_MONSTERS; ++i)
- if (menv[i].alive())
- max_spawn--;
+ for (monster_iterator mi; mi; ++mi)
+ if (mi->alive())
if (max_spawn <= 0)
{
diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc
index 91d006d747..f7a694d840 100644
--- a/crawl-ref/source/xom.cc
+++ b/crawl-ref/source/xom.cc
@@ -26,9 +26,10 @@
#include "message.h"
#include "misc.h"
#include "mon-behv.h"
+#include "mon-iter.h"
#include "mon-util.h"
-#include "monplace.h"
-#include "monstuff.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
#include "mutation.h"
#include "notes.h"
#include "options.h"
@@ -84,7 +85,7 @@ static const spell_type _xom_nontension_spells[] =
// Spells to be cast at tension > 0, i.e. usually in battle situations.
static const spell_type _xom_tension_spells[] =
{
- SPELL_BLINK, SPELL_CONFUSING_TOUCH, SPELL_CAUSE_FEAR, SPELL_MASS_SLEEP,
+ SPELL_BLINK, SPELL_CONFUSING_TOUCH, SPELL_CAUSE_FEAR, SPELL_ENGLACIATION,
SPELL_DISPERSAL, SPELL_STONESKIN, SPELL_RING_OF_FLAMES,
SPELL_OLGREBS_TOXIC_RADIANCE, SPELL_TUKIMAS_VORPAL_BLADE,
SPELL_MAXWELLS_SILVER_HAMMER, SPELL_FIRE_BRAND, SPELL_FREEZING_AURA,
@@ -1197,14 +1198,10 @@ static int _xom_do_potion(bool debug = false)
static int _xom_confuse_monsters(int sever, bool debug = false)
{
bool rc = false;
- monsters *monster;
- for (unsigned i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi(&you.get_los()); mi; ++mi)
{
- monster = &menv[i];
-
- if (monster->type == MONS_NO_MONSTER || !mons_near(monster)
- || monster->wont_attack()
- || !mons_class_is_confusable(monster->type)
+ if (mi->wont_attack()
+ || !mons_class_is_confusable(mi->type)
|| one_chance_in(20))
{
continue;
@@ -1213,14 +1210,14 @@ static int _xom_confuse_monsters(int sever, bool debug = false)
if (debug)
return (XOM_GOOD_CONFUSION);
- if (monster->add_ench(mon_enchant(ENCH_CONFUSION, 0,
+ if (mi->add_ench(mon_enchant(ENCH_CONFUSION, 0,
KC_FRIENDLY, random2(sever))))
{
// Only give this message once.
if (!rc)
god_speaks(GOD_XOM, _get_xom_speech("confusion").c_str());
- simple_monster_message(monster, " looks rather confused.");
+ simple_monster_message(*mi, " looks rather confused.");
rc = true;
}
}
@@ -1265,12 +1262,14 @@ static int _xom_send_allies(int sever, bool debug = false)
{
monster_type mon_type = _xom_random_demon(sever);
- summons[i] =
- create_monster(
- mgen_data(mon_type, BEH_FRIENDLY,
- 3, MON_SUMM_AID,
- you.pos(), MHITYOU,
- MG_FORCE_BEH, GOD_XOM));
+ mgen_data mg(mon_type, BEH_FRIENDLY, &you, 3, MON_SUMM_AID,
+ you.pos(), MHITYOU, MG_FORCE_BEH, GOD_XOM);
+
+ // Even though the friendlies are charged to you for accounting,
+ // they should still show as Xom's fault if one of them kills you.
+ mg.non_actor_summoner = "Xom";
+
+ summons[i] = create_monster(mg);
if (summons[i] != -1)
{
@@ -1328,6 +1327,7 @@ static int _xom_send_allies(int sever, bool debug = false)
|| (!is_demonic[i] && hostiletype == 2))
{
mon->attitude = ATT_HOSTILE;
+ // XXX need to reset summon quota here?
behaviour_event(mon, ME_ALERT, MHITYOU);
}
}
@@ -1370,10 +1370,12 @@ static int _xom_send_one_ally(int sever, bool debug = false)
if (different && one_chance_in(4))
beha = BEH_HOSTILE;
- const int summons =
- create_monster(
- mgen_data(mon_type, beha, 6, MON_SUMM_AID, you.pos(), MHITYOU,
- MG_FORCE_BEH, GOD_XOM));
+ mgen_data mg(mon_type, beha, (beha == BEH_FRIENDLY) ? &you : 0, 6,
+ MON_SUMM_AID, you.pos(), MHITYOU, MG_FORCE_BEH, GOD_XOM);
+
+ mg.non_actor_summoner = "Xom";
+
+ const int summons = create_monster(mg);
if (summons != -1)
{
@@ -1541,24 +1543,16 @@ static int _xom_swap_weapons(bool debug = false)
}
std::vector<monsters *> mons_wpn;
- for (unsigned i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi(&you); mi; ++mi)
{
- monsters* m = &menv[i];
-
- if (!m->alive())
- continue;
-
- if (!you.see_cell(m->pos()))
- continue;
-
- if (!wpn || m->wont_attack() || m->is_summoned()
- || mons_itemuse(m) < MONUSE_STARTING_EQUIPMENT
- || (m->flags & MF_HARD_RESET))
+ if (!wpn || mi->wont_attack() || mi->is_summoned()
+ || mons_itemuse(*mi) < MONUSE_STARTING_EQUIPMENT
+ || (mi->flags & MF_HARD_RESET))
{
continue;
}
- const int mweap = m->inv[MSLOT_WEAPON];
+ const int mweap = mi->inv[MSLOT_WEAPON];
if (mweap == NON_ITEM)
continue;
@@ -1567,11 +1561,11 @@ static int _xom_swap_weapons(bool debug = false)
// Let's be nice about this.
if (weapon.base_type == OBJ_WEAPONS
&& !(weapon.flags & ISFLAG_SUMMONED)
- && you.can_wield(weapon, true) && m->can_wield(*wpn, true)
+ && you.can_wield(weapon, true) && mi->can_wield(*wpn, true)
&& !get_weapon_brand(weapon) != SPWPN_DISTORTION
&& (!is_artefact(weapon) || _art_is_safe(weapon)))
{
- mons_wpn.push_back(m);
+ mons_wpn.push_back(*mi);
}
}
if (mons_wpn.empty())
@@ -1677,18 +1671,9 @@ static int _xom_rearrange_pieces(int sever, bool debug = false)
return (XOM_DID_NOTHING);
std::vector<monsters *> mons;
- for (unsigned i = 0; i < MAX_MONSTERS; ++i)
- {
- monsters* m = &menv[i];
+ for (monster_iterator mi(&you); mi; ++mi)
+ mons.push_back(*mi);
- if (!m->alive())
- continue;
-
- if (!you.see_cell(m->pos()))
- continue;
-
- mons.push_back(m);
- }
if (mons.empty())
return (XOM_DID_NOTHING);
@@ -1741,24 +1726,16 @@ static int _xom_rearrange_pieces(int sever, bool debug = false)
static int _xom_animate_monster_weapon(int sever, bool debug = false)
{
std::vector<monsters *> mons_wpn;
- for (unsigned i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi(&you); mi; ++mi)
{
- monsters* m = &menv[i];
-
- if (!m->alive())
- continue;
-
- if (!you.see_cell(m->pos()))
- continue;
-
- if (m->wont_attack() || m->is_summoned()
- || mons_itemuse(m) < MONUSE_STARTING_EQUIPMENT
- || (m->flags & MF_HARD_RESET))
+ if (mi->wont_attack() || mi->is_summoned()
+ || mons_itemuse(*mi) < MONUSE_STARTING_EQUIPMENT
+ || (mi->flags & MF_HARD_RESET))
{
continue;
}
- const int mweap = m->inv[MSLOT_WEAPON];
+ const int mweap = mi->inv[MSLOT_WEAPON];
if (mweap == NON_ITEM)
continue;
@@ -1771,7 +1748,7 @@ static int _xom_animate_monster_weapon(int sever, bool debug = false)
&& !is_special_unrandom_artefact(weapon)
&& !get_weapon_brand(weapon) != SPWPN_DISTORTION)
{
- mons_wpn.push_back(m);
+ mons_wpn.push_back(*mi);
}
}
if (mons_wpn.empty())
@@ -1791,10 +1768,14 @@ static int _xom_animate_monster_weapon(int sever, bool debug = false)
ASSERT(wpn != NON_ITEM);
const int dur = std::min(2 + (random2(sever) / 5), 6);
- const int monster = create_monster(
- mgen_data(MONS_DANCING_WEAPON, BEH_FRIENDLY,
- dur, SPELL_TUKIMAS_DANCE,
- mon->pos(), mon->mindex(), 0, GOD_XOM));
+
+ mgen_data mg(MONS_DANCING_WEAPON, BEH_FRIENDLY, &you, dur,
+ SPELL_TUKIMAS_DANCE, mon->pos(), mon->mindex(),
+ 0, GOD_XOM);
+
+ mg.non_actor_summoner = "Xom";
+
+ const int monster = create_monster(mg);
if (monster == -1)
return (XOM_DID_NOTHING);
@@ -1881,10 +1862,13 @@ static int _xom_send_major_ally(int sever, bool debug = false)
if (!is_demonic && one_chance_in(4))
beha = BEH_HOSTILE;
- const int summons =
- create_monster(
- mgen_data(_xom_random_demon(sever, one_chance_in(8)), beha,
- 0, 0, you.pos(), MHITYOU, MG_FORCE_BEH, GOD_XOM));
+ mgen_data mg(_xom_random_demon(sever, one_chance_in(8)), beha,
+ (beha == BEH_FRIENDLY) ? &you : 0,
+ 0, 0, you.pos(), MHITYOU, MG_FORCE_BEH, GOD_XOM);
+
+ mg.non_actor_summoner = "Xom";
+
+ const int summons = create_monster(mg);
if (summons != -1)
{
@@ -2846,22 +2830,18 @@ static int _xom_player_confusion_effect(int sever, bool debug = false)
bool mons_too = false;
if (coinflip())
{
- for (unsigned i = 0; i < MAX_MONSTERS; ++i)
+ for (monster_iterator mi(&you.get_los()); mi; ++mi)
{
- monsters* const monster = &menv[i];
-
- if (!monster->alive()
- || !mons_near(monster)
- || !mons_class_is_confusable(monster->type)
+ if (!mons_class_is_confusable(mi->type)
|| one_chance_in(20))
{
continue;
}
- if (monster->add_ench(mon_enchant(ENCH_CONFUSION, 0,
+ if (mi->add_ench(mon_enchant(ENCH_CONFUSION, 0,
KC_FRIENDLY, random2(sever))))
{
- simple_monster_message(monster,
+ simple_monster_message(*mi,
" looks rather confused.");
}
mons_too = true;
@@ -3212,7 +3192,7 @@ static int _xom_summon_hostiles(int sever, bool debug = false)
{
if (create_monster(
mgen_data::hostile_at(
- _xom_random_demon(sever),
+ _xom_random_demon(sever), "Xom",
true, 4, MON_SUMM_WRATH, you.pos(), 0,
GOD_XOM)) != -1)
{