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>2007-08-23 18:52:05 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2007-08-23 18:52:05 +0000
commita42cf252322e22af17e24e3f5e8f2f7a35cc0bd7 (patch)
tree36bd351605e76e4d35492ed03a258d8b303ba325 /crawl-ref/source/monplace.cc
parent72acf198cb29df6fc60463fc042356f549f10b43 (diff)
downloadcrawl-ref-a42cf252322e22af17e24e3f5e8f2f7a35cc0bd7.tar.gz
crawl-ref-a42cf252322e22af17e24e3f5e8f2f7a35cc0bd7.zip
Monsters coming up or down staircases will now
be chosen according to the destination. And yes, this does mean that occasionally an elf summoner will cross the Orc/Elf border etc, which could make things harder. On the other hand, that's just one staircase out of (at least!) seven, and monsters entering the level through the upstairs will likewise be a bit easier. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@2030 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/monplace.cc')
-rw-r--r--crawl-ref/source/monplace.cc153
1 files changed, 117 insertions, 36 deletions
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index 55bc258d88..3e0c01ac01 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -13,6 +13,7 @@
#include "AppHdr.h"
#include "monplace.h"
+#include "branch.h"
#include "externs.h"
#include "lev-pand.h"
#include "makeitem.h"
@@ -301,7 +302,7 @@ monster_type pick_random_monster(const level_id &place,
mon_type = static_cast<monster_type>(random2(NUM_MONSTERS));
count++;
}
- while (mons_rarity(mon_type) == 0 && count < 2000);
+ while (mons_rarity(mon_type, place) == 0 && count < 2000);
if (count == 2000)
return (MONS_PROGRAM_BUG);
@@ -332,6 +333,13 @@ bool place_monster(int &id, int mon_type, int power, beh_type behaviour,
int band_monsters[BIG_BAND]; // band monster types
int lev_mons = power; // final 'power'
int i;
+
+ // player shoved out of the way?
+ bool shoved = false;
+ unsigned char stair_gfx = 0;
+ int tries = 0;
+ int pval = 0;
+ level_id place = level_id::current();
// set initial id to -1 (unsuccessful create)
id = -1;
@@ -341,18 +349,89 @@ bool place_monster(int &id, int mon_type, int power, beh_type behaviour,
return (false);
// (2) take care of random monsters
- if (mon_type == RANDOM_MONSTER
- && player_in_branch( BRANCH_HALL_OF_BLADES ))
- {
- mon_type = MONS_DANCING_WEAPON;
- }
-
if (mon_type == RANDOM_MONSTER)
{
- mon_type = pick_random_monster(level_id::current(), lev_mons,
+ // respect destination level for staircases
+ if (proximity == PROX_NEAR_STAIRS)
+ {
+ while(++tries <= 320)
+ {
+ px = 5 + random2(GXM - 10);
+ py = 5 + random2(GYM - 10);
+
+ if (mgrd[px][py] != NON_MONSTER
+ || (px == you.x_pos && py == you.y_pos))
+ {
+ continue;
+ }
+
+ // Is the monster happy where we want to put it?
+ unsigned char grid_wanted = monster_habitat(mon_type);
+ if (!grid_compatible(grid_wanted, grd[px][py], true))
+ continue;
+
+ // Is the grid verboten?
+ if (!unforbidden( coord_def(px, py), mmask ))
+ continue;
+
+ // don't generate monsters on top of teleport traps
+ int trap = trap_at_xy(px, py);
+ if (trap >= 0)
+ {
+ if (env.trap[trap].type == TRAP_TELEPORT)
+ continue;
+ }
+
+ // check whether there's a stair
+ // and whether it leads to another branch
+ pval = near_stairs(px, py, 1, stair_gfx, place.branch);
+
+ // no monsters spawned in the Temple
+ if (branches[place.branch].id == BRANCH_ECUMENICAL_TEMPLE)
+ continue;
+
+ // found a position near the stairs!
+ if (pval > 0)
+ break;
+ }
+ if (tries > 320)
+ { // give up and try somewhere else
+ proximity = PROX_AWAY_FROM_PLAYER;
+ }
+ else
+ {
+ if ( stair_gfx == '>' ) // deeper level
+ lev_mons++;
+ else if (stair_gfx == '<') // higher level
+ {
+ // monsters don't come from outside the dungeon
+ if (lev_mons <= 0)
+ {
+ proximity = PROX_AWAY_FROM_PLAYER;
+ // or maybe allow 1st level monsters, having visited the
+ // surface, to re-enter the dungeon
+ // in that case lev_mons stays as it is
+ }
+ else
+ lev_mons--;
+ }
+// mprf("branch := %d, level := %d",
+// branches[place.branch].id, lev_mons+1);
+
+ }
+ } // end proximity check
+
+ if (branches[place.branch].id == BRANCH_HALL_OF_BLADES)
+ mon_type = MONS_DANCING_WEAPON;
+ else
+ {
+ // now pick a monster of the given branch and level
+ mon_type = pick_random_monster(place, lev_mons,
lev_mons);
- if (mon_type == MONS_PROGRAM_BUG)
- return (false);
+
+ if (mon_type == MONS_PROGRAM_BUG)
+ return (false);
+ }
}
// (3) decide on banding (good lord!)
@@ -368,22 +447,24 @@ bool place_monster(int &id, int mon_type, int power, beh_type behaviour,
band_monsters[i] = band_member( band, power );
}
- // Monsters that can't move shouldn't be taking the stairs -- bwr
- if (proximity == PROX_NEAR_STAIRS && mons_class_is_stationary( mon_type ))
- proximity = PROX_AWAY_FROM_PLAYER;
+ if (proximity == PROX_NEAR_STAIRS)
+ {
+ // for some cases disallow monsters on stairs
+ if (mons_class_is_stationary( mon_type )
+ || pval == 2 && (mons_speed(mon_type) == 0
+ || grd[px][py] == DNGN_LAVA || grd[px][py] == DNGN_DEEP_WATER))
+ {
+ proximity = PROX_AWAY_FROM_PLAYER;
+ }
+ }
// (4) for first monster, choose location. This is pretty intensive.
bool proxOK;
bool close_to_player;
- // player shoved out of the way?
- bool shoved = false;
- unsigned char stair_gfx = 0;
- int pval = 0;
-
if (!summoned)
{
- int tries = 0;
+ tries = 0;
// try to pick px, py that is
// a) not occupied
// b) compatible
@@ -391,23 +472,27 @@ bool place_monster(int &id, int mon_type, int power, beh_type behaviour,
unsigned char grid_wanted = monster_habitat(mon_type);
while(true)
{
- tries ++;
- // give up on stair placement?
- if (proximity == PROX_NEAR_STAIRS)
+ // handled above, won't change anymore
+ if (proximity == PROX_NEAR_STAIRS && tries)
{
- if (tries > 320)
- {
- proximity = PROX_AWAY_FROM_PLAYER;
- tries = 0;
- }
+ proximity = PROX_AWAY_FROM_PLAYER;
+ tries = 0;
}
// Dropped number of tries from 60.
- else if (tries > 45)
+ else if (tries >= 45)
return (false);
- px = 5 + random2(GXM - 10);
- py = 5 + random2(GYM - 10);
-
+ tries ++;
+
+ // placement already decided for PROX_NEAR_STAIRS
+ if (proximity != PROX_NEAR_STAIRS)
+ {
+ px = 5 + random2(GXM - 10);
+ py = 5 + random2(GYM - 10);
+ }
+
+ // Let's recheck these even for PROX_NEAR_STAIRS, just in case
+
// occupied?
if (mgrd[px][py] != NON_MONSTER
|| (px == you.x_pos && py == you.y_pos))
@@ -456,8 +541,7 @@ bool place_monster(int &id, int mon_type, int power, beh_type behaviour,
break;
case PROX_NEAR_STAIRS:
- pval = near_stairs(px, py, 1, stair_gfx);
- if (pval == 2)
+ if (pval == 2) // player on stairs
{
// 0 speed monsters can't shove player out of their way.
if (mons_speed(mon_type) == 0)
@@ -546,9 +630,6 @@ bool place_monster(int &id, int mon_type, int power, beh_type behaviour,
lev_mons, extra, false, dur);
}
- // if summoned onto traps, directly affect monster
- menv[id].apply_location_effects();
-
// placement of first monster, at least, was a success.
return (true);
}