summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/religion.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/religion.cc')
-rw-r--r--crawl-ref/source/religion.cc655
1 files changed, 489 insertions, 166 deletions
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index 37e25dee7f..ca4453b50e 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -74,87 +74,111 @@
#include "terrain.h"
#include "tutorial.h"
#include "view.h"
+#include "xom.h"
+
+#if DEBUG_RELIGION
+# define DEBUG_DIAGNOSTICS 1
+# define DEBUG_GIFTS 1
+# define DEBUG_SACRIFICE 1
+# define DEBUG_PIETY 1
+#endif
// Item offer messages for the gods:
// & is replaced by "is" or "are" as appropriate for the item.
// % is replaced by "s" or "" as appropriate.
-// First message is if there's no piety gain, second is if there is.
-const char *sacrifice[NUM_GODS][2] =
+// First message is if there's no piety gain, second is if piety gain
+// is one, third message is for piety gain > 1 (currently unused).
+const char *sacrifice[NUM_GODS][3] =
{
// No god
{
" & eaten by a bored swarm of bugs.",
+ " & eaten by a swarm of bugs.",
" & eaten by a ravening swarm of bugs."
},
// Zin
{
- " faintly glow% silver and disappear%.",
- " glow% silver and disappear%.",
+ " barely glow% and disappear%.",
+ " glow% silver and disappear%.",
+ " glow% blindingly silver and disappear%.",
},
// TSO
{
- " glow% a golden colour and disappear%.",
- " glow% a brilliant golden colour and disappear%.",
+ " faintly glow% and disappear%.",
+ " glow% a golden colour and disappear%.",
+ " glow% a brilliant golden colour and disappear%.",
},
// Kikubaaqudgha
{
- " slowly rot% away.",
- " rot% away in an instant.",
+ " slowly rot% away.",
+ " rot% away.",
+ " rot% away in an instant.",
},
// Yredelemnul
{
" slowly crumble% to dust.",
" crumble% to dust.",
+ " turn% to dust in an instant.",
},
// Xom (no sacrifices)
{
" & eaten by a bored bug.",
" & eaten by a bug.",
+ " & eaten by a greedy bug.",
},
// Vehumet
{
- " burn% into nothingness.",
- " explode% into nothingness.",
+ " fade% into nothingness.",
+ " burn% into nothingness.",
+ " explode% into nothingness.",
},
// Okawaru
{
- " & consumed by flame.",
- " & consumed in a burst of flame.",
+ " slowly burn% to ash.",
+ " & consumed by flame.",
+ " & consumed in a burst of flame.",
},
// Makhleb
{
- " flare% red and disappear%.",
- " flare% blood-red and disappear%.",
+ " disappear% without a sign.",
+ " flare% red and disappear%.",
+ " flare% blood-red and disappear%.",
},
// Sif Muna
{
- " glow% very faintly for a moment, and & gone.",
- " glow% faintly for a moment, and & gone.",
+ " & gone without a glow.",
+ " glow% faintly for a moment, and & gone.",
+ " glow% for a moment, and & gone.",
},
// Trog
{
- " & consumed in a column of flame.",
- " & consumed in a roaring column of flame.",
+ " & slowly consumed by flames.",
+ " & consumed in a column of flame.",
+ " & consumed in a roaring column of flame.",
},
// Nemelex
{
- " glow% slightly and disappear%.",
- " glow% with a rainbow of weird colours and disappear%.",
+ " disappear% without a glow.",
+ " glow% slightly and disappear%.",
+ " glow% with a rainbow of weird colours and disappear%.",
},
// Elyvilon
{
- " slowly evaporate%.",
- " evaporate%.",
+ " slowly evaporate%.",
+ " evaporate%.",
+ " glow% and evaporate%.",
},
// Lugonu
{
- " & disappears into the void.",
- " & consumed by the void.",
+ " & disappears into the void.",
+ " & consumed by the void.",
+ " & voraciously consumed by the void.",
},
// Beogh
{
- " slowly crumble% into the ground.",
- " crumble% into the ground.",
+ " slowly crumble% into the ground.",
+ " crumble% into the ground.",
+ " disintegrate% into the ground.",
}
};
@@ -218,10 +242,10 @@ const char* god_gain_power_messages[NUM_GODS][MAX_GOD_ABILITIES] =
"call in reinforcement",
"" },
// Nemelex
- { "peek at the first card of a deck",
+ { "peek at three random cards from a deck",
"draw cards from decks in your inventory",
"choose one out of three cards",
- "",
+ "mark decks",
"order the the top five cards of a deck, forfeiting the rest" },
// Elyvilon
{ "call upon Elyvilon for minor healing",
@@ -304,10 +328,10 @@ const char* god_lose_power_messages[NUM_GODS][MAX_GOD_ABILITIES] =
"call in reinforcement",
"" },
// Nemelex
- { "peek at the first card of a deck",
+ { "peek at three random cards from a deck",
"draw cards from decks in your inventory",
"choose one out of three cards",
- "",
+ "mark decks",
"order decks" },
// Elyvilon
{ "call upon Elyvilon for minor healing",
@@ -336,7 +360,7 @@ void inc_penance(int god, int val);
void inc_penance(int val);
static bool followers_abandon_you(void); // Beogh
-static bool is_evil_god(god_type god)
+bool is_evil_god(god_type god)
{
return
god == GOD_KIKUBAAQUDGHA ||
@@ -347,7 +371,7 @@ static bool is_evil_god(god_type god)
god == GOD_LUGONU;
}
-static bool is_good_god(god_type god)
+bool is_good_god(god_type god)
{
return
god == GOD_SHINING_ONE ||
@@ -372,6 +396,9 @@ void dec_penance(god_type god, int val)
{
if (you.penance[god] > 0)
{
+#if DEBUG_PIETY
+ mprf(MSGCH_DIAGNOSTICS, "Decreasing penance by %d", val);
+#endif
if (you.penance[god] <= val)
{
simple_god_message(" seems mollified.", god);
@@ -422,20 +449,45 @@ static void inc_gift_timeout(int val)
you.gift_timeout += val;
} // end inc_gift_timeout()
-static monster_type random_undead_servant(int religion /* unused */)
+// Only Yredelemnul and Okawaru use this for now
+static monster_type random_servant(god_type god)
{
// error trapping {dlb}
monster_type thing_called = MONS_PROGRAM_BUG;
int temp_rand = random2(100);
- thing_called = ((temp_rand > 66) ? MONS_WRAITH : // 33%
- (temp_rand > 52) ? MONS_WIGHT : // 12%
- (temp_rand > 40) ? MONS_SPECTRAL_WARRIOR : // 16%
- (temp_rand > 31) ? MONS_ROTTING_HULK : // 9%
- (temp_rand > 23) ? MONS_SKELETAL_WARRIOR : // 8%
- (temp_rand > 16) ? MONS_VAMPIRE : // 7%
- (temp_rand > 10) ? MONS_GHOUL : // 6%
- (temp_rand > 4) ? MONS_MUMMY // 6%
- : MONS_FLAYED_GHOST); // 5%
+
+ switch (god)
+ {
+ case GOD_YREDELEMNUL:
+ // undead
+ thing_called = ((temp_rand > 66) ? MONS_WRAITH : // 33%
+ (temp_rand > 52) ? MONS_WIGHT : // 12%
+ (temp_rand > 40) ? MONS_SPECTRAL_WARRIOR : // 16%
+ (temp_rand > 31) ? MONS_ROTTING_HULK : // 9%
+ (temp_rand > 23) ? MONS_SKELETAL_WARRIOR : // 8%
+ (temp_rand > 16) ? MONS_VAMPIRE : // 7%
+ (temp_rand > 10) ? MONS_GHOUL : // 6%
+ (temp_rand > 4) ? MONS_MUMMY // 6%
+ : MONS_FLAYED_GHOST); // 5%
+ break;
+ case GOD_OKAWARU:
+ // warriors
+ thing_called = ((temp_rand > 84) ? MONS_ORC_WARRIOR :
+ (temp_rand > 69) ? MONS_ORC_KNIGHT :
+ (temp_rand > 59) ? MONS_NAGA_WARRIOR :
+ (temp_rand > 49) ? MONS_CENTAUR_WARRIOR :
+ (temp_rand > 39) ? MONS_STONE_GIANT :
+ (temp_rand > 29) ? MONS_FIRE_GIANT :
+ (temp_rand > 19) ? MONS_FROST_GIANT :
+ (temp_rand > 9) ? MONS_CYCLOPS :
+ (temp_rand > 4) ? MONS_HILL_GIANT
+ : MONS_TITAN);
+
+ break;
+ default:
+ break;
+ }
+
return (thing_called);
}
@@ -487,11 +539,193 @@ static bool need_missile_gift()
&& ammo_count(launcher) < 20 + random2(35));
}
+static void get_pure_deck_weights(int weights[])
+{
+ weights[0] = you.sacrifice_value[OBJ_ARMOUR] + 1;
+ weights[1] = you.sacrifice_value[OBJ_WEAPONS] +
+ you.sacrifice_value[OBJ_STAVES] +
+ you.sacrifice_value[OBJ_MISSILES] + 1;
+ weights[2] = you.sacrifice_value[OBJ_MISCELLANY] +
+ you.sacrifice_value[OBJ_JEWELLERY] +
+ you.sacrifice_value[OBJ_BOOKS] +
+ you.sacrifice_value[OBJ_GOLD];
+ weights[3] = you.sacrifice_value[OBJ_CORPSES] / 2;
+ weights[4] = you.sacrifice_value[OBJ_POTIONS] +
+ you.sacrifice_value[OBJ_SCROLLS] +
+ you.sacrifice_value[OBJ_WANDS] +
+ you.sacrifice_value[OBJ_FOOD];
+}
+
+static void update_sacrifice_weights(int which)
+{
+ switch ( which )
+ {
+ case 0:
+ you.sacrifice_value[OBJ_ARMOUR] /= 5;
+ you.sacrifice_value[OBJ_ARMOUR] *= 4;
+ break;
+ case 1:
+ you.sacrifice_value[OBJ_WEAPONS] /= 5;
+ you.sacrifice_value[OBJ_STAVES] /= 5;
+ you.sacrifice_value[OBJ_MISSILES] /= 5;
+ you.sacrifice_value[OBJ_WEAPONS] *= 4;
+ you.sacrifice_value[OBJ_STAVES] *= 4;
+ you.sacrifice_value[OBJ_MISSILES] *= 4;
+ break;
+ case 2:
+ you.sacrifice_value[OBJ_MISCELLANY] /= 5;
+ you.sacrifice_value[OBJ_JEWELLERY] /= 5;
+ you.sacrifice_value[OBJ_BOOKS] /= 5;
+ you.sacrifice_value[OBJ_GOLD] /= 5;
+ you.sacrifice_value[OBJ_MISCELLANY] *= 4;
+ you.sacrifice_value[OBJ_JEWELLERY] *= 4;
+ you.sacrifice_value[OBJ_BOOKS] *= 4;
+ you.sacrifice_value[OBJ_GOLD] *= 4;
+ case 3:
+ you.sacrifice_value[OBJ_CORPSES] /= 5;
+ you.sacrifice_value[OBJ_CORPSES] *= 4;
+ break;
+ case 4:
+ you.sacrifice_value[OBJ_POTIONS] /= 5;
+ you.sacrifice_value[OBJ_SCROLLS] /= 5;
+ you.sacrifice_value[OBJ_WANDS] /= 5;
+ you.sacrifice_value[OBJ_FOOD] /= 5;
+ you.sacrifice_value[OBJ_POTIONS] *= 4;
+ you.sacrifice_value[OBJ_SCROLLS] *= 4;
+ you.sacrifice_value[OBJ_WANDS] *= 4;
+ you.sacrifice_value[OBJ_FOOD] *= 4;
+ break;
+ }
+}
+
+#if DEBUG_GIFTS || DEBUG_CARDS
+static void show_pure_deck_chances()
+{
+ int weights[5];
+
+ get_pure_deck_weights(weights);
+
+ float total = (float) (weights[0] + weights[1] + weights[2] + weights[3] +
+ weights[4]);
+
+ mprf(MSGCH_DIAGNOSTICS, "Pure cards chances: "
+ "escape %0.2f%%, destruction %0.2f%%, dungeons %0.2f%%,"
+ "summoning %0.2f%%, wonders %0.2f%%",
+ (float)weights[0] / total * 100.0,
+ (float)weights[1] / total * 100.0,
+ (float)weights[2] / total * 100.0,
+ (float)weights[3] / total * 100.0,
+ (float)weights[4] / total * 100.0);
+}
+#endif
+
+static void give_nemelex_gift()
+{
+ if ( grid_destroys_items(grd[you.x_pos][you.y_pos]) )
+ return;
+
+ // Nemelex will give at least one gift early.
+ if ((you.num_gifts[GOD_NEMELEX_XOBEH] == 0
+ && random2(piety_breakpoint(1)) < you.piety) ||
+ (random2(MAX_PIETY) <= you.piety
+ && one_chance_in(3)
+ && !you.attribute[ATTR_CARD_COUNTDOWN]))
+ {
+ misc_item_type gift_type;
+ if ( random2(MAX_PIETY) <= you.piety )
+ {
+ // make a pure deck
+ const misc_item_type pure_decks[] = {
+ MISC_DECK_OF_ESCAPE,
+ MISC_DECK_OF_DESTRUCTION,
+ MISC_DECK_OF_DUNGEONS,
+ MISC_DECK_OF_SUMMONING,
+ MISC_DECK_OF_WONDERS
+ };
+ int weights[5];
+ get_pure_deck_weights(weights);
+ const int choice = choose_random_weighted(weights, weights+5);
+ gift_type = pure_decks[choice];
+#if DEBUG_GIFTS || DEBUG_CARDS
+ show_pure_deck_chances();
+#endif
+ update_sacrifice_weights(choice);
+ }
+ else
+ {
+ // make a mixed deck
+ const misc_item_type mixed_decks[] = {
+ MISC_DECK_OF_WAR,
+ MISC_DECK_OF_CHANGES,
+ MISC_DECK_OF_DEFENSE
+ };
+ gift_type = RANDOM_ELEMENT(mixed_decks);
+ }
+
+ int thing_created = items( 1, OBJ_MISCELLANY, gift_type,
+ true, 1, MAKE_ITEM_RANDOM_RACE );
+
+ if (thing_created != NON_ITEM)
+ {
+ // Piety|Common | Rare |Legendary
+ // --------------------------------
+ // 0: 95.00%, 5.00%, 0.00%
+ // 20: 86.00%, 10.50%, 3.50%
+ // 40: 77.00%, 16.00%, 7.00%
+ // 60: 68.00%, 21.50%, 10.50%
+ // 80: 59.00%, 27.00%, 14.00%
+ // 100: 50.00%, 32.50%, 17.50%
+ // 120: 41.00%, 38.00%, 21.00%
+ // 140: 32.00%, 43.50%, 24.50%
+ // 160: 23.00%, 49.00%, 28.00%
+ // 180: 14.00%, 54.50%, 31.50%
+ // 200: 5.00%, 60.00%, 35.00%
+ int common_weight = 95 - (90 * you.piety / MAX_PIETY);
+ int rare_weight = 5 + (55 * you.piety / MAX_PIETY);
+ int legend_weight = 0 + (35 * you.piety / MAX_PIETY);
+
+ deck_rarity_type rarity = static_cast<deck_rarity_type>(
+ random_choose_weighted(common_weight,
+ DECK_RARITY_COMMON,
+ rare_weight,
+ DECK_RARITY_RARE,
+ legend_weight,
+ DECK_RARITY_LEGENDARY,
+ 0));
+
+ item_def &deck(mitm[thing_created]);
+
+ deck.special = rarity;
+ deck.colour = deck_rarity_to_color(rarity);
+
+ move_item_to_grid( &thing_created, you.x_pos, you.y_pos );
+ origin_acquired(deck, you.religion);
+
+ simple_god_message(" grants you a gift!");
+ more();
+ canned_msg(MSG_SOMETHING_APPEARS);
+
+ you.attribute[ATTR_CARD_COUNTDOWN] = 10;
+ inc_gift_timeout(5 + random2avg(9, 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);
+
// Zin worshippers are the only ones that can pray to ask Zin for stuff.
if (prayed_for != (you.religion == GOD_ZIN))
return;
+
+ god_acting gdact;
+
+#if DEBUG_DIAGNOSTICS || DEBUG_GIFTS
+ int old_gifts = you.num_gifts[ you.religion ];
+#endif
// Consider a gift if we don't have a timeout and weren't
// already praying when we prayed.
@@ -519,66 +753,7 @@ static void do_god_gift(bool prayed_for)
break;
case GOD_NEMELEX_XOBEH:
- if (random2(200) <= you.piety
- && one_chance_in(3)
- && !you.attribute[ATTR_CARD_COUNTDOWN]
- && !grid_destroys_items(grd[you.x_pos][you.y_pos]))
- {
- misc_item_type gift_type;
- if ( random2(200) <= you.piety )
- {
- // make a pure deck
- const misc_item_type pure_decks[] = {
- MISC_DECK_OF_ESCAPE,
- MISC_DECK_OF_DESTRUCTION,
- MISC_DECK_OF_DUNGEONS,
- MISC_DECK_OF_SUMMONING,
- MISC_DECK_OF_WONDERS
- };
- int weights[5];
- // FIXME do something with OBJ_FOOD,
- // OBJ_WANDS, OBJ_JEWELLERY, OBJ_BOOKS
- // (and maybe OBJ_ORBS...)
- weights[0] = you.sacrifice_value[OBJ_SCROLLS] +
- you.sacrifice_value[OBJ_ARMOUR] + 1;
- weights[1] = you.sacrifice_value[OBJ_WEAPONS] +
- you.sacrifice_value[OBJ_STAVES] +
- you.sacrifice_value[OBJ_MISSILES] + 1;
- weights[2] = you.sacrifice_value[OBJ_MISCELLANY];
- weights[3] = you.sacrifice_value[OBJ_CORPSES] * 100;
- weights[4] = you.sacrifice_value[OBJ_POTIONS];
- gift_type = pure_decks[choose_random_weighted(weights,
- weights+5)];
- }
- else
- {
- // make a mixed deck
- const misc_item_type mixed_decks[] = {
- MISC_DECK_OF_WAR,
- MISC_DECK_OF_CHANGES,
- MISC_DECK_OF_DEFENSE
- };
- gift_type = RANDOM_ELEMENT(mixed_decks);
- }
-
- int thing_created = items( 1, OBJ_MISCELLANY, gift_type,
- true, 1, MAKE_ITEM_RANDOM_RACE );
-
- if (thing_created != NON_ITEM)
- {
- move_item_to_grid( &thing_created, you.x_pos, you.y_pos );
- origin_acquired(mitm[thing_created], you.religion);
-
- simple_god_message(" grants you a gift!");
- more();
- canned_msg(MSG_SOMETHING_APPEARS);
-
- you.attribute[ATTR_CARD_COUNTDOWN] = 10;
- inc_gift_timeout(5 + random2avg(9, 2));
- you.num_gifts[you.religion]++;
- take_note(Note(NOTE_GOD_GIFT, you.religion));
- }
- }
+ give_nemelex_gift();
break;
case GOD_OKAWARU:
@@ -632,13 +807,12 @@ static void do_god_gift(bool prayed_for)
case GOD_YREDELEMNUL:
if (random2(you.piety) > 80 && one_chance_in(5))
{
- monster_type thing_called =
- random_undead_servant(GOD_YREDELEMNUL);
+ monster_type thing_called =
+ random_servant(GOD_YREDELEMNUL);
- if (create_monster( thing_called, 0, BEH_FRIENDLY,
- you.x_pos, you.y_pos,
- you.pet_target, MAKE_ITEM_RANDOM_RACE )
- != -1)
+ if (create_monster(thing_called, 0, BEH_FRIENDLY,
+ you.x_pos, you.y_pos, you.pet_target,
+ MAKE_ITEM_RANDOM_RACE) != -1)
{
simple_god_message(" grants you an undead servant!");
more();
@@ -737,6 +911,12 @@ static void do_god_gift(bool prayed_for)
break;
}
} // end of gift giving
+
+#if DEBUG_DIAGNOSTICS || DEBUG_GIFTS
+ if (old_gifts < you.num_gifts[ you.religion ])
+ mprf(MSGCH_DIAGNOSTICS, "Total number of gifts from this god: %d",
+ you.num_gifts[ you.religion ] );
+#endif
}
static bool is_risky_sacrifice(const item_def& item)
@@ -1054,7 +1234,8 @@ void god_speaks( god_type god, const char *mesg )
// This function is the merger of done_good() and naughty().
// Returns true if god was interested (good or bad) in conduct.
-bool did_god_conduct( conduct_type thing_done, int level, const actor *victim )
+bool did_god_conduct( conduct_type thing_done, int level, bool known,
+ const actor *victim )
{
bool ret = false;
int piety_change = 0;
@@ -1063,15 +1244,28 @@ bool did_god_conduct( conduct_type thing_done, int level, const actor *victim )
if (you.religion == GOD_NO_GOD || you.religion == GOD_XOM)
return (false);
+ god_acting gdact;
+
switch (thing_done)
{
case DID_DRINK_BLOOD:
switch (you.religion)
{
- case GOD_ZIN:
case GOD_SHINING_ONE:
+ if (!known)
+ {
+ simple_god_message(" did not appreciate that!");
+ break;
+ }
+ penance = level;
+ // deliberate fall-through
+ case GOD_ZIN:
case GOD_ELYVILON:
- // no penance as this can happen accidentally
+ if (!known)
+ {
+ simple_god_message(" did not appreciate that!");
+ break;
+ }
piety_change = -2*level;
ret = true;
break;
@@ -1080,7 +1274,22 @@ bool did_god_conduct( conduct_type thing_done, int level, const actor *victim )
}
break;
- // If you make some god like these acts, modify did_god_conduct call
+ case DID_CANNIBALISM:
+ switch (you.religion)
+ {
+ case GOD_ZIN:
+ case GOD_SHINING_ONE:
+ case GOD_ELYVILON:
+ piety_change = -level;
+ penance = level;
+ ret = true;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ // If you make some god like these acts, modify did_god_conduct call
// in beam.cc with god_likes_necromancy check or something similar
case DID_NECROMANCY:
case DID_UNHOLY:
@@ -1090,8 +1299,14 @@ bool did_god_conduct( conduct_type thing_done, int level, const actor *victim )
case GOD_ZIN:
case GOD_SHINING_ONE:
case GOD_ELYVILON:
+ if (!known && thing_done != DID_ATTACK_HOLY)
+ {
+ simple_god_message(" did not appreciate that!");
+ break;
+ }
piety_change = -level;
- penance = level * ((you.religion == GOD_ZIN) ? 2 : 1);
+ if (known)
+ penance = level * ((you.religion == GOD_SHINING_ONE) ? 2 : 1);
ret = true;
break;
default:
@@ -1122,7 +1337,8 @@ bool did_god_conduct( conduct_type thing_done, int level, const actor *victim )
(victim && mons_species(victim->id()) == MONS_ORC))
{
piety_change = -level;
- penance = level * 3;
+ if (known)
+ penance = level * 3;
ret = true;
}
break;
@@ -1427,6 +1643,31 @@ bool did_god_conduct( conduct_type thing_done, int level, const actor *victim )
{
piety_change = level;
ret = true;
+
+ // For a stacked deck, 0% chance of card countdown decrement
+ // drawing a card which doesn't use up the deck, and 40%
+ // on a card which does. For a non-stacked deck, an
+ // average 50% of decrement for drawing a card which doesn't
+ // use up the deck, and 80% on a card which does use up the
+ // deck.
+ int chance = 0;
+ switch(level)
+ {
+ case 0: chance = 0; break;
+ case 1: chance = 40; break;
+ case 2: chance = 70; break;
+ default:
+ case 3: chance = 100; break;
+ }
+
+ if (random2(100) < chance && you.attribute[ATTR_CARD_COUNTDOWN])
+ {
+ you.attribute[ATTR_CARD_COUNTDOWN]--;
+#if DEBUG_DIAGNOSTICS || DEBUG_CARDS || DEBUG_GIFTS
+ mprf(MSGCH_DIAGNOSTICS, "Countdown down to %d",
+ you.attribute[ATTR_CARD_COUNTDOWN]);
+#endif
+ }
}
break;
@@ -1478,13 +1719,12 @@ bool did_god_conduct( conduct_type thing_done, int level, const actor *victim )
"Necromancy", "Unholy", "Attack Holy", "Attack Friend",
"Friend Died", "Stab", "Poison", "Field Sacrifice",
"Kill Living", "Kill Undead", "Kill Demon", "Kill Natural Evil",
- "Kill Wizard",
- "Kill Priest", "Kill Angel", "Undead Slave Kill Living",
- "Servant Kill Living", "Servant Kill Undead",
- "Servant Kill Demon", "Servant Kill Natural Evil",
- "Servant Kill Angel",
+ "Kill Wizard", "Kill Priest", "Kill Angel", "Undead Slave Kill Living",
+ "Servant Kill Living", "Servant Kill Undead", "Servant Kill Demon",
+ "Servant Kill Natural Evil", "Servant Kill Angel",
"Spell Memorise", "Spell Cast", "Spell Practise", "Spell Nonutility",
- "Cards", "Stimulants", "Drink Blood", "Eat Meat", "Create Life"
+ "Cards", "Stimulants", "Drink Blood", "Cannibalism", "Eat Meat",
+ "Create Life"
};
ASSERT(ARRAYSIZE(conducts) == NUM_CONDUCTS);
@@ -1502,7 +1742,7 @@ bool did_god_conduct( conduct_type thing_done, int level, const actor *victim )
void gain_piety(int pgn)
{
// Xom uses piety differently...
- if (you.religion == GOD_XOM)
+ if (you.religion == GOD_XOM || you.religion == GOD_NO_GOD)
return;
// check to see if we owe anything first
@@ -1521,13 +1761,22 @@ void gain_piety(int pgn)
// Slow down piety gain to account for the fact that gifts
// no longer have a piety cost for getting them
if (!one_chance_in(4))
+ {
+#if DEBUG_PIETY
+ mprf(MSGCH_DIAGNOSTICS, "Piety slowdown due to gift timeout.");
+#endif
return;
+ }
}
+#if DEBUG_PIETY
+ mprf(MSGCH_DIAGNOSTICS, "Piety increasing by %d", pgn);
+#endif
+
// slow down gain at upper levels of piety
if (you.religion != GOD_SIF_MUNA)
{
- if (you.piety > 199
+ if (you.piety >= MAX_PIETY
|| (you.piety > 150 && one_chance_in(3))
|| (you.piety > 100 && one_chance_in(3)))
{
@@ -1539,7 +1788,7 @@ void gain_piety(int pgn)
{
// Sif Muna has a gentler taper off because training becomes
// naturally slower as the player gains in spell skills.
- if ((you.piety > 199) ||
+ if ((you.piety >= MAX_PIETY) ||
(you.piety > 150 && one_chance_in(5)))
{
do_god_gift(false);
@@ -1550,6 +1799,8 @@ void gain_piety(int pgn)
int old_piety = you.piety;
you.piety += pgn;
+ if (you.piety > MAX_PIETY)
+ you.piety = MAX_PIETY;
for ( int i = 0; i < MAX_GOD_ABILITIES; ++i )
{
@@ -1602,11 +1853,24 @@ static bool need_water_walking()
grd[you.x_pos][you.y_pos] == DNGN_DEEP_WATER;
}
+static bool is_evil_weapon(item_def weap)
+{
+ if (weap.base_type != OBJ_WEAPONS)
+ return false;
+
+ return (is_demonic(weap)
+ || weap.special == SPWPN_VAMPIRICISM
+ || weap.special == SPWPN_PAIN
+ || weap.special == SPWPN_DRAINING);
+}
+
bool ely_destroy_weapons()
{
if (you.religion != GOD_ELYVILON)
return false;
-
+
+ god_acting gdact;
+
bool success = false;
int i = igrd[you.x_pos][you.y_pos];
while (i != NON_ITEM)
@@ -1627,7 +1891,8 @@ bool ely_destroy_weapons()
#endif
bool pgain = false;
- if (random2(value) >= random2(250) // artefacts (incl. most randarts)
+ if (is_evil_weapon(mitm[i])
+ || random2(value) >= random2(250) // artefacts (incl. most randarts)
|| random2(value) >= random2(100) && one_chance_in(1 + you.piety/50)
|| (mitm[i].base_type == OBJ_WEAPONS
&& (you.piety < 30 || player_under_penance())))
@@ -1635,7 +1900,18 @@ bool ely_destroy_weapons()
pgain = true;
gain_piety(1);
}
-
+
+ std::ostream& strm = msg::streams(MSGCH_GOD);
+ strm << mitm[i].name(DESC_CAP_THE);
+
+ if (!pgain)
+ strm << " barely";
+
+ if ( mitm[i].quantity == 1 )
+ strm << " shimmers and breaks into pieces." << std::endl;
+ else
+ strm << " shimmer and break into pieces." << std::endl;
+
std::ostream& strm = msg::streams(MSGCH_GOD);
strm << mitm[i].name(DESC_CAP_THE);
@@ -1656,7 +1932,6 @@ bool ely_destroy_weapons()
{
mpr("There are no weapons here to destroy!");
}
-
return success;
}
@@ -1666,6 +1941,8 @@ bool trog_burn_books()
if (you.religion != GOD_TROG)
return (false);
+ god_acting gdact;
+
int i = igrd[you.x_pos][you.y_pos];
while (i != NON_ITEM)
{
@@ -1770,7 +2047,6 @@ bool trog_burn_books()
simple_god_message(" is delighted!", GOD_TROG);
gain_piety(totalpiety);
}
-
return (true);
}
@@ -1778,6 +2054,10 @@ void lose_piety(int pgn)
{
const int old_piety = you.piety;
+#if DEBUG_PIETY
+ mprf(MSGCH_DIAGNOSTICS, "Piety decreasing by %d", pgn);
+#endif
+
if (you.piety - pgn < 0)
you.piety = 0;
else
@@ -1885,9 +2165,10 @@ static bool zin_retribution()
if (!is_evil_god(you.religion))
return false;
+ bool success = false;
+
if (random2(you.experience_level) > 7 && !one_chance_in(5))
{
- bool success = false;
const int how_many = 1 + (you.experience_level / 10) + random2(3);
for (int i = 0; i < how_many; i++)
@@ -1904,8 +2185,11 @@ static bool zin_retribution()
else
{
// god_gift == false gives unfriendly
- summon_swarm( you.experience_level * 20, true, false );
- simple_god_message(" sends a plague down upon you!", god);
+ success = summon_swarm( you.experience_level * 20, true, false );
+ simple_god_message(success ?
+ " sends a plague down upon you!" :
+ "'s plague fails to arrive.",
+ god);
}
return false;
@@ -1989,13 +2273,11 @@ static bool yredelemnul_retribution()
for (int i = 0; i < how_many; i++)
{
- monster_type punisher =
- random_undead_servant(GOD_YREDELEMNUL);
+ monster_type punisher = random_servant(GOD_YREDELEMNUL);
- if (create_monster( punisher, 0, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU, 250 ) != -1)
+ if (create_monster(punisher, 0, BEH_HOSTILE,
+ you.x_pos, you.y_pos, MHITYOU, 250) != -1)
count++;
-
}
simple_god_message(count > 1? " sends servants to punish you." :
@@ -2021,7 +2303,7 @@ static bool trog_retribution()
{
// Would be better if berserking monsters were available,
// we just send some big bruisers for now.
- bool success = false;
+ int count = 0;
int points = 3 + you.experience_level * 3;
while (points > 0)
@@ -2051,13 +2333,12 @@ static bool trog_retribution()
if (create_monster(punisher, 0, BEH_HOSTILE, you.x_pos,
you.y_pos, MHITYOU, 250) != -1)
- success = true;
+ count++;
}
-
- simple_god_message(success ?
- " sends monsters to punish you." :
- " has no time to punish you...now.",
- god);
+
+ simple_god_message(count > 1 ? " sends monsters to punish you." :
+ count > 0 ? " sends a monster to punish you." :
+ " has no time to punish you...now.", god);
}
else if ( !one_chance_in(3) )
{
@@ -2075,7 +2356,8 @@ static bool trog_retribution()
case 1:
case 2:
- lose_stat(STAT_STRENGTH, 1 + random2(you.strength / 5), true);
+ lose_stat(STAT_STRENGTH, 1 + random2(you.strength / 5), true,
+ "divine retribution from Trog");
break;
case 3:
@@ -2244,18 +2526,7 @@ static bool okawaru_retribution()
for (int i = 0; i < how_many; i++)
{
- const int temp_rand = random2(100);
-
- monster_type punisher = ((temp_rand > 84) ? MONS_ORC_WARRIOR :
- (temp_rand > 69) ? MONS_ORC_KNIGHT :
- (temp_rand > 59) ? MONS_NAGA_WARRIOR :
- (temp_rand > 49) ? MONS_CENTAUR_WARRIOR :
- (temp_rand > 39) ? MONS_STONE_GIANT :
- (temp_rand > 29) ? MONS_FIRE_GIANT :
- (temp_rand > 19) ? MONS_FROST_GIANT :
- (temp_rand > 9) ? MONS_CYCLOPS :
- (temp_rand > 4) ? MONS_HILL_GIANT
- : MONS_TITAN);
+ monster_type punisher = random_servant(GOD_OKAWARU);
if (create_monster(punisher, 0, BEH_HOSTILE,
you.x_pos, you.y_pos, MHITYOU, 250) != -1)
@@ -2282,7 +2553,8 @@ static bool sif_muna_retribution()
{
case 0:
case 1:
- lose_stat(STAT_INTELLIGENCE, 1 + random2( you.intel / 5 ), true);
+ lose_stat(STAT_INTELLIGENCE, 1 + random2( you.intel / 5 ), true,
+ "divine retribution from Sif Muna");
break;
case 2:
@@ -2408,6 +2680,8 @@ void divine_retribution( god_type god )
if (god == you.religion && is_good_god(god) )
return;
+ god_acting gdact(god, true);
+
bool do_more = true;
switch (god)
{
@@ -2477,7 +2751,7 @@ bool followers_abandon_you()
{
for ( int x = xstart; x < xend; ++x )
{
- const unsigned char targ_monst = mgrd[x][y];
+ const unsigned short targ_monst = mgrd[x][y];
if ( targ_monst != NON_MONSTER )
{
monsters *monster = &menv[targ_monst];
@@ -2547,6 +2821,8 @@ bool followers_abandon_you()
// Destroying orcish idols (a.k.a. idols of Beogh) may anger Beogh
void beogh_idol_revenge()
{
+ god_acting gdact(GOD_BEOGH, true);
+
// Beogh watches his charges closely, but for others doesn't always notice
if (you.religion == GOD_BEOGH
|| (you.species == SP_HILL_ORC && coinflip())
@@ -2705,6 +2981,7 @@ void beogh_convert_orc(monsters *orc, bool emergency)
void excommunication(void)
{
const god_type old_god = you.religion;
+ god_acting gdact(old_god, true);
take_note(Note(NOTE_LOSE_GOD, old_god));
@@ -2860,6 +3137,8 @@ void altar_prayer(void)
if (you.religion == GOD_XOM)
return;
+ god_acting gdact;
+
// TSO blesses long swords with holy wrath
if (you.religion == GOD_SHINING_ONE
&& !you.num_gifts[GOD_SHINING_ONE]
@@ -2958,7 +3237,10 @@ void offer_items()
if (you.religion == GOD_NO_GOD || !god_likes_items(you.religion))
return;
- int i = igrd[you.x_pos][you.y_pos];
+ god_acting gdact;
+
+ int num_sacced = 0;
+ int i = igrd[you.x_pos][you.y_pos];
while (i != NON_ITEM)
{
item_def &item(mitm[i]);
@@ -2966,7 +3248,7 @@ void offer_items()
const int value = item_value( item, true );
- if (item_is_stationary(item) || !god_likes_item(you.religion, mitm[i]))
+ if (item_is_stationary(item) || !god_likes_item(you.religion, item))
{
i = next;
continue;
@@ -2974,7 +3256,7 @@ void offer_items()
bool gained_piety = false;
-#ifdef DEBUG_DIAGNOSTICS
+#if DEBUG_DIAGNOSTICS || DEBUG_SACRIFICE
mprf(MSGCH_DIAGNOSTICS, "Sacrifice item value: %d", value);
#endif
@@ -2995,22 +3277,49 @@ void offer_items()
}
}
- you.sacrifice_value[mitm[i].base_type] += value;
if (you.attribute[ATTR_CARD_COUNTDOWN] && random2(800) < value)
{
you.attribute[ATTR_CARD_COUNTDOWN]--;
-#ifdef DEBUG_DIAGNOSTICS
+#if DEBUG_DIAGNOSTICS || DEBUG_CARDS || DEBUG_SACRIFICE
mprf(MSGCH_DIAGNOSTICS, "Countdown down to %d",
you.attribute[ATTR_CARD_COUNTDOWN]);
#endif
}
- if ((mitm[i].base_type == OBJ_CORPSES && coinflip())
- // Nemelex piety gain is fairly fast.
- || random2(value) >= random2(60))
+ // Aproximate piety gain chance.
+ // Value: %
+ // ---------
+ // 10: 9.0%
+ // 20: 17.5%
+ // 30: 25.5%
+ // 40: 34.0%
+ // 50: 42.5%
+ // 60: 50.0%
+ // 70: 58.0%
+ // 80: 63.0%
+ if ((item.base_type == OBJ_CORPSES &&
+ one_chance_in(2+you.piety/50))
+ // Nemelex piety gain is fairly fast...at least
+ // when you have low piety.
+ || value/2 >= random2(30 + you.piety/2))
{
gain_piety(1);
gained_piety = true;
}
+
+ if (item.base_type == OBJ_FOOD && item.sub_type == FOOD_CHUNK)
+ // No sacrifice value for chunks of flesh, since food
+ // value goes towards decks of wonder.
+ ;
+ else if (item.base_type == OBJ_CORPSES)
+ {
+#if DEBUG_GIFTS || DEBUG_CARDS || DEBUG_SACRIFICE
+ mprf(MSGCH_DIAGNOSTICS, "Corpse mass is %d",
+ item_mass(item));
+#endif
+ you.sacrifice_value[item.base_type] += item_mass(item);
+ }
+ else
+ you.sacrifice_value[item.base_type] += value;
break;
case GOD_ZIN:
@@ -3047,9 +3356,16 @@ void offer_items()
<< sacrifice_message(you.religion, mitm[i],
gained_piety)
<< std::endl;
+ item_was_destroyed(mitm[i]);
destroy_item(i);
i = next;
+ num_sacced++;
}
+
+#if DEBUG_GIFTS || DEBUG_CARDS || DEBUG_SACRIFICE
+ if (num_sacced > 0 && you.religion == GOD_NEMELEX_XOBEH)
+ show_pure_deck_chances();
+#endif
}
void god_pitch(god_type which_god)
@@ -3076,6 +3392,7 @@ void god_pitch(god_type which_god)
if (which_god == GOD_LUGONU && you.penance[GOD_LUGONU])
{
simple_god_message(" is most displeased with you!", which_god);
+ god_acting gdact(GOD_LUGONU, true);
lugonu_retribution();
return;
}
@@ -3174,6 +3491,12 @@ bool god_hates_butchery(god_type god)
return (god == GOD_ELYVILON);
}
+bool god_protects_from_harm(god_type god)
+{
+ return (god == GOD_ZIN || god == GOD_SHINING_ONE ||
+ god == GOD_ELYVILON || god == GOD_YREDELEMNUL);
+}
+
void offer_corpse(int corpse)
{
// We always give the "good" (piety-gain) message when doing