summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/debug.cc12
-rw-r--r--crawl-ref/source/dungeon.cc21
-rw-r--r--crawl-ref/source/mapdef.cc16
-rw-r--r--crawl-ref/source/mapmark.cc2
-rw-r--r--crawl-ref/source/mon-data.h2
-rw-r--r--crawl-ref/source/mon-util.cc74
-rw-r--r--crawl-ref/source/mon-util.h15
-rw-r--r--crawl-ref/source/monplace.cc153
-rw-r--r--crawl-ref/source/monspeak.cc2
-rw-r--r--crawl-ref/source/stuff.cc11
-rw-r--r--crawl-ref/source/view.cc59
11 files changed, 238 insertions, 129 deletions
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc
index d38b849866..68dad70bbc 100644
--- a/crawl-ref/source/debug.cc
+++ b/crawl-ref/source/debug.cc
@@ -438,7 +438,11 @@ void create_spec_monster_name(int x, int y)
mons_spec mspec = mlist.get_monster(0);
if (!force_place && mspec.mid != -1)
{
- coord_def place = find_newmons_square(mspec.mid, coord_def(x, y));
+ int type = mspec.mid;
+ if (mons_class_is_zombified(mspec.mid))
+ type = mspec.monbase;
+
+ coord_def place = find_newmons_square(type, coord_def(x, y));
if (in_bounds(place))
{
x = place.x;
@@ -453,11 +457,11 @@ void create_spec_monster_name(int x, int y)
if (!dgn_place_monster(mspec, you.your_level, x, y, false))
{
- mpr("Unable to place monster");
+ mpr("Unable to place monster.");
return;
}
- // Need to set a name for the player ghost
+ // Need to set a name for the player ghost.
if (mspec.mid == MONS_PLAYER_GHOST)
{
unsigned short mid = mgrd[x][y];
@@ -485,7 +489,7 @@ void create_spec_monster_name(int x, int y)
ghost.name = "John Doe";
char input_str[80];
- mpr( "Make player ghost which species? (case-sensitive) ", MSGCH_PROMPT );
+ mpr("Make player ghost which species? (case-sensitive) ", MSGCH_PROMPT);
get_input_line( input_str, sizeof( input_str ) );
int sp_id = get_species_by_abbrev(input_str);
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index 7855e3db40..5ab12f34b2 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -4102,7 +4102,7 @@ bool dgn_place_map(int map, bool generating_level, bool clobber,
const map_def *mdef = map_by_index(map);
bool did_map = false;
- bool fixup = false;
+ bool fixup = false;
if (mdef->orient == MAP_ENCOMPASS && !generating_level)
{
@@ -4119,6 +4119,7 @@ bool dgn_place_map(int map, bool generating_level, bool clobber,
mprf(MSGCH_DIAGNOSTICS,
"Cannot generate encompass map '%s' without clobber=true",
mdef->name.c_str());
+
return (false);
}
}
@@ -4538,7 +4539,7 @@ bool dgn_place_monster(mons_spec &mspec,
{
if (mspec.mid != -1)
{
- const int mid = mspec.mid;
+ const int mid = mspec.mid;
const bool m_generate_awake = (generate_awake || mspec.generate_awake);
const bool m_patrolling = (patrolling || mspec.patrolling);
@@ -4555,10 +4556,15 @@ bool dgn_place_monster(mons_spec &mspec,
if (mid != RANDOM_MONSTER && mid < NUM_MONSTERS)
{
+ // Don't place a unique monster a second time.
+ // (Boris is handled specially.)
if (mons_is_unique(mid) && you.unique_creatures[mid])
return (false);
- const habitat_type habitat = mons_habitat_by_type(mid);
+ const int type = mons_class_is_zombified(mid) ? mspec.monbase
+ : mid;
+
+ const habitat_type habitat = mons_habitat_by_type(type);
if (habitat != HT_LAND)
grd[vx][vy] = habitat2grid(habitat);
}
@@ -7286,6 +7292,9 @@ static void _build_river( dungeon_feature_type river_type ) //mv
}
else
grd[i][j] = river_type;
+
+ // Override existing markers.
+ env.markers.remove_markers_at(coord_def(i, j), MAT_ANY);
}
}
}
@@ -7306,7 +7315,6 @@ static void _build_lake(dungeon_feature_type lake_type) //mv
y1 = 5 + random2(GYM - 30);
x2 = x1 + 4 + random2(16);
y2 = y1 + 8 + random2(12);
- // mpr("lake");
for (j = y1; j < y2; j++)
{
@@ -7337,7 +7345,12 @@ static void _build_lake(dungeon_feature_type lake_type) //mv
// So we'll avoid the silliness of monsters and items
// on lava and deep water grids. -- bwr
if (!one_chance_in(200) && _may_overwrite_pos(i,j))
+ {
grd[i][j] = lake_type;
+
+ // Override markers. (No underwater portals, please.)
+ env.markers.remove_markers_at(coord_def(i, j), MAT_ANY);
+ }
}
}
}
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index d330a6e666..135da21ca1 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -1950,9 +1950,9 @@ mons_list::mons_spec_slot mons_list::parse_mons_spec(std::string spec)
if (mspec.genweight == TAG_UNFOUND || mspec.genweight <= 0)
mspec.genweight = 10;
- mspec.fix_mons = strip_tag(mon_str, "fix_mons");
+ mspec.fix_mons = strip_tag(mon_str, "fix_mons");
mspec.generate_awake = strip_tag(mon_str, "generate_awake");
- mspec.patrolling = strip_tag(mon_str, "patrolling");
+ mspec.patrolling = strip_tag(mon_str, "patrolling");
std::string colour = strip_tag_prefix(mon_str, "col:");
if (!colour.empty())
@@ -1985,9 +1985,9 @@ mons_list::mons_spec_slot mons_list::parse_mons_spec(std::string spec)
return (slot);
}
- mspec.mid = nspec.mid;
+ mspec.mid = nspec.mid;
mspec.monbase = nspec.monbase;
- mspec.number = nspec.number;
+ mspec.number = nspec.number;
}
if (mspec.items.size() > 0)
@@ -2056,10 +2056,10 @@ void mons_list::get_zombie_type(std::string s, mons_spec &spec) const
// This order must match zombie_types, indexed from one.
static const monster_type zombie_montypes[][2] =
- {
- { MONS_PROGRAM_BUG, MONS_PROGRAM_BUG },
- { MONS_ZOMBIE_SMALL, MONS_ZOMBIE_LARGE },
- { MONS_SKELETON_SMALL, MONS_SKELETON_LARGE },
+ { // small // large
+ { MONS_PROGRAM_BUG, MONS_PROGRAM_BUG },
+ { MONS_ZOMBIE_SMALL, MONS_ZOMBIE_LARGE },
+ { MONS_SKELETON_SMALL, MONS_SKELETON_LARGE },
{ MONS_SIMULACRUM_SMALL, MONS_SIMULACRUM_LARGE }
};
diff --git a/crawl-ref/source/mapmark.cc b/crawl-ref/source/mapmark.cc
index 1041470e6e..75ffcab11e 100644
--- a/crawl-ref/source/mapmark.cc
+++ b/crawl-ref/source/mapmark.cc
@@ -340,8 +340,10 @@ void map_lua_marker::notify_dgn_event(const dgn_event &e)
push_fn_args("event");
clua_push_dgn_event(dlua, &e);
if (!dlua.callfn("dlua_marker_method", 4, 0))
+ {
mprf(MSGCH_ERROR, "notify_dgn_event: Lua error: %s",
dlua.error.c_str());
+ }
}
std::string map_lua_marker::call_str_fn(const char *fn) const
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index a41e4b6f3f..0f609174c8 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -3707,7 +3707,7 @@
0, 14, MONS_PANDEMONIUM_DEMON, MONS_PANDEMONIUM_DEMON, MH_DEMONIC, -5,
{ {AT_HIT, AF_PLAIN, 5}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
{ 4, 2, 3, 0 },
- 1, 2, MST_GHOST, CE_NOCORPSE, Z_NOZOMBIE, S_RANDOM, I_HIGH,
+ 1, 2, MST_GHOST, CE_NOCORPSE, Z_NOZOMBIE, S_DEMON_TAUNT, I_HIGH,
HT_LAND, 10, DEFAULT_ENERGY, MONUSE_OPEN_DOORS, SIZE_LARGE
},
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 9a20ca6164..9bc7092d78 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -583,12 +583,51 @@ int get_shout_noise_level(const shout_type shout)
}
}
-shout_type mons_shouts(int mc)
+// Only the beast uses S_RANDOM for noise type.
+// Pandemonium lords can also get here but they can use almost anything.
+static bool _shout_fits_monster(int type, int shout)
+{
+ if (shout == NUM_SHOUTS || shout >= NUM_LOUDNESS)
+ return (false);
+
+ // For demon lords almost everything is fair game.
+ // It's only used for the shouting verb ("say", "whine", "roar", ...)
+ // anyway.
+ if (type != MONS_BEAST)
+ return (shout != S_BUZZ && shout != S_WHINE);
+
+ switch (shout)
+ {
+ // 2-headed ogres, bees or mosquitos never fit.
+ case S_SHOUT2:
+ case S_BUZZ:
+ case S_WHINE:
+ // The beast cannot speak.
+ case S_DEMON_TAUNT:
+ // Silent is boring.
+ case S_SILENT:
+ return (false);
+ default:
+ return (true);
+ }
+}
+
+// If demon_shout is true, we're trying to find a random loudness for
+// a pandemonium lord trying to shout.
+shout_type mons_shouts(int mc, bool demon_shout)
{
shout_type u = smc->shouts;
- if (u == S_RANDOM)
- u = static_cast<shout_type>(random2(NUM_SHOUTS));
+ // Pandemonium lords use this to get the noises.
+ if (u == S_RANDOM || demon_shout && u == S_DEMON_TAUNT)
+ {
+ const int max_shout = (u == S_RANDOM ? NUM_SHOUTS : NUM_LOUDNESS);
+ do
+ {
+ u = static_cast<shout_type>(random2(max_shout));
+ }
+ while (!_shout_fits_monster(mc, u));
+ }
return (u);
}
@@ -6208,13 +6247,14 @@ static std::string _pluralise_player_genus()
// Replaces the "@foo@" strings in monster shout and monster speak
// definitions.
std::string do_mon_str_replacements(const std::string &in_msg,
- const monsters* monster)
+ const monsters* monster, int s_type)
{
std::string msg = in_msg;
description_level_type nocap = DESC_NOCAP_THE, cap = DESC_CAP_THE;
std::string name =
monster->is_named()? monster->name(DESC_CAP_THE) : "";
+
if (!name.empty() && player_monster_visible(monster))
{
msg = replace_all(msg, "@the_something@", name);
@@ -6306,7 +6346,7 @@ std::string do_mon_str_replacements(const std::string &in_msg,
msg = replace_all(msg, "@possessive@",
monster->pronoun(PRONOUN_NOCAP_POSSESSIVE));
- // replace with "you are" for atheists
+ // Replace with "you are" for atheists.
msg = replace_all(msg, "@god_is@", _replace_god_name(true, false));
msg = replace_all(msg, "@God_is@", _replace_god_name(true, true));
@@ -6314,7 +6354,7 @@ std::string do_mon_str_replacements(const std::string &in_msg,
msg = replace_all(msg, "@player_god@", _replace_god_name(false, false));
msg = replace_all(msg, "@Player_god@", _replace_god_name(false, true));
- // replace with species specific insults
+ // Replace with species specific insults.
if (msg.find("@species_insult_") != std::string::npos)
{
msg = replace_all(msg, "@species_insult_adj1@",
@@ -6341,21 +6381,27 @@ std::string do_mon_str_replacements(const std::string &in_msg,
"croaks",
"growls",
"hisses",
- "breathes", // S_VERY_SOFT
- "whispers", // S_SOFT
- "says", // S_NORMAL
- "shouts", // S_LOUD
- "screams" // S_VERY_LOUD
+ "sneers", // S_DEMON_TAUNT
+ "buggily says", // NUM_SHOUTS
+ "breathes", // S_VERY_SOFT
+ "whispers", // S_SOFT
+ "says", // S_NORMAL
+ "shouts", // S_LOUD
+ "screams" // S_VERY_LOUD
};
- if (mons_shouts(monster->type) >= NUM_SHOUTS)
+ if (s_type < 0 || s_type >= NUM_LOUDNESS || s_type == NUM_SHOUTS)
+ s_type = mons_shouts(monster->type);
+
+ if (s_type < 0 || s_type >= NUM_LOUDNESS || s_type == NUM_SHOUTS)
{
mpr("Invalid @says@ type.", MSGCH_DIAGNOSTICS);
msg = replace_all(msg, "@says@", "buggily says");
}
else
- msg = replace_all(msg, "@says@",
- sound_list[mons_shouts(monster->type)]);
+ {
+ msg = replace_all(msg, "@says@", sound_list[s_type]);
+ }
// The proper possessive for a word ending in an "s" is to
// put an apostrophe after the "s": "Chris" -> "Chris'",
diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h
index 0dbc4dc974..e8d01f48ad 100644
--- a/crawl-ref/source/mon-util.h
+++ b/crawl-ref/source/mon-util.h
@@ -217,14 +217,16 @@ enum shout_type
S_SHOUT2, // shout twice (e.g. two-headed ogres)
S_ROAR, // roar
S_SCREAM, // scream
- S_BELLOW, // bellow (?)
+ S_BELLOW, // bellow (yaks)
S_SCREECH, // screech
S_BUZZ, // buzz
S_MOAN, // moan
- S_WHINE, // irritating whine (mosquito)
+ S_WHINE, // irritating whine (mosquitos)
S_CROAK, // frog croak
S_GROWL, // for bears
S_HISS, // for snakes and lizards
+ S_DEMON_TAUNT, // for pandemonium lords
+ NUM_SHOUTS,
// Loudness setting for shouts that are only defined in dat/shout.txt
S_VERY_SOFT,
@@ -233,7 +235,7 @@ enum shout_type
S_LOUD,
S_VERY_LOUD,
- NUM_SHOUTS,
+ NUM_LOUDNESS,
S_RANDOM
};
@@ -420,7 +422,7 @@ bool mons_player_visible( const monsters *mon );
* called from: view
* *********************************************************************** */
int get_shout_noise_level(const shout_type shout);
-shout_type mons_shouts(int mclass);
+shout_type mons_shouts(int mclass, bool demon_shout = false);
bool mons_is_unique(int mclass);
@@ -684,9 +686,10 @@ void init_mon_name_cache();
monster_type get_monster_by_name(std::string name, bool exact = false);
std::string do_mon_str_replacements(const std::string &msg,
- const monsters* monster);
+ const monsters* monster, int s_type = -1);
-enum mon_body_shape {
+enum mon_body_shape
+{
MON_SHAPE_HUMANOID,
MON_SHAPE_HUMANOID_WINGED,
MON_SHAPE_HUMANOID_TAILED,
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index fb5dec3f53..0df2f1f352 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -389,15 +389,19 @@ static monster_type resolve_monster_type(monster_type mon_type,
|| drac_colour_incompatible(mon_type, base_type)));
}
else if (mon_type == RANDOM_BASE_DRACONIAN)
+ {
mon_type =
static_cast<monster_type>(
random_range(MONS_BLACK_DRACONIAN, MONS_PALE_DRACONIAN));
+ }
else if (mon_type == RANDOM_NONBASE_DRACONIAN)
+ {
mon_type =
static_cast<monster_type>(
random_range(MONS_DRACONIAN_CALLER, MONS_DRACONIAN_SCORCHER));
+ }
- // (2) take care of non-drac random monsters
+ // (2) Take care of non-draconian random monsters.
if (mon_type == RANDOM_MONSTER)
{
level_id place = level_id::current();
@@ -417,29 +421,30 @@ static monster_type resolve_monster_type(monster_type mon_type,
if (!unforbidden( pos, mmask ))
continue;
- // don't generate monsters on top of teleport traps
+ // Don't generate monsters on top of teleport traps.
int trap = trap_at_xy(pos.x, pos.y);
if (trap >= 0)
{
if (!can_place_on_trap(mon_type, env.trap[trap].type))
- continue;
+ continue;
}
- // check whether there's a stair
- // and whether it leads to another branch
- pval = near_stairs(pos, 1,
- *stair_type, place.branch);
+ // Check whether there's a stair
+ // and whether it leads to another branch.
+ pval = near_stairs(pos, 1, *stair_type, place.branch);
- // no monsters spawned in the Temple
+ // No monsters spawned in the Temple.
if (branches[place.branch].id == BRANCH_ECUMENICAL_TEMPLE)
continue;
- // found a position near the stairs!
+ // Found a position near the stairs!
if (pval > 0)
break;
}
+
if (tries > 320)
- { // give up and try somewhere else
+ {
+ // Give up and try somewhere else.
proximity = PROX_AWAY_FROM_PLAYER;
}
else
@@ -448,11 +453,11 @@ static monster_type resolve_monster_type(monster_type mon_type,
++*lev_mons;
else if (*stair_type == DCHAR_STAIRS_UP) // higher level
{
- // monsters don't come from outside the dungeon
+ // Monsters don't come from outside the dungeon.
if (*lev_mons <= 0)
{
proximity = PROX_AWAY_FROM_PLAYER;
- // in that case lev_mons stays as it is
+ // In that case lev_mons stays as it is.
}
else
--*lev_mons;
@@ -464,36 +469,64 @@ static monster_type resolve_monster_type(monster_type mon_type,
mon_type = MONS_DANCING_WEAPON;
else
{
- // now pick a monster of the given branch and level
+ // Now pick a monster of the given branch and level.
mon_type = pick_random_monster(place, *lev_mons, *lev_mons);
}
}
return (mon_type);
}
+// A short function to check the results of near_stairs().
+// Returns 0 if the point is not near stairs.
+// Returns 1 if the point is near unoccupied stairs.
+// Returns 2 if the point is near player-occupied stairs.
+static int _is_near_stairs(coord_def &p)
+{
+ int result = 0;
+ for (int i = -1; i <= 1; i++)
+ for (int j = -1; j <= 1; j++)
+ {
+ if (!in_bounds(p))
+ continue;
+
+ const dungeon_feature_type feat = grd(p);
+ if (is_stair(feat))
+ {
+ // Shouldn't matter for escape hatches.
+ if (grid_is_escape_hatch(feat))
+ continue;
+
+ // Should there be several stairs, don't overwrite the
+ // player on stairs info.
+ if (result < 2)
+ result = (p == you.pos()? 2 : 1);
+ }
+ }
+
+ return result;
+}
+
int place_monster(mgen_data mg)
{
int band_size = 0;
monster_type band_monsters[BIG_BAND]; // band monster types
int tries = 0;
- int pval = 0;
dungeon_char_type stair_type = NUM_DCHAR_TYPES;
int id = -1;
- // (1) early out (summoned to occupied grid)
+ // (1) Early out (summoned to occupied grid).
if (mg.use_position() && mgrd(mg.pos) != NON_MONSTER)
return (false);
- mg.cls =
- resolve_monster_type(mg.cls, mg.proximity, mg.base_type,
- mg.pos, mg.map_mask,
- &stair_type, &mg.power);
+ mg.cls = resolve_monster_type(mg.cls, mg.proximity, mg.base_type,
+ mg.pos, mg.map_mask,
+ &stair_type, &mg.power);
if (mg.cls == MONS_PROGRAM_BUG)
return (false);
- // (3) decide on banding (good lord!)
+ // (3) Decide on banding (good lord!)
band_size = 1;
band_monsters[0] = mg.cls;
@@ -505,11 +538,13 @@ int place_monster(mgen_data mg)
band_monsters[i] = _band_member( band, mg.power );
}
+ // Returns 2 if the monster is placed near player-occupied stairs.
+ int pval = _is_near_stairs(mg.pos);
if (mg.proximity == PROX_NEAR_STAIRS)
{
- // for some cases disallow monsters on stairs
+ // For some cases disallow monsters on stairs.
if (mons_class_is_stationary( mg.cls )
- || (pval == 2
+ || (pval == 2 // Stairs occupied by player.
&& (mons_speed(mg.cls) == 0 || grd(mg.pos) == DNGN_LAVA
|| grd(mg.pos) == DNGN_DEEP_WATER)))
{
@@ -517,18 +552,18 @@ int place_monster(mgen_data mg)
}
}
- // (4) for first monster, choose location. This is pretty intensive.
+ // (4) For first monster, choose location. This is pretty intensive.
bool proxOK;
bool close_to_player;
- // player shoved out of the way?
+ // Player shoved out of the way?
bool shoved = false;
if (!mg.use_position())
{
tries = 0;
- // try to pick px, py that is
+ // Try to pick px, py that is
// a) not occupied
// b) compatible
// c) in the 'correct' proximity to the player
@@ -541,7 +576,7 @@ int place_monster(mgen_data mg)
if (tries++ >= 45)
return (false);
- // placement already decided for PROX_NEAR_STAIRS
+ // Placement already decided for PROX_NEAR_STAIRS.
if (mg.proximity != PROX_NEAR_STAIRS)
mg.pos = random_in_bounds();
@@ -558,8 +593,8 @@ int place_monster(mgen_data mg)
if (!unforbidden( mg.pos, mg.map_mask ))
continue;
- // don't generate monsters on top of teleport traps
- // (how did they get there?)
+ // Don't generate monsters on top of teleport traps.
+ // (How did they get there?)
int trap = trap_at_xy(mg.pos.x, mg.pos.y);
if (trap >= 0)
{
@@ -567,7 +602,7 @@ int place_monster(mgen_data mg)
continue;
}
- // check proximity to player
+ // Check proximity to player.
proxOK = true;
switch (mg.proximity)
@@ -602,10 +637,10 @@ int place_monster(mgen_data mg)
proxOK = false;
break;
}
- // swap the monster and the player spots, unless the
+ // Swap the monster and the player spots, unless the
// monster was generated in lava or deep water.
- if (grd(mg.pos) == DNGN_LAVA ||
- grd(mg.pos) == DNGN_DEEP_WATER)
+ if (grd(mg.pos) == DNGN_LAVA
+ || grd(mg.pos) == DNGN_DEEP_WATER)
{
proxOK = false;
break;
@@ -633,7 +668,7 @@ int place_monster(mgen_data mg)
if (id == -1)
return (id);
- // message to player from stairwell/gate appearance?
+ // Message to player from stairwell/gate appearance?
if (see_grid(mg.pos) && mg.proximity == PROX_NEAR_STAIRS)
{
std::string msg;
@@ -663,12 +698,13 @@ int place_monster(mgen_data mg)
mpr(msg.c_str());
}
- // special case: must update the view for monsters created in player LOS
+ // Special case: must update the view for monsters created
+ // in player LOS.
viewwindow(true, false);
}
- // now, forget about banding if the first placement failed, or there's too
- // many monsters already, or we successfully placed by stairs
+ // Now, forget about banding if the first placement failed, or there are
+ // too many monsters already, or we successfully placed by stairs.
if (id >= MAX_MONSTERS - 30 || mg.proximity == PROX_NEAR_STAIRS)
return (id);
@@ -677,20 +713,19 @@ int place_monster(mgen_data mg)
menv[id].flags |= MF_BAND_MEMBER;
mgen_data band_template = mg;
- // (5) for each band monster, loop call to place_monster_aux().
+ // (5) For each band monster, loop call to place_monster_aux().
for (int i = 1; i < band_size; i++)
{
if (band_monsters[i] == MONS_PROGRAM_BUG)
break;
band_template.cls = band_monsters[i];
- const int band_id =
- _place_monster_aux( band_template, false );
+ const int band_id = _place_monster_aux( band_template, false );
if (band_id != -1 && band_id != NON_MONSTER)
menv[band_id].flags |= MF_BAND_MEMBER;
}
- // placement of first monster, at least, was a success.
+ // Placement of first monster, at least, was a success.
return (id);
}
@@ -1760,7 +1795,7 @@ int mons_place( mgen_data mg )
if (you.char_direction == GDT_ASCENDING && mg.cls == RANDOM_MONSTER
&& you.level_type == LEVEL_DUNGEON && !mg.summoned())
{
- mg.cls = pick_zot_exit_defender();
+ mg.cls = pick_zot_exit_defender();
mg.flags |= MG_PERMIT_BANDS;
}
@@ -1769,7 +1804,7 @@ int mons_place( mgen_data mg )
int mid = -1;
- // translate level_type
+ // Translate level_type.
switch (mg.level_type)
{
case LEVEL_PANDEMONIUM:
@@ -1809,7 +1844,7 @@ int mons_place( mgen_data mg )
if (!(mg.flags & MG_FORCE_BEH))
player_angers_monster(creation);
- // make summoned being aware of player's presence
+ // Make summoned being aware of player's presence.
behaviour_event(creation, ME_ALERT, MHITYOU);
if (creation->type == MONS_RAKSHASA_FAKE && !one_chance_in(3))
@@ -1824,8 +1859,10 @@ int mons_place( mgen_data mg )
static dungeon_feature_type _monster_habitat_feature(int mtype)
{
- return ((mtype == RANDOM_MONSTER) ? DNGN_FLOOR
- : habitat2grid( mons_habitat_by_type(mtype) ));
+ if (mtype == RANDOM_MONSTER)
+ return DNGN_FLOOR;
+
+ return habitat2grid( mons_habitat_by_type(mtype) );
}
class newmons_square_find : public travel_pathfind
@@ -1913,7 +1950,7 @@ coord_def find_newmons_square(int mons_class, const coord_def &p)
// Might be better if we chose a space and tried to match the monster
// to it in the case of RANDOM_MONSTER, that way if the target square
- // is surrounded by water of lava this function would work. -- bwr
+ // is surrounded by water or lava this function would work. -- bwr
if (empty_surrounds( p.x, p.y, spcw, 2, true, empty ))
{
pos.x = empty[0];
@@ -1967,25 +2004,28 @@ bool player_angers_monster(monsters *mon, bool actual)
int create_monster( mgen_data mg )
{
int summd = -1;
- if (!(mg.force_place()
- && in_bounds(mg.pos)
- && mons_class_can_pass(mg.cls, grd(mg.pos))
- && mgrd(mg.pos) == NON_MONSTER
- && mg.pos != you.pos()))
+ int type = (mons_class_is_zombified(mg.cls) ? mg.base_type
+ : mg.cls);
+
+ if (!mg.force_place()
+ || !in_bounds(mg.pos)
+ || mgrd(mg.pos) != NON_MONSTER
+ || mg.pos == you.pos()
+ || !mons_class_can_pass(type, grd(mg.pos)))
{
- mg.pos = find_newmons_square(mg.cls, mg.pos);
+ mg.pos = find_newmons_square(type, mg.pos);
}
if (in_bounds(mg.pos))
summd = mons_place( mg );
- // determine whether creating a monster is successful (summd != -1) {dlb}:
- // then handle the outcome {dlb}:
+ // Determine whether creating a monster is successful (summd != -1) {dlb}:
+ // then handle the outcome. {dlb}:
if (summd == -1 && see_grid( mg.pos ))
mpr("You see a puff of smoke.");
- // the return value is either -1 (failure of some sort)
- // or the index of the monster placed (if I read things right) {dlb}
+ // The return value is either -1 (failure of some sort)
+ // or the index of the monster placed (if I read things right). {dlb}
return (summd);
}
@@ -1995,6 +2035,7 @@ bool empty_surrounds(int emx, int emy, dungeon_feature_type spc_wanted,
FixedVector < char, 2 > &empty)
{
bool success;
+
// Assume all player summoning originates from player x,y.
bool playerSummon = (emx == you.x_pos && emy == you.y_pos);
diff --git a/crawl-ref/source/monspeak.cc b/crawl-ref/source/monspeak.cc
index 42b5ece123..dde4db4341 100644
--- a/crawl-ref/source/monspeak.cc
+++ b/crawl-ref/source/monspeak.cc
@@ -204,7 +204,7 @@ static std::string _player_ghost_speak_str(const monsters *monster,
return msg;
}
-// returns true if something is said
+// Returns true if something is said.
bool mons_speaks(const monsters *monster)
{
// Invisible monster tries to remain unnoticed. Unless they're
diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc
index c17d4bf1fb..2c30a5d7d9 100644
--- a/crawl-ref/source/stuff.cc
+++ b/crawl-ref/source/stuff.cc
@@ -1417,10 +1417,9 @@ int fuzz_value(int val, int lowfuzz, int highfuzz, int naverage)
return val + random2avg(lfuzz + hfuzz + 1, naverage) - lfuzz;
}
-// returns 0 if the point is not near stairs
-// returns 1 if the point is near unoccupied stairs
-// returns 2 if the point is near player-occupied stairs
-
+// Returns 0 if the point is not near stairs.
+// Returns 1 if the point is near unoccupied stairs.
+// Returns 2 if the point is near player-occupied stairs.
int near_stairs(const coord_def &p, int max_dist,
dungeon_char_type &stair_type,
branch_type &branch)
@@ -1437,13 +1436,13 @@ int near_stairs(const coord_def &p, int max_dist,
const dungeon_feature_type feat = grd(np);
if (is_stair(feat))
{
- // shouldn't happen for escape hatches
+ // Shouldn't happen for escape hatches.
if (grid_is_escape_hatch(feat))
continue;
stair_type = get_feature_dchar(feat);
- // is it a branch stair?
+ // Is it a branch stair?
for (int i = 0; i < NUM_BRANCHES; ++i)
{
if (branches[i].entry_stairs == feat)
diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc
index 0ccaa3aa98..97fef59e95 100644
--- a/crawl-ref/source/view.cc
+++ b/crawl-ref/source/view.cc
@@ -864,34 +864,32 @@ static void _handle_seen_interrupt(monsters* monster)
void handle_monster_shouts(monsters* monster, bool force)
{
- if (!force
- && (!you.turn_is_over || random2(30) < you.skills[SK_STEALTH]))
- {
+ if (!force && (!you.turn_is_over || random2(30) < you.skills[SK_STEALTH]))
+ return;
+
+ // Friendly or neutral monsters don't shout.
+ if (!force && (mons_friendly(monster) || mons_neutral(monster)))
return;
- }
// Get it once, since monster might be S_RANDOM, in which case
// mons_shouts() will return a different value every time.
- const shout_type type = mons_shouts(monster->type);
+ shout_type s_type = mons_shouts(monster->type, false);
// Silent monsters can give noiseless "visual shouts" if the
// player can see them, in which case silence isn't checked for.
- if (!force && (mons_friendly(monster) || mons_neutral(monster))
- || (type == S_SILENT && !player_monster_visible(monster))
- || (type != S_SILENT && (silenced(you.x_pos, you.y_pos)
- || silenced(monster->x, monster->y))))
+ if (s_type == S_SILENT && !player_monster_visible(monster)
+ || s_type != S_SILENT && (silenced(you.x_pos, you.y_pos)
+ || silenced(monster->x, monster->y)))
{
return;
}
- int noise_level = get_shout_noise_level(type);
- std::string default_msg_key;
+ std::string default_msg_key = "";
- switch (type)
+ switch (s_type)
{
- case NUM_SHOUTS:
- case S_RANDOM:
- default_msg_key = "__BUGGY";
+ case S_SILENT:
+ // No default message.
break;
case S_SHOUT:
default_msg_key = "__SHOUT";
@@ -932,19 +930,17 @@ void handle_monster_shouts(monsters* monster, bool force)
case S_HISS:
default_msg_key = "__HISS";
break;
+ case S_DEMON_TAUNT:
+ default_msg_key = "__DEMON_TAUNT";
+ break;
default:
- default_msg_key = "";
+ default_msg_key = "__BUGGY";
}
- // Use get_monster_data(monster->type) to bypass mon_shouts()
- // replacing S_RANDOM with a random value.
- if (mons_is_demon( monster->type ) && coinflip()
- && (type != S_SILENT ||
- get_monster_data(monster->type)->shouts == S_RANDOM))
- {
- noise_level = 8;
- default_msg_key = "__DEMON_TAUNT";
- }
+ // Now that we have the message key, get a random verb and noise level
+ // for pandemonium lords.
+ if (s_type == S_DEMON_TAUNT)
+ s_type = mons_shouts(monster->type, true);
std::string msg, suffix;
std::string key = mons_type_name(monster->type, DESC_PLAIN);
@@ -993,16 +989,20 @@ void handle_monster_shouts(monsters* monster, bool force)
}
if (default_msg_key == "__BUGGY")
+ {
msg::streams(MSGCH_SOUND) << "You hear something buggy!"
<< std::endl;
- else if ((msg == "" || msg == "__NONE")
- && mons_shouts(monster->type) == S_SILENT)
+ }
+ else if (s_type == S_SILENT && (msg == "" || msg == "__NONE"))
+ {
; // No "visual shout" defined for silent monster, do nothing
+ }
else if (msg == "")
{
msg::streams(MSGCH_DIAGNOSTICS)
<< "No shout entry for default shout type '"
<< default_msg_key << "'" << std::endl;
+
msg::streams(MSGCH_SOUND) << "You hear something buggy!"
<< std::endl;
}
@@ -1016,7 +1016,7 @@ void handle_monster_shouts(monsters* monster, bool force)
}
else
{
- msg = do_mon_str_replacements(msg, monster);
+ msg = do_mon_str_replacements(msg, monster, s_type);
msg_channel_type channel = MSGCH_TALK;
std::string param = "";
@@ -1028,7 +1028,7 @@ void handle_monster_shouts(monsters* monster, bool force)
msg = msg.substr(pos + 1);
}
- if (mons_shouts(monster->type) == S_SILENT || param == "VISUAL")
+ if (s_type == S_SILENT || param == "VISUAL")
channel = MSGCH_TALK_VISUAL;
else if (param == "SOUND")
channel = MSGCH_SOUND;
@@ -1049,6 +1049,7 @@ void handle_monster_shouts(monsters* monster, bool force)
msg::streams(channel) << msg << std::endl;
}
+ const int noise_level = get_shout_noise_level(s_type);
if (noise_level > 0)
noisy(noise_level, monster->x, monster->y);
}