summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source')
-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
148 files changed, 3880 insertions, 2380 deletions
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)
{