summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2009-01-12 09:32:55 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2009-01-12 09:32:55 +0000
commitaf82384c240a924e921b96d81b8dd295aa1f2a80 (patch)
tree247955562bf7669c24fce930959fe206942784ec /crawl-ref/source
parent53dd513378a230964bd09f3de2a1bcfaeabc37be (diff)
downloadcrawl-ref-af82384c240a924e921b96d81b8dd295aa1f2a80.tar.gz
crawl-ref-af82384c240a924e921b96d81b8dd295aa1f2a80.zip
Fix bug #2089989: only place friendly god gifts after the player's turn is
over, so that any in-progress effects won't hurt them, thus turning them hostile and angering the player's god. Also try to avoid placing god gifts (friendly or hostile) in a damaging cloud, and if it's unavoidable and placing a friendly god gift there would anger the god then don't place them at all. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8426 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/acr.cc7
-rw-r--r--crawl-ref/source/monplace.cc26
-rw-r--r--crawl-ref/source/monstuff.cc113
-rw-r--r--crawl-ref/source/monstuff.h9
-rw-r--r--crawl-ref/source/religion.cc293
-rw-r--r--crawl-ref/source/religion.h2
6 files changed, 355 insertions, 95 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index fb73e3728b..ca1e0e33d3 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -1197,6 +1197,10 @@ static void _do_wizard_command(int wiz_command, bool silent_fail)
formatted_mpr(formatted_string::parse_string("Not a <magenta>Wizard</magenta> Command."));
break;
}
+ // Force the placement of any delayed monster gifts.
+ you.turn_is_over = true;
+ religion_turn_end();
+
you.turn_is_over = false;
}
@@ -3108,6 +3112,9 @@ static void _check_sanctuary()
void world_reacts()
{
+ if (!crawl_state.arena)
+ religion_turn_end();
+
crawl_state.clear_god_acting();
#ifdef USE_TILE
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index 8032d753c9..4fd5585a5c 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -2427,6 +2427,32 @@ int create_monster(mgen_data mg, bool fail_msg)
|| !mons_class_can_pass(montype, grd(mg.pos)))
{
mg.pos = find_newmons_square(montype, mg.pos);
+ // Gods other than Xom will try to avoid placing their monsters
+ // directly in harm's way.
+ if (mg.god != GOD_NO_GOD && mg.god != GOD_XOM)
+ {
+ monsters dummy;
+ dummy.type = mg.cls;
+ dummy.base_monster = mg.base_type;
+ dummy.god = mg.god;
+
+ int tries = 0;
+ while (tries++ < 50
+ && mons_avoids_cloud(&dummy, env.cgrid(mg.pos), NULL, true))
+ {
+ mg.pos = find_newmons_square(montype, mg.pos);
+ }
+ const int cloud_num = env.cgrid(mg.pos);
+ // Don't place friendly god gift in a damaging cloud created by
+ // you if that would anger the god.
+ if (mons_avoids_cloud(&dummy, cloud_num, NULL, true)
+ && mg.behaviour == BEH_FRIENDLY
+ && god_hates_attacking_friend(you.religion, &dummy)
+ && YOU_KILL(env.cloud[cloud_num].killer))
+ {
+ return (-1);
+ }
+ }
}
if (in_bounds(mg.pos))
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 4f5133e899..ad2ab21330 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -4734,8 +4734,12 @@ static bool _is_player_or_mon_sanct(const monsters* monster)
|| is_sanctuary(monster->pos()));
}
-static bool _mons_avoids_cloud(const monsters *monster, cloud_type cl_type)
+bool mons_avoids_cloud(const monsters *monster, cloud_type cl_type,
+ bool placement, bool extra_careful)
{
+ if (placement)
+ extra_careful = true;
+
switch (cl_type)
{
case CLOUD_MIASMA:
@@ -4746,6 +4750,9 @@ static bool _mons_avoids_cloud(const monsters *monster, cloud_type cl_type)
if (mons_res_fire(monster) > 1)
return (false);
+ if (extra_careful)
+ return (true);
+
if (monster->hit_points >= 15 + random2avg(46, 5))
return (false);
break;
@@ -4753,6 +4760,8 @@ static bool _mons_avoids_cloud(const monsters *monster, cloud_type cl_type)
case CLOUD_STINK:
if (mons_res_poison(monster) > 0)
return (false);
+ if (extra_careful)
+ return (true);
if (x_chance_in_y(monster->hit_dice - 1, 5))
return (false);
if (monster->hit_points >= random2avg(19, 2))
@@ -4763,6 +4772,9 @@ static bool _mons_avoids_cloud(const monsters *monster, cloud_type cl_type)
if (mons_res_cold(monster) > 1)
return (false);
+ if (extra_careful)
+ return (true);
+
if (monster->hit_points >= 15 + random2avg(46, 5))
return (false);
break;
@@ -4771,11 +4783,17 @@ static bool _mons_avoids_cloud(const monsters *monster, cloud_type cl_type)
if (mons_res_poison(monster) > 0)
return (false);
+ if (extra_careful)
+ return (true);
+
if (monster->hit_points >= random2avg(37, 4))
return (false);
break;
case CLOUD_GREY_SMOKE:
+ if (placement)
+ return (false);
+
// This isn't harmful, but dumb critters might think so.
if (mons_intel(monster) > I_ANIMAL || coinflip())
return (false);
@@ -4792,13 +4810,64 @@ static bool _mons_avoids_cloud(const monsters *monster, cloud_type cl_type)
}
// Exceedingly dumb creatures will wander into harmful clouds.
- if (is_harmless_cloud(cl_type) || mons_intel(monster) == I_PLANT)
+ if (is_harmless_cloud(cl_type)
+ || mons_intel(monster) == I_PLANT && !extra_careful)
+ {
return (false);
+ }
// If we get here, the cloud is potentially harmful.
return (true);
}
+// Like the above, but prevents monsters from moving into cloud if it
+// would anger the player's god, and also allows a monster to move from
+// one damaging cloud to another, even if they're of different types.
+bool mons_avoids_cloud(const monsters *monster, int cloud_num,
+ cloud_type *cl_type, bool placement)
+{
+ if (cloud_num == EMPTY_CLOUD)
+ {
+ if (cl_type != NULL)
+ *cl_type = CLOUD_NONE;
+
+ return (false);
+ }
+
+ const cloud_struct &cloud = env.cloud[cloud_num];
+
+ if (cl_type != NULL)
+ *cl_type = cloud.type;
+
+ const bool careful_friendly
+ = YOU_KILL(cloud.killer) && mons_friendly(monster)
+ && god_hates_attacking_friend(you.religion, monster);
+
+ // Is the target cloud okay?
+ if (!mons_avoids_cloud(monster, cloud.type, placement, careful_friendly))
+ return (false);
+
+ // If we're already in a cloud that we'd want to avoid then moving
+ // from one to the other is okay.
+ if (!in_bounds(monster->pos()) || monster->pos() == cloud.pos)
+ return (true);
+
+ const int our_cloud_num = env.cgrid(monster->pos());
+
+ if (our_cloud_num == EMPTY_CLOUD)
+ return (true);
+
+ const cloud_struct &our_cloud = env.cloud[our_cloud_num];
+
+ // Don't move monster from a cloud that won't anger their god to one
+ // that will.
+ if (!YOU_KILL(our_cloud.killer) && careful_friendly)
+ return (true);
+
+ return (!mons_avoids_cloud(monster, our_cloud.type, true,
+ careful_friendly));
+}
+
//---------------------------------------------------------------
//
// handle_nearby_ability
@@ -6751,13 +6820,13 @@ static void _handle_monster_move(int i, monsters *monster)
monster->shield_blocks = 0;
- const int cloud_num = env.cgrid(monster->pos());
- const cloud_type cl_type = cloud_num == EMPTY_CLOUD ? CLOUD_NONE
- : env.cloud[cloud_num].type;
-
- if (cloud_num != EMPTY_CLOUD)
+ cloud_type cl_type;
+ const int cloud_num = env.cgrid(monster->pos());
+ const bool avoid_cloud = mons_avoids_cloud(monster, cloud_num,
+ &cl_type);
+ if (cl_type != CLOUD_NONE)
{
- if (_mons_avoids_cloud(monster, cl_type))
+ if (avoid_cloud)
{
if (mons_is_submerged(monster))
{
@@ -6801,8 +6870,7 @@ static void _handle_monster_move(int i, monsters *monster)
ASSERT(in_bounds(monster->target) || monster->target.origin());
// Submerging monsters will hide from clouds.
- if (cloud_num != EMPTY_CLOUD && _mons_avoids_cloud(monster, cl_type)
- && monster_can_submerge(monster, grd(monster->pos()))
+ if (avoid_cloud && monster_can_submerge(monster, grd(monster->pos()))
&& !monster->submerged())
{
monster->add_ench(ENCH_SUBMERGED);
@@ -6865,7 +6933,7 @@ static void _handle_monster_move(int i, monsters *monster)
// cloud on top of the water.
if (monster->hit_points <= monster->max_hit_points / 2
|| monster->has_ench(ENCH_FEAR)
- || _mons_avoids_cloud(monster, cl_type))
+ || avoid_cloud)
{
monster->speed_increment -= non_move_energy;
continue;
@@ -7778,15 +7846,11 @@ static bool _mon_can_move_to_pos(const monsters *monster,
if (monster->type == MONS_FIRE_ELEMENTAL || one_chance_in(5))
no_water = true;
- const int targ_cloud_num = env.cgrid(targ);
- const cloud_type targ_cloud_type =
- (targ_cloud_num == EMPTY_CLOUD) ? CLOUD_NONE
- : env.cloud[targ_cloud_num].type;
+ cloud_type targ_cloud_type;
+ const int targ_cloud_num = env.cgrid(targ);
- const int curr_cloud_num = env.cgrid(monster->pos());
- const cloud_type curr_cloud_type =
- (curr_cloud_num == EMPTY_CLOUD) ? CLOUD_NONE
- : env.cloud[curr_cloud_num].type;
+ if (mons_avoids_cloud(monster, targ_cloud_num, &targ_cloud_type))
+ return (false);
if (mons_class_flag(monster->type, M_BURROWS)
&& (target_grid == DNGN_ROCK_WALL
@@ -7898,17 +7962,6 @@ static bool _mon_can_move_to_pos(const monsters *monster,
if (!_is_trap_safe(monster, targ, just_check))
return (false);
- if (targ_cloud_num != EMPTY_CLOUD)
- {
- if (curr_cloud_num != EMPTY_CLOUD
- && targ_cloud_type == curr_cloud_type)
- {
- return (true);
- }
-
- return !_mons_avoids_cloud(monster, targ_cloud_type);
- }
-
// If we end up here the monster can safely move.
return (true);
}
diff --git a/crawl-ref/source/monstuff.h b/crawl-ref/source/monstuff.h
index 63bd62f371..3dea7bb035 100644
--- a/crawl-ref/source/monstuff.h
+++ b/crawl-ref/source/monstuff.h
@@ -213,4 +213,13 @@ int mons_thrown_weapon_damage(const item_def *weap);
int mons_natural_regen_rate(monsters *monster);
+bool mons_avoids_cloud(const monsters *monster, cloud_type cl_type,
+ bool placement = false,
+ bool extra_careful = false);
+
+// Like the above, but prevents monsters from moving into cloud if it
+// would anger the player's god, and also allows a monster to move from
+// one damaging cloud to another.
+bool mons_avoids_cloud(const monsters *monster, int cloud_num,
+ cloud_type *cl_type = NULL, bool placement = false);
#endif
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index 15198e1095..3221708ea3 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -382,6 +382,14 @@ static bool _make_god_gifts_hostile(bool level_only = true);
static void _print_sacrifice_message(god_type, const item_def &,
piety_gain_t, bool = false);
+typedef void (*delayed_callback)(const mgen_data &mg, int &midx, int placed);
+
+static void _delayed_monster(const mgen_data &mg,
+ delayed_callback callback = NULL);
+static void _delayed_monster_done(std::string success, std::string failure,
+ delayed_callback callback = NULL);
+static void _place_delayed_monsters();
+
/////////////////////////////////////////////////////////////////////
// god_conduct_trigger
@@ -935,22 +943,26 @@ static int _yred_random_servants(int threshold, bool force_hostile = false)
if (mon == MONS_FLYING_SKULL)
how_many = 2 + random2(4);
- int count = 0;
+ mgen_data mg(mon, !force_hostile ? BEH_FRIENDLY : BEH_HOSTILE,
+ 0, 0, you.pos(), !force_hostile ? you.pet_target : MHITYOU,
+ 0, GOD_YREDELEMNUL);
- for (int i = 0; i < how_many; ++i)
+ int created = 0;
+ if (force_hostile)
{
- if (create_monster(
- mgen_data(mon,
- !force_hostile ? BEH_FRIENDLY : BEH_HOSTILE,
- 0, 0, you.pos(),
- !force_hostile ? you.pet_target : MHITYOU,
- 0, GOD_YREDELEMNUL)) != -1)
+ for (int i = 0; i < how_many; ++i)
{
- count++;
+ if (create_monster(mg) != -1)
+ created++;
}
}
+ else
+ {
+ for (int i = 0; i < how_many; ++i)
+ _delayed_monster(mg);
+ }
- return (count);
+ return (created);
}
static bool _okawaru_random_servant()
@@ -971,16 +983,9 @@ static bool _okawaru_random_servant()
(temp_rand < 95) ? MONS_HILL_GIANT // 5%
: MONS_TITAN); // 5%
- bool success = false;
-
- if (create_monster(
- mgen_data::hostile_at(mon,
- you.pos(), 0, 0, true, GOD_OKAWARU)) != -1)
- {
- success = true;
- }
-
- return (success);
+ return (create_monster(
+ mgen_data::hostile_at(mon,
+ you.pos(), 0, 0, true, GOD_OKAWARU)) != -1);
}
static const item_def* _find_missile_launcher(int skill)
@@ -1502,12 +1507,34 @@ static bool _tso_blessing_friendliness(monsters* mon)
base_increase + random2(base_increase));
}
+static void _beogh_reinf_callback(const mgen_data &mg, int &midx, int placed)
+{
+ ASSERT(mg.god == GOD_BEOGH);
+
+ // Beogh tries a second time to place reinforcements.
+ if (midx == -1)
+ midx = create_monster(mg);
+
+ if (midx == -1)
+ return;
+
+ monsters* mon = &menv[midx];
+
+ mon->flags |= MF_ATT_CHANGE_ATTEMPT;
+
+ bool high_level = (mon->type == MONS_ORC_PRIEST
+ || mon->type == MONS_ORC_WARRIOR
+ || mon->type == MONS_ORC_KNIGHT);
+
+ // For high level orcs, there's a chance of being named.
+ if (high_level && one_chance_in(5))
+ give_monster_proper_name(mon);
+}
+
// If you don't currently have any followers, send a small band to help
// you out.
-static bool _beogh_blessing_reinforcement()
+static void _beogh_blessing_reinforcement()
{
- bool success = false;
-
// Possible reinforcement.
const monster_type followers[] = {
MONS_ORC, MONS_ORC, MONS_ORC_WIZARD, MONS_ORC_PRIEST
@@ -1533,25 +1560,11 @@ static bool _beogh_blessing_reinforcement()
else
follower_type = RANDOM_ELEMENT(followers);
- int monster =
- create_monster(
- mgen_data(follower_type, BEH_FRIENDLY, 0, 0,
- you.pos(), you.pet_target, 0, GOD_BEOGH));
-
- if (monster != -1)
- {
- monsters *mon = &menv[monster];
- mon->flags |= MF_ATT_CHANGE_ATTEMPT;
-
- // For high level orcs, there's a chance of being named.
- if (high_level && one_chance_in(5))
- give_monster_proper_name(mon);
-
- success = true;
- }
+ _delayed_monster(
+ mgen_data(follower_type, BEH_FRIENDLY, 0, 0,
+ you.pos(), you.pet_target, 0, GOD_BEOGH),
+ _beogh_reinf_callback);
}
-
- return (success);
}
static bool _beogh_blessing_priesthood(monsters* mon)
@@ -1625,20 +1638,18 @@ bool bless_follower(monsters *follower,
{
// If no follower was found, attempt to send
// reinforcement.
- bool reinforced = _beogh_blessing_reinforcement();
+ _beogh_blessing_reinforcement();
- if (!reinforced || coinflip())
- {
- // Try again, or possibly send more reinforcement.
- if (_beogh_blessing_reinforcement())
- reinforced = true;
- }
+ // Possibly send more reinforcement.
+ if (coinflip())
+ _beogh_blessing_reinforcement();
- if (!reinforced)
- return (false);
+ _delayed_monster_done("Beogh blesses you with "
+ "reinforcements.", "");
- result = "reinforcement";
- goto blessing_done;
+ // Return true, even though the reinforcements might
+ // not be placed.
+ return (true);
}
}
}
@@ -1832,6 +1843,18 @@ blessing_done:
return (true);
}
+static void _delayed_gift_callback(const mgen_data &mg, int &midx,
+ int placed)
+{
+ if (placed <= 0)
+ return;
+
+ more();
+ _inc_gift_timeout(4 + random2avg(7, 2));
+ you.num_gifts[you.religion]++;
+ take_note(Note(NOTE_GOD_GIFT, you.religion));
+}
+
static void _do_god_gift(bool prayed_for)
{
ASSERT(you.religion != GOD_NO_GOD);
@@ -1927,18 +1950,10 @@ static void _do_god_gift(bool prayed_for)
{
// The maximum threshold occurs at piety_breakpoint(5).
int threshold = (you.piety - piety_breakpoint(2)) * 20 / 9;
- int how_many = _yred_random_servants(threshold);
+ _yred_random_servants(threshold);
- if (how_many > 0)
- {
- simple_god_message(
- how_many > 1 ? " grants you several undead servants!"
- : " grants you an undead servant!");
- more();
- _inc_gift_timeout(4 + random2avg(7, 2));
- you.num_gifts[you.religion]++;
- take_note(Note(NOTE_GOD_GIFT, you.religion));
- }
+ _delayed_monster_done("grants you @an@ undead servant@s@!",
+ "", _delayed_gift_callback);
}
break;
@@ -3112,12 +3127,23 @@ static FixedVector<bool, NUM_MONSTERS> _first_attack_was_friendly;
void religion_turn_start()
{
+ if (you.turn_is_over)
+ religion_turn_end();
+
_first_attack_conduct.init(true);
_first_attack_was_unchivalric.init(false);
_first_attack_was_friendly.init(false);
crawl_state.clear_god_acting();
}
+void religion_turn_end()
+{
+ ASSERT(you.turn_is_over);
+ _place_delayed_monsters();
+}
+
+#define NEW_GIFT_FLAGS (MF_JUST_SUMMONED | MF_GOD_GIFT)
+
void set_attack_conducts(god_conduct_trigger conduct[3], const monsters *mon,
bool known)
{
@@ -3125,7 +3151,14 @@ void set_attack_conducts(god_conduct_trigger conduct[3], const monsters *mon,
if (mons_friendly(mon))
{
- if(_first_attack_conduct[midx]
+ if ((mon->flags & NEW_GIFT_FLAGS) == NEW_GIFT_FLAGS)
+ {
+ mprf(MSGCH_ERROR, "Newly created friendly god gift '%s' was hurt "
+ "by you, shouldn't be possible; please file a bug report.",
+ mon->name(DESC_PLAIN, true).c_str());
+ _first_attack_was_friendly[midx] = true;
+ }
+ else if(_first_attack_conduct[midx]
|| _first_attack_was_friendly[midx])
{
conduct[0].set(DID_ATTACK_FRIEND, 5, known, mon);
@@ -4769,6 +4802,9 @@ bool divine_retribution( god_type god )
return (false);
}
+ if (you.turn_is_over)
+ religion_turn_end();
+
god_acting gdact(god, true);
bool do_more = true;
@@ -4825,6 +4861,9 @@ bool divine_retribution( god_type god )
// point...the punishment might have reduced penance further.
dec_penance(god, 1 + random2(3));
+ if (you.turn_is_over)
+ religion_turn_end();
+
return (did_retrib);
}
@@ -6024,6 +6063,11 @@ bool god_hates_attacking_friend(god_type god, const actor *fr)
if (!fr || fr->kill_alignment() != KC_FRIENDLY)
return (false);
+ return god_hates_attacking_friend(god, fr->mons_species());
+}
+
+bool god_hates_attacking_friend(god_type god, int species)
+{
switch (god)
{
case GOD_ZIN:
@@ -6032,7 +6076,7 @@ bool god_hates_attacking_friend(god_type god, const actor *fr)
case GOD_OKAWARU:
return (true);
case GOD_BEOGH: // added penance to avoid killings for loot
- return (mons_species(fr->id()) == MONS_ORC);
+ return (species == MONS_ORC);
default:
return (false);
@@ -6680,6 +6724,9 @@ static bool _need_free_piety()
//jmf: moved stuff from effects::handle_time()
void handle_god_time()
{
+ if (you.turn_is_over)
+ religion_turn_end();
+
if (one_chance_in(100))
{
// Choose a god randomly from those to whom we owe penance.
@@ -6804,6 +6851,9 @@ void handle_god_time()
DEBUGSTR("Bad god, no bishop!");
}
}
+
+ if (you.turn_is_over)
+ religion_turn_end();
}
// yet another wrapper for mpr() {dlb}:
@@ -7031,3 +7081,116 @@ int get_tension(god_type god)
return std::max(0, tension);
}
+
+/////////////////////////////////////////////////////////////////////////////
+// Stuff for placing god gift monsters after the player's turn has ended.
+/////////////////////////////////////////////////////////////////////////////
+
+static std::vector<mgen_data> _delayed_data;
+static std::deque<delayed_callback> _delayed_callbacks;
+static std::deque<unsigned int> _delayed_done_trigger_pos;
+static std::deque<delayed_callback> _delayed_done_callbacks;
+static std::deque<std::string> _delayed_success;
+static std::deque<std::string> _delayed_failure;
+
+static void _delayed_monster(const mgen_data &mg, delayed_callback callback)
+{
+ _delayed_data.push_back(mg);
+ _delayed_callbacks.push_back(callback);
+}
+
+static void _delayed_monster_done(std::string success, std::string failure,
+ delayed_callback callback)
+{
+ const unsigned int size = _delayed_data.size();
+ ASSERT(size > 0);
+
+ _delayed_done_trigger_pos.push_back(size - 1);
+ _delayed_success.push_back(success);
+ _delayed_failure.push_back(failure);
+ _delayed_done_callbacks.push_back(callback);
+}
+
+static void _place_delayed_monsters()
+{
+ int placed = 0;
+ god_type prev_god = GOD_NO_GOD;
+ for (unsigned int i = 0; i < _delayed_data.size(); i++)
+ {
+ mgen_data &mg = _delayed_data[i];
+ delayed_callback cback = _delayed_callbacks[i];
+
+ if (prev_god != mg.god)
+ {
+ placed = 0;
+ prev_god = mg.god;
+ }
+
+ int midx = create_monster(mg);
+
+ if (cback)
+ (*cback)(mg, midx, placed);
+
+ if (midx != -1)
+ placed++;
+
+ if (_delayed_done_trigger_pos.size() > 0
+ && _delayed_done_trigger_pos[0] == i)
+ {
+ cback = _delayed_done_callbacks[0];
+
+ std::string msg;
+ if (placed > 0)
+ msg = _delayed_success[0];
+ else
+ msg = _delayed_failure[0];
+
+ if (placed == 1)
+ {
+ msg = replace_all(msg, "@a@", "a");
+ msg = replace_all(msg, "@an@", "an");
+ }
+ else
+ {
+ msg = replace_all(msg, "@a@", "");
+ msg = replace_all(msg, "@an@", "");
+ }
+
+ if (placed > 1)
+ msg = replace_all(msg, "@s@", "s");
+ else
+ msg = replace_all(msg, "@s@", "");
+
+ prev_god = GOD_NO_GOD;
+ _delayed_done_trigger_pos.pop_front();
+ _delayed_success.pop_front();
+ _delayed_failure.pop_front();
+ _delayed_done_callbacks.pop_front();
+
+ if (msg == "")
+ {
+ if (cback)
+ (*cback)(mg, midx, placed);
+ continue;
+ }
+
+ // Fake it coming from simple_god_message().
+ if (msg[0] == ' ' || msg[0] == '\'')
+ msg = god_name(mg.god) + msg;
+
+ msg = apostrophise_fixup(msg);
+ trim_string(msg);
+
+ god_speaks(mg.god, msg.c_str());
+
+ if (cback)
+ (*cback)(mg, midx, placed);
+ }
+ }
+
+ _delayed_data.clear();
+ _delayed_callbacks.clear();
+ _delayed_done_trigger_pos.clear();
+ _delayed_success.clear();
+ _delayed_failure.clear();
+} // _place_delayed_monsters()
diff --git a/crawl-ref/source/religion.h b/crawl-ref/source/religion.h
index 16f56447f6..d9767c282f 100644
--- a/crawl-ref/source/religion.h
+++ b/crawl-ref/source/religion.h
@@ -153,9 +153,11 @@ bool bless_follower(monsters *follower = NULL,
bool force = false);
bool god_hates_attacking_friend(god_type god, const actor *fr);
+bool god_hates_attacking_friend(god_type god, int species);
bool god_likes_items(god_type god);
void religion_turn_start();
+void religion_turn_end();
int get_tension(god_type god = you.religion);
#endif