summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/monplace.cc
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-06-01 12:27:44 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-06-01 12:27:44 +0000
commit033b2f5904e3a87e5ce2605b2779be860bf46682 (patch)
tree538907b1b7b6475845ec008d953c188047851ad8 /crawl-ref/source/monplace.cc
parentcd46d3d8df2dfddda422fa80cfc47240de365b13 (diff)
downloadcrawl-ref-033b2f5904e3a87e5ce2605b2779be860bf46682.tar.gz
crawl-ref-033b2f5904e3a87e5ce2605b2779be860bf46682.zip
Fix 1937489: Remove map markers overwritten by lakes or rivers, as was
already done for vaults. Modify monster speech to make the beast only use some selected shouts (i.e. not "You hear an irritating whine") and NEVER do the demon taunts since it cannot speak. Demon lords can use almost the whole array of speaking verbs except for "buzz" and "whine". git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5400 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/monplace.cc')
-rw-r--r--crawl-ref/source/monplace.cc153
1 files changed, 97 insertions, 56 deletions
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);