summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/abyss.cc63
-rw-r--r--crawl-ref/source/abyss.h1
-rw-r--r--crawl-ref/source/acr.cc3
-rw-r--r--crawl-ref/source/enum.h4
-rw-r--r--crawl-ref/source/externs.h9
-rw-r--r--crawl-ref/source/fight.cc11
-rw-r--r--crawl-ref/source/files.cc105
-rw-r--r--crawl-ref/source/items.cc4
-rw-r--r--crawl-ref/source/makefile.obj1
-rw-r--r--crawl-ref/source/misc.cc5
-rw-r--r--crawl-ref/source/mon-util.cc92
-rw-r--r--crawl-ref/source/monstuff.cc11
-rw-r--r--crawl-ref/source/mtransit.cc159
-rw-r--r--crawl-ref/source/mtransit.h39
-rw-r--r--crawl-ref/source/spells1.cc3
-rw-r--r--crawl-ref/source/spells4.cc2
-rw-r--r--crawl-ref/source/spl-cast.cc12
-rw-r--r--crawl-ref/source/tags.cc358
-rw-r--r--crawl-ref/source/travel.h9
19 files changed, 604 insertions, 287 deletions
diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc
index ac82243fff..eb00207c74 100644
--- a/crawl-ref/source/abyss.cc
+++ b/crawl-ref/source/abyss.cc
@@ -21,6 +21,7 @@
#include "cloud.h"
#include "misc.h"
#include "monplace.h"
+#include "mtransit.h"
#include "dungeon.h"
#include "items.h"
#include "lev-pand.h"
@@ -190,35 +191,27 @@ static void generate_area(unsigned char gx1, unsigned char gy1,
}
}
+static void abyss_lose_monster(monsters &mons)
+{
+ if (mons.needs_transit())
+ mons.set_transit( level_id(LEVEL_ABYSS) );
+
+ mons.reset();
+}
void area_shift(void)
/*******************/
{
for (unsigned int i = 0; i < MAX_MONSTERS; i++)
{
- if (menv[i].type == -1)
- {
+ monsters &m = menv[i];
+
+ if (!m.alive())
continue;
- }
// remove non-nearby monsters
- if (menv[i].x < you.x_pos - 10
- || menv[i].x >= you.x_pos + 11
- || menv[i].y < you.y_pos - 10 || menv[i].y >= you.y_pos + 11)
- {
- menv[i].type = -1;
-
- mgrd[menv[i].x][menv[i].y] = NON_MONSTER;
-
- for (unsigned int j = 0; j < NUM_MONSTER_SLOTS; j++)
- {
- if (menv[i].inv[j] != NON_ITEM)
- {
- destroy_item( menv[i].inv[j] );
- menv[i].inv[j] = NON_ITEM;
- }
- }
- }
+ if (grid_distance(m.x, m.y, you.x_pos, you.y_pos) > 10)
+ abyss_lose_monster(m);
}
for (int i = 5; i < (GXM - 5); i++)
@@ -226,17 +219,17 @@ void area_shift(void)
for (int j = 5; j < (GYM - 5); j++)
{
// don't modify terrain by player
- if (i >= you.x_pos - 10 && i < you.x_pos + 11
- && j >= you.y_pos - 10 && j < you.y_pos + 11)
- {
+ if (grid_distance(i, j, you.x_pos, you.y_pos) <= 10)
continue;
- }
// nuke terrain otherwise
grd[i][j] = DNGN_UNSEEN;
// nuke items
destroy_item_stack( i, j );
+
+ if (mgrd[i][j] != NON_MONSTER)
+ abyss_lose_monster( menv[ mgrd[i][j] ] );
}
}
@@ -298,8 +291,20 @@ void area_shift(void)
mons_place( RANDOM_MONSTER, BEH_HOSTILE, MHITNOT, false, 1, 1,
LEVEL_ABYSS, PROX_AWAY_FROM_PLAYER ); // PROX_ANYWHERE?
}
+
+ // And allow monsters in transit another chance to return.
+ place_transiting_monsters();
}
+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) );
+ }
+}
void abyss_teleport( bool new_area )
/**********************************/
@@ -336,6 +341,12 @@ void abyss_teleport( bool new_area )
init_pandemonium(); // get new monsters
set_colours_from_monsters(); // and new colours
+ for (i = 0; i < MAX_MONSTERS; i++)
+ {
+ if (menv[i].alive())
+ abyss_lose_monster(menv[i]);
+ }
+
// Orbs and fixed artefacts are marked as "lost in the abyss"
for (k = 0; k < MAX_ITEMS; k++)
{
@@ -356,9 +367,6 @@ void abyss_teleport( bool new_area )
}
}
- for (i = 0; i < MAX_MONSTERS; i++)
- menv[i].type = -1;
-
for (i = 0; i < MAX_CLOUDS; i++)
delete_cloud( i );
@@ -384,4 +392,5 @@ void abyss_teleport( bool new_area )
if ( one_chance_in(5) )
grd[you.x_pos + 1][you.y_pos] = DNGN_ALTAR_LUCY;
+ place_transiting_monsters();
}
diff --git a/crawl-ref/source/abyss.h b/crawl-ref/source/abyss.h
index 9ecef56114..d25770473f 100644
--- a/crawl-ref/source/abyss.h
+++ b/crawl-ref/source/abyss.h
@@ -33,5 +33,6 @@ void area_shift(void);
* *********************************************************************** */
void abyss_teleport( bool new_area );
+void save_abyss_uniques();
#endif
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index f92c3747b3..a3a1bebe24 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -2981,8 +2981,7 @@ static void move_player(int move_x, int move_y)
ig2++;
}
- snprintf( info, INFO_SIZE, "Number of items present: %d", ig2 );
- mpr( info, MSGCH_DIAGNOSTICS );
+ mprf( MSGCH_DIAGNOSTICS, "Number of items present: %d", ig2 );
ig2 = 0;
for (igly = 0; igly < MAX_MONSTERS; igly++)
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index efce88b640..70b41f74d6 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -2374,8 +2374,9 @@ enum monster_flag_type
MF_SEEN = 0x40, // Player already seen monster
MF_DIVINE_PROTECTION = 0x80, // Monster has divine protection.
- MF_KNOWN_MIMIC = 0x100 // Mimic that has taken a swing at the PC,
+ MF_KNOWN_MIMIC = 0x100, // Mimic that has taken a swing at the PC,
// or that the player has inspected with ?
+ MF_BANISHED = 0x200 // Monster that has been banished.
};
enum mon_dam_level_type
@@ -3624,6 +3625,7 @@ enum tag_type // used during save/load process to identify data blocks
TAG_LEVEL_MONSTERS, // monsters
TAG_GHOST, // ghost
TAG_LEVEL_ATTITUDE, // monster attitudes
+ TAG_LOST_MONSTERS, // monsters in transit
NUM_TAGS
};
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index cd7002855c..e2083c1c3a 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -816,6 +816,7 @@ struct mon_attack_def
};
class ghost_demon;
+class level_id;
class monsters : public actor
{
@@ -857,9 +858,17 @@ public:
std::auto_ptr<ghost_demon> ghost; // Ghost information.
public:
+ bool needs_transit() const;
+ void set_transit(level_id destination);
+ bool find_place_to_live(bool near_player = false);
+ bool find_place_near_player();
+ bool find_home_in(coord_def s, coord_def e);
+ bool find_home_anywhere();
+
void set_ghost(const ghost_demon &ghost);
void ghost_init();
void pandemon_init();
+ void destroy_inventory();
void reset();
void load_spells(int spellbook);
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 7b46f788d3..0d741668c5 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -495,6 +495,8 @@ bool melee_attack::player_attack()
if (cancel_attack)
return (false);
+ coord_def where = defender->pos();
+
if (player_hits_monster())
{
did_hit = true;
@@ -533,11 +535,14 @@ bool melee_attack::player_attack()
const bool did_primary_hit = did_hit;
- if (unarmed_ok && player_aux_unarmed())
+ if (unarmed_ok && where == defender->pos() && player_aux_unarmed())
return (true);
- if ((did_primary_hit || did_hit) && def->type != -1)
+ if ((did_primary_hit || did_hit) && def->alive()
+ && where == defender->pos())
+ {
print_wounds(def);
+ }
return (did_primary_hit || did_hit);
}
@@ -1691,7 +1696,7 @@ bool melee_attack::apply_damage_brand()
break;
}
- if (coinflip())
+ if (you.level_type != LEVEL_ABYSS && coinflip())
{
emit_nodmg_hit_message();
defender->banish();
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index 5e73131373..3beb2d137e 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -68,6 +68,7 @@
#include "monstuff.h"
#include "mon-util.h"
#include "mstuff2.h"
+#include "mtransit.h"
#include "notes.h"
#include "player.h"
#include "randart.h"
@@ -540,14 +541,6 @@ bool travel_load_map( char branch, int absdepth )
return true;
}
-struct follower {
- monsters mons;
- std::vector<item_def> items;
-
- follower() : mons(), items() { }
- follower(const monsters &m) : mons(m), items() { }
-};
-
void load( unsigned char stair_taken, int load_mode, bool was_a_labyrinth,
char old_level, char where_were_you2 )
{
@@ -623,21 +616,8 @@ void load( unsigned char stair_taken, int load_mode, bool was_a_labyrinth,
#endif
follower f(*fmenv);
-
- for (int minvc = 0; minvc < NUM_MONSTER_SLOTS; ++minvc)
- {
- const int item = fmenv->inv[minvc];
- if (item == NON_ITEM)
- {
- f.items.push_back(item_def());
- continue;
- }
-
- f.items.push_back(mitm[item]);
- destroy_item( item );
- }
-
followers.push_back(f);
+ fmenv->destroy_inventory();
monster_cleanup(fmenv);
}
} // end of grabbing followers
@@ -887,88 +867,22 @@ found_stair:
if (mgrd[you.x_pos][you.y_pos] != NON_MONSTER)
monster_teleport(&menv[mgrd[you.x_pos][you.y_pos]], true);
- int following = 0;
-
// actually "move" the followers if applicable
if ((you.level_type == LEVEL_DUNGEON
|| you.level_type == LEVEL_PANDEMONIUM)
&& load_mode == LOAD_ENTER_LEVEL)
{
- for (int ic = 0; ic < 2; ic++)
+ while (!followers.empty())
{
- for (count_x = you.x_pos - 6; count_x < you.x_pos + 7;
- count_x++)
- {
- for (count_y = you.y_pos - 6; count_y < you.y_pos + 7;
- count_y++)
- {
- if (ic == 0
- && ((count_x < you.x_pos - 1)
- || (count_x > you.x_pos + 1)
- || (count_y < you.y_pos - 1)
- || (count_y > you.y_pos + 1)))
- {
- continue;
- }
-
- if (count_x == you.x_pos && count_y == you.y_pos)
- continue;
-
- if (mgrd[count_x][count_y] != NON_MONSTER
- || grd[count_x][count_y] < DNGN_FLOOR)
- {
- continue;
- }
-
- while (menv[following].type != -1)
- {
- following++;
-
- if (following >= MAX_MONSTERS)
- goto out_of_foll;
- }
-
- if (followers.size())
- {
- follower f = followers.front();
- followers.erase(followers.begin());
-
- menv[following] = f.mons;
- menv[following].x = count_x;
- menv[following].y = count_y;
- menv[following].target_x = 0;
- menv[following].target_y = 0;
- menv[following].flags |= MF_JUST_SUMMONED;
-
- for (int minvc = 0; minvc < NUM_MONSTER_SLOTS; minvc++)
- {
- menv[following].inv[minvc] = NON_ITEM;
-
- const item_def &minvitem = f.items[minvc];
- if (minvitem.base_type != OBJ_UNASSIGNED)
- {
- int itmf = get_item_slot(0);
- if (itmf == NON_ITEM)
- {
- menv[following].inv[minvc] = NON_ITEM;
- continue;
- }
-
- mitm[itmf] = minvitem;
- mitm[itmf].x = 0;
- mitm[itmf].y = 0;
- mitm[itmf].link = NON_ITEM;
- menv[following].inv[minvc] = itmf;
- }
- }
- mgrd[count_x][count_y] = following;
- } // followers.size()
- }
- }
+ follower f = followers.front();
+ followers.erase(followers.begin());
+ f.place(true);
}
} // end of moving followers
- out_of_foll:
+ // Load monsters in transit.
+ place_transiting_monsters();
+
redraw_all();
// Sanity forcing of monster inventory items (required?)
@@ -1253,7 +1167,6 @@ void load_ghost(void)
}
}
-
void restore_game(void)
{
std::string charFile = get_savedir_filename(you.your_name, "", "sav");
diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc
index 98a2c732e2..eb62d1fc99 100644
--- a/crawl-ref/source/items.cc
+++ b/crawl-ref/source/items.cc
@@ -2182,12 +2182,16 @@ static void update_enchantments( struct monsters *mon, int levels )
case ENCH_ABJ_VI:
if (remove_enchant_levels( mon, i, ENCH_ABJ_I, levels ))
{
+ // Re-add ABJ_I so that monster_die doesn't try to send the
+ // monster to the Abyss on KILL_RESET.
+ mons_add_ench( mon, ENCH_ABJ_I );
monster_die( mon, KILL_RESET, 0 );
}
break;
case ENCH_SHORT_LIVED:
+ mons_add_ench( mon, ENCH_ABJ_I );
monster_die( mon, KILL_RESET, 0 );
break;
diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj
index c192363222..a1bea5253a 100644
--- a/crawl-ref/source/makefile.obj
+++ b/crawl-ref/source/makefile.obj
@@ -45,6 +45,7 @@ monstuff.o \
monspeak.o \
mon-util.o \
mstuff2.o \
+mtransit.o \
mutation.o \
newgame.o \
notes.o \
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index 19da6b667e..4dc7bc2544 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -35,6 +35,7 @@
#include "externs.h"
+#include "abyss.h"
#include "branch.h"
#include "cloud.h"
#include "delay.h"
@@ -834,6 +835,10 @@ void down_stairs( bool remove_stairs, int old_level, int force_stair )
if (collect_travel_data)
old_level_info.update();
+ // Preserve abyss uniques now, since this Abyss level will be deleted.
+ if (you.level_type == LEVEL_ABYSS)
+ save_abyss_uniques();
+
if (you.level_type == LEVEL_PANDEMONIUM
&& stair_find == DNGN_TRANSIT_PANDEMONIUM)
{
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 243b8f03e4..9b61ec053c 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -32,10 +32,12 @@
#include "debug.h"
#include "itemname.h"
#include "itemprop.h"
+#include "items.h"
#include "Kills.h"
#include "misc.h"
#include "monplace.h"
#include "mstuff2.h"
+#include "mtransit.h"
#include "player.h"
#include "randart.h"
#include "stuff.h"
@@ -2781,8 +2783,6 @@ void monsters::expose_to_element(beam_type, int)
void monsters::banish()
{
- // [dshaligram] FIXME: We should really put these monsters on a
- // queue and load them when the player enters the Abyss.
monster_die(this, KILL_RESET, 0);
}
@@ -3041,19 +3041,84 @@ void monsters::ghost_init()
inv.init(NON_ITEM);
enchantment.init(ENCH_NONE);
+ find_place_to_live();
+}
+
+bool monsters::find_home_in(coord_def s, coord_def e)
+{
+ for (int iy = s.y; iy <= e.y; ++iy)
+ {
+ for (int ix = s.x; ix <= e.x; ++ix)
+ {
+ if (!in_bounds(ix, iy))
+ continue;
+
+ if (ix == you.x_pos && iy == you.y_pos)
+ continue;
+
+ if (mgrd[ix][iy] != NON_MONSTER || grd[ix][iy] < DNGN_FLOOR)
+ continue;
+
+ x = ix;
+ y = iy;
+ return (true);
+ }
+ }
+
+ return (false);
+}
+
+bool monsters::find_place_near_player()
+{
+ return (find_home_in( you.pos() - coord_def(1, 1),
+ you.pos() + coord_def(1, 1) )
+ || find_home_in( you.pos() - coord_def(6, 6),
+ you.pos() + coord_def(6, 6) ));
+}
+
+bool monsters::find_home_anywhere()
+{
+ int tries = 600;
do
{
- x = random2(GXM - 20) + 10;
- y = random2(GYM - 20) + 10;
+ x = random_range(6, GXM - 7);
+ y = random_range(6, GYM - 7);
}
- while ((grd[x][y] != DNGN_FLOOR)
- || (mgrd[x][y] != NON_MONSTER));
+ while ((grd[x][y] != DNGN_FLOOR
+ || mgrd[x][y] != NON_MONSTER)
+ && tries-- > 0);
- mgrd[x][y] = monster_index(this);
+ return (tries >= 0);
+}
+
+bool monsters::find_place_to_live(bool near_player)
+{
+ if ((near_player && find_place_near_player())
+ || find_home_anywhere())
+ {
+ mgrd[x][y] = monster_index(this);
+ return (true);
+ }
+
+ return (false);
+}
+
+void monsters::destroy_inventory()
+{
+ for (int j = 0; j < NUM_MONSTER_SLOTS; j++)
+ {
+ if (inv[j] != NON_ITEM)
+ {
+ destroy_item( inv[j] );
+ inv[j] = NON_ITEM;
+ }
+ }
}
void monsters::reset()
{
+ destroy_inventory();
+
enchantment.init(ENCH_NONE);
inv.init(NON_ITEM);
@@ -3076,6 +3141,19 @@ void monsters::reset()
ghost.reset(NULL);
}
+bool monsters::needs_transit() const
+{
+ return ((mons_is_unique(type)
+ || (flags & MF_BANISHED)
+ || (you.level_type == LEVEL_DUNGEON && hit_dice > 8 + random2(25)))
+ && !mons_has_ench(this, ENCH_ABJ_I, ENCH_ABJ_VI));
+}
+
+void monsters::set_transit(level_id dest)
+{
+ add_monster_to_transit(dest, *this);
+}
+
void monsters::load_spells(int book)
{
spells.init(MS_NO_SPELL);
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index bf34d15dc1..eb8c5915a4 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -338,6 +338,7 @@ void monster_die(monsters *monster, char killer, int i, bool silent)
int monster_killed = monster_index(monster);
bool death_message =
!silent && mons_near(monster) && player_monster_visible(monster);
+ bool in_transit = false;
// From time to time Trog gives you a little bonus
if (killer == KILL_YOU && you.berserker)
@@ -660,6 +661,13 @@ void monster_die(monsters *monster, char killer, int i, bool silent)
place_cloud( CLOUD_GREY_SMOKE_MON + random2(3), monster->x,
monster->y, 1 + random2(3) );
+ if (monster->needs_transit())
+ {
+ monster->flags |= MF_BANISHED;
+ monster->set_transit( level_id(LEVEL_ABYSS) );
+ in_transit = true;
+ }
+
// fall-through
case KILL_DISMISSED:
@@ -697,7 +705,7 @@ void monster_die(monsters *monster, char killer, int i, bool silent)
random2avg(88, 3), 100, "a mummy death curse" );
}
}
- else if (monster->type == MONS_BORIS)
+ else if (monster->type == MONS_BORIS && !in_transit)
{
// XXX: actual blood curse effect for Boris? -- bwr
@@ -2091,6 +2099,7 @@ static bool handle_enchantment(struct monsters *monster)
if (monster->enchantment[p] < ENCH_ABJ_I)
{
+ monster->enchantment[p] = ENCH_ABJ_I;
monster_die(monster, KILL_RESET, 0);
died = true;
}
diff --git a/crawl-ref/source/mtransit.cc b/crawl-ref/source/mtransit.cc
new file mode 100644
index 0000000000..bb58f68909
--- /dev/null
+++ b/crawl-ref/source/mtransit.cc
@@ -0,0 +1,159 @@
+/*
+ * File: mtransit.cc
+ * Summary: Tracks monsters that are in suspended animation between levels.
+ * Written by: Darshan Shaligram
+ *
+ * Modified for Crawl Reference by $Author: dshaligram $ on $Date: 2007-03-15T20:10:20.648083Z $
+ */
+
+#include "AppHdr.h"
+
+#include "mtransit.h"
+#include "items.h"
+#include "mon-util.h"
+#include "stuff.h"
+
+#define MAX_LOST 100
+
+monsters_in_transit the_lost_ones;
+
+static void place_lost_monsters(m_transit_list &m);
+
+static void cull_lost(m_transit_list &mlist, int how_many)
+{
+ // First pass, drop non-uniques.
+ m_transit_list::iterator i = mlist.begin();
+
+ for ( ; i != mlist.end(); )
+ {
+ m_transit_list::iterator finger = i++;
+ if (!mons_is_unique(finger->mons.type))
+ {
+ mlist.erase(finger);
+
+ if (--how_many <= 0)
+ return;
+ }
+ }
+
+ // If we're still over the limit (unlikely), just lose
+ // the old ones.
+ while (how_many-- > MAX_LOST && !mlist.empty())
+ mlist.erase( mlist.begin() );
+}
+
+void add_monster_to_transit(level_id lid, const monsters &m)
+{
+ m_transit_list &mlist = the_lost_ones[lid];
+ mlist.push_back(m);
+
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Monster in transit: %s",
+ m.name(DESC_PLAIN).c_str());
+#endif
+
+ const int how_many = mlist.size();
+ if (how_many > MAX_LOST)
+ cull_lost(mlist, how_many);
+}
+
+void place_transiting_monsters()
+{
+ level_id c = level_id::current();
+
+ monsters_in_transit::iterator i = the_lost_ones.find(c);
+ if (i == the_lost_ones.end())
+ return;
+
+ place_lost_monsters(i->second);
+ if (i->second.empty())
+ the_lost_ones.erase(i);
+}
+
+static bool place_lost_monster(follower &f)
+{
+ return (f.place(false));
+}
+
+static void place_lost_monsters(m_transit_list &m)
+{
+ for (m_transit_list::iterator i = m.begin();
+ i != m.end(); )
+ {
+ m_transit_list::iterator mon = i++;
+
+ // Transiting monsters have a 50% chance of being placed.
+ if (coinflip())
+ continue;
+
+ if (place_lost_monster(*mon))
+ m.erase(mon);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// follower
+
+follower::follower(const monsters &m) : mons(m), items()
+{
+ load_mons_items();
+}
+
+void follower::load_mons_items()
+{
+ for (int i = 0; i < NUM_MONSTER_SLOTS; ++i)
+ if (mons.inv[i] != NON_ITEM)
+ items[i] = mitm[ mons.inv[i] ];
+ else
+ items[i].clear();
+}
+
+bool follower::place(bool near_player)
+{
+ for (int i = 0; i < MAX_MONSTERS - 5; ++i)
+ {
+ monsters &m = menv[i];
+ if (m.alive())
+ continue;
+
+ m = mons;
+ if (m.find_place_to_live(near_player))
+ {
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Placed follower: %s",
+ m.name(DESC_PLAIN).c_str());
+#endif
+ m.target_x = m.target_y = 0;
+ m.flags |= MF_JUST_SUMMONED;
+
+ restore_mons_items(m);
+ return (true);
+ }
+
+ m.reset();
+ break;
+ }
+
+ return (false);
+}
+
+void follower::restore_mons_items(monsters &m)
+{
+ for (int i = 0; i < NUM_MONSTER_SLOTS; ++i)
+ {
+ if (items[i].base_type == OBJ_UNASSIGNED)
+ m.inv[i] = NON_ITEM;
+ else
+ {
+ const int islot = get_item_slot(0);
+ m.inv[i] = islot;
+ if (islot == NON_ITEM)
+ continue;
+
+ item_def &it = mitm[islot];
+ it = items[i];
+ it.x = it.y = 0;
+ it.link = NON_ITEM;
+ }
+ }
+}
diff --git a/crawl-ref/source/mtransit.h b/crawl-ref/source/mtransit.h
new file mode 100644
index 0000000000..3ffc0adfc8
--- /dev/null
+++ b/crawl-ref/source/mtransit.h
@@ -0,0 +1,39 @@
+/*
+ * File: mtransit.h
+ * Summary: Tracking monsters in transit between levels.
+ * Written by: Darshan Shaligram
+ *
+ * Modified for Crawl Reference by $Author: dshaligram $ on $Date: 2007-03-15T20:10:20.648083Z $
+ */
+
+#ifndef MTRANSIT_H
+#define MTRANSIT_H
+
+#include "AppHdr.h"
+#include "travel.h"
+#include <map>
+#include <list>
+
+struct follower
+{
+ monsters mons;
+ FixedVector<item_def, NUM_MONSTER_SLOTS> items;
+
+ follower() : mons(), items() { }
+ follower(const monsters &m);
+ bool place(bool near_player = false);
+ void load_mons_items();
+ void restore_mons_items(monsters &m);
+};
+
+typedef std::list<follower> m_transit_list;
+typedef std::map<level_id, m_transit_list> monsters_in_transit;
+
+extern monsters_in_transit the_lost_ones;
+
+void add_monster_to_transit(level_id dest, const monsters &m);
+
+// Places (some of the) monsters eligible to be placed on this level.
+void place_transiting_monsters();
+
+#endif
diff --git a/crawl-ref/source/spells1.cc b/crawl-ref/source/spells1.cc
index 127f932915..ae7546c451 100644
--- a/crawl-ref/source/spells1.cc
+++ b/crawl-ref/source/spells1.cc
@@ -667,7 +667,10 @@ void abjuration(int pow)
abjLevel -= 1 + (random2(pow) / 8);
if (abjLevel < ENCH_ABJ_I)
+ {
+ mons_add_ench(monster, ENCH_ABJ_I);
monster_die(monster, KILL_RESET, 0);
+ }
else
{
simple_monster_message(monster, " shudders.");
diff --git a/crawl-ref/source/spells4.cc b/crawl-ref/source/spells4.cc
index 17b6b4518a..341bc90502 100644
--- a/crawl-ref/source/spells4.cc
+++ b/crawl-ref/source/spells4.cc
@@ -1417,7 +1417,7 @@ static int distortion_monsters(int x, int y, int pow, int message)
}
else if (one_chance_in(3))
{
- monster_die(defender, KILL_RESET, 0);
+ defender->banish();
return 1;
}
else if (message)
diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc
index ec0873abde..0eade5c58e 100644
--- a/crawl-ref/source/spl-cast.cc
+++ b/crawl-ref/source/spl-cast.cc
@@ -249,7 +249,7 @@ static int apply_vehumet_wizardry_boost(int spell, int chance)
{
int wizardry = player_mag_abil(false);
int fail_reduce = 100;
- int wiz_factor = 86;
+ int wiz_factor = 87;
if (you.religion == GOD_VEHUMET
&& you.duration[DUR_PRAYER]
@@ -258,8 +258,8 @@ static int apply_vehumet_wizardry_boost(int spell, int chance)
|| spell_typematch(spell, SPTYP_SUMMONING)))
{
// [dshaligram] Fail rate multiplier used to be .5, scaled
- // back to 60%.
- fail_reduce = fail_reduce * 60 / 100;
+ // back to 67%.
+ fail_reduce = fail_reduce * 67 / 100;
}
// [dshaligram] Apply wizardry factor here, rather than mixed into the
@@ -267,12 +267,12 @@ static int apply_vehumet_wizardry_boost(int spell, int chance)
while (wizardry-- > 0)
{
fail_reduce = fail_reduce * wiz_factor / 100;
- wiz_factor += (100 - wiz_factor) / 5;
+ wiz_factor += (100 - wiz_factor) / 3;
}
// Hard cap on fail rate reduction.
- if (fail_reduce < 40)
- fail_reduce = 40;
+ if (fail_reduce < 50)
+ fail_reduce = 50;
return (chance * fail_reduce / 100);
}
diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc
index 63fe4fc70b..ebf7587c2c 100644
--- a/crawl-ref/source/tags.cc
+++ b/crawl-ref/source/tags.cc
@@ -76,6 +76,7 @@
#include "itemprop.h"
#include "monstuff.h"
#include "mon-util.h"
+#include "mtransit.h"
#include "randart.h"
#include "skills.h"
#include "skills2.h"
@@ -99,9 +100,11 @@ FixedArray < bool, MAX_LEVELS, NUM_BRANCHES > tmp_file_pairs;
static void tag_construct_you(struct tagHeader &th);
static void tag_construct_you_items(struct tagHeader &th);
static void tag_construct_you_dungeon(struct tagHeader &th);
+static void tag_construct_lost_monsters(tagHeader &th);
static void tag_read_you(struct tagHeader &th, char minorVersion);
static void tag_read_you_items(struct tagHeader &th, char minorVersion);
static void tag_read_you_dungeon(struct tagHeader &th);
+static void tag_read_lost_monsters(tagHeader &th, int minorVersion);
static void tag_construct_level(struct tagHeader &th);
static void tag_construct_level_items(struct tagHeader &th);
@@ -118,6 +121,10 @@ static void tag_read_ghost(struct tagHeader &th, char minorVersion);
static void marshallGhost(tagHeader &th, const ghost_demon &ghost);
static ghost_demon unmarshallGhost( tagHeader &th );
+static void marshall_monster(tagHeader &th, const monsters &m);
+static void unmarshall_monster(tagHeader &th, monsters &m);
+static void marshall_item(tagHeader &th, const item_def &item);
+static void unmarshall_item(tagHeader &th, item_def &item);
// provide a wrapper for file writing, just in case.
int write2(FILE * file, const char *buffer, unsigned int count)
@@ -219,10 +226,11 @@ void marshallMap(struct tagHeader &th, const std::map<key,value>& data,
}
}
-void marshall_level_id( struct tagHeader& th, const level_id& id )
+void marshall_level_id( tagHeader& th, const level_id& id )
{
marshallByte(th, id.branch );
marshallLong(th, id.depth );
+ marshallByte(th, id.level_type);
}
void marshall_level_pos( struct tagHeader& th, const level_pos& lpos )
@@ -234,17 +242,15 @@ void marshall_level_pos( struct tagHeader& th, const level_pos& lpos )
template<typename key, typename value>
void unmarshallMap(struct tagHeader& th, std::map<key,value>& data,
- key (*key_unmarshall) (struct tagHeader&),
- value (*value_unmarshall)(struct tagHeader&) )
+ key (*key_unmarshall) (tagHeader&),
+ value (*value_unmarshall)(tagHeader&) )
{
long i, len = unmarshallLong(th);
key k;
- value v;
for ( i = 0; i < len; ++i )
{
k = key_unmarshall(th);
- v = value_unmarshall(th);
- data[k] = v;
+ data[k] = value_unmarshall(th);
}
}
@@ -254,12 +260,13 @@ T unmarshall_long_as( struct tagHeader& th )
return static_cast<T>(unmarshallLong(th));
}
-level_id unmarshall_level_id( struct tagHeader& th )
+level_id unmarshall_level_id( tagHeader& th )
{
level_id id;
id.branch = unmarshallByte(th);
id.depth = unmarshallLong(th);
- return id;
+ id.level_type = unmarshallByte(th);
+ return (id);
}
level_pos unmarshall_level_pos( struct tagHeader& th )
@@ -267,7 +274,7 @@ level_pos unmarshall_level_pos( struct tagHeader& th )
level_pos lpos;
lpos.pos.x = unmarshallLong(th);
lpos.pos.y = unmarshallLong(th);
- lpos.id = unmarshall_level_id(th);
+ lpos.id = unmarshall_level_id(th);
return lpos;
}
@@ -459,6 +466,9 @@ void tag_construct(struct tagHeader &th, int tagID)
case TAG_GHOST:
tag_construct_ghost(th);
break;
+ case TAG_LOST_MONSTERS:
+ tag_construct_lost_monsters(th);
+ break;
default:
// I don't know how to make that!
break;
@@ -557,6 +567,9 @@ int tag_read(FILE *fp, char minorVersion)
case TAG_GHOST:
tag_read_ghost(th, minorVersion);
break;
+ case TAG_LOST_MONSTERS:
+ tag_read_lost_monsters(th, minorVersion);
+ break;
default:
// I don't know how to read that!
return 0;
@@ -602,8 +615,11 @@ void tag_set_expected(char tags[], int fileType)
switch(fileType)
{
case TAGTYPE_PLAYER:
- if (i >= TAG_YOU && i <=TAG_YOU_DUNGEON)
+ if ((i >= TAG_YOU && i <=TAG_YOU_DUNGEON)
+ || i == TAG_LOST_MONSTERS)
+ {
tags[i] = 1;
+ }
break;
case TAGTYPE_PLAYER_NAME:
if (i == TAG_YOU)
@@ -910,6 +926,53 @@ static void tag_construct_you_dungeon(struct tagHeader &th)
marshall_level_pos, marshall_as_long<portal_type>);
}
+static void marshall_follower(tagHeader &th, const follower &f)
+{
+ marshall_monster(th, f.mons);
+ for (int i = 0; i < NUM_MONSTER_SLOTS; ++i)
+ marshall_item(th, f.items[i]);
+}
+
+static void unmarshall_follower(tagHeader &th, follower &f)
+{
+ unmarshall_monster(th, f.mons);
+ for (int i = 0; i < NUM_MONSTER_SLOTS; ++i)
+ unmarshall_item(th, f.items[i]);
+}
+
+static void marshall_follower_list(tagHeader &th, const m_transit_list &mlist)
+{
+ marshallShort( th, mlist.size() );
+
+ for (m_transit_list::const_iterator mi = mlist.begin();
+ mi != mlist.end(); ++mi)
+ {
+ marshall_follower( th, *mi );
+ }
+}
+
+static m_transit_list unmarshall_follower_list(tagHeader &th)
+{
+ m_transit_list mlist;
+
+ const int size = unmarshallShort(th);
+
+ for (int i = 0; i < size; ++i)
+ {
+ follower f;
+ unmarshall_follower(th, f);
+ mlist.push_back(f);
+ }
+
+ return (mlist);
+}
+
+static void tag_construct_lost_monsters(tagHeader &th)
+{
+ marshallMap( th, the_lost_ones, marshall_level_id,
+ marshall_follower_list );
+}
+
static void tag_read_you(struct tagHeader &th, char minorVersion)
{
char buff[20]; // For birth date
@@ -1200,7 +1263,8 @@ static void tag_read_you_dungeon(struct tagHeader &th)
}
unmarshallMap(th, stair_level,
- unmarshall_long_as<branch_type>, unmarshall_level_id);
+ unmarshall_long_as<branch_type>,
+ unmarshall_level_id);
unmarshallMap(th, shops_present,
unmarshall_level_pos, unmarshall_long_as<shop_type>);
unmarshallMap(th, altars_present,
@@ -1209,6 +1273,14 @@ static void tag_read_you_dungeon(struct tagHeader &th)
unmarshall_level_pos, unmarshall_long_as<portal_type>);
}
+static void tag_read_lost_monsters(tagHeader &th, int minorVersion)
+{
+ the_lost_ones.clear();
+
+ unmarshallMap(th, the_lost_ones,
+ unmarshall_level_id, unmarshall_follower_list);
+}
+
// ------------------------------- level tags ---------------------------- //
static void tag_construct_level(struct tagHeader &th)
@@ -1262,6 +1334,62 @@ static void tag_construct_level(struct tagHeader &th)
}
}
+static void marshall_item(tagHeader &th, const item_def &item)
+{
+ marshallByte(th, item.base_type);
+ marshallByte(th, item.sub_type);
+ marshallShort(th, item.plus);
+ marshallShort(th, item.plus2);
+ marshallLong(th, item.special);
+ marshallShort(th, item.quantity);
+
+ marshallByte(th, item.colour);
+ marshallShort(th, item.x);
+ marshallShort(th, item.y);
+ marshallLong(th, item.flags);
+
+ marshallShort(th, item.link); // unused
+ marshallShort(th, igrd[item.x][item.y]); // unused
+
+ marshallByte(th, item.slot);
+
+ marshallShort(th, item.orig_place);
+ marshallShort(th, item.orig_monnum);
+ marshallString(th, item.inscription.c_str(), 80);
+}
+
+static void unmarshall_item(tagHeader &th, item_def &item)
+{
+ item.base_type = (unsigned char) unmarshallByte(th);
+ item.sub_type = (unsigned char) unmarshallByte(th);
+ item.plus = unmarshallShort(th);
+ item.plus2 = unmarshallShort(th);
+ item.special = unmarshallLong(th);
+ item.quantity = unmarshallShort(th);
+ item.colour = (unsigned char) unmarshallByte(th);
+ item.x = unmarshallShort(th);
+ item.y = unmarshallShort(th);
+ item.flags = (unsigned long) unmarshallLong(th);
+
+ // [dshaligram] FIXME, remove this kludge when ARM_CAP is fully
+ // integrated.
+ if (item.base_type == OBJ_ARMOUR && item.sub_type == ARM_CAP)
+ item.sub_type = ARM_HELMET;
+
+ unmarshallShort(th); // mitm[].link -- unused
+ unmarshallShort(th); // igrd[item.x][item.y] -- unused
+
+ item.slot = unmarshallByte(th);
+ item.inscription.clear();
+
+ item.orig_place = unmarshallShort(th);
+ item.orig_monnum = unmarshallShort(th);
+
+ char insstring[80];
+ unmarshallString(th, insstring, 80);
+ item.inscription = std::string(insstring);
+}
+
static void tag_construct_level_items(struct tagHeader &th)
{
int i;
@@ -1278,37 +1406,53 @@ static void tag_construct_level_items(struct tagHeader &th)
// how many items?
marshallShort(th, MAX_ITEMS);
for (i = 0; i < MAX_ITEMS; ++i)
+ marshall_item(th, mitm[i]);
+}
+
+static void marshall_monster(tagHeader &th, const monsters &m)
+{
+ marshallByte(th, m.ac);
+ marshallByte(th, m.ev);
+ marshallByte(th, m.hit_dice);
+ marshallByte(th, m.speed);
+ marshallByte(th, m.speed_increment);
+ marshallByte(th, m.behaviour);
+ marshallByte(th, m.x);
+ marshallByte(th, m.y);
+ marshallByte(th, m.target_x);
+ marshallByte(th, m.target_y);
+ marshallLong(th, m.flags);
+
+ for (int j = 0; j < NUM_MON_ENCHANTS; j++)
+ marshallByte(th, m.enchantment[j]);
+
+ marshallShort(th, m.type);
+ marshallShort(th, m.hit_points);
+ marshallShort(th, m.max_hit_points);
+ marshallShort(th, m.number);
+ marshallShort(th, m.colour);
+
+ for (int j = 0; j < NUM_MONSTER_SLOTS; j++)
+ marshallShort(th, m.inv[j]);
+
+ for (int j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j)
+ marshallShort(th, m.spells[j]);
+
+ marshallByte(th, m.god);
+
+ if (m.type == MONS_PLAYER_GHOST || m.type == MONS_PANDEMONIUM_DEMON)
{
- marshallByte(th, mitm[i].base_type);
- marshallByte(th, mitm[i].sub_type);
- marshallShort(th, mitm[i].plus);
- marshallShort(th, mitm[i].plus2);
- marshallLong(th, mitm[i].special);
- marshallShort(th, mitm[i].quantity);
-
- marshallByte(th, mitm[i].colour);
- marshallShort(th, mitm[i].x);
- marshallShort(th, mitm[i].y);
- marshallLong(th, mitm[i].flags);
-
- marshallShort(th, mitm[i].link); // unused
- marshallShort(th, igrd[mitm[i].x][mitm[i].y]); // unused
-
- marshallByte(th, mitm[i].slot);
-
- marshallShort(th, mitm[i].orig_place);
- marshallShort(th, mitm[i].orig_monnum);
- marshallString(th, mitm[i].inscription.c_str(), 80);
+ // *Must* have ghost field set.
+ ASSERT(m.ghost.get());
+ marshallGhost(th, *m.ghost);
}
}
static void tag_construct_level_monsters(struct tagHeader &th)
{
- int i,j;
-
// how many mons_alloc?
marshallByte(th, 20);
- for (i = 0; i < 20; ++i)
+ for (int i = 0; i < 20; ++i)
marshallShort(th, env.mons_alloc[i]);
// how many monsters?
@@ -1318,46 +1462,8 @@ static void tag_construct_level_monsters(struct tagHeader &th)
// how many monster inventory slots?
marshallByte(th, NUM_MONSTER_SLOTS);
- for (i = 0; i < MAX_MONSTERS; i++)
- {
- const monsters &m = menv[i];
-
- marshallByte(th, m.ac);
- marshallByte(th, m.ev);
- marshallByte(th, m.hit_dice);
- marshallByte(th, m.speed);
- marshallByte(th, m.speed_increment);
- marshallByte(th, m.behaviour);
- marshallByte(th, m.x);
- marshallByte(th, m.y);
- marshallByte(th, m.target_x);
- marshallByte(th, m.target_y);
- marshallLong(th, m.flags);
-
- for (j = 0; j < NUM_MON_ENCHANTS; j++)
- marshallByte(th, m.enchantment[j]);
-
- marshallShort(th, m.type);
- marshallShort(th, m.hit_points);
- marshallShort(th, m.max_hit_points);
- marshallShort(th, m.number);
- marshallShort(th, m.colour);
-
- for (j = 0; j < NUM_MONSTER_SLOTS; j++)
- marshallShort(th, m.inv[j]);
-
- for (j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j)
- marshallShort(th, m.spells[j]);
-
- marshallByte(th, m.god);
-
- if (m.type == MONS_PLAYER_GHOST || m.type == MONS_PANDEMONIUM_DEMON)
- {
- // *Must* have ghost field set.
- ASSERT(m.ghost.get());
- marshallGhost(th, *m.ghost);
- }
- }
+ for (int i = 0; i < MAX_MONSTERS; i++)
+ marshall_monster(th, menv[i]);
}
void tag_construct_level_attitude(struct tagHeader &th)
@@ -1450,41 +1556,49 @@ static void tag_read_level_items(struct tagHeader &th, char minorVersion)
// how many items?
count = unmarshallShort(th);
for (i = 0; i < count; ++i)
- {
- mitm[i].base_type = (unsigned char) unmarshallByte(th);
- mitm[i].sub_type = (unsigned char) unmarshallByte(th);
- mitm[i].plus = unmarshallShort(th);
- mitm[i].plus2 = unmarshallShort(th);
- mitm[i].special = unmarshallLong(th);
- mitm[i].quantity = unmarshallShort(th);
- mitm[i].colour = (unsigned char) unmarshallByte(th);
- mitm[i].x = unmarshallShort(th);
- mitm[i].y = unmarshallShort(th);
- mitm[i].flags = (unsigned long) unmarshallLong(th);
-
- // [dshaligram] FIXME, remove this kludge when ARM_CAP is fully
- // integrated.
- if (mitm[i].base_type == OBJ_ARMOUR && mitm[i].sub_type == ARM_CAP)
- mitm[i].sub_type = ARM_HELMET;
-
- unmarshallShort(th); // mitm[].link -- unused
- unmarshallShort(th); // igrd[mitm[i].x][mitm[i].y] -- unused
-
- mitm[i].slot = unmarshallByte(th);
- mitm[i].inscription.clear();
+ unmarshall_item(th, mitm[i]);
+}
- mitm[i].orig_place = unmarshallShort(th);
- mitm[i].orig_monnum = unmarshallShort(th);
-
- char insstring[80];
- unmarshallString(th, insstring, 80);
- mitm[i].inscription = std::string(insstring);
- }
+static void unmarshall_monster(tagHeader &th, monsters &m)
+{
+ m.ac = unmarshallByte(th);
+ m.ev = unmarshallByte(th);
+ m.hit_dice = unmarshallByte(th);
+ m.speed = unmarshallByte(th);
+ // Avoid sign extension when loading files (Elethiomel's hang)
+ m.speed_increment = (unsigned char) unmarshallByte(th);
+ m.behaviour = unmarshallByte(th);
+ m.x = unmarshallByte(th);
+ m.y = unmarshallByte(th);
+ m.target_x = unmarshallByte(th);
+ m.target_y = unmarshallByte(th);
+ m.flags = unmarshallLong(th);
+
+ for (int j = 0; j < NUM_MON_ENCHANTS; j++)
+ m.enchantment[j] = unmarshallByte(th);
+
+ m.type = unmarshallShort(th);
+ m.hit_points = unmarshallShort(th);
+ m.max_hit_points = unmarshallShort(th);
+ m.number = unmarshallShort(th);
+
+ m.colour = unmarshallShort(th);
+
+ for (int j = 0; j < NUM_MONSTER_SLOTS; j++)
+ m.inv[j] = unmarshallShort(th);
+
+ for (int j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j)
+ m.spells[j] = unmarshallShort(th);
+
+ m.god = (god_type) unmarshallByte(th);
+
+ if (m.type == MONS_PLAYER_GHOST || m.type == MONS_PANDEMONIUM_DEMON)
+ m.set_ghost( unmarshallGhost(th) );
}
static void tag_read_level_monsters(struct tagHeader &th, char minorVersion)
{
- int i,j;
+ int i;
int count, ecount, icount;
// how many mons_alloc?
@@ -1502,41 +1616,7 @@ static void tag_read_level_monsters(struct tagHeader &th, char minorVersion)
for (i = 0; i < count; i++)
{
monsters &m = menv[i];
-
- m.ac = unmarshallByte(th);
- m.ev = unmarshallByte(th);
- m.hit_dice = unmarshallByte(th);
- m.speed = unmarshallByte(th);
- // Avoid sign extension when loading files (Elethiomel's hang)
- m.speed_increment = (unsigned char) unmarshallByte(th);
- m.behaviour = unmarshallByte(th);
- m.x = unmarshallByte(th);
- m.y = unmarshallByte(th);
- m.target_x = unmarshallByte(th);
- m.target_y = unmarshallByte(th);
- m.flags = unmarshallLong(th);
-
- for (j = 0; j < ecount; j++)
- m.enchantment[j] = unmarshallByte(th);
-
- m.type = unmarshallShort(th);
- m.hit_points = unmarshallShort(th);
- m.max_hit_points = unmarshallShort(th);
- m.number = unmarshallShort(th);
-
- m.colour = unmarshallShort(th);
-
- for (j = 0; j < icount; j++)
- m.inv[j] = unmarshallShort(th);
-
- for (j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j)
- m.spells[j] = unmarshallShort(th);
-
- m.god = (god_type) unmarshallByte(th);
-
- if (m.type == MONS_PLAYER_GHOST || m.type == MONS_PANDEMONIUM_DEMON)
- m.set_ghost( unmarshallGhost(th) );
-
+ unmarshall_monster(th, m);
// place monster
if (m.type != -1)
mgrd[m.x][m.y] = i;
diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h
index c8bca8e0c6..1490f9df56 100644
--- a/crawl-ref/source/travel.h
+++ b/crawl-ref/source/travel.h
@@ -169,14 +169,15 @@ public:
bool operator == ( const level_id &id ) const
{
- return branch == id.branch && depth == id.depth
- && level_type == id.level_type;
+ return (level_type == LEVEL_DUNGEON?
+ branch == id.branch && depth == id.depth
+ && level_type == id.level_type
+ : level_type == id.level_type);
}
bool operator != ( const level_id &id ) const
{
- return branch != id.branch || depth != id.depth
- || level_type != id.level_type;
+ return !operator == (id);
}
bool operator <( const level_id &id ) const