summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/debug.cc2
-rw-r--r--crawl-ref/source/decks.cc20
-rw-r--r--crawl-ref/source/externs.h11
-rw-r--r--crawl-ref/source/mon-util.cc200
-rw-r--r--crawl-ref/source/mon-util.h1
-rw-r--r--crawl-ref/source/monplace.cc7
-rw-r--r--crawl-ref/source/monstuff.cc46
-rw-r--r--crawl-ref/source/monstuff.h24
-rw-r--r--crawl-ref/source/religion.cc58
-rw-r--r--crawl-ref/source/religion.h2
-rw-r--r--crawl-ref/source/stuff.h5
-rw-r--r--crawl-ref/source/tags.cc13
-rw-r--r--crawl-ref/source/tags.h4
-rw-r--r--crawl-ref/source/xom.cc16
14 files changed, 189 insertions, 220 deletions
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc
index cbc1d14429..0aa7ca040b 100644
--- a/crawl-ref/source/debug.cc
+++ b/crawl-ref/source/debug.cc
@@ -3563,7 +3563,7 @@ void debug_apply_monster_blessing(monsters* mon)
else
god = GOD_SHINING_ONE;
- if (!bless_follower(monster_index(mon), god, _force_suitable, true))
+ if (!bless_follower(mon, god, _force_suitable, true))
mprf("%s won't bless this monster for you!", god_name(god).c_str());
}
#endif
diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc
index c64eca497e..14c67f1a8e 100644
--- a/crawl-ref/source/decks.cc
+++ b/crawl-ref/source/decks.cc
@@ -1346,24 +1346,24 @@ static void _swap_monster_card(int power, deck_rarity_type rarity)
// Swap between you and another monster.
// Don't choose yourself unless there are no other monsters
// nearby.
- const int mon_to_swap = choose_random_nearby_monster(0);
- if ( mon_to_swap == NON_MONSTER )
+ monsters *mon_to_swap = choose_random_nearby_monster(0);
+ if ( !mon_to_swap )
{
mpr("You spin around.");
}
else
{
- monsters& mon = menv[mon_to_swap];
- const coord_def newpos = menv[mon_to_swap].pos();
+ monsters& mon(*mon_to_swap);
+ const coord_def newpos = mon.pos();
// pick the monster up
- mgrd[mon.x][mon.y] = NON_MONSTER;
+ mgrd(newpos) = NON_MONSTER;
mon.x = you.x_pos;
mon.y = you.y_pos;
// plunk it down
- mgrd[mon.x][mon.y] = mon_to_swap;
+ mgrd(mon.pos()) = monster_index(mon_to_swap);
// move you to its previous location
you.moveto(newpos);
@@ -1403,19 +1403,19 @@ static void _damnation_card(int power, deck_rarity_type rarity)
for ( int i = 0; i < 1 + extra_targets; ++i )
{
// pick a random monster nearby to banish (or yourself)
- const int mon_to_banish = choose_random_nearby_monster(1);
+ monsters *mon_to_banish = choose_random_nearby_monster(1);
// bonus banishments only banish monsters
- if ( i != 0 && mon_to_banish == NON_MONSTER )
+ if ( i != 0 && !mon_to_banish )
continue;
- if ( mon_to_banish == NON_MONSTER ) // banish yourself!
+ if ( !mon_to_banish ) // banish yourself!
{
banished(DNGN_ENTER_ABYSS, "drawing a card");
break; // don't banish anything else
}
else
- menv[mon_to_banish].banish();
+ mon_to_banish->banish();
}
}
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 852c35d2e5..71af54fc6c 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -1010,8 +1010,11 @@ public:
~monsters();
monsters &operator = (const monsters &other);
+ void reset();
public:
+ std::string mname;
+
int type;
int hit_points;
int max_hit_points;
@@ -1050,10 +1053,14 @@ public:
// AI_SEE_MONSTER
public:
+ // Returns true if the monster is named with a proper name, or is
+ // a player ghost.
+ bool is_named() const;
+ const monsterentry *find_monsterentry() const;
+
void init_experience();
void mark_summoned(int longevity, bool mark_items_summoned );
-
bool has_action_energy() const;
void check_redraw(const coord_def &oldpos) const;
void apply_location_effects();
@@ -1098,7 +1105,6 @@ public:
void ghost_init();
void pandemon_init();
void destroy_inventory();
- void reset();
void load_spells(mon_spellbook_type spellbook);
actor *get_foe() const;
@@ -1262,7 +1268,6 @@ private:
coord_def &chosen,
int &nvalid) const;
bool has_spell_of_type(unsigned) const;
- const monsterentry *find_monsterentry() const;
};
struct cloud_struct
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 3f52027037..3982b29782 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -472,8 +472,7 @@ bool invalid_monster_class(int mclass)
bool invalid_monster_index(int i)
{
- return (i < 0
- || i >= MAX_MONSTERS);
+ return (i < 0 || i >= MAX_MONSTERS);
}
bool mons_is_statue(int mc)
@@ -1373,6 +1372,7 @@ void define_monster(monsters &mons)
int col = mons_class_colour(mons.type);
mon_spellbook_type spells = MST_NO_SPELLS;
+ mons.mname.clear();
hd = m->hpdice[0];
// misc
@@ -1629,6 +1629,11 @@ static std::string _str_monam(const monsters& mon, description_level_type desc,
if (mon.type == MONS_PANDEMONIUM_DEMON)
return mon.ghost->name;
+ // If the monster has an explicit name, return that, handling it like
+ // a unique's name.
+ if (!mon.mname.empty())
+ return mon.mname;
+
std::string result;
// Start building the name string.
@@ -1750,20 +1755,34 @@ std::string mons_type_name(int type, description_level_type desc )
return result;
}
+// XXX: unique as in "proper name", not unique as in "name not used elsewhere"?
+static std::string _get_unique_monster_name(const monsters *mon)
+{
+ const monsterentry *me = mon->find_monsterentry();
+ if (!me)
+ return ("");
+
+ std::string name = getRandNameString(me->name, " name");
+ if (!name.empty())
+ return name;
+
+ name = getRandNameString(get_monster_data(mons_genus(mon->type))->name,
+ " name");
+
+ if (!name.empty())
+ return name;
+
+ name = getRandNameString("generic_monster_name");
+ return name;
+}
+
// Fills the number parameter (if not otherwise needed) with a seed for
// random name choice from randname.txt.
bool give_unique_monster_name(monsters *mon, bool orcs_only)
{
// already has a unique name
- if (mon->number > 0 && mon->number != MONS_PROGRAM_BUG)
- return false;
-
- // already have a name
- if (mons_is_unique(mon->type) || mon->type == MONS_PLAYER_GHOST
- || mon->type == MONS_PANDEMONIUM_DEMON)
- {
- return false;
- }
+ if (mon->is_named())
+ return (false);
// Since this is called from the various divine blessing routines,
// don't bless non-orcs, and normally don't bless plain orcs, either.
@@ -1775,79 +1794,11 @@ bool give_unique_monster_name(monsters *mon, bool orcs_only)
return false;
}
}
- else
- {
- // need their number parameter for other information
- if (mon->type == MONS_HYDRA // #heads
- || mon->type == MONS_ABOMINATION_SMALL // colour
- || mon->type == MONS_ABOMINATION_LARGE // colour
- || mon->type == MONS_MANTICORE // #spikes
- || mons_genus(mon->type) == MONS_DRACONIAN // subspecies
- || mons_class_is_zombified(mon->type)) // zombie type
- {
- return false;
- }
- }
-
- // randomly pick a number
- // XXX: Why does unsigned int (number's type) get munged on save & reload?
- mon->number = (unsigned char) random_int();
-// mprf(MSGCH_DIAGNOSTICS, "new monster number is %d", mon->number);
-
- return (mon->number != 0 && mon->number != MONS_PROGRAM_BUG);
-}
-
-std::string get_unique_monster_name(const monsters *mon)
-{
- if (mon->type == MONS_PLAYER_GHOST)
- return mon->ghost->name + "'s ghost";
-
- if (mon->type == MONS_PANDEMONIUM_DEMON)
- return mon->ghost->name;
-
- if (mons_is_unique(mon->type))
- return get_monster_data(mon->type)->name;
-
- // Since the seed for the monster name is stored in mon->number
- // any monster that uses number for something else cannot be named.
- if (mon->type == MONS_HYDRA // #heads
- || mon->type == MONS_ABOMINATION_SMALL // colour
- || mon->type == MONS_ABOMINATION_LARGE // colour
- || mon->type == MONS_MANTICORE // #spikes
- || mons_genus(mon->type) == MONS_DRACONIAN // subspecies
- || mons_class_is_zombified(mon->type)) // zombie type
- {
- return "";
- }
-
- // unnamed, sorry
- if (mon->number <= 0 || mon->number == MONS_PROGRAM_BUG)
- return "";
-
-// mprf(MSGCH_DIAGNOSTICS, "get name from number %d", mon->number);
-
- rng_save_excursion rng_state;
- seed_rng( mon->number );
-
- std::string name
- = getRandNameString(get_monster_data(mon->type)->name, " name");
-
- if (!name.empty())
- return name;
-
- name = getRandNameString(get_monster_data(mons_genus(mon->type))->name,
- " name");
-
- if (!name.empty())
- return name;
- name = getRandNameString("generic_monster_name");
-
- return name;
+ mon->mname = _get_unique_monster_name(mon);
+ return (mon->is_named());
}
-/* ********************* END PUBLIC FUNCTIONS ********************* */
-
// see mons_init for initialization of mon_entry array.
monsterentry *get_monster_data(int p_monsterid)
{
@@ -2612,8 +2563,39 @@ monsters &monsters::operator = (const monsters &mon)
return (*this);
}
+void monsters::reset()
+{
+ destroy_inventory();
+
+ mname.clear();
+ enchantments.clear();
+ ench_countdown = 0;
+ inv.init(NON_ITEM);
+
+ flags = 0;
+ experience = 0L;
+ type = -1;
+ hit_points = 0;
+ max_hit_points = 0;
+ hit_dice = 0;
+ ac = 0;
+ ev = 0;
+ speed_increment = 0;
+ attitude = ATT_HOSTILE;
+ behaviour = BEH_SLEEP;
+ foe = MHITNOT;
+ number = 0;
+
+ if (in_bounds(x, y))
+ mgrd[x][y] = NON_MONSTER;
+
+ x = y = 0;
+ ghost.reset(NULL);
+}
+
void monsters::init_with(const monsters &mon)
{
+ mname = mon.mname;
type = mon.type;
hit_points = mon.hit_points;
max_hit_points = mon.max_hit_points;
@@ -3914,14 +3896,13 @@ item_def *monsters::shield()
return (mslot_item(MSLOT_SHIELD));
}
-std::string monsters::name(description_level_type desc) const
+bool monsters::is_named() const
{
- std::string monnam = "";
- if (player_monster_visible(this))
- monnam = get_unique_monster_name(this);
- if (!monnam.empty())
- return monnam;
+ return (!mname.empty() || mons_is_unique(type));
+}
+std::string monsters::name(description_level_type desc) const
+{
return this->name(desc, false);
}
@@ -3933,8 +3914,8 @@ std::string monsters::name(description_level_type desc, bool force_vis) const
if (possessive)
desc = DESC_NOCAP_THE;
- std::string mname = _str_monam(*this, desc, force_vis);
- return (possessive? apostrophise(mname) : mname);
+ std::string monnam = _str_monam(*this, desc, force_vis);
+ return (possessive? apostrophise(monnam) : monnam);
}
std::string monsters::pronoun(pronoun_type pro) const
@@ -4305,6 +4286,7 @@ void monsters::set_ghost(const ghost_demon &g)
TileGhostInit(g);
#endif
ghost.reset( new ghost_demon(g) );
+ mname = ghost->name;
}
void monsters::pandemon_init()
@@ -4446,35 +4428,6 @@ void monsters::destroy_inventory()
}
}
-void monsters::reset()
-{
- destroy_inventory();
-
- enchantments.clear();
- ench_countdown = 0;
- inv.init(NON_ITEM);
-
- flags = 0;
- experience = 0L;
- type = -1;
- hit_points = 0;
- max_hit_points = 0;
- hit_dice = 0;
- ac = 0;
- ev = 0;
- speed_increment = 0;
- attitude = ATT_HOSTILE;
- behaviour = BEH_SLEEP;
- foe = MHITNOT;
- number = 0;
-
- if (in_bounds(x, y))
- mgrd[x][y] = NON_MONSTER;
-
- x = y = 0;
- ghost.reset(NULL);
-}
-
bool monsters::needs_transit() const
{
return ((mons_is_unique(type)
@@ -5809,17 +5762,17 @@ void monsters::react_to_damage(int damage)
if (needs_message)
{
- const std::string mname = name(DESC_CAP_THE);
- mprf("%s shudders%s.", mname.c_str(),
+ const std::string monnam = name(DESC_CAP_THE);
+ mprf("%s shudders%s.", monnam.c_str(),
spawned >= 5 ? " alarmingly" :
spawned >= 3 ? " violently" :
spawned > 1 ? " vigorously" : "");
if (spawned == 1)
- mprf("%s spits out another jelly.", mname.c_str());
+ mprf("%s spits out another jelly.", monnam.c_str());
else
{
mprf("%s spits out %s more jellies.",
- mname.c_str(),
+ monnam.c_str(),
number_in_words(spawned).c_str());
}
}
@@ -6080,7 +6033,8 @@ std::string do_mon_str_replacements(const std::string &in_msg,
std::string msg = in_msg;
description_level_type nocap = DESC_NOCAP_THE, cap = DESC_CAP_THE;
- std::string name = get_unique_monster_name(monster);
+ 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);
diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h
index 34089fd724..fc1715ba8b 100644
--- a/crawl-ref/source/mon-util.h
+++ b/crawl-ref/source/mon-util.h
@@ -387,7 +387,6 @@ monsters *monster_at(const coord_def &pos);
std::string mons_type_name(int type, description_level_type desc);
bool give_unique_monster_name(monsters *mon, bool orcs_only = true);
-std::string get_unique_monster_name(const monsters *mon);
// last updated 12may2000 {dlb}
/* ***********************************************************************
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index 9f98a18fef..c74d4cdb2a 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -716,11 +716,8 @@ static int place_monster_aux( int mon_type, beh_type behaviour, int target,
if (id == MAX_MONSTERS)
return -1;
- menv[id].inv.init(NON_ITEM);
- // scrap monster enchantments
- menv[id].enchantments.clear();
- menv[id].ench_countdown = 0;
-
+ menv[id].reset();
+
// setup habitat and placement
// If the space is occupied, try some neighbouring square instead.
if (first_band_member && mgrd[px][py] == NON_MONSTER
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index a75a471916..7d73b0cdc4 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -418,7 +418,7 @@ static void _give_monster_experience( monsters *victim,
|| you.religion == GOD_BEOGH
&& random2(you.piety) >= piety_breakpoint(2))
{
- bless_follower(killer_index);
+ bless_follower(mon);
}
}
}
@@ -1121,8 +1121,11 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent)
monsters *mon = &menv[i];
// Randomly bless the follower who killed.
- if (!one_chance_in(3) && bless_follower(i))
+ if (!one_chance_in(3) && mon->alive()
+ && bless_follower(mon))
+ {
break;
+ }
if (mon->alive() && mon->hit_points < mon->max_hit_points)
{
@@ -1140,7 +1143,7 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent)
&& !one_chance_in(3)
&& !invalid_monster_index(i))
{
- bless_follower(i);
+ bless_follower(&menv[i]);
}
}
@@ -2604,22 +2607,21 @@ bool choose_any_monster(const monsters* mon)
// for the type of monster wanted.
// If prefer_named is true, named monsters (including uniques) are twice as
// likely to get chosen compared with non-named ones.
-int choose_random_nearby_monster(int weight,
- bool (*suitable)(const monsters* mon),
- bool in_sight, bool prefer_named)
+monsters *choose_random_nearby_monster(int weight,
+ bool (*suitable)(const monsters* mon),
+ bool in_sight, bool prefer_named)
{
return choose_random_monster_on_level(weight, suitable, in_sight, true,
prefer_named);
}
-int choose_random_monster_on_level(int weight,
- bool (*suitable)(const monsters* mon),
- bool in_sight, bool near_by,
- bool prefer_named)
+monsters *choose_random_monster_on_level(int weight,
+ bool (*suitable)(const monsters* mon),
+ bool in_sight, bool near_by,
+ bool prefer_named)
{
+ monsters *chosen = NULL;
int mons_count = weight;
- int result = NON_MONSTER;
- int mon;
int xstart = 0, ystart = 0;
int xend = GXM, yend = GYM;
@@ -2642,23 +2644,27 @@ int choose_random_monster_on_level(int weight,
for ( int x = xstart; x < xend; ++x )
if ( mgrd[x][y] != NON_MONSTER && (!in_sight || see_grid(x,y)) )
{
- mon = mgrd[x][y];
- if (suitable(&menv[mon]))
+ monsters *mon = &menv[mgrd[x][y]];
+ if (suitable(mon))
{
- if (prefer_named
- && !(get_unique_monster_name(&menv[mon]).empty()))
+ // FIXME: if the intent is to favour monsters
+ // named by $DEITY, we should set a flag on the
+ // monster (something like MF_DEITY_PREFERRED) and
+ // use that instead of checking the name, given
+ // that other monsters can also have names.
+ if (prefer_named && mon->is_named())
{
mons_count += 2;
// named monsters have doubled chances
if (random2(mons_count) < 2)
- result = mon;
+ chosen = mon;
}
else if (one_chance_in(++mons_count))
- result = mon;
+ chosen = mon;
}
}
-
- return result;
+
+ return chosen;
}
// note that this function *completely* blocks messaging for monsters
diff --git a/crawl-ref/source/monstuff.h b/crawl-ref/source/monstuff.h
index 96f16883d1..5fc1a8a25a 100644
--- a/crawl-ref/source/monstuff.h
+++ b/crawl-ref/source/monstuff.h
@@ -123,17 +123,19 @@ bool simple_monster_message(const monsters *monster, const char *event,
description_level_type descrip = DESC_CAP_THE);
bool choose_any_monster(const monsters* mon);
-int choose_random_nearby_monster(int weight,
- bool (*suitable)(const monsters* mon) =
- choose_any_monster,
- bool in_sight = true,
- bool prefer_named = false);
-
-int choose_random_monster_on_level(int weight,
- bool (*suitable)(const monsters* mon) =
- choose_any_monster,
- bool in_sight = true, bool near_by = false,
- bool prefer_named = false);
+monsters *choose_random_nearby_monster(
+ int weight,
+ bool (*suitable)(const monsters* mon) =
+ choose_any_monster,
+ bool in_sight = true,
+ bool prefer_named = false);
+
+monsters *choose_random_monster_on_level(
+ int weight,
+ bool (*suitable)(const monsters* mon) =
+ choose_any_monster,
+ bool in_sight = true, bool near_by = false,
+ bool prefer_named = false);
/* ***********************************************************************
* called from: acr
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index 3f372efab0..3cfa93071e 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -1092,18 +1092,17 @@ static bool _beogh_blessing_priesthood(monsters* mon)
// one, bless a random follower within sight of the player, if any, or,
// with decreasing chances, any follower on the level.
// Blessing can be enforced with a wizard mode command.
-bool bless_follower(int follower,
+bool bless_follower(monsters *follower,
god_type god,
bool (*suitable)(const monsters* mon),
bool force)
{
int chance = (force ? coinflip() : random2(20));
- monsters *mon = NULL;
std::string result;
// If a follower was specified, and it's suitable, pick it.
// Otherwise, pick a random follower within sight of the player.
- if (follower == -1 || (!force && !suitable(&menv[follower])))
+ if (!follower || (!force && !suitable(follower)))
{
if (god != GOD_BEOGH)
return false;
@@ -1114,7 +1113,7 @@ bool bless_follower(int follower,
// Choose a random follower in LOS, preferably a named one (10% chance).
follower = choose_random_nearby_monster(0, suitable, true, true);
- if (follower == NON_MONSTER)
+ if (!follower)
{
if (coinflip())
return false;
@@ -1122,7 +1121,7 @@ bool bless_follower(int follower,
// Try again, without the LOS restriction (5% chance).
follower = choose_random_nearby_monster(0, suitable, false, true);
- if (follower == NON_MONSTER)
+ if (!follower)
{
if (coinflip())
return false;
@@ -1131,7 +1130,7 @@ bool bless_follower(int follower,
follower = choose_random_monster_on_level(0, suitable,
false, false, true);
- if (follower == NON_MONSTER)
+ if (!follower)
{
// If no follower was found, attempt to send
// reinforcement.
@@ -1153,10 +1152,7 @@ bool bless_follower(int follower,
}
}
}
- ASSERT(follower != -1 && follower != NON_MONSTER);
-
- // Else, apply blessing to chosen follower.
- mon = &menv[follower];
+ ASSERT(follower);
if (chance == 0) // 5% chance of holy branding, or priesthood
{
@@ -1167,7 +1163,7 @@ bool bless_follower(int follower,
{
// Brand a monster's weapon with holy wrath, if
// possible.
- if (_tso_blessing_holy_wpn(mon))
+ if (_tso_blessing_holy_wpn(follower))
{
result = "holy attack power";
goto blessing_done;
@@ -1179,7 +1175,7 @@ bool bless_follower(int follower,
{
// Brand a monster's armour with positive energy, if
// possible.
- if (_tso_blessing_holy_arm(mon))
+ if (_tso_blessing_holy_arm(follower))
{
result = "life defence";
goto blessing_done;
@@ -1191,7 +1187,7 @@ bool bless_follower(int follower,
case GOD_BEOGH:
// Turn a monster into a priestly monster, if possible.
- if (_beogh_blessing_priesthood(mon))
+ if (_beogh_blessing_priesthood(follower))
{
result = "priesthood";
goto blessing_done;
@@ -1214,18 +1210,18 @@ bool bless_follower(int follower,
if (coinflip())
{
- affected = _blessing_wpn(mon);
+ affected = _blessing_wpn(follower);
if (!affected || coinflip())
{
- if (_blessing_wpn(mon))
+ if (_blessing_wpn(follower))
affected = true;
}
if (affected)
{
result = "extra attack power";
- give_unique_monster_name(mon);
+ give_unique_monster_name(follower);
goto blessing_done;
}
else if (force)
@@ -1233,18 +1229,18 @@ bool bless_follower(int follower,
}
else
{
- affected = _blessing_AC(mon);
+ affected = _blessing_AC(follower);
if (!affected || coinflip())
{
- if (_blessing_AC(mon))
+ if (_blessing_AC(follower))
affected = true;
}
if (affected)
{
result = "extra defence";
- give_unique_monster_name(mon);
+ give_unique_monster_name(follower);
goto blessing_done;
}
else if (force)
@@ -1261,11 +1257,11 @@ bool bless_follower(int follower,
// Extend a monster's stay if it's abjurable, optionally
// making it friendly if it's charmed. If neither is
// possible, deliberately fall through.
- bool more_time = _tso_blessing_extend_stay(mon);
+ bool more_time = _tso_blessing_extend_stay(follower);
bool friendliness = false;
if (!more_time || coinflip())
- friendliness = _tso_blessing_friendliness(mon);
+ friendliness = _tso_blessing_friendliness(follower);
if (more_time && friendliness)
result = "friendliness and more time in this world";
@@ -1288,7 +1284,7 @@ bool bless_follower(int follower,
// possible.
if (coinflip())
{
- if (_blessing_balms(mon))
+ if (_blessing_balms(follower))
{
result = "divine balms";
goto blessing_done;
@@ -1297,12 +1293,12 @@ bool bless_follower(int follower,
mpr("Couldn't apply balms.");
}
- bool healing = _blessing_healing(mon, false);
+ bool healing = _blessing_healing(follower, false);
bool vigour = false;
// Maybe give an extra hit point.
if (!healing || coinflip())
- vigour = _blessing_healing(mon, true);
+ vigour = _blessing_healing(follower, true);
if (healing && vigour)
result = "healing and extra vigour";
@@ -1329,18 +1325,19 @@ blessing_done:
bool see_follower = false;
std::string whom = "";
- if (follower == NON_MONSTER)
+ if (!follower)
whom = "you";
else
{
- if (mons_near(mon) && player_monster_visible(mon))
+ if (mons_near(follower) && player_monster_visible(follower))
see_follower = true;
if (see_follower)
{
- whom = get_unique_monster_name(mon);
- if (whom.empty())
- whom = "your " + mon->name(DESC_PLAIN);
+ if (follower->is_named())
+ whom = follower->name(DESC_PLAIN);
+ else
+ whom = "your " + follower->name(DESC_PLAIN);
}
else // cannot see who was blessed
whom = "a follower";
@@ -1355,7 +1352,7 @@ blessing_done:
if (see_follower)
{
unsigned char old_flash_colour = you.flash_colour;
- coord_def c(mon->x, mon->y);
+ coord_def c(follower->pos());
you.flash_colour = god_colour(god);
view_update_at(c);
@@ -1365,6 +1362,7 @@ blessing_done:
you.flash_colour = old_flash_colour;
view_update_at(c);
+ update_screen();
}
#endif
diff --git a/crawl-ref/source/religion.h b/crawl-ref/source/religion.h
index 7e972edeef..e870841980 100644
--- a/crawl-ref/source/religion.h
+++ b/crawl-ref/source/religion.h
@@ -78,7 +78,7 @@ bool tso_stab_safe_monster(const actor *act);
bool is_good_follower(const monsters* mon);
bool is_orcish_follower(const monsters* mon);
bool is_follower(const monsters* mon);
-bool bless_follower(int follower = -1,
+bool bless_follower(monsters *follower = NULL,
god_type god = you.religion,
bool (*suitable)(const monsters* mon) = is_follower,
bool force = false);
diff --git a/crawl-ref/source/stuff.h b/crawl-ref/source/stuff.h
index d7b59c6cb4..8d07f41206 100644
--- a/crawl-ref/source/stuff.h
+++ b/crawl-ref/source/stuff.h
@@ -162,8 +162,9 @@ void zap_los_monsters();
class rng_save_excursion
{
public:
- rng_save_excursion() { push_rng_state(); }
- ~rng_save_excursion() { pop_rng_state(); }
+ rng_save_excursion(long seed) { push_rng_state(); seed_rng(seed); }
+ rng_save_excursion() { push_rng_state(); }
+ ~rng_save_excursion() { pop_rng_state(); }
};
template<typename Iterator>
diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc
index 7cad040f15..92b4c994ee 100644
--- a/crawl-ref/source/tags.cc
+++ b/crawl-ref/source/tags.cc
@@ -99,6 +99,9 @@ extern std::map<level_id, std::string> level_annotations;
// temp file pairs used for file level cleanup
FixedArray < bool, MAX_LEVELS, NUM_BRANCHES > tmp_file_pairs;
+// The minor version for the tag currently being read.
+static int _tag_minor_version = -1;
+
// Reads input in network byte order, from a file or buffer.
unsigned char reader::readByte()
{
@@ -706,6 +709,7 @@ tag_type tag_read(FILE *fp, char minorVersion)
return TAG_NO_TAG;
}
+ unwind_var<int> tag_minor_version(_tag_minor_version, minorVersion);
// ok, we have data now.
reader th(buf);
switch (tag_id)
@@ -790,7 +794,7 @@ 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;
@@ -1580,7 +1584,6 @@ static void tag_read_you_dungeon(reader &th)
static void tag_read_lost_monsters(reader &th, int minorVersion)
{
the_lost_ones.clear();
-
unmarshallMap(th, the_lost_ones,
unmarshall_level_id, unmarshall_follower_list);
}
@@ -1755,6 +1758,7 @@ static mon_enchant unmarshall_mon_enchant(reader &th)
static void marshall_monster(writer &th, const monsters &m)
{
+ marshallString(th, m.mname);
marshallByte(th, m.ac);
marshallByte(th, m.ev);
marshallByte(th, m.hit_dice);
@@ -2011,6 +2015,11 @@ static void tag_read_level_items(reader &th, char minorVersion)
static void unmarshall_monster(reader &th, monsters &m)
{
+ m.reset();
+
+ if (_tag_minor_version >= TAG_MINOR_MONNAM)
+ m.mname = unmarshallString(th, 100);
+
m.ac = unmarshallByte(th);
m.ev = unmarshallByte(th);
m.hit_dice = unmarshallByte(th);
diff --git a/crawl-ref/source/tags.h b/crawl-ref/source/tags.h
index ff10c242e3..b7ff700e69 100644
--- a/crawl-ref/source/tags.h
+++ b/crawl-ref/source/tags.h
@@ -47,12 +47,14 @@ enum tag_major_version
TAG_MAJOR_VERSION = 5
};
+// Minor version will be reset to zero when major version changes.
enum tag_minor_version
{
TAG_MINOR_PIETY = 2, // Added piety_hysteresis
TAG_MINOR_QUIVER = 3, // Added quiver
TAG_MINOR_MAPMARK = 4, // Added sizes to map markers
- TAG_MINOR_VERSION = 4 // Current version
+ TAG_MINOR_MONNAM = 5, // Monsters get individual names
+ TAG_MINOR_VERSION = 5 // Current version
};
diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc
index c6dd4be7c2..617517fd7e 100644
--- a/crawl-ref/source/xom.cc
+++ b/crawl-ref/source/xom.cc
@@ -622,15 +622,13 @@ static bool xom_is_good(int sever)
if (!there_are_monsters_nearby())
goto try_again;
- int monster = choose_random_nearby_monster(0,
- choose_mutatable_monster);
+ monsters *mon =
+ choose_random_nearby_monster(0, choose_mutatable_monster);
- if (monster != NON_MONSTER)
+ if (mon)
{
god_speaks(GOD_XOM, _get_xom_speech("good monster polymorph"));
- monsters* mon = &menv[monster];
-
if (mons_wont_attack(mon))
monster_polymorph(mon, RANDOM_MONSTER, PPT_MORE);
else
@@ -807,15 +805,13 @@ static bool xom_is_bad(int sever)
if (!there_are_monsters_nearby())
goto try_again;
- int monster = choose_random_nearby_monster(0,
- choose_mutatable_monster);
+ monsters *mon =
+ choose_random_nearby_monster(0, choose_mutatable_monster);
- if (monster != NON_MONSTER)
+ if (mon)
{
god_speaks(GOD_XOM, _get_xom_speech("bad monster polymorph"));
- monsters* mon = &menv[monster];
-
if (mons_wont_attack(mon))
monster_polymorph(mon, RANDOM_MONSTER, PPT_LESS);
else