1 /**
2  * @file
3  * @brief Misc religion related functions.
4 **/
5 
6 #include "AppHdr.h"
7 
8 #include "religion.h"
9 
10 #include <algorithm>
11 #include <cmath>
12 #include <cstdio>
13 #include <cstdlib>
14 #include <cstring>
15 #include <functional>
16 #include <sstream>
17 
18 #include "ability.h"
19 #include "acquire.h"
20 #include "act-iter.h"
21 #include "areas.h"
22 #include "attitude-change.h"
23 #include "branch.h"
24 #include "chardump.h"
25 #include "coordit.h"
26 #include "dactions.h"
27 #include "database.h"
28 #include "decks.h"
29 #include "delay.h"
30 #include "describe-god.h"
31 #include "dgn-event.h"
32 #include "dlua.h"
33 #include "english.h"
34 #include "env.h"
35 #include "god-abil.h"
36 #include "god-companions.h"
37 #include "god-conduct.h"
38 #include "god-item.h"
39 #include "god-passive.h"
40 #include "god-prayer.h"
41 #include "god-wrath.h"
42 #include "hints.h"
43 #include "hiscores.h"
44 #include "invent.h"
45 #include "item-name.h"
46 #include "item-prop.h"
47 #include "item-status-flag-type.h"
48 #include "items.h"
49 #include "level-state-type.h"
50 #include "libutil.h"
51 #include "makeitem.h"
52 #include "message.h"
53 #include "mon-gear.h" // give_shield
54 #include "mon-place.h"
55 #include "mutation.h"
56 #include "nearby-danger.h"
57 #include "notes.h"
58 #include "output.h"
59 #include "player-equip.h"
60 #include "player-stats.h"
61 #include "prompt.h"
62 #include "randbook.h"
63 #include "shopping.h"
64 #include "skills.h"
65 #include "spl-book.h"
66 #include "sprint.h"
67 #include "state.h"
68 #include "stringutil.h"
69 #include "tag-version.h"
70 #include "terrain.h"
71 #include "transform.h"
72 #include "view.h"
73 
74 #ifdef DEBUG_RELIGION
75 #    define DEBUG_DIAGNOSTICS
76 #    define DEBUG_GIFTS
77 #    define DEBUG_SACRIFICE
78 #    define DEBUG_PIETY
79 #endif
80 
81 #define PIETY_HYSTERESIS_LIMIT 1
82 
83 static weapon_type _hepliaklqana_weapon_type(monster_type mc, int HD);
84 static brand_type _hepliaklqana_weapon_brand(monster_type mc, int HD);
85 static armour_type _hepliaklqana_shield_type(monster_type mc, int HD);
86 static special_armour_type _hepliaklqana_shield_ego(int HD);
87 
88 const vector<god_power> god_powers[NUM_GODS] =
89 {
90     // no god
91     { },
92 
93     // Zin
94     {   { 1, ABIL_ZIN_RECITE, "recite Zin's Axioms of Law" },
95         { 2, ABIL_ZIN_VITALISATION, "call upon Zin for vitalisation" },
96         { 3, ABIL_ZIN_IMPRISON, "call upon Zin to imprison the lawless" },
97         { 5, ABIL_ZIN_SANCTUARY, "call upon Zin to create a sanctuary" },
98         { 6, "Zin will now cleanse your potions of mutation.",
99              "Zin will no longer cleanse your potions of mutation.",
100              "Zin will cleanse your potions of mutation." },
101         {-1, ABIL_ZIN_DONATE_GOLD, "donate money to Zin" },
102     },
103 
104     // TSO
105     {   { 1, "You and your allies can now gain power from killing the unholy and evil.",
106              "You and your allies can no longer gain power from killing the unholy and evil.",
107              "You and your allies can gain power from killing the unholy and evil." },
108         { 2, ABIL_TSO_DIVINE_SHIELD, "call upon the Shining One for a divine shield" },
109         { 4, ABIL_TSO_CLEANSING_FLAME, "channel blasts of cleansing flame", },
110         { 5, ABIL_TSO_SUMMON_DIVINE_WARRIOR, "summon a divine warrior" },
111         { 7, ABIL_TSO_BLESS_WEAPON,
112              "The Shining One will bless your weapon with holy wrath... once.",
113              "The Shining One is no longer ready to bless your weapon." },
114     },
115 
116     // Kikubaaqudgha
117     {   { 1, ABIL_KIKU_RECEIVE_CORPSES, "receive cadavers from Kikubaaqudgha" },
118         { 2, "Kikubaaqudgha is now protecting you from necromantic miscasts and death curses.",
119              "Kikubaaqudgha will no longer protect you from necromantic miscasts or death curses.",
120              "Kikubaaqudgha protects you from necromantic miscasts and death curses." },
121         { 4, "Kikubaaqudgha is now protecting you from unholy torment.",
122              "Kikubaaqudgha will no longer protect you from unholy torment.",
123              "Kikubaaqudgha protects you from unholy torment." },
124         { 5, ABIL_KIKU_TORMENT, "invoke torment by sacrificing a corpse" },
125         { 7, ABIL_KIKU_BLESS_WEAPON,
126              "Kikubaaqudgha will grant you forbidden knowledge or bloody your weapon with pain... once.",
127              "Kikubaaqudgha is no longer ready to enhance your necromancy." },
128         { 7, ABIL_KIKU_GIFT_CAPSTONE_SPELLS,
129              "Kikubaaqudgha will grant you forbidden knowledge.",
130              "Kikubaaqudgha is no longer ready to enhance your necromancy." },
131     },
132 
133     // Yredelemnul
134     {   { 1, ABIL_YRED_ANIMATE_REMAINS, "animate remains" },
135         { 2, ABIL_YRED_RECALL_UNDEAD_SLAVES, "recall your undead slaves" },
136         { 2, ABIL_YRED_INJURY_MIRROR, "mirror injuries on your foes" },
137         { 3, ABIL_YRED_ANIMATE_DEAD, "animate legions of the dead" },
138         { 3, "Yredelemnul will now gift you servants as you gain piety.",
139              "Yredelemnul will no longer gift you servants.",
140              "Yredelemnul will gift you servants as you gain piety." },
141         { 4, ABIL_YRED_DRAIN_LIFE, "drain ambient life force" },
142         { 5, ABIL_YRED_ENSLAVE_SOUL, "enslave living souls" },
143     },
144 
145     // Xom
146     { },
147 
148     // Vehumet
149     {   { 1, "gain magical power from killing" },
150         { 3, "Vehumet is now aiding your destructive spells.",
151              "Vehumet will no longer aid your destructive spells.",
152              "Vehumet aids your destructive spells." },
153         { 4, "Vehumet is now extending the range of your destructive spells.",
154              "Vehumet will no longer extend the range of your destructive spells.",
155              "Vehumet extends the range of your destructive spells." },
156     },
157 
158     // Okawaru
159     {   { 1, ABIL_OKAWARU_HEROISM, "gain great but temporary skills" },
160         { 3, "Okawaru will now gift you ammunition as you gain piety.",
161              "Okawaru will no longer gift you ammunition.",
162              "Okawaru will gift you ammunition as you gain piety." },
163         { 5, ABIL_OKAWARU_FINESSE, "speed up your combat" },
164         { 5, "Okawaru will now gift you equipment as you gain piety.",
165              "Okawaru will no longer gift you equipment.",
166              "Okawaru will gift you equipment as you gain piety." },
167     },
168 
169     // Makhleb
170     {   { 1, "gain health from killing" },
171         { 2, ABIL_MAKHLEB_MINOR_DESTRUCTION,
172              "harness Makhleb's destructive might" },
173         { 3, ABIL_MAKHLEB_LESSER_SERVANT_OF_MAKHLEB,
174              "summon a lesser servant of Makhleb" },
175         { 4, ABIL_MAKHLEB_MAJOR_DESTRUCTION,
176              "hurl Makhleb's greater destruction" },
177         { 5, ABIL_MAKHLEB_GREATER_SERVANT_OF_MAKHLEB,
178              "summon a greater servant of Makhleb" },
179     },
180 
181     // Sif Muna
182     {   { 1, ABIL_SIF_MUNA_CHANNEL_ENERGY,
183              "call upon Sif Muna for magical energy" },
184         { 3, ABIL_SIF_MUNA_FORGET_SPELL,
185              "freely open your mind to new spells",
186              "forget spells at will" },
187         { 4, ABIL_SIF_MUNA_DIVINE_EXEGESIS,
188              "call upon Sif Muna to cast any spell from your library" },
189         { 5, "Sif Muna will now gift you books as you gain piety.",
190              "Sif Muna will no longer gift you books.",
191              "Sif Muna will gift you books as you gain piety." },
192     },
193 
194     // Trog
195     {
196         { 1, ABIL_TROG_BERSERK, "go berserk at will" },
197         { 2, ABIL_TROG_HAND,
198              "call upon Trog for regeneration and willpower" },
199         { 4, ABIL_TROG_BROTHERS_IN_ARMS, "call in reinforcements" },
200         { 5, "Trog will now gift you melee weapons as you gain piety.",
201              "Trog will no longer gift you weapons.",
202              "Trog will gift you melee weapons as you gain piety." },
203     },
204 
205     // Nemelex
206     {
207         { 0, "draw from decks of power" },
208         { 1, "Nemelex will now gift you decks of power as you gain piety.",
209              "Nemelex will no longer gift you decks.",
210              "Nemelex will gift you decks of power as you gain piety." },
211         { 3, ABIL_NEMELEX_TRIPLE_DRAW, "choose one out of three cards" },
212         { 4, ABIL_NEMELEX_DEAL_FOUR, "deal four cards at a time" },
213         { 5, ABIL_NEMELEX_STACK_FIVE, "stack five cards from your decks",
214                                     "stack cards" },
215     },
216 
217     // Elyvilon
218     {   { 1, ABIL_ELYVILON_LESSER_HEALING, "provide lesser healing for yourself" },
219         { 2, ABIL_ELYVILON_HEAL_OTHER, "heal and attempt to pacify others" },
220         { 3, ABIL_ELYVILON_PURIFICATION, "purify yourself" },
221         { 4, ABIL_ELYVILON_GREATER_HEALING, "provide greater healing for yourself" },
222         { 5, ABIL_ELYVILON_DIVINE_VIGOUR, "call upon Elyvilon for divine vigour" },
223         { 1, ABIL_ELYVILON_LIFESAVING, "call on Elyvilon to save your life" },
224     },
225 
226     // Lugonu
227     {   { 1, ABIL_LUGONU_ABYSS_EXIT,
228              "depart the Abyss",
229              "depart the Abyss at will" },
230         { 2, ABIL_LUGONU_BEND_SPACE, "bend space around yourself" },
231         { 3, ABIL_LUGONU_BANISH, "banish your foes" },
232         { 4, ABIL_LUGONU_CORRUPT, "corrupt the fabric of space" },
233         { 5, ABIL_LUGONU_ABYSS_ENTER, "gate yourself to the Abyss" },
234         { 7, ABIL_LUGONU_BLESS_WEAPON,
235              "Lugonu will corrupt your weapon with distortion... once.",
236              "Lugonu is no longer ready to corrupt your weapon." },
237     },
238 
239     // Beogh
240     {   { 2, ABIL_BEOGH_SMITING, "smite your foes" },
241         { 3, "gain orcish followers" },
242         { 4, ABIL_BEOGH_RECALL_ORCISH_FOLLOWERS, "recall your orcish followers" },
243         { 5, "walk on water" },
244         { 5, ABIL_BEOGH_GIFT_ITEM, "give items to your followers" },
245         { 6, ABIL_BEOGH_RESURRECTION, "revive fallen orcs" },
246     },
247 
248     // Jiyva
249     {   { 1, ABIL_JIYVA_CALL_JELLY, "request a jelly" },
250         { 3, "Jiyva will now mutate your body and modify your attributes as you gain piety.",
251              "Jiyva will no longer mutate your body and modify your attributes.",
252              "Jiyva will mutate your body and modify your attributes as you gain piety." },
253         { 3, "Jiyva is now protecting you from corrosive effects.",
254              "Jiyva will no longer protect you from corrosive effects.",
255              "Jiyva protects you from corrosive effects." },
256         { 4, ABIL_JIYVA_SLIMIFY, "turn your foes to slime" },
257         { 5, "You may now expel jellies when seriously injured.",
258              "You will no longer expel jellies when injured.",
259              "You may expel jellies when seriously injured." },
260         { 5, ABIL_JIYVA_CURE_BAD_MUTATION,
261              "call upon Jiyva to remove your harmful mutations" },
262     },
263 
264     // Fedhas
265     {
266         { 2, ABIL_FEDHAS_WALL_OF_BRIARS, "encircle yourself with summoned briar patches"},
267         { 3, ABIL_FEDHAS_GROW_BALLISTOMYCETE, "grow a ballistomycete" },
268         { 4, ABIL_FEDHAS_OVERGROW, "transform dungeon walls and trees into plant allies"},
269         { 5, ABIL_FEDHAS_GROW_OKLOB, "grow an oklob plant" },
270     },
271 
272     // Cheibriados
273     {   { 0, ABIL_CHEIBRIADOS_TIME_BEND, "bend time to slow others" },
274         { 1, "Cheibriados is now slowing the effects of poison on you.",
275              "Cheibriados will no longer slow the effects of poison on you.",
276              "Cheibriados slows the effects of poison on you." },
277         { 3, ABIL_CHEIBRIADOS_DISTORTION, "warp the flow of time around you" },
278         { 4, ABIL_CHEIBRIADOS_SLOUCH, "inflict damage on those overly hasty" },
279         { 5, ABIL_CHEIBRIADOS_TIME_STEP, "step out of the flow of time" },
280     },
281 
282     // Ashenzari
283     {   { 0, "Ashenzari warns you of distant threats and treasures.\n"
284              "Ashenzari reveals the structure of the dungeon to you.\n"
285              "Ashenzari shows you where magical portals lie.\n"
286              "Ashenzari prevents you from stumbling into unseen traps.\n"
287              "Ashenzari identifies your possessions." },
288         { 2, "Ashenzari will now reveal the unseen.",
289              "Ashenzari will no longer reveal the unseen.",
290              "Ashenzari reveals the unseen." },
291         { 3, "Ashenzari will now keep your mind clear.",
292              "Ashenzari will no longer keep your mind clear.",
293              "Ashenzari keeps your mind clear." },
294         { 4, "Ashenzari will now grant you astral sight.",
295              "Ashenzari will no longer grant you astral sight.",
296              "Ashenzari grants you astral sight." },
297     },
298 
299     // Dithmenos
300     {   { 2, ABIL_DITHMENOS_SHADOW_STEP,
301              "step into the shadows of nearby creatures" },
302         { 3, "You will now sometimes bleed smoke when heavily injured by enemies.",
303              "You will no longer bleed smoke.",
304              "You sometimes bleed smoke when heavily injured by enemies." },
305         { 4, "Your shadow now sometimes tangibly mimics your actions.",
306              "Your shadow no longer tangibly mimics your actions.",
307              "Your shadow sometimes tangibly mimics your actions." },
308         { 5, ABIL_DITHMENOS_SHADOW_FORM,
309              "transform into a swirling mass of shadows" },
310     },
311 
312     // Gozag
313     {   { 0, ABIL_GOZAG_POTION_PETITION, "petition Gozag for potion effects" },
314         { 0, ABIL_GOZAG_CALL_MERCHANT,
315              "fund merchants seeking to open stores in the dungeon" },
316         { 0, ABIL_GOZAG_BRIBE_BRANCH,
317              "bribe branches to halt enemies' attacks and recruit allies" },
318     },
319 
320     // Qazlal
321     {
322         { 0, "Qazlal grants you and your divine allies immunity to clouds." },
323         { 1, "You are now surrounded by a storm.",
324              "Your storm dissipates completely.",
325              "You are surrounded by a storm." },
326         { 2, ABIL_QAZLAL_UPHEAVAL, "call upon nature to destroy your foes" },
327         { 3, ABIL_QAZLAL_ELEMENTAL_FORCE, "give life to nearby clouds" },
328         { 4, "The storm surrounding you is now powerful enough to repel missiles.",
329              "The storm surrounding you is now too weak to repel missiles.",
330              "The storm surrounding you is powerful enough to repel missiles." },
331         { 4, "You will now adapt resistances upon receiving elemental damage.",
332              "You will no longer adapt resistances upon receiving elemental damage.",
333              "You adapt resistances upon receiving elemental damage." },
334         { 5, ABIL_QAZLAL_DISASTER_AREA,
335              "call upon nature's wrath in a wide area around you" },
336     },
337 
338     // Ru
339     {   { 1, "You now exude an aura of power that intimidates your foes.",
340              "You no longer exude an aura of power that intimidates your foes.",
341              "You now exude an aura of power that intimidates your foes." },
342         { 2, "Your aura of power can now strike those that harm you.",
343              "Your aura of power no longer strikes those that harm you.",
344              "Your aura of power can strike those that harm you." },
345         { 3, ABIL_RU_DRAW_OUT_POWER, "heal your body and restore your magic" },
346         { 4, ABIL_RU_POWER_LEAP, "gather your power into a mighty leap" },
347         { 5, ABIL_RU_APOCALYPSE, "wreak a terrible wrath on your foes" },
348     },
349 
350 #if TAG_MAJOR_VERSION == 34
351     // Pakellas
352     {
353         { 0, "gain magical power from killing" },
354     },
355 #endif
356 
357     // Uskayaw
358     {
359         { 1, ABIL_USKAYAW_STOMP, "stomp with the beat" },
360         { 2, ABIL_USKAYAW_LINE_PASS, "pass through a line of other dancers" },
361         { 3, "Uskayaw will force your foes to helplessly watch your dance.",
362              "Uskayaw will no longer force your foes to helplessly watch your dance."},
363         { 4, "Uskayaw will force your foes to share their pain.",
364              "Uskayaw will no longer force your foes to share their pain."},
365         { 5, ABIL_USKAYAW_GRAND_FINALE, "merge with and destroy a victim" },
366     },
367 
368     // Hepliaklqana
369     {   { 1, ABIL_HEPLIAKLQANA_RECALL, "recall your ancestor" },
370         { 1, ABIL_HEPLIAKLQANA_IDENTITY, "remember your ancestor's identity" },
371         { 3, ABIL_HEPLIAKLQANA_TRANSFERENCE, "swap creatures with your ancestor" },
372         { 4, ABIL_HEPLIAKLQANA_IDEALISE, "heal and protect your ancestor" },
373         { 5, "drain nearby creatures when transferring your ancestor"},
374     },
375 
376     // Wu Jian
377     {   { 0, "perform damaging attacks by moving towards foes",
378              "perform lunging strikes" },
379         { 1, "lightly attack monsters by moving around them",
380              "perform spinning attacks" },
381         { 2, ABIL_WU_JIAN_WALLJUMP,
382              "perform airborne attacks" },
383         { 3, ABIL_WU_JIAN_SERPENTS_LASH, "briefly move at supernatural speeds",
384              "move at supernatural speeds" },
385         { 5, ABIL_WU_JIAN_HEAVENLY_STORM,
386              "summon a storm of heavenly clouds to empower your attacks",
387              "summon a storm of heavenly clouds" },
388     },
389 };
390 
get_god_powers(god_type god)391 vector<god_power> get_god_powers(god_type god)
392 {
393     vector<god_power> ret;
394     for (const auto& power : god_powers[god])
395     {
396         // hack :( don't show fake hp restore
397         if (god == GOD_VEHUMET && power.rank == 1
398             && you.has_mutation(MUT_HP_CASTING))
399         {
400             continue;
401         }
402         if (!(power.abil != ABIL_NON_ABILITY
403               && fixup_ability(power.abil) == ABIL_NON_ABILITY))
404         {
405             ret.push_back(power);
406         }
407     }
408     return ret;
409 }
410 
411 /**
412  * Print a description of getting/losing this power.
413  *
414  * @param gaining If true, use this->gain; otherwise, use this->loss.
415  * @param fmt  A string containing "%s" that will be used as a format
416  *             string with our string as parameter; it is not used if
417  *             our string begins with a capital letter. IF THIS DOES
418  *             NOT CONTAIN "%s", OR CONTAINS OTHER FORMAT SPECIFIERS,
419  *             BEHAVIOUR IS UNDEFINED.
420  * @return a string suitable for being read by the user.
421  */
display(bool gaining,const char * fmt) const422 void god_power::display(bool gaining, const char* fmt) const
423 {
424     // hack: don't mention the necronomicon alone unless it wasn't
425     // already mentioned by the other message
426     if (abil == ABIL_KIKU_GIFT_CAPSTONE_SPELLS
427         && !you.has_mutation(MUT_NO_GRASPING))
428     {
429         return;
430     }
431     const char* str = gaining ? gain : loss;
432     if (isupper(str[0]))
433         god_speaks(you.religion, str);
434     else
435         god_speaks(you.religion, make_stringf(fmt, str).c_str());
436 }
437 
438 static void _place_delayed_monsters();
439 
is_evil_god(god_type god)440 bool is_evil_god(god_type god)
441 {
442     return god == GOD_KIKUBAAQUDGHA
443            || god == GOD_MAKHLEB
444            || god == GOD_YREDELEMNUL
445            || god == GOD_BEOGH
446            || god == GOD_LUGONU
447            || god == GOD_DITHMENOS;
448 }
449 
is_good_god(god_type god)450 bool is_good_god(god_type god)
451 {
452     return god == GOD_ZIN
453            || god == GOD_SHINING_ONE
454            || god == GOD_ELYVILON;
455 }
456 
is_chaotic_god(god_type god)457 bool is_chaotic_god(god_type god)
458 {
459     return god == GOD_XOM
460            || god == GOD_MAKHLEB
461            || god == GOD_LUGONU
462            || god == GOD_JIYVA;
463 }
464 
is_unknown_god(god_type god)465 bool is_unknown_god(god_type god)
466 {
467     return god == GOD_NAMELESS;
468 }
469 
470 // Not appearing in new games, but still extant.
_is_disabled_god(god_type god)471 static bool _is_disabled_god(god_type god)
472 {
473     switch (god)
474     {
475 #if TAG_MAJOR_VERSION == 34
476     // Disabled, pending a rework.
477     case GOD_PAKELLAS:
478         return true;
479 #endif
480 
481     default:
482         return false;
483     }
484 }
485 
is_unavailable_god(god_type god)486 bool is_unavailable_god(god_type god)
487 {
488     if (_is_disabled_god(god))
489         return true;
490 
491     if (god == GOD_JIYVA && jiyva_is_dead())
492         return true;
493 
494     return false;
495 }
496 
god_has_name(god_type god)497 bool god_has_name(god_type god)
498 {
499     return god != GOD_NO_GOD && god != GOD_NAMELESS;
500 }
501 
random_god()502 god_type random_god()
503 {
504     god_type god;
505 
506     do
507     {
508         god = static_cast<god_type>(random2(NUM_GODS - 1) + 1);
509     }
510     while (is_unavailable_god(god));
511 
512     return god;
513 }
514 
515 
god_iterator()516 god_iterator::god_iterator() :
517     i(0) { } // might be ok to start with GOD_ZIN instead?
518 
operator bool() const519 god_iterator::operator bool() const
520 {
521     return i < NUM_GODS;
522 }
523 
operator *() const524 god_type god_iterator::operator*() const
525 {
526     if (i < NUM_GODS)
527         return (god_type)i;
528     else
529         return GOD_NO_GOD;
530 }
531 
operator ->() const532 god_type god_iterator::operator->() const
533 {
534     return **this;
535 }
536 
operator ++()537 god_iterator& god_iterator::operator++()
538 {
539     ++i;
540     return *this;
541 }
542 
operator ++(int)543 god_iterator god_iterator::operator++(int)
544 {
545     god_iterator copy = *this;
546     ++(*this);
547     return copy;
548 }
549 
550 
active_penance(god_type god)551 bool active_penance(god_type god)
552 {
553     // Good gods only have active wrath when they hate your current god.
554     return player_under_penance(god)
555            && !is_unavailable_god(god)
556            && god != GOD_ASHENZARI
557            && god != GOD_GOZAG
558            && god != GOD_RU
559            && god != GOD_HEPLIAKLQANA
560 #if TAG_MAJOR_VERSION == 34
561            && god != GOD_PAKELLAS
562 #endif
563            && god != GOD_ELYVILON
564            && (god == you.religion && !is_good_god(god)
565                || god_hates_your_god(god, you.religion));
566 }
567 
568 // True for gods whose wrath is passive and expires with XP gain.
xp_penance(god_type god)569 bool xp_penance(god_type god)
570 {
571     return player_under_penance(god)
572            && !is_unavailable_god(god)
573            && (god == GOD_ASHENZARI
574                || god == GOD_GOZAG
575                || god == GOD_HEPLIAKLQANA
576 #if TAG_MAJOR_VERSION == 34
577                || god == GOD_PAKELLAS
578 #endif
579                || god == GOD_ELYVILON)
580            && god_hates_your_god(god, you.religion);
581 }
582 
dec_penance(god_type god,int val)583 void dec_penance(god_type god, int val)
584 {
585     if (val <= 0 || you.penance[god] <= 0)
586         return;
587 
588 #ifdef DEBUG_PIETY
589     mprf(MSGCH_DIAGNOSTICS, "Decreasing penance by %d", val);
590 #endif
591     if (you.penance[god] <= val)
592     {
593         const bool had_halo = have_passive(passive_t::halo);
594         const bool had_umbra = have_passive(passive_t::umbra);
595 
596         you.penance[god] = 0;
597 
598         mark_milestone("god.mollify",
599                        "mollified " + god_name(god) + ".");
600 
601         const bool dead_jiyva = (god == GOD_JIYVA && jiyva_is_dead());
602 
603         simple_god_message(
604             make_stringf(" seems mollified%s.",
605                          dead_jiyva ? ", and vanishes" : "").c_str(),
606             god);
607 
608         if (dead_jiyva)
609             add_daction(DACT_REMOVE_JIYVA_ALTARS);
610 
611         take_note(Note(NOTE_MOLLIFY_GOD, god));
612 
613         if (you_worship(god))
614         {
615             // Redraw piety display and, in case the best skill is Invocations,
616             // redraw the god title.
617             you.redraw_title = true;
618 
619             // TSO's halo is once more available.
620             if (!had_halo && have_passive(passive_t::halo))
621             {
622                 mprf(MSGCH_GOD, "Your divine halo returns!");
623                 invalidate_agrid(true);
624             }
625             if (!had_umbra && have_passive(passive_t::umbra))
626             {
627                 mprf(MSGCH_GOD, "Your aura of darkness returns!");
628                 invalidate_agrid(true);
629             }
630             if (have_passive(passive_t::sinv))
631             {
632                 mprf(MSGCH_GOD, "Your vision regains its divine sight.");
633                 autotoggle_autopickup(false);
634             }
635             if (have_passive(passive_t::stat_boost))
636             {
637                 simple_god_message(" restores the support of your attributes.");
638                 redraw_screen();
639                 update_screen();
640                 notify_stat_change();
641             }
642             if (have_passive(passive_t::storm_shield))
643             {
644                 mprf(MSGCH_GOD, "A storm instantly forms around you!");
645                 you.redraw_armour_class = true; // also handles shields
646             }
647             // When you've worked through all your penance, you get
648             // another chance to make hostile slimes strict neutral.
649 
650             if (have_passive(passive_t::neutral_slimes))
651                 add_daction(DACT_SLIME_NEW_ATTEMPT);
652 
653             if (have_passive(passive_t::friendly_plants)
654                 && env.forest_awoken_until)
655             {
656                 // XXX: add a dact here & on-join to handle offlevel
657                 // awakened forests?
658                 for (monster_iterator mi; mi; ++mi)
659                      mi->del_ench(ENCH_AWAKEN_FOREST);
660             }
661         }
662         else
663         {
664 #if TAG_MAJOR_VERSION == 34
665             if (god == GOD_PAKELLAS)
666             {
667                 // Penance just ended w/o worshipping Pakellas;
668                 // notify the player that MP regeneration will start again.
669                 mprf(MSGCH_GOD, god, "You begin regenerating magic.");
670             }
671             else
672 #endif
673             if (god == GOD_HEPLIAKLQANA)
674             {
675                 calc_hp(); // frailty ends
676                 mprf(MSGCH_GOD, god, "Your full life essence returns.");
677             }
678         }
679     }
680     else
681     {
682         you.penance[god] -= val;
683         return;
684     }
685 
686     // We only get this far if we just mollified a god.
687     // If we just mollified a god, see if we have any angry gods left.
688     // If we don't, clear the stored wrath / XP counter.
689     god_iterator it;
690     for (; it; ++it)
691     {
692         if (active_penance(*it))
693             break;
694     }
695 
696     if (it)
697         return;
698 
699     you.attribute[ATTR_GOD_WRATH_COUNT] = 0;
700     you.attribute[ATTR_GOD_WRATH_XP] = 0;
701 }
702 
dec_penance(int val)703 void dec_penance(int val)
704 {
705     dec_penance(you.religion, val);
706 }
707 
708 // TODO: find out what this is duplicating & deduplicate it
_need_water_walking()709 static bool _need_water_walking()
710 {
711     return you.ground_level() && !you.has_mutation(MUT_MERTAIL)
712            && env.grid(you.pos()) == DNGN_DEEP_WATER;
713 }
714 
_grant_temporary_waterwalk()715 static void _grant_temporary_waterwalk()
716 {
717     mprf("Your water-walking will last only until you reach solid ground.");
718     you.props[TEMP_WATERWALK_KEY] = true;
719 }
720 
jiyva_is_dead()721 bool jiyva_is_dead()
722 {
723     return you.royal_jelly_dead
724            && !you_worship(GOD_JIYVA) && !you.penance[GOD_JIYVA];
725 }
726 
set_penance_xp_timeout()727 void set_penance_xp_timeout()
728 {
729     if (you.attribute[ATTR_GOD_WRATH_XP] > 0)
730         return;
731 
732     // TODO: make this more random?
733     you.attribute[ATTR_GOD_WRATH_XP] +=
734         max(div_rand_round(exp_needed(you.experience_level + 1)
735                           - exp_needed(you.experience_level),
736                           200),
737             1);
738 }
739 
_inc_penance(god_type god,int val)740 static void _inc_penance(god_type god, int val)
741 {
742     if (val <= 0)
743         return;
744 
745     if (!player_under_penance(god))
746     {
747         god_acting gdact(god, true);
748 
749         take_note(Note(NOTE_PENANCE, god));
750 
751         const bool had_halo = have_passive(passive_t::halo);
752         const bool had_umbra = have_passive(passive_t::umbra);
753 
754         you.penance[god] += val;
755         you.penance[god] = min((uint8_t)MAX_PENANCE, you.penance[god]);
756 
757         if (had_halo && !have_passive(passive_t::halo))
758         {
759             mprf(MSGCH_GOD, god, "Your divine halo fades away.");
760             invalidate_agrid();
761         }
762         if (had_umbra && !have_passive(passive_t::umbra))
763         {
764             mprf(MSGCH_GOD, god, "Your aura of darkness fades away.");
765             invalidate_agrid();
766         }
767 
768         if (will_have_passive(passive_t::water_walk)
769             && _need_water_walking() && !have_passive(passive_t::water_walk))
770         {
771             _grant_temporary_waterwalk();
772         }
773 
774         if (will_have_passive(passive_t::stat_boost))
775         {
776             redraw_screen();
777             update_screen();
778             notify_stat_change();
779         }
780 
781         if (god == GOD_TROG)
782         {
783             if (you.duration[DUR_TROGS_HAND])
784                 trog_remove_trogs_hand();
785 
786             make_god_gifts_disappear();
787         }
788         else if (god == GOD_ZIN)
789         {
790             if (you.duration[DUR_DIVINE_STAMINA])
791                 zin_remove_divine_stamina();
792             if (env.sanctuary_time)
793                 remove_sanctuary();
794         }
795         else if (god == GOD_SHINING_ONE)
796         {
797             if (you.duration[DUR_DIVINE_SHIELD])
798                 tso_remove_divine_shield();
799 
800             make_god_gifts_disappear();
801         }
802         else if (god == GOD_ELYVILON)
803         {
804             if (you.duration[DUR_DIVINE_VIGOUR])
805                 elyvilon_remove_divine_vigour();
806         }
807         else if (god == GOD_JIYVA)
808         {
809             if (you.duration[DUR_SLIMIFY])
810                 you.duration[DUR_SLIMIFY] = 0;
811         }
812         else if (god == GOD_QAZLAL)
813         {
814             // Can't use have_passive(passive_t::storm_shield) because we
815             // just gained penance.
816             if (you.piety >= piety_breakpoint(0))
817             {
818                 mprf(MSGCH_GOD, god, "The storm surrounding you dissipates.");
819                 you.redraw_armour_class = true;
820             }
821             if (you.duration[DUR_QAZLAL_FIRE_RES])
822             {
823                 mprf(MSGCH_DURATION, "Your resistance to fire fades away.");
824                 you.duration[DUR_QAZLAL_FIRE_RES] = 0;
825             }
826             if (you.duration[DUR_QAZLAL_COLD_RES])
827             {
828                 mprf(MSGCH_DURATION, "Your resistance to cold fades away.");
829                 you.duration[DUR_QAZLAL_COLD_RES] = 0;
830             }
831             if (you.duration[DUR_QAZLAL_ELEC_RES])
832             {
833                 mprf(MSGCH_DURATION,
834                      "Your resistance to electricity fades away.");
835                 you.duration[DUR_QAZLAL_ELEC_RES] = 0;
836             }
837             if (you.duration[DUR_QAZLAL_AC])
838             {
839                 mprf(MSGCH_DURATION,
840                      "Your resistance to physical damage fades away.");
841                 you.duration[DUR_QAZLAL_AC] = 0;
842                 you.redraw_armour_class = true;
843             }
844         }
845         else if (god == GOD_SIF_MUNA)
846         {
847             if (you.duration[DUR_CHANNEL_ENERGY])
848                 you.duration[DUR_CHANNEL_ENERGY] = 0;
849 #if TAG_MAJOR_VERSION == 34
850             if (you.attribute[ATTR_DIVINE_ENERGY])
851                 you.attribute[ATTR_DIVINE_ENERGY] = 0;
852 #endif
853         }
854         else if (god == GOD_OKAWARU)
855         {
856             if (you.duration[DUR_HEROISM])
857                 okawaru_remove_heroism();
858             if (you.duration[DUR_FINESSE])
859                 okawaru_remove_finesse();
860         }
861 
862         if (you_worship(god))
863         {
864             // Redraw piety display and, in case the best skill is Invocations,
865             // redraw the god title.
866             you.redraw_title = true;
867         }
868     }
869     else
870     {
871         you.penance[god] += val;
872         you.penance[god] = min((uint8_t)MAX_PENANCE, you.penance[god]);
873     }
874 
875     set_penance_xp_timeout();
876 }
877 
_inc_penance(int val)878 static void _inc_penance(int val)
879 {
880     _inc_penance(you.religion, val);
881 }
882 
_set_penance(god_type god,int val)883 static void _set_penance(god_type god, int val)
884 {
885     you.penance[god] = val;
886 }
887 
_set_wrath_penance(god_type god)888 static void _set_wrath_penance(god_type god)
889 {
890     _set_penance(god, initial_wrath_penance_for(god));
891 }
892 
_inc_gift_timeout(int val)893 static void _inc_gift_timeout(int val)
894 {
895     if (200 - you.gift_timeout < val)
896         you.gift_timeout = 200;
897     else
898         you.gift_timeout += val;
899 }
900 
901 // These are sorted in order of power.
902 static monster_type _yred_servants[] =
903 {
904     MONS_MUMMY, MONS_WIGHT, MONS_FLYING_SKULL, MONS_WRAITH,
905     MONS_VAMPIRE, MONS_PHANTASMAL_WARRIOR, MONS_SKELETAL_WARRIOR,
906     MONS_FLAYED_GHOST, MONS_VAMPIRE_KNIGHT, MONS_GHOUL, MONS_BONE_DRAGON,
907     MONS_PROFANE_SERVITOR
908 };
909 
910 #define MIN_YRED_SERVANT_THRESHOLD 3
911 #define MAX_YRED_SERVANT_THRESHOLD ARRAYSZ(_yred_servants)
912 
_yred_high_level_servant(monster_type type)913 static bool _yred_high_level_servant(monster_type type)
914 {
915     return type == MONS_BONE_DRAGON
916            || type == MONS_PROFANE_SERVITOR;
917 }
918 
yred_random_servants(unsigned int threshold,bool force_hostile)919 int yred_random_servants(unsigned int threshold, bool force_hostile)
920 {
921     if (threshold == 0)
922     {
923         if (force_hostile)
924         {
925             // This implies wrath - scale the threshold with XL.
926             threshold =
927                 MIN_YRED_SERVANT_THRESHOLD
928                 + (MAX_YRED_SERVANT_THRESHOLD - MIN_YRED_SERVANT_THRESHOLD)
929                   * you.experience_level / 27;
930         }
931         else
932             threshold = ARRAYSZ(_yred_servants);
933     }
934     else
935     {
936         threshold = min(static_cast<unsigned int>(ARRAYSZ(_yred_servants)),
937                         threshold);
938     }
939 
940     const unsigned int servant = random2(threshold);
941 
942     // Skip some of the weakest servants, once the threshold is high.
943     if ((servant + 2) * 2 < threshold)
944         return -1;
945 
946     monster_type mon_type = _yred_servants[servant];
947 
948     // Cap some of the strongest servants.
949     if (!force_hostile && _yred_high_level_servant(mon_type))
950     {
951         int current_high_level = 0;
952         for (auto &entry : companion_list)
953         {
954             monster* mons = monster_by_mid(entry.first);
955             if (!mons)
956                 mons = &entry.second.mons.mons;
957             if (_yred_high_level_servant(mons->type))
958                 current_high_level++;
959         }
960 
961         if (current_high_level >= 3)
962             return -1;
963     }
964 
965     int how_many = (mon_type == MONS_FLYING_SKULL) ? 2 + random2(4)
966                                                    : 1;
967 
968     mgen_data mg(mon_type, !force_hostile ? BEH_FRIENDLY : BEH_HOSTILE,
969                  you.pos(), MHITYOU);
970     mg.set_summoned(!force_hostile ? &you : 0, 0, 0, GOD_YREDELEMNUL);
971 
972     if (force_hostile)
973         mg.non_actor_summoner = "the anger of Yredelemnul";
974 
975     int created = 0;
976     if (force_hostile)
977     {
978         mg.extra_flags |= (MF_NO_REWARD | MF_HARD_RESET);
979 
980         for (; how_many > 0; --how_many)
981         {
982             if (create_monster(mg))
983                 created++;
984         }
985     }
986     else
987     {
988         for (; how_many > 0; --how_many)
989             delayed_monster(mg);
990     }
991 
992     return created;
993 }
994 
_want_missile_gift()995 static bool _want_missile_gift()
996 {
997     skill_type sk = best_skill(SK_SLINGS, SK_THROWING);
998     // Default to throwing if all missile skills are at zero.
999     if (you.skills[sk] == 0)
1000         sk = SK_THROWING;
1001     return you.piety >= piety_breakpoint(2)
1002            && random2(you.piety) > 70
1003            && one_chance_in(8)
1004            && x_chance_in_y(1 + you.skills[sk], 12);
1005 }
1006 
_want_nemelex_gift()1007 static bool _want_nemelex_gift()
1008 {
1009     if (you.piety < piety_breakpoint(0))
1010         return false;
1011     const int piety_over_one_star = you.piety - piety_breakpoint(0);
1012 
1013     // Nemelex will give at least one gift early.
1014     if (!you.num_total_gifts[GOD_NEMELEX_XOBEH]
1015         && x_chance_in_y(piety_over_one_star + 1, piety_breakpoint(1)))
1016     {
1017         return true;
1018     }
1019 
1020     return one_chance_in(3) && x_chance_in_y(piety_over_one_star + 1, MAX_PIETY);
1021 }
1022 
_give_nemelex_gift(bool forced=false)1023 static bool _give_nemelex_gift(bool forced = false)
1024 {
1025     if (!forced && !_want_nemelex_gift())
1026         return false;
1027 
1028     if (gift_cards())
1029     {
1030         simple_god_message(" deals you some cards!");
1031         mprf(MSGCH_GOD, "You now have %s.", deck_summary().c_str());
1032     }
1033     else
1034         simple_god_message(" goes to deal, but finds you have enough cards.");
1035     _inc_gift_timeout(5 + random2avg(9, 2));
1036     you.num_current_gifts[you.religion]++;
1037     you.num_total_gifts[you.religion]++;
1038     take_note(Note(NOTE_GOD_GIFT, you.religion));
1039     return true;
1040 }
1041 
1042 #if TAG_MAJOR_VERSION == 34
1043 /**
1044  * From the given list of items, return a random unseen item, if there are any.
1045  * Otherwise, just return any of them at random.
1046  *
1047  * If we cared, we could make this a template function to return more specific
1048  * types than 'int'. (That's probably not important, though.)
1049  *
1050  * @param item_types        A list of item types to choose from.
1051  * @param seen_func         How to tell whether the item was seen.
1052  * @return                  A random item type; e.g. WAND_ACID.
1053  */
_preferably_unseen_item(const vector<int> & item_types,function<bool (int)> seen_func)1054 static int _preferably_unseen_item(const vector<int> &item_types,
1055                                    function<bool(int)> seen_func)
1056 {
1057     ASSERT(item_types.size());
1058     vector<int> unseen;
1059     for (auto item : item_types)
1060         if (!seen_func(item))
1061             unseen.emplace_back(item);
1062 
1063     if (unseen.size())
1064         return unseen[random2(unseen.size())];
1065     return item_types[random2(item_types.size())];
1066 }
1067 #endif
1068 
_delayed_gift_callback(const mgen_data &,monster * & mon,int placed)1069 static void _delayed_gift_callback(const mgen_data &/*mg*/, monster *&mon,
1070                                    int placed)
1071 {
1072     if (placed <= 0)
1073         return;
1074     ASSERT(mon);
1075 
1076     // Make sure monsters are shown.
1077     viewwindow();
1078     update_screen();
1079     more();
1080     _inc_gift_timeout(4 + random2avg(7, 2));
1081     you.num_current_gifts[you.religion]++;
1082     you.num_total_gifts[you.religion]++;
1083     string gift;
1084     if (placed == 1)
1085         gift = mon->name(DESC_A);
1086     else
1087     {
1088         gift = make_stringf("%d %s", placed,
1089                             pluralise(mon->name(DESC_PLAIN)).c_str());
1090     }
1091 
1092     take_note(Note(NOTE_GOD_GIFT, you.religion, 0, gift));
1093 }
1094 
_jiyva_mutate()1095 static bool _jiyva_mutate()
1096 {
1097     simple_god_message(" alters your body.");
1098 
1099     const int rand = random2(100);
1100 
1101     if (rand < 5)
1102         return delete_mutation(RANDOM_SLIME_MUTATION, "Jiyva's grace", true, false, true);
1103     else if (rand < 30)
1104         return delete_mutation(RANDOM_NON_SLIME_MUTATION, "Jiyva's grace", true, false, true);
1105     else if (rand < 55)
1106         return mutate(RANDOM_MUTATION, "Jiyva's grace", true, false, true);
1107     else if (rand < 75)
1108         return mutate(RANDOM_SLIME_MUTATION, "Jiyva's grace", true, false, true);
1109     else
1110         return mutate(RANDOM_GOOD_MUTATION, "Jiyva's grace", true, false, true);
1111 }
1112 
vehumet_is_offering(spell_type spell)1113 bool vehumet_is_offering(spell_type spell)
1114 {
1115     return you.vehumet_gifts.count(spell);
1116 }
1117 
vehumet_accept_gift(spell_type spell)1118 void vehumet_accept_gift(spell_type spell)
1119 {
1120     if (vehumet_is_offering(spell))
1121     {
1122         you.vehumet_gifts.erase(spell);
1123         you.duration[DUR_VEHUMET_GIFT] = 0;
1124     }
1125 }
1126 
_add_to_old_gifts(spell_type spell)1127 static void _add_to_old_gifts(spell_type spell)
1128 {
1129     you.old_vehumet_gifts.insert(spell);
1130 }
1131 
_is_old_gift(spell_type spell)1132 static bool _is_old_gift(spell_type spell)
1133 {
1134     return you.old_vehumet_gifts.count(spell);
1135 }
1136 
_vehumet_eligible_gift_spells(set<spell_type> excluded_spells)1137 static set<spell_type> _vehumet_eligible_gift_spells(set<spell_type> excluded_spells)
1138 {
1139     set<spell_type> eligible_spells;
1140 
1141     const int gifts = you.num_total_gifts[you.religion];
1142     if (gifts >= NUM_VEHUMET_GIFTS)
1143         return eligible_spells;
1144 
1145     const int min_lev[] = {1,1,2,3,3,4,4,5,5,5,5,6,8};
1146     const int max_lev[] = {1,2,3,4,5,7,7,7,7,7,7,8,9};
1147     COMPILE_CHECK(ARRAYSZ(min_lev) == NUM_VEHUMET_GIFTS);
1148     COMPILE_CHECK(ARRAYSZ(max_lev) == NUM_VEHUMET_GIFTS);
1149     int min_level = min_lev[gifts];
1150     int max_level = max_lev[gifts];
1151 
1152     if (min_level > you.experience_level)
1153         return eligible_spells;
1154 
1155     set<spell_type> backup_spells;
1156     for (int i = 0; i < NUM_SPELLS; ++i)
1157     {
1158         spell_type spell = static_cast<spell_type>(i);
1159         if (!is_valid_spell(spell))
1160             continue;
1161 
1162         if (excluded_spells.count(spell))
1163             continue;
1164 
1165         if (vehumet_supports_spell(spell)
1166             && !you.has_spell(spell)
1167             && !you.spell_library[spell]
1168             && is_player_book_spell(spell)
1169             && spell_difficulty(spell) <= max_level
1170             && spell_difficulty(spell) >= min_level)
1171         {
1172             if (!_is_old_gift(spell))
1173                 eligible_spells.insert(spell);
1174             else
1175                 backup_spells.insert(spell);
1176         }
1177     }
1178     // Don't get stuck just because all spells have been seen/offered.
1179     if (eligible_spells.empty())
1180     {
1181         if (backup_spells.empty())
1182         {
1183             // This is quite improbable to happen, but in this case just
1184             // skip the gift and increment the gift counter.
1185             if (gifts <= 12)
1186             {
1187                 you.num_current_gifts[you.religion]++;
1188                 you.num_total_gifts[you.religion]++;
1189             }
1190         }
1191         return backup_spells;
1192     }
1193     return eligible_spells;
1194 }
1195 
_vehumet_weighting(spell_type spell)1196 static int _vehumet_weighting(spell_type spell)
1197 {
1198     int bias = 100 + elemental_preference(spell, 10);
1199     return bias;
1200 }
1201 
_vehumet_find_spell_gift(set<spell_type> excluded_spells)1202 static spell_type _vehumet_find_spell_gift(set<spell_type> excluded_spells)
1203 {
1204     set<spell_type> eligible_spells = _vehumet_eligible_gift_spells(excluded_spells);
1205     spell_type spell = SPELL_NO_SPELL;
1206     int total_weight = 0;
1207     int this_weight = 0;
1208     for (auto elig : eligible_spells)
1209     {
1210         this_weight = _vehumet_weighting(elig);
1211         total_weight += this_weight;
1212         if (x_chance_in_y(this_weight, total_weight))
1213             spell = elig;
1214     }
1215     return spell;
1216 }
1217 
_vehumet_get_spell_gifts()1218 static set<spell_type> _vehumet_get_spell_gifts()
1219 {
1220     set<spell_type> offers;
1221     unsigned int num_offers = you.num_total_gifts[you.religion] == 12 ? 3 : 1;
1222     while (offers.size() < num_offers)
1223     {
1224         spell_type offer = _vehumet_find_spell_gift(offers);
1225         if (offer == SPELL_NO_SPELL)
1226             break;
1227         offers.insert(offer);
1228     }
1229     return offers;
1230 }
1231 
1232 #if TAG_MAJOR_VERSION == 34
1233 /// Has the player ID'd the given type of wand?
_seen_wand(int wand)1234 static bool _seen_wand(int wand)
1235 {
1236     return get_ident_type(OBJ_WANDS, wand);
1237 }
1238 
_pakellas_low_wand()1239 static int _pakellas_low_wand()
1240 {
1241     static const vector<int> low_wands = {
1242         WAND_FLAME,
1243         WAND_POLYMORPH,
1244     };
1245 
1246     return _preferably_unseen_item(low_wands, _seen_wand);
1247 }
1248 
_pakellas_high_wand()1249 static int _pakellas_high_wand()
1250 {
1251     vector<int> high_wands = {
1252         WAND_PARALYSIS,
1253         WAND_ICEBLAST,
1254         WAND_ACID,
1255     };
1256     if (!you.get_mutation_level(MUT_NO_LOVE))
1257         high_wands.emplace_back(WAND_CHARMING);
1258 
1259     return _preferably_unseen_item(high_wands, _seen_wand);
1260 }
1261 
_pakellas_low_misc()1262 static int _pakellas_low_misc()
1263 {
1264     // Limited uses, so any of these are fine even if they've been seen before.
1265     return random_choose(MISC_BOX_OF_BEASTS,
1266                          MISC_PHANTOM_MIRROR);
1267 }
1268 
_pakellas_high_misc()1269 static int _pakellas_high_misc()
1270 {
1271     static const vector<int> high_miscs = {
1272         MISC_PHIAL_OF_FLOODS,
1273         MISC_LIGHTNING_ROD,
1274     };
1275 
1276     return _preferably_unseen_item(high_miscs, [](int misc) {
1277         return you.seen_misc[misc];
1278     });
1279 }
1280 
_give_pakellas_gift()1281 static bool _give_pakellas_gift()
1282 {
1283     // Break early if giving a gift now means it would be lost.
1284     if (feat_eliminates_items(env.grid(you.pos())))
1285         return false;
1286 
1287     bool success = false;
1288     object_class_type basetype = OBJ_UNASSIGNED;
1289     int subtype = -1;
1290 
1291     if (you.piety >= piety_breakpoint(0)
1292         && you.num_total_gifts[GOD_PAKELLAS] == 0)
1293     {
1294         basetype = OBJ_WANDS;
1295         subtype = _pakellas_low_wand();
1296     }
1297     else if (you.piety >= piety_breakpoint(1)
1298              && you.num_total_gifts[GOD_PAKELLAS] == 1)
1299     {
1300         // All the evoker options here are summon-based, so give another
1301         // low-level wand instead under Sacrifice Love.
1302         if (you.get_mutation_level(MUT_NO_LOVE))
1303         {
1304             basetype = OBJ_WANDS;
1305             subtype = _pakellas_low_wand();
1306         }
1307         else
1308         {
1309             basetype = OBJ_MISCELLANY;
1310             subtype = _pakellas_low_misc();
1311         }
1312     }
1313     else if (you.piety >= piety_breakpoint(2)
1314              && you.num_total_gifts[GOD_PAKELLAS] == 2)
1315     {
1316         basetype = OBJ_WANDS;
1317         subtype = _pakellas_high_wand();
1318     }
1319     else if (you.piety >= piety_breakpoint(3)
1320              && you.num_total_gifts[GOD_PAKELLAS] == 3)
1321     {
1322         basetype = OBJ_MISCELLANY;
1323         subtype = _pakellas_high_misc();
1324     }
1325     else if (you.piety >= piety_breakpoint(4)
1326              && you.num_total_gifts[GOD_PAKELLAS] == 4)
1327     {
1328         basetype = random_choose(OBJ_WANDS, OBJ_MISCELLANY);
1329         subtype = (basetype == OBJ_WANDS) ? _pakellas_high_wand()
1330                                           : _pakellas_high_misc();
1331     }
1332 
1333     if (basetype == OBJ_UNASSIGNED)
1334         return false;
1335     else
1336     {
1337         ASSERT(subtype >= 0);
1338         int thing_created = items(true, basetype, subtype, 1, 0,
1339                                   you.religion);
1340 
1341         if (thing_created == NON_ITEM)
1342             return false;
1343 
1344         move_item_to_grid(&thing_created, you.pos(), true);
1345 
1346         if (thing_created != NON_ITEM)
1347             success = true;
1348     }
1349 
1350     if (success)
1351     {
1352         simple_god_message(" grants you a gift!");
1353         // included in default force_more_message
1354 
1355         you.num_current_gifts[you.religion]++;
1356         you.num_total_gifts[you.religion]++;
1357         take_note(Note(NOTE_GOD_GIFT, you.religion));
1358 
1359         return true;
1360     }
1361 
1362     return false;
1363 }
1364 #endif
1365 
_give_trog_oka_gift(bool forced)1366 static bool _give_trog_oka_gift(bool forced)
1367 {
1368     // Break early if giving a gift now means it would be lost.
1369     if (feat_eliminates_items(env.grid(you.pos())))
1370         return false;
1371 
1372     // No use for anything below. (No guarantees this will work right if these
1373     // mutations can ever appear separately.)
1374     if (you.has_mutation(MUT_NO_GRASPING) && you.has_mutation(MUT_NO_ARMOUR))
1375         return false;
1376 
1377     const bool want_equipment = forced
1378                                 || (you.piety >= piety_breakpoint(4)
1379                                     && random2(you.piety) > 120
1380                                     && one_chance_in(4));
1381     // Oka can gift missiles, but if equipment is successful, we choose
1382     // equipment unless the gift was forced by wizard mode. In that case,
1383     // missiles, weapons, and armour all get equal weight below.
1384     const bool want_missiles = you_worship(GOD_OKAWARU)
1385                                && (forced
1386                                    || !want_equipment && _want_missile_gift());
1387     object_class_type gift_type;
1388 
1389     if (you_worship(GOD_TROG) && want_equipment)
1390         gift_type = OBJ_WEAPONS;
1391     else if (you_worship(GOD_OKAWARU) && (want_equipment || want_missiles))
1392     {
1393         gift_type = random_choose_weighted(
1394                 want_equipment, OBJ_WEAPONS,
1395                 want_equipment, OBJ_ARMOUR,
1396                 want_missiles,  OBJ_MISSILES);
1397     }
1398     else
1399         return false;
1400 
1401     switch (gift_type)
1402     {
1403     case OBJ_MISSILES:
1404         simple_god_message(" grants you ammunition!");
1405         break;
1406     case OBJ_WEAPONS:
1407         simple_god_message(" grants you a weapon!");
1408         break;
1409     case OBJ_ARMOUR:
1410         simple_god_message(" grants you armour!");
1411         break;
1412     default:
1413         simple_god_message(" grants you bugs!");
1414         break;
1415     }
1416 
1417     const bool success =
1418         acquirement_create_item(gift_type, you.religion,
1419                 false, you.pos()) != NON_ITEM;
1420     if (!success)
1421     {
1422         mpr("...but nothing appears.");
1423         return false;
1424     }
1425     switch (gift_type)
1426     {
1427     case OBJ_MISSILES:
1428         _inc_gift_timeout(4 + roll_dice(2, 4));
1429         break;
1430     case OBJ_ARMOUR:
1431         if (you_worship(GOD_OKAWARU) && gift_type == OBJ_ARMOUR)
1432             _inc_gift_timeout(30 + random2avg(15, 2));
1433         // intentionally fallthrough to OBJ_WEAPONS
1434     case OBJ_WEAPONS:
1435         _inc_gift_timeout(30 + random2avg(19, 2));
1436         break;
1437     default:
1438         break;
1439     }
1440     you.num_current_gifts[you.religion]++;
1441     you.num_total_gifts[you.religion]++;
1442     take_note(Note(NOTE_GOD_GIFT, you.religion));
1443     return true;
1444 }
1445 
_give_yred_gift(bool forced)1446 static bool _give_yred_gift(bool forced)
1447 {
1448     bool success = false;
1449     if (forced || (random2(you.piety) >= piety_breakpoint(2)
1450                    && one_chance_in(4)))
1451     {
1452         unsigned int threshold = MIN_YRED_SERVANT_THRESHOLD
1453                                  + you.num_current_gifts[you.religion] / 2;
1454         threshold = max(threshold,
1455             static_cast<unsigned int>(MIN_YRED_SERVANT_THRESHOLD));
1456         threshold = min(threshold,
1457             static_cast<unsigned int>(MAX_YRED_SERVANT_THRESHOLD));
1458 
1459         if (yred_random_servants(threshold) != -1)
1460         {
1461             delayed_monster_done(" grants you @servant@!",
1462                                  _delayed_gift_callback);
1463             success = true;
1464         }
1465     }
1466     return success;
1467 }
1468 
_gift_jiyva_gift(bool forced)1469 static bool _gift_jiyva_gift(bool forced)
1470 {
1471     if (forced || you.piety >= piety_breakpoint(2)
1472                   && random2(you.piety) > 50
1473                   && one_chance_in(4) && !you.gift_timeout
1474                   && you.can_safely_mutate())
1475     {
1476         if (_jiyva_mutate())
1477         {
1478             _inc_gift_timeout(15 + roll_dice(2, 4));
1479             you.num_current_gifts[you.religion]++;
1480             you.num_total_gifts[you.religion]++;
1481             return true;
1482         }
1483         else
1484             mpr("You feel as though nothing has changed.");
1485     }
1486     return false;
1487 }
1488 
_handle_uskayaw_ability_unlocks()1489 static bool _handle_uskayaw_ability_unlocks()
1490 {
1491     bool success = false;
1492     // Uskayaw's triggered abilities trigger if you set the timer to -1.
1493     // We do this so that we trigger at the end of the round instead of
1494     // at the time we deal damage.
1495     if (you.piety == piety_breakpoint(2)
1496         && you.props[USKAYAW_AUDIENCE_TIMER].get_int() == 0)
1497     {
1498         you.props[USKAYAW_AUDIENCE_TIMER] = -1;
1499         success = true;
1500     }
1501     else if (you.piety == piety_breakpoint(3)
1502         && you.props[USKAYAW_BOND_TIMER].get_int() == 0)
1503     {
1504         you.props[USKAYAW_BOND_TIMER] = -1;
1505         success = true;
1506     }
1507     return success;
1508 }
1509 
_give_sif_gift(bool forced)1510 static bool _give_sif_gift(bool forced)
1511 {
1512     // Smokeless fire and books don't get along.
1513     if (you.has_mutation(MUT_INNATE_CASTER))
1514         return false;
1515 
1516     // Break early if giving a gift now means it would be lost.
1517     if (feat_eliminates_items(env.grid(you.pos())))
1518         return false;
1519 
1520     if (!forced && (you.piety < piety_breakpoint(4)
1521                     || random2(you.piety) < 101 || coinflip()))
1522     {
1523         return false;
1524     }
1525 
1526     // Sif Muna special: Keep quiet if acquirement fails
1527     // because the player already has seen all spells.
1528     int item_index = acquirement_create_item(OBJ_BOOKS, you.religion,
1529                                              true, you.pos());
1530     if (item_index == NON_ITEM)
1531         return false;
1532 
1533     simple_god_message(" grants you a gift!");
1534     // included in default force_more_message
1535 
1536     you.num_current_gifts[you.religion]++;
1537     you.num_total_gifts[you.religion]++;
1538     const int n_spells = spells_in_book(env.item[item_index]).size();
1539     _inc_gift_timeout(10 + n_spells * 6 + random2avg(19, 2));
1540     take_note(Note(NOTE_GOD_GIFT, you.religion));
1541 
1542     return true;
1543 }
1544 
_give_kiku_gift(bool forced)1545 static bool _give_kiku_gift(bool forced)
1546 {
1547     // Djinn can't receive spell gifts.
1548     if (you.has_mutation(MUT_INNATE_CASTER))
1549         return false;
1550 
1551     const bool first_gift = !you.num_total_gifts[you.religion];
1552 
1553     // Kikubaaqudgha gives two sets of spells in a quick succession.
1554     if (!forced && (you.piety < piety_breakpoint(0)
1555                     || !first_gift && you.piety < piety_breakpoint(2)
1556                     || you.num_total_gifts[you.religion] > 1))
1557     {
1558         return false;
1559     }
1560 
1561     vector<spell_type> chosen_spells;
1562 
1563     // Each set should guarantee the player at least one corpse-using spell, to
1564     // complement Receive Corpses.
1565     if (first_gift)
1566     {
1567         chosen_spells.push_back(SPELL_PAIN);
1568         if (you.can_bleed(false))
1569         {
1570             chosen_spells.push_back(SPELL_SUBLIMATION_OF_BLOOD);
1571             chosen_spells.push_back(random_choose(SPELL_CORPSE_ROT,
1572                                                   SPELL_ANIMATE_SKELETON));
1573         }
1574         else
1575         {
1576             chosen_spells.push_back(SPELL_CORPSE_ROT);
1577             chosen_spells.push_back(SPELL_ANIMATE_SKELETON);
1578         }
1579         chosen_spells.push_back(SPELL_VAMPIRIC_DRAINING);
1580     }
1581     else
1582     {
1583         chosen_spells.push_back(random_choose(SPELL_ANIMATE_DEAD,
1584                                               SPELL_SIMULACRUM));
1585         chosen_spells.push_back((you.has_mutation(MUT_NO_GRASPING)
1586                                  || coinflip()) ? SPELL_BORGNJORS_VILE_CLUTCH
1587                                                 : SPELL_EXCRUCIATING_WOUNDS);
1588         chosen_spells.push_back(random_choose(SPELL_AGONY,
1589                                               SPELL_DEATH_CHANNEL));
1590 
1591         spell_type extra_spell;
1592         do
1593         {
1594             extra_spell = random_choose(SPELL_ANIMATE_DEAD,
1595                                         SPELL_AGONY,
1596                                         SPELL_BORGNJORS_VILE_CLUTCH,
1597                                         SPELL_EXCRUCIATING_WOUNDS,
1598                                         SPELL_SIMULACRUM,
1599                                         SPELL_DEATH_CHANNEL);
1600             if (you.has_mutation(MUT_NO_GRASPING)
1601                 && extra_spell == SPELL_EXCRUCIATING_WOUNDS)
1602             {
1603                 extra_spell = SPELL_NO_SPELL;
1604             }
1605 
1606             if (find(begin(chosen_spells), end(chosen_spells), extra_spell)
1607                 != end(chosen_spells))
1608             {
1609                 extra_spell = SPELL_NO_SPELL;
1610             }
1611         }
1612         while (extra_spell == SPELL_NO_SPELL);
1613 
1614         chosen_spells.push_back(extra_spell);
1615         chosen_spells.push_back(SPELL_DISPEL_UNDEAD);
1616     }
1617 
1618     simple_god_message(" grants you a gift!");
1619     // included in default force_more_message
1620     library_add_spells(chosen_spells);
1621 
1622     you.num_current_gifts[you.religion]++;
1623     you.num_total_gifts[you.religion]++;
1624     take_note(Note(NOTE_GOD_GIFT, you.religion));
1625 
1626     return true;
1627 }
1628 
_handle_veh_gift(bool forced)1629 static bool _handle_veh_gift(bool forced)
1630 {
1631     bool success = false;
1632     const int gifts = you.num_total_gifts[you.religion];
1633     if (forced || !you.duration[DUR_VEHUMET_GIFT]
1634                   && !you.has_mutation(MUT_INNATE_CASTER)
1635                   && (you.piety >= piety_breakpoint(0) && gifts == 0
1636                       || you.piety >= piety_breakpoint(0) + random2(6) + 18 * gifts && gifts <= 5
1637                       || you.piety >= piety_breakpoint(4) && gifts <= 11 && one_chance_in(20)
1638                       || you.piety >= piety_breakpoint(5) && gifts <= 12 && one_chance_in(20)))
1639     {
1640         set<spell_type> offers = _vehumet_get_spell_gifts();
1641         if (!offers.empty())
1642         {
1643             you.vehumet_gifts = offers;
1644             string prompt = " offers you knowledge of ";
1645             for (auto it = offers.begin(); it != offers.end(); ++it)
1646             {
1647                 if (it != offers.begin())
1648                 {
1649                     if (offers.size() > 2)
1650                         prompt += ",";
1651                     prompt += " ";
1652                     auto next = it;
1653                     next++;
1654                     if (next == offers.end())
1655                         prompt += "and ";
1656                 }
1657                 prompt += spell_title(*it);
1658                 _add_to_old_gifts(*it);
1659                 take_note(Note(NOTE_OFFERED_SPELL, *it));
1660             }
1661             prompt += ".";
1662             if (gifts >= NUM_VEHUMET_GIFTS - 1)
1663             {
1664                 prompt += " These spells will remain available"
1665                           " as long as you worship Vehumet.";
1666             }
1667 
1668             you.duration[DUR_VEHUMET_GIFT] = (100 + random2avg(100, 2)) * BASELINE_DELAY;
1669             if (gifts >= 5)
1670                 _inc_gift_timeout(30 + random2avg(30, 2));
1671             you.num_current_gifts[you.religion]++;
1672             you.num_total_gifts[you.religion]++;
1673 
1674             simple_god_message(prompt.c_str());
1675             // included in default force_more_message
1676 
1677             success = true;
1678         }
1679     }
1680     return success;
1681 }
1682 
mons_make_god_gift(monster & mon,god_type god)1683 void mons_make_god_gift(monster& mon, god_type god)
1684 {
1685     const god_type acting_god =
1686         (crawl_state.is_god_acting()) ? crawl_state.which_god_acting()
1687                                       : GOD_NO_GOD;
1688 
1689     if (god == GOD_NO_GOD && acting_god == GOD_NO_GOD)
1690         return;
1691 
1692     if (god == GOD_NO_GOD)
1693         god = acting_god;
1694 
1695     if (mon.flags & MF_GOD_GIFT)
1696     {
1697         dprf("Monster '%s' was already a gift of god '%s', now god '%s'.",
1698              mon.name(DESC_PLAIN, true).c_str(),
1699              god_name(mon.god).c_str(),
1700              god_name(god).c_str());
1701     }
1702 
1703     mon.god = god;
1704     mon.flags |= MF_GOD_GIFT;
1705 }
1706 
mons_is_god_gift(const monster & mon,god_type god)1707 bool mons_is_god_gift(const monster& mon, god_type god)
1708 {
1709     return (mon.flags & MF_GOD_GIFT) && mon.god == god;
1710 }
1711 
is_yred_undead_slave(const monster & mon)1712 bool is_yred_undead_slave(const monster& mon)
1713 {
1714     return mon.alive() && mon.holiness() & MH_UNDEAD
1715            && mon.attitude == ATT_FRIENDLY
1716            && mons_is_god_gift(mon, GOD_YREDELEMNUL);
1717 }
1718 
is_orcish_follower(const monster & mon)1719 bool is_orcish_follower(const monster& mon)
1720 {
1721     return mon.alive() && mon.attitude == ATT_FRIENDLY
1722            && mons_is_god_gift(mon, GOD_BEOGH);
1723 }
1724 
is_fellow_slime(const monster & mon)1725 bool is_fellow_slime(const monster& mon)
1726 {
1727     return mon.alive() && mons_is_slime(mon)
1728            && mon.attitude == ATT_STRICT_NEUTRAL
1729            && mons_is_god_gift(mon, GOD_JIYVA);
1730 }
1731 
_is_plant_follower(const monster * mon)1732 static bool _is_plant_follower(const monster* mon)
1733 {
1734     return mon->alive() && mons_is_plant(*mon)
1735            && mon->attitude == ATT_FRIENDLY;
1736 }
1737 
_has_jelly()1738 static bool _has_jelly()
1739 {
1740     ASSERT(you_worship(GOD_JIYVA));
1741 
1742     for (monster_iterator mi; mi; ++mi)
1743         if (mons_is_god_gift(**mi, GOD_JIYVA))
1744             return true;
1745     return false;
1746 }
1747 
is_follower(const monster & mon)1748 bool is_follower(const monster& mon)
1749 {
1750     if (you_worship(GOD_YREDELEMNUL))
1751         return is_yred_undead_slave(mon);
1752     else if (will_have_passive(passive_t::convert_orcs))
1753         return is_orcish_follower(mon);
1754     else if (you_worship(GOD_JIYVA))
1755         return is_fellow_slime(mon);
1756     else if (you_worship(GOD_FEDHAS))
1757         return _is_plant_follower(&mon);
1758     else
1759     {
1760         return mon.alive() && mon.attitude == ATT_FRIENDLY
1761                && !mons_is_conjured(mon.type);
1762     }
1763 }
1764 
1765 /**
1766  * What's the name of the ally Hepliaklqana granted the player?
1767  *
1768  * @return      The ally's name.
1769  */
hepliaklqana_ally_name()1770 string hepliaklqana_ally_name()
1771 {
1772     return you.props[HEPLIAKLQANA_ALLY_NAME_KEY].get_string();
1773 }
1774 
1775 /**
1776  * How much HD should the ally granted by Hepliaklqana have?
1777  *
1778  * @return      The player's xl * 2/3.
1779  */
_hepliaklqana_ally_hd()1780 static int _hepliaklqana_ally_hd()
1781 {
1782     if (!crawl_state.need_save) // on main menu or otherwise don't have 'you'
1783         return 27; // v0v
1784     // round up
1785     return (you.experience_level - 1) * 2 / 3 + 1;
1786 }
1787 
1788 /**
1789  * How much max HP should the ally granted by Hepliaklqana have?
1790  *
1791  * @return      5/hd from 1-11 HD, 10/hd from 12-18.
1792  *              (That is, 5 HP at 1 HD, 120 at 18.)
1793  */
hepliaklqana_ally_hp()1794 int hepliaklqana_ally_hp()
1795 {
1796     const int HD = _hepliaklqana_ally_hd();
1797     return HD * 5 + max(0, (HD - 12) * 5);
1798 }
1799 
1800 /**
1801  * Choose an antique name for a Hepliaklqana-granted ancestor.
1802  *
1803  * @param gender    The ancestor's gender.
1804  * @return          An appropriate name; e.g. Hrodulf, Citali, Aat.
1805  */
_make_ancestor_name(gender_type gender)1806 static string _make_ancestor_name(gender_type gender)
1807 {
1808     const string gender_name = gender == GENDER_MALE ? " male " :
1809                                gender == GENDER_FEMALE ? " female " : " ";
1810     const string suffix = gender_name + "name";
1811     const string name = getRandNameString("ancestor", suffix);
1812     return name.empty() ? make_name() : name;
1813 }
1814 
1815 /// Setup when gaining a Hepliaklqana ancestor.
_setup_hepliaklqana_ancestor()1816 static void _setup_hepliaklqana_ancestor()
1817 {
1818     // initial setup.
1819     if (!you.props.exists(HEPLIAKLQANA_ALLY_NAME_KEY))
1820     {
1821         const gender_type gender = random_choose(GENDER_NEUTRAL,
1822                                                  GENDER_MALE,
1823                                                  GENDER_FEMALE);
1824 
1825         you.props[HEPLIAKLQANA_ALLY_NAME_KEY] = _make_ancestor_name(gender);
1826         you.props[HEPLIAKLQANA_ALLY_GENDER_KEY] = gender;
1827     }
1828 }
1829 
1830 /**
1831  * Creates a mgen_data with the information needed to create the ancestor
1832  * granted by Hepliaklqana.
1833  *
1834  * XXX: should this be populating a mgen_data passed by reference, rather than
1835  * returning one on the stack?
1836  *
1837  * @return    The mgen_data that creates a hepliaklqana ancestor.
1838  */
hepliaklqana_ancestor_gen_data()1839 mgen_data hepliaklqana_ancestor_gen_data()
1840 {
1841     _setup_hepliaklqana_ancestor();
1842     const monster_type type = you.props.exists(HEPLIAKLQANA_ALLY_TYPE_KEY) ?
1843         (monster_type)you.props[HEPLIAKLQANA_ALLY_TYPE_KEY].get_int() :
1844         MONS_ANCESTOR;
1845     mgen_data mg(type, BEH_FRIENDLY, you.pos(), MHITYOU, MG_AUTOFOE);
1846     mg.set_summoned(&you, 0, 0, GOD_HEPLIAKLQANA);
1847     mg.hd = _hepliaklqana_ally_hd();
1848     mg.hp = hepliaklqana_ally_hp();
1849     mg.extra_flags |= MF_NO_REWARD;
1850     mg.mname = hepliaklqana_ally_name();
1851     mg.props[MON_GENDER_KEY]
1852         = you.props[HEPLIAKLQANA_ALLY_GENDER_KEY].get_int();
1853     return mg;
1854 }
1855 
1856 /// Print a message for an ancestor's *something* being gained.
_regain_memory(const monster & ancestor,string memory)1857 static void _regain_memory(const monster &ancestor, string memory)
1858 {
1859     mprf("%s regains the memory of %s %s.",
1860          ancestor.name(DESC_YOUR, true).c_str(),
1861          ancestor.pronoun(PRONOUN_POSSESSIVE, true).c_str(),
1862          memory.c_str());
1863 }
1864 
_item_ego_name(object_class_type base_type,int brand)1865 static string _item_ego_name(object_class_type base_type, int brand)
1866 {
1867     switch (base_type)
1868     {
1869     case OBJ_WEAPONS:
1870     {
1871         // 'remembers... draining' reads better than 'drain', but 'flame'
1872         // reads better than 'flaming'
1873         const bool terse = brand == SPWPN_FLAMING
1874                            || brand == SPWPN_ANTIMAGIC;
1875         return brand_type_name((brand_type) brand, terse);
1876     }
1877     case OBJ_ARMOUR:
1878         // XXX: hack
1879         return "reflection";
1880     default:
1881         die("unsupported object type");
1882     }
1883 }
1884 
1885 /// Print a message for an ancestor's item being gained/type upgraded.
_regain_item_memory(const monster & ancestor,object_class_type base_type,int sub_type,int brand)1886 static void _regain_item_memory(const monster &ancestor,
1887                                 object_class_type base_type,
1888                                 int sub_type,
1889                                 int brand)
1890 {
1891     const string base_name = item_base_name(base_type, sub_type);
1892     if (!brand)
1893     {
1894         _regain_memory(ancestor, base_name);
1895         return;
1896     }
1897 
1898     const string ego_name = _item_ego_name(base_type, brand);
1899     const string item_name
1900         = make_stringf("%s of %s",
1901                        item_base_name(base_type, sub_type).c_str(),
1902                        ego_name.c_str());
1903     _regain_memory(ancestor, item_name);
1904 }
1905 
1906 /**
1907  * Update the ancestor's stats after the player levels up. Upgrade HD and HP,
1908  * and give appropriate messaging for that and any other notable upgrades
1909  * (spells, resists, etc).
1910  *
1911  * @param quiet_force     Whether to squash messages & force upgrades,
1912  *                        even if the HD is unchanged.
1913  */
upgrade_hepliaklqana_ancestor(bool quiet_force)1914 void upgrade_hepliaklqana_ancestor(bool quiet_force)
1915 {
1916     monster* ancestor = hepliaklqana_ancestor_mon();
1917     if (!ancestor || !ancestor->alive())
1918         return;
1919 
1920     // housekeeping
1921     ancestor->mname = hepliaklqana_ally_name();
1922     ancestor->props[MON_GENDER_KEY]
1923         = you.props[HEPLIAKLQANA_ALLY_GENDER_KEY].get_int();
1924 
1925     const int old_hd = ancestor->get_experience_level();
1926     const int hd = _hepliaklqana_ally_hd();
1927     ancestor->set_hit_dice(hd);
1928     if (old_hd == hd && !quiet_force)
1929         return; // assume nothing changes except at different HD
1930 
1931     const int old_mhp = ancestor->max_hit_points;
1932     ancestor->max_hit_points = hepliaklqana_ally_hp();
1933     ancestor->hit_points =
1934         div_rand_round(ancestor->hit_points * ancestor->max_hit_points,
1935                        old_mhp);
1936 
1937     if (!quiet_force)
1938     {
1939         mprf("%s remembers more of %s old skill.",
1940              ancestor->name(DESC_YOUR, true).c_str(),
1941              ancestor->pronoun(PRONOUN_POSSESSIVE, true).c_str());
1942     }
1943 
1944     set_ancestor_spells(*ancestor, !quiet_force);
1945 
1946     const bool ancestor_offlevel = companion_is_elsewhere(ancestor->mid);
1947     if (ancestor_offlevel)
1948         add_daction(DACT_UPGRADE_ANCESTOR);
1949 
1950     // assumption: ancestors can lose weapons (very rarely - tukima's),
1951     // and it's weird for them to just reappear, so only upgrade existing ones
1952     if (ancestor->weapon())
1953     {
1954         if (!ancestor_offlevel)
1955             upgrade_hepliaklqana_weapon(ancestor->type, *ancestor->weapon());
1956 
1957         const weapon_type wpn = _hepliaklqana_weapon_type(ancestor->type, hd);
1958         const brand_type brand = _hepliaklqana_weapon_brand(ancestor->type, hd);
1959         if (wpn != _hepliaklqana_weapon_type(ancestor->type, old_hd)
1960             && !quiet_force)
1961         {
1962             _regain_item_memory(*ancestor, OBJ_WEAPONS, wpn, brand);
1963         }
1964         else if (brand != _hepliaklqana_weapon_brand(ancestor->type, old_hd)
1965                  && !quiet_force)
1966         {
1967             mprf("%s remembers %s %s %s.",
1968                  ancestor->name(DESC_YOUR, true).c_str(),
1969                  ancestor->pronoun(PRONOUN_POSSESSIVE, true).c_str(),
1970                  apostrophise(item_base_name(OBJ_WEAPONS, wpn)).c_str(),
1971                  brand_type_name(brand, brand != SPWPN_DRAINING));
1972         }
1973     }
1974     // but shields can't be lost, and *can* be gained (knight at hd 5)
1975     // so give them out as appropriate
1976     if (!ancestor_offlevel)
1977     {
1978         if (ancestor->shield())
1979             upgrade_hepliaklqana_shield(*ancestor, *ancestor->shield());
1980         else
1981             give_shield(ancestor);
1982     }
1983 
1984     const armour_type shld = _hepliaklqana_shield_type(ancestor->type, hd);
1985     if (shld != _hepliaklqana_shield_type(ancestor->type, old_hd)
1986         && !quiet_force)
1987     {
1988         // doesn't currently support egos varying separately from shield types
1989         _regain_item_memory(*ancestor, OBJ_ARMOUR, shld,
1990                             _hepliaklqana_shield_ego(hd));
1991     }
1992 
1993     if (quiet_force)
1994         return;
1995 }
1996 
1997 /**
1998  * What type of weapon should an ancestor of the given HD have?
1999  *
2000  * @param mc   The type of ancestor in question.
2001  * @param HD   The HD of the ancestor in question.
2002  * @return     An appropriate weapon_type.
2003  */
_hepliaklqana_weapon_type(monster_type mc,int HD)2004 static weapon_type _hepliaklqana_weapon_type(monster_type mc, int HD)
2005 {
2006     switch (mc)
2007     {
2008     case MONS_ANCESTOR_HEXER:
2009         return HD < 16 ? WPN_DAGGER : WPN_QUICK_BLADE;
2010     case MONS_ANCESTOR_KNIGHT:
2011         return HD < 10 ? WPN_FLAIL : WPN_BROAD_AXE;
2012     case MONS_ANCESTOR_BATTLEMAGE:
2013         return HD < 13 ? WPN_QUARTERSTAFF : WPN_LAJATANG;
2014     default:
2015         return NUM_WEAPONS; // should never happen
2016     }
2017 }
2018 
2019 /**
2020  * What brand should an ancestor of the given HD's weapon have, if any?
2021  *
2022  * @param mc   The type of ancestor in question.
2023  * @param HD   The HD of the ancestor in question.
2024  * @return     An appropriate weapon_type.
2025  */
_hepliaklqana_weapon_brand(monster_type mc,int HD)2026 static brand_type _hepliaklqana_weapon_brand(monster_type mc, int HD)
2027 {
2028     switch (mc)
2029     {
2030         case MONS_ANCESTOR_HEXER:
2031             return HD < 16 ?   SPWPN_DRAINING :
2032                                SPWPN_ANTIMAGIC;
2033         case MONS_ANCESTOR_KNIGHT:
2034             return HD < 10 ?   SPWPN_NORMAL :
2035                    HD < 16 ?   SPWPN_FLAMING :
2036                                SPWPN_SPEED;
2037         case MONS_ANCESTOR_BATTLEMAGE:
2038             return HD < 13 ?   SPWPN_NORMAL :
2039                                SPWPN_FREEZING;
2040         default:
2041             return SPWPN_NORMAL;
2042     }
2043 }
2044 
2045 /**
2046  * Setup an ancestor's weapon after their class is chosen, when the player
2047  * levels up, or after they're resummoned (or initially created for wrath).
2048  *
2049  * @param[in]   mtyp          The ancestor for whom the weapon is intended.
2050  * @param[out]  item          The item to be configured.
2051  * @param       notify        Whether messages should be printed when something
2052  *                            changes. (Weapon type or brand.)
2053  */
upgrade_hepliaklqana_weapon(monster_type mtyp,item_def & item)2054 void upgrade_hepliaklqana_weapon(monster_type mtyp, item_def &item)
2055 {
2056     ASSERT(mons_is_hepliaklqana_ancestor(mtyp));
2057     if (mtyp == MONS_ANCESTOR)
2058         return; // bare-handed!
2059 
2060     item.base_type = OBJ_WEAPONS;
2061     item.sub_type = _hepliaklqana_weapon_type(mtyp,
2062                                               _hepliaklqana_ally_hd());
2063     item.brand = _hepliaklqana_weapon_brand(mtyp,
2064                                             _hepliaklqana_ally_hd());
2065     item.plus = 0;
2066     item.flags |= ISFLAG_KNOW_TYPE | ISFLAG_SUMMONED;
2067 }
2068 
2069 /**
2070  * What kind of shield should an ancestor of the given HD be given?
2071  *
2072  * @param mc        The type of ancestor in question.
2073  * @param HD        The HD (XL) of the ancestor in question.
2074  * @return          An appropriate type of shield, or NUM_ARMOURS.
2075  */
_hepliaklqana_shield_type(monster_type mc,int HD)2076 static armour_type _hepliaklqana_shield_type(monster_type mc, int HD)
2077 {
2078     if (mc != MONS_ANCESTOR_KNIGHT)
2079         return NUM_ARMOURS;
2080     if (HD < 13)
2081         return ARM_KITE_SHIELD;
2082     return ARM_TOWER_SHIELD;
2083 }
2084 
_hepliaklqana_shield_ego(int HD)2085 static special_armour_type _hepliaklqana_shield_ego(int HD)
2086 {
2087     return HD < 13 ? SPARM_NORMAL : SPARM_REFLECTION;
2088 }
2089 
2090 /**
2091  * Setup an ancestor's weapon after their class is chosen, when the player
2092  * levels up, or after they're resummoned (or initially created for wrath).
2093  *
2094  * @param[in]   ancestor      The ancestor for whom the weapon is intended.
2095  * @param[out]  item          The item to be configured.
2096  * @return                    True iff the ancestor should have a weapon.
2097  */
upgrade_hepliaklqana_shield(const monster & ancestor,item_def & item)2098 void upgrade_hepliaklqana_shield(const monster &ancestor, item_def &item)
2099 {
2100     ASSERT(mons_is_hepliaklqana_ancestor(ancestor.type));
2101     const int HD = ancestor.get_experience_level();
2102     const armour_type shield_type = _hepliaklqana_shield_type(ancestor.type,
2103                                                               HD);
2104     if (shield_type == NUM_ARMOURS)
2105         return; // no shield yet!
2106 
2107     item.base_type = OBJ_ARMOUR;
2108     item.sub_type = shield_type;
2109     item.brand = _hepliaklqana_shield_ego(HD);
2110     item.plus = 0;
2111     item.flags |= ISFLAG_KNOW_TYPE | ISFLAG_SUMMONED;
2112     item.quantity = 1;
2113 }
2114 
2115 ///////////////////////////////
do_god_gift(bool forced)2116 bool do_god_gift(bool forced)
2117 {
2118     ASSERT(!you_worship(GOD_NO_GOD));
2119 
2120     god_acting gdact;
2121 
2122 #if defined(DEBUG_DIAGNOSTICS) || defined(DEBUG_GIFTS)
2123     int old_num_current_gifts = you.num_current_gifts[you.religion];
2124     int old_num_total_gifts = you.num_total_gifts[you.religion];
2125 #endif
2126 
2127     bool success = false;
2128 
2129     // Consider a gift if we don't have a timeout and aren't under penance
2130     if (forced || !player_under_penance() && !you.gift_timeout)
2131     {
2132         // Remember to check for water/lava.
2133         switch (you.religion)
2134         {
2135         default:
2136             break;
2137 
2138         case GOD_NEMELEX_XOBEH:
2139             success = _give_nemelex_gift(forced);
2140             break;
2141 
2142 #if TAG_MAJOR_VERSION == 34
2143         case GOD_PAKELLAS:
2144             success = _give_pakellas_gift();
2145             break;
2146 #endif
2147 
2148         case GOD_OKAWARU:
2149         case GOD_TROG:
2150             success = _give_trog_oka_gift(forced);
2151             break;
2152 
2153         case GOD_YREDELEMNUL:
2154             success = _give_yred_gift(forced);
2155             break;
2156 
2157         case GOD_JIYVA:
2158             success = _gift_jiyva_gift(forced);
2159             break;
2160 
2161         case GOD_USKAYAW:
2162             success = _handle_uskayaw_ability_unlocks();
2163             break;
2164 
2165         case GOD_KIKUBAAQUDGHA:
2166             success = _give_kiku_gift(forced);
2167             break;
2168 
2169         case GOD_SIF_MUNA:
2170             success = _give_sif_gift(forced);
2171             break;
2172 
2173         case GOD_VEHUMET:
2174             success = _handle_veh_gift(forced);
2175             break;
2176         }                       // switch (you.religion)
2177     }                           // End of gift giving.
2178 
2179     if (success)
2180         stop_running(false);
2181 
2182 #if defined(DEBUG_DIAGNOSTICS) || defined(DEBUG_GIFTS)
2183     if (old_num_current_gifts < you.num_current_gifts[you.religion])
2184     {
2185         mprf(MSGCH_DIAGNOSTICS, "Current number of gifts from this god: %d",
2186              you.num_current_gifts[you.religion]);
2187     }
2188     if (old_num_total_gifts < you.num_total_gifts[you.religion])
2189     {
2190         mprf(MSGCH_DIAGNOSTICS, "Total number of gifts from this god: %d",
2191              you.num_total_gifts[you.religion]);
2192     }
2193 #endif
2194     return success;
2195 }
2196 
god_name(god_type which_god,bool long_name)2197 string god_name(god_type which_god, bool long_name)
2198 {
2199     if (which_god == GOD_JIYVA)
2200     {
2201         return god_name_jiyva(long_name) +
2202                (long_name? " the Shapeless" : "");
2203     }
2204 
2205     if (long_name)
2206     {
2207         const string shortname = god_name(which_god, false);
2208         const string longname = getMiscString(shortname + " lastname");
2209         return longname.empty()? shortname : longname;
2210     }
2211 
2212     switch (which_god)
2213     {
2214     case GOD_NO_GOD:        return "No God";
2215     case GOD_RANDOM:        return "random";
2216     case GOD_NAMELESS:      return "nameless";
2217     case GOD_ZIN:           return "Zin";
2218     case GOD_SHINING_ONE:   return "the Shining One";
2219     case GOD_KIKUBAAQUDGHA: return "Kikubaaqudgha";
2220     case GOD_YREDELEMNUL:   return "Yredelemnul";
2221     case GOD_VEHUMET:       return "Vehumet";
2222     case GOD_OKAWARU:       return "Okawaru";
2223     case GOD_MAKHLEB:       return "Makhleb";
2224     case GOD_SIF_MUNA:      return "Sif Muna";
2225     case GOD_TROG:          return "Trog";
2226     case GOD_NEMELEX_XOBEH: return "Nemelex Xobeh";
2227     case GOD_ELYVILON:      return "Elyvilon";
2228     case GOD_LUGONU:        return "Lugonu";
2229     case GOD_BEOGH:         return "Beogh";
2230     case GOD_FEDHAS:        return "Fedhas";
2231     case GOD_CHEIBRIADOS:   return "Cheibriados";
2232     case GOD_XOM:           return "Xom";
2233     case GOD_ASHENZARI:     return "Ashenzari";
2234     case GOD_DITHMENOS:     return "Dithmenos";
2235     case GOD_GOZAG:         return "Gozag";
2236     case GOD_QAZLAL:        return "Qazlal";
2237     case GOD_RU:            return "Ru";
2238 #if TAG_MAJOR_VERSION == 34
2239     case GOD_PAKELLAS:      return "Pakellas";
2240 #endif
2241     case GOD_USKAYAW:       return "Uskayaw";
2242     case GOD_HEPLIAKLQANA:  return "Hepliaklqana";
2243     case GOD_WU_JIAN:     return "Wu Jian";
2244     case GOD_JIYVA: // This is handled at the beginning of the function
2245     case GOD_ECUMENICAL:    return "an unknown god";
2246     case NUM_GODS:          return "Buggy";
2247     }
2248     return "";
2249 }
2250 
god_name_jiyva(bool second_name)2251 string god_name_jiyva(bool second_name)
2252 {
2253     string name = "Jiyva";
2254     if (second_name)
2255         name += " " + you.jiyva_second_name;
2256 
2257     return name;
2258 }
2259 
wu_jian_random_sifu_name()2260 string wu_jian_random_sifu_name()
2261 {
2262     switch (random2(7))
2263     {
2264         case 0: return "Yunchang";
2265         case 1: return "Lu Zhishen";
2266         case 2: return "Xiang Ba";
2267         case 3: return "Ma Yunglu";
2268         case 4: return "Hu Sanniang";
2269         case 5: return "Gene Jian Bin";
2270         case 6: return "Cai Fang";
2271         default: return "Bug";
2272     }
2273 }
2274 
str_to_god(const string & _name,bool exact)2275 god_type str_to_god(const string &_name, bool exact)
2276 {
2277     string target(_name);
2278     trim_string(target);
2279     lowercase(target);
2280 
2281     if (target.empty())
2282         return GOD_NO_GOD;
2283 
2284     int      num_partials = 0;
2285     god_type partial      = GOD_NO_GOD;
2286     for (god_iterator it; it; ++it)
2287     {
2288         god_type god = *it;
2289         string name = lowercase_string(god_name(god, false));
2290 
2291         if (name == target)
2292             return god;
2293 
2294         if (!exact && name.find(target) != string::npos)
2295         {
2296             // Return nothing for ambiguous partial names.
2297             num_partials++;
2298             if (num_partials > 1)
2299                 return GOD_NO_GOD;
2300             partial = god;
2301         }
2302     }
2303 
2304     if (!exact && num_partials == 1)
2305         return partial;
2306 
2307     return GOD_NO_GOD;
2308 }
2309 
god_speaks(god_type god,const char * mesg)2310 void god_speaks(god_type god, const char *mesg)
2311 {
2312     ASSERT(!crawl_state.game_is_arena());
2313 
2314     int orig_mon = env.mgrid(you.pos());
2315 
2316     monster fake_mon;
2317     fake_mon.type       = MONS_PROGRAM_BUG;
2318     fake_mon.mid        = MID_NOBODY;
2319     fake_mon.hit_points = 1;
2320     fake_mon.god        = god;
2321     fake_mon.set_position(you.pos());
2322     fake_mon.foe        = MHITYOU;
2323     fake_mon.mname      = "FAKE GOD MONSTER";
2324 
2325     mprf(MSGCH_GOD, god, "%s", do_mon_str_replacements(mesg, fake_mon).c_str());
2326 
2327     fake_mon.reset();
2328     env.mgrid(you.pos()) = orig_mon;
2329 }
2330 
religion_turn_start()2331 void religion_turn_start()
2332 {
2333     if (you.turn_is_over)
2334         religion_turn_end();
2335 
2336     crawl_state.clear_god_acting();
2337 }
2338 
religion_turn_end()2339 void religion_turn_end()
2340 {
2341     ASSERT(you.turn_is_over);
2342     _place_delayed_monsters();
2343 }
2344 
2345 /** Punish the character for some divine transgression.
2346  *
2347  * @param piety_loss The amount of penance imposed; may be scaled.
2348  * @param penance The amount of penance imposed; may be scaled.
2349  */
dock_piety(int piety_loss,int penance)2350 void dock_piety(int piety_loss, int penance)
2351 {
2352     static int last_piety_lecture   = -1;
2353     static int last_penance_lecture = -1;
2354 
2355     if (piety_loss <= 0 && penance <= 0)
2356         return;
2357 
2358     piety_loss = piety_scale(piety_loss);
2359     penance    = piety_scale(penance);
2360 
2361     if (piety_loss)
2362     {
2363         if (last_piety_lecture != you.num_turns)
2364         {
2365             // output guilt message:
2366             mprf("You feel%sguilty.",
2367                  (piety_loss == 1) ? " a little " :
2368                  (piety_loss <  5) ? " " :
2369                  (piety_loss < 10) ? " very "
2370                                    : " extremely ");
2371         }
2372 
2373         last_piety_lecture = you.num_turns;
2374         lose_piety(piety_loss);
2375     }
2376 
2377     if (you.piety < 1)
2378         excommunication();
2379     else if (penance)       // only if still in religion
2380     {
2381         if (last_penance_lecture != you.num_turns)
2382         {
2383             god_speaks(you.religion,
2384                        "\"You will pay for your transgression, mortal!\"");
2385         }
2386         last_penance_lecture = you.num_turns;
2387         _inc_penance(penance);
2388     }
2389 }
2390 
2391 // Scales a piety number, applying modifiers (faith).
piety_scale(int piety)2392 int piety_scale(int piety)
2393 {
2394     return piety + (you.faith() * div_rand_round(piety, 4));
2395 }
2396 
2397 /** Gain or lose piety to reach a certain value.
2398  *
2399  * If the player cannot gain piety (because they worship Xom, Gozag, or
2400  * no god), their piety will be unchanged.
2401  *
2402  * @param piety The new piety value.
2403  * @pre piety is between 0 and MAX_PIETY, inclusive.
2404  */
set_piety(int piety)2405 void set_piety(int piety)
2406 {
2407     ASSERT(piety >= 0);
2408     ASSERT(piety <= MAX_PIETY);
2409 
2410     // Ru max piety is 6*
2411     if (you_worship(GOD_RU) && piety > piety_breakpoint(5))
2412         piety = piety_breakpoint(5);
2413 
2414     // We have to set the exact piety value this way, because diff may
2415     // be decreased to account for things like penance and gift timeout.
2416     int diff;
2417     do
2418     {
2419         diff = piety - you.piety;
2420         if (diff > 0)
2421         {
2422             if (!gain_piety(diff, 1, false))
2423                 break;
2424         }
2425         else if (diff < 0)
2426             lose_piety(-diff);
2427     }
2428     while (diff != 0);
2429 }
2430 
_gain_piety_point()2431 static void _gain_piety_point()
2432 {
2433     // check to see if we owe anything first
2434     if (player_under_penance(you.religion))
2435     {
2436         dec_penance(1);
2437         return;
2438     }
2439     else if (you.gift_timeout > 0)
2440     {
2441         you.gift_timeout--;
2442 
2443         // Slow down piety gain to account for the fact that gifts
2444         // no longer have a piety cost for getting them.
2445         // Jiyva is an exception because there's usually a time-out and
2446         // the gifts aren't that precious.
2447         if (!one_chance_in(4) && !you_worship(GOD_JIYVA)
2448             && !you_worship(GOD_NEMELEX_XOBEH))
2449         {
2450 #ifdef DEBUG_PIETY
2451             mprf(MSGCH_DIAGNOSTICS, "Piety slowdown due to gift timeout.");
2452 #endif
2453             return;
2454         }
2455     }
2456 
2457     // slow down gain at upper levels of piety
2458     if (!you_worship(GOD_RU))
2459     {
2460         if (you.piety >= MAX_PIETY
2461             || you.piety >= piety_breakpoint(5) && one_chance_in(3)
2462             || you.piety >= piety_breakpoint(3) && one_chance_in(3))
2463         {
2464             do_god_gift();
2465             return;
2466         }
2467     }
2468     else
2469     {
2470         // Ru piety doesn't modulate or taper and Ru doesn't give gifts.
2471         // Ru max piety is 160 (6*)
2472         if (you.piety >= piety_breakpoint(5))
2473             return;
2474     }
2475 
2476     int old_piety = you.piety;
2477     // Apply hysteresis.
2478     // piety_hysteresis is the amount of _loss_ stored up, so this
2479     // may look backwards.
2480     if (you.piety_hysteresis)
2481         you.piety_hysteresis--;
2482     else if (you.piety < MAX_PIETY)
2483         you.piety++;
2484 
2485     if (piety_rank() > piety_rank(old_piety))
2486     {
2487         // Redraw piety display and, in case the best skill is Invocations,
2488         // redraw the god title.
2489         you.redraw_title = true;
2490 
2491         const int rank = piety_rank();
2492         take_note(Note(NOTE_PIETY_RANK, you.religion, rank));
2493 
2494         // For messaging reasons, we want to get our ancestor before
2495         // we get the associated recall / rename powers.
2496         if (rank == rank_for_passive(passive_t::frail))
2497         {
2498             calc_hp(); // adjust for frailty
2499             // In exchange for your hp, you get an ancestor!
2500             const mgen_data mg = hepliaklqana_ancestor_gen_data();
2501             delayed_monster(mg);
2502             simple_god_message(make_stringf(" forms a fragment of your life essence"
2503                                             " into the memory of your ancestor, %s!",
2504                                             mg.mname.c_str()).c_str());
2505         }
2506 
2507         for (const auto& power : get_god_powers(you.religion))
2508         {
2509 
2510             if (power.rank == rank
2511                 || power.rank == 7 && can_do_capstone_ability(you.religion))
2512             {
2513                 power.display(true, "You can now %s.");
2514 #ifdef USE_TILE_LOCAL
2515                 tiles.layout_statcol();
2516                 redraw_screen();
2517                 update_screen();
2518 #endif
2519                 learned_something_new(HINT_NEW_ABILITY_GOD);
2520                 // Preserve the old hotkey
2521                 if (power.abil == ABIL_YRED_ANIMATE_DEAD)
2522                 {
2523                     replace(begin(you.ability_letter_table),
2524                             end(you.ability_letter_table),
2525                             ABIL_YRED_ANIMATE_REMAINS, ABIL_YRED_ANIMATE_DEAD);
2526                 }
2527             }
2528         }
2529         if (rank == rank_for_passive(passive_t::halo))
2530             mprf(MSGCH_GOD, "A divine halo surrounds you!");
2531         if (rank == rank_for_passive(passive_t::umbra))
2532             mprf(MSGCH_GOD, "You are shrouded in an aura of darkness!");
2533         if (rank == rank_for_passive(passive_t::sinv))
2534             autotoggle_autopickup(false);
2535         if (rank == rank_for_passive(passive_t::clarity))
2536         {
2537             // Inconsistent with donning amulets, but matches the
2538             // message better and is not abusable.
2539             you.duration[DUR_CONF] = 0;
2540         }
2541         if (rank >= rank_for_passive(passive_t::identify_items))
2542             auto_id_inventory();
2543 
2544         // TODO: add one-time ability check in have_passive
2545         if (have_passive(passive_t::unlock_slime_vaults) && can_do_capstone_ability(you.religion))
2546         {
2547             simple_god_message(" will now unseal the treasures of the "
2548                                "Slime Pits.");
2549             dlua.callfn("dgn_set_persistent_var", "sb",
2550                         "fix_slime_vaults", true);
2551             // If we're on Slime:$, pretend we just entered the level
2552             // in order to bring down the vault walls.
2553             if (level_id::current() == level_id(BRANCH_SLIME, brdepth[BRANCH_SLIME]))
2554                 dungeon_events.fire_event(DET_ENTERED_LEVEL);
2555 
2556             you.one_time_ability_used.set(you.religion);
2557         }
2558         if (you_worship(GOD_HEPLIAKLQANA)
2559             && rank == 2 && !you.props.exists(HEPLIAKLQANA_ALLY_TYPE_KEY))
2560         {
2561            god_speaks(you.religion,
2562                       "You may now remember your ancestor's life.");
2563         }
2564     }
2565 
2566     // The player's symbol depends on Beogh piety.
2567     if (you_worship(GOD_BEOGH))
2568         update_player_symbol();
2569 
2570     if (have_passive(passive_t::stat_boost)
2571         && chei_stat_boost(old_piety) < chei_stat_boost())
2572     {
2573         string msg = " raises the support of your attributes";
2574         if (have_passive(passive_t::slowed))
2575             msg += " as your movement slows";
2576         msg += ".";
2577         simple_god_message(msg.c_str());
2578         notify_stat_change();
2579     }
2580 
2581     if (you_worship(GOD_QAZLAL)
2582         && qazlal_sh_boost(old_piety) != qazlal_sh_boost())
2583     {
2584         you.redraw_armour_class = true;
2585     }
2586 
2587     if (have_passive(passive_t::halo) || have_passive(passive_t::umbra))
2588     {
2589         // Piety change affects halo / umbra radius.
2590         invalidate_agrid(true);
2591     }
2592 
2593     do_god_gift();
2594 }
2595 
2596 /**
2597  * Gain an amount of piety.
2598  *
2599  * @param original_gain The numerator of the nominal piety gain.
2600  * @param denominator The denominator of the nominal piety gain.
2601  * @param should_scale_piety Should the piety gain be scaled by faith/Sprint?
2602  * @return True if something happened, or if another call with the same
2603  *   arguments might cause something to happen (because of random number
2604  *   rolls).
2605  */
gain_piety(int original_gain,int denominator,bool should_scale_piety)2606 bool gain_piety(int original_gain, int denominator, bool should_scale_piety)
2607 {
2608     if (original_gain <= 0)
2609         return false;
2610 
2611     // Xom uses piety differently; Gozag doesn't at all.
2612     if (you_worship(GOD_NO_GOD)
2613         || you_worship(GOD_XOM)
2614         || you_worship(GOD_GOZAG))
2615     {
2616         return false;
2617     }
2618 
2619     int pgn = should_scale_piety ? piety_scale(original_gain) : original_gain;
2620 
2621     if (crawl_state.game_is_sprint() && should_scale_piety)
2622         pgn = sprint_modify_piety(pgn);
2623 
2624     pgn = div_rand_round(pgn, denominator);
2625     while (pgn-- > 0)
2626         _gain_piety_point();
2627     if (you.piety > you.piety_max[you.religion])
2628     {
2629         if (you.piety >= piety_breakpoint(5)
2630             && you.piety_max[you.religion] < piety_breakpoint(5))
2631         {
2632             mark_milestone("god.maxpiety", "became the Champion of "
2633                            + god_name(you.religion) + ".");
2634         }
2635         you.piety_max[you.religion] = you.piety;
2636     }
2637     return true;
2638 }
2639 
2640 /** Reduce piety and handle side-effects.
2641  *
2642  * Appropriate for cases where the player has not sinned, but must lose piety
2643  * anyway, such as costs for abilities.
2644  *
2645  * @param pgn The precise amount of piety lost.
2646  */
lose_piety(int pgn)2647 void lose_piety(int pgn)
2648 {
2649     if (pgn <= 0)
2650         return;
2651 
2652     const int old_piety = you.piety;
2653 
2654     // Apply hysteresis.
2655     const int old_hysteresis = you.piety_hysteresis;
2656     you.piety_hysteresis = min<int>(PIETY_HYSTERESIS_LIMIT,
2657                                     you.piety_hysteresis + pgn);
2658     const int pgn_borrowed = (you.piety_hysteresis - old_hysteresis);
2659     pgn -= pgn_borrowed;
2660 #ifdef DEBUG_PIETY
2661     mprf(MSGCH_DIAGNOSTICS,
2662          "Piety decreasing by %d (and %d added to hysteresis)",
2663          pgn, pgn_borrowed);
2664 #endif
2665 
2666     if (you.piety - pgn < 0)
2667         you.piety = 0;
2668     else
2669         you.piety -= pgn;
2670 
2671     // Don't bother printing out these messages if you're under
2672     // penance, you wouldn't notice since all these abilities
2673     // are withheld.
2674     if (!player_under_penance()
2675         && piety_rank(old_piety) > piety_rank())
2676     {
2677         // Redraw piety display and, in case the best skill is Invocations,
2678         // redraw the god title.
2679         you.redraw_title = true;
2680 
2681         const int old_rank = piety_rank(old_piety);
2682 
2683         for (const auto& power : get_god_powers(you.religion))
2684         {
2685             if (power.rank == old_rank
2686                 || power.rank == 7 && old_rank == 6
2687                    && !you.one_time_ability_used[you.religion])
2688             {
2689                 power.display(false, "You can no longer %s.");
2690                 // Preserve the old hotkey
2691                 if (power.abil == ABIL_YRED_ANIMATE_DEAD)
2692                 {
2693                     replace(begin(you.ability_letter_table),
2694                             end(you.ability_letter_table),
2695                             ABIL_YRED_ANIMATE_DEAD, ABIL_YRED_ANIMATE_REMAINS);
2696                 }
2697 #if TAG_MAJOR_VERSION == 34
2698                 // Deactivate the toggle
2699                 if (power.abil == ABIL_SIF_MUNA_DIVINE_ENERGY)
2700                     you.attribute[ATTR_DIVINE_ENERGY] = 0;
2701 #endif
2702             }
2703         }
2704 #ifdef USE_TILE_LOCAL
2705         tiles.layout_statcol();
2706         redraw_screen();
2707         update_screen();
2708 #endif
2709 
2710         if (will_have_passive(passive_t::frail) && !have_passive(passive_t::frail))
2711         {
2712             // hep: just lost 1*
2713             // remove companion (gained at same tier as frail)
2714             add_daction(DACT_ALLY_HEPLIAKLQANA);
2715             remove_all_companions(GOD_HEPLIAKLQANA);
2716             calc_hp(); // adjust for frailty
2717         }
2718     }
2719 
2720     if (you.piety > 0 && you.piety <= 5)
2721         learned_something_new(HINT_GOD_DISPLEASED);
2722 
2723     if (will_have_passive(passive_t::water_walk) && _need_water_walking()
2724         && !have_passive(passive_t::water_walk))
2725     {
2726         _grant_temporary_waterwalk();
2727     }
2728     if (will_have_passive(passive_t::stat_boost)
2729         && chei_stat_boost(old_piety) > chei_stat_boost())
2730     {
2731         string msg = " lowers the support of your attributes";
2732         if (will_have_passive(passive_t::slowed))
2733             msg += " as your movement quickens";
2734         msg += ".";
2735         simple_god_message(msg.c_str());
2736         notify_stat_change();
2737     }
2738 
2739     if (you_worship(GOD_QAZLAL)
2740         && qazlal_sh_boost(old_piety) != qazlal_sh_boost())
2741     {
2742         you.redraw_armour_class = true;
2743     }
2744 
2745     if (will_have_passive(passive_t::halo)
2746         || will_have_passive(passive_t::umbra))
2747     {
2748         // Piety change affects halo / umbra radius.
2749         invalidate_agrid(true);
2750     }
2751 }
2752 
2753 // Fedhas worshipers are on the hook for most plants and fungi
2754 //
2755 // If fedhas worshipers kill a protected monster they lose piety,
2756 // if they attack a friendly one they get penance,
2757 // if a friendly one dies they lose piety.
_fedhas_protects_species(monster_type mc)2758 static bool _fedhas_protects_species(monster_type mc)
2759 {
2760     return mons_class_is_plant(mc)
2761            && mons_class_holiness(mc) & MH_PLANT;
2762 }
2763 
2764 /// Whether fedhas would protect `target` from harm if called on to do so.
fedhas_protects(const monster * target)2765 bool fedhas_protects(const monster *target)
2766 {
2767     return target && _fedhas_protects_species(mons_base_type(*target));
2768 }
2769 
2770 /**
2771  * Does some god protect monster `target` from harm triggered by `agent`?
2772  * @param agent  The source of the damage. If nullptr, the damage has no source.
2773  *               (Currently, no god does protect in this case.)
2774  * @param target A monster that is the target of the damage.
2775  * @param quiet  If false, do messaging to indicate that target has escaped
2776  *               damage.
2777  * @return       Whether target should escape damage.
2778  */
god_protects(const actor * agent,const monster * target,bool quiet)2779 bool god_protects(const actor *agent, const monster *target, bool quiet)
2780 {
2781     // The alignment check is to allow a penanced player to continue to fight
2782     // hostiles that would otherwise be protected, in case what they angered can
2783     // fight back
2784 
2785     const bool aligned = agent && target
2786         && ((agent->is_player()
2787                 ? target->friendly()
2788                 : mons_atts_aligned(target->attitude,
2789                                                 agent->as_monster()->attitude))
2790             || target->neutral());
2791     // XX does it matter whether this just checks fedhas vs.
2792     // the shoot_through_plants passive
2793     if (aligned
2794         && ((agent->is_player() || agent->as_monster()->friendly())
2795                         && have_passive(passive_t::shoot_through_plants)
2796             || agent->is_monster() && agent->deity() == GOD_FEDHAS) // purely theoretical?
2797         && fedhas_protects(target))
2798     {
2799         if (!quiet && you.can_see(*target))
2800         {
2801             simple_god_message(
2802                         make_stringf(" protects %s plant from harm.",
2803                             agent->is_player() ? "your" : "a").c_str(),
2804                         GOD_FEDHAS);
2805         }
2806         return true;
2807     }
2808 
2809     if (agent && target && agent->is_player()
2810         && mons_is_hepliaklqana_ancestor(target->type))
2811     {
2812         // TODO: this message does not work very well for all sorts of attacks
2813         // should this be a god message?
2814         if (!quiet && you.can_see(*target))
2815             mprf("%s avoids your attack.", target->name(DESC_THE).c_str());
2816         return true;
2817     }
2818     return false;
2819 }
2820 
2821 /**
2822  * Does some god protect monster `target` from harm triggered by the player?
2823  * @param target A monster that is the target of the damage.
2824  * @param quiet  If false, do messaging to indicate that target has escaped
2825  *               damage.
2826  * @return       Whether target should escape damage.
2827  */
god_protects(const monster * target,bool quiet)2828 bool god_protects(const monster *target, bool quiet)
2829 {
2830     return god_protects(&you, target, quiet);
2831 }
2832 
2833 /// Whether Fedhas would set `target` to a neutral attitude
fedhas_neutralises(const monster & target)2834 bool fedhas_neutralises(const monster& target)
2835 {
2836     return mons_is_plant(target)
2837            && target.holiness() & MH_PLANT
2838            && target.type != MONS_SNAPLASHER_VINE
2839            && target.type != MONS_SNAPLASHER_VINE_SEGMENT;
2840 }
2841 
_god_hates_your_god_reaction(god_type god,god_type your_god)2842 static string _god_hates_your_god_reaction(god_type god, god_type your_god)
2843 {
2844     if (god_hates_your_god(god, your_god))
2845     {
2846         // Non-good gods always hate your current god.
2847         if (!is_good_god(god))
2848             return "";
2849 
2850         // Zin hates chaotic gods.
2851         if (god == GOD_ZIN && is_chaotic_god(your_god))
2852             return " for chaos";
2853 
2854         if (is_evil_god(your_god))
2855             return " for evil";
2856     }
2857 
2858     return "";
2859 }
2860 
2861 /**
2862  * When you abandon this god, how much penance do you gain? (How long does the
2863  * wrath last?
2864  *
2865  * @param god   The god in question.
2866  * @return      The initial penance for the given god's wrath.
2867  */
initial_wrath_penance_for(god_type god)2868 int initial_wrath_penance_for(god_type god)
2869 {
2870     // TODO: transform to data (tables)
2871     switch (god)
2872     {
2873         case GOD_ASHENZARI:
2874         case GOD_BEOGH:
2875         case GOD_ELYVILON:
2876         case GOD_GOZAG:
2877         case GOD_HEPLIAKLQANA:
2878         case GOD_LUGONU:
2879         case GOD_NEMELEX_XOBEH:
2880         case GOD_TROG:
2881         case GOD_XOM:
2882             return 50;
2883         case GOD_FEDHAS:
2884         case GOD_KIKUBAAQUDGHA:
2885         case GOD_JIYVA:
2886         case GOD_SHINING_ONE:
2887         case GOD_SIF_MUNA:
2888         case GOD_YREDELEMNUL:
2889             return 30;
2890         case GOD_CHEIBRIADOS:
2891         case GOD_DITHMENOS:
2892         case GOD_MAKHLEB:
2893 #if TAG_MAJOR_VERSION == 34
2894         case GOD_PAKELLAS:
2895 #endif
2896         case GOD_QAZLAL:
2897         case GOD_VEHUMET:
2898         case GOD_ZIN:
2899         default:
2900             return 25;
2901         case GOD_RU:
2902             return 0;
2903     }
2904 }
2905 
_ash_uncurse()2906 static void _ash_uncurse()
2907 {
2908     bool uncursed = false;
2909     // iterate backwards so we shatter a ring on the macabre finger
2910     // necklace before the amulet
2911     for (int eq_typ = NUM_EQUIP - 1; eq_typ >= EQ_FIRST_EQUIP; eq_typ--)
2912     {
2913         const int slot = you.equip[eq_typ];
2914         if (slot == -1)
2915             continue;
2916         if (!uncursed)
2917         {
2918             mprf(MSGCH_GOD, GOD_ASHENZARI, "Your curses shatter.");
2919             uncursed = true;
2920         }
2921         unequip_item(static_cast<equipment_type>(eq_typ));
2922     }
2923 }
2924 
excom_xp_docked()2925 int excom_xp_docked()
2926 {
2927     return exp_needed(min<int>(you.max_level, 27) + 1)
2928          - exp_needed(min<int>(you.max_level, 27));
2929 }
2930 
excommunication(bool voluntary,god_type new_god)2931 void excommunication(bool voluntary, god_type new_god)
2932 {
2933     const god_type old_god = you.religion;
2934     ASSERT(old_god != new_god);
2935     ASSERT(old_god != GOD_NO_GOD);
2936 
2937     const bool had_halo       = have_passive(passive_t::halo);
2938     const bool had_umbra      = have_passive(passive_t::umbra);
2939     const bool had_water_walk = have_passive(passive_t::water_walk);
2940     const bool had_stat_boost = have_passive(passive_t::stat_boost);
2941     const int  old_piety      = you.piety;
2942 
2943     god_acting gdact(old_god, true);
2944 
2945     take_note(Note(NOTE_LOSE_GOD, old_god));
2946 
2947     you.duration[DUR_PIETY_POOL] = 0; // your loss
2948     you.duration[DUR_RECITE] = 0;
2949     you.piety = 0;
2950     you.piety_hysteresis = 0;
2951 
2952     // so that the player isn't punished for "switching" between good gods via aX
2953     if (is_good_god(old_god) && voluntary)
2954     {
2955         you.saved_good_god_piety = old_piety;
2956         you.previous_good_god = old_god;
2957     }
2958     else
2959     {
2960         you.saved_good_god_piety = 0;
2961         you.previous_good_god = GOD_NO_GOD;
2962     }
2963 
2964     you.num_current_gifts[old_god] = 0;
2965 
2966     you.religion = GOD_NO_GOD;
2967 
2968     you.redraw_title = true;
2969 
2970     // Renouncing may have changed the conducts on our wielded or
2971     // quivered weapons, so refresh the display.
2972     you.wield_change = true;
2973     quiver::set_needs_redraw();
2974 
2975     mpr("You have lost your religion!");
2976     // included in default force_more_message
2977 
2978     if (old_god == GOD_BEOGH)
2979     {
2980         // The player's symbol depends on Beogh worship.
2981         update_player_symbol();
2982     }
2983 
2984     mark_milestone("god.renounce", "abandoned " + god_name(old_god) + ".");
2985 #ifdef DGL_WHEREIS
2986     whereis_record();
2987 #endif
2988 
2989     if (god_hates_your_god(old_god, new_god))
2990     {
2991         simple_god_message(
2992             make_stringf(" does not appreciate desertion%s!",
2993                          _god_hates_your_god_reaction(old_god, new_god).c_str()).c_str(),
2994             old_god);
2995     }
2996 
2997     if (had_halo)
2998     {
2999         mprf(MSGCH_GOD, old_god, "Your divine halo fades away.");
3000         invalidate_agrid(true);
3001     }
3002     if (had_umbra)
3003     {
3004         mprf(MSGCH_GOD, old_god, "Your aura of darkness fades away.");
3005         invalidate_agrid(true);
3006     }
3007     // You might have lost water walking at a bad time...
3008     if (had_water_walk && _need_water_walking())
3009         _grant_temporary_waterwalk();
3010     if (had_stat_boost)
3011     {
3012         redraw_screen();
3013         update_screen();
3014         notify_stat_change();
3015     }
3016 
3017     switch (old_god)
3018     {
3019     case GOD_KIKUBAAQUDGHA:
3020         mprf(MSGCH_GOD, old_god, "You sense decay."); // in the state of Denmark
3021         add_daction(DACT_ROT_CORPSES);
3022         break;
3023 
3024     case GOD_YREDELEMNUL:
3025         you.duration[DUR_MIRROR_DAMAGE] = 0;
3026         if (query_daction_counter(DACT_ALLY_YRED_SLAVE))
3027         {
3028             simple_god_message(" reclaims all of your granted undead slaves!",
3029                                old_god);
3030             add_daction(DACT_ALLY_YRED_SLAVE);
3031             remove_all_companions(GOD_YREDELEMNUL);
3032         }
3033         break;
3034 
3035     case GOD_VEHUMET:
3036         you.vehumet_gifts.clear();
3037         you.duration[DUR_VEHUMET_GIFT] = 0;
3038         break;
3039 
3040     case GOD_MAKHLEB:
3041         make_god_gifts_disappear();
3042         break;
3043 
3044     case GOD_TROG:
3045         if (you.duration[DUR_TROGS_HAND])
3046             trog_remove_trogs_hand();
3047         make_god_gifts_disappear();
3048         break;
3049 
3050     case GOD_BEOGH:
3051         if (query_daction_counter(DACT_ALLY_BEOGH))
3052         {
3053             simple_god_message("'s voice booms out, \"Who do you think you "
3054                                "are?\"", old_god);
3055             mprf(MSGCH_MONSTER_ENCHANT, "All of your followers decide to abandon you.");
3056             add_daction(DACT_ALLY_BEOGH);
3057             remove_all_companions(GOD_BEOGH);
3058         }
3059 
3060         env.level_state |= LSTATE_BEOGH;
3061         break;
3062 
3063     case GOD_SIF_MUNA:
3064         if (you.duration[DUR_CHANNEL_ENERGY])
3065             you.duration[DUR_CHANNEL_ENERGY] = 0;
3066 #if TAG_MAJOR_VERSION == 34
3067         if (you.attribute[ATTR_DIVINE_ENERGY])
3068             you.attribute[ATTR_DIVINE_ENERGY] = 0;
3069 #endif
3070         break;
3071 
3072     case GOD_NEMELEX_XOBEH:
3073         reset_cards();
3074         mprf(MSGCH_GOD, old_god, "Your access to %s's decks is revoked.",
3075              god_name(old_god).c_str());
3076         break;
3077 
3078     case GOD_SHINING_ONE:
3079         if (you.duration[DUR_DIVINE_SHIELD])
3080             tso_remove_divine_shield();
3081 
3082         make_god_gifts_disappear();
3083         break;
3084 
3085     case GOD_ZIN:
3086         if (you.duration[DUR_DIVINE_STAMINA])
3087             zin_remove_divine_stamina();
3088 
3089         if (env.sanctuary_time)
3090             remove_sanctuary();
3091         break;
3092 
3093     case GOD_ELYVILON:
3094         you.duration[DUR_LIFESAVING] = 0;
3095         if (you.duration[DUR_DIVINE_VIGOUR])
3096             elyvilon_remove_divine_vigour();
3097         you.exp_docked[old_god] = excom_xp_docked();
3098         you.exp_docked_total[old_god] = you.exp_docked[old_god];
3099         break;
3100 
3101     case GOD_JIYVA:
3102         if (you.duration[DUR_SLIMIFY])
3103             you.duration[DUR_SLIMIFY] = 0;
3104 
3105         if (query_daction_counter(DACT_ALLY_SLIME))
3106         {
3107             mprf(MSGCH_MONSTER_ENCHANT, "All of your fellow slimes turn on you.");
3108             add_daction(DACT_ALLY_SLIME);
3109         }
3110         break;
3111 
3112     case GOD_FEDHAS:
3113         if (query_daction_counter(DACT_ALLY_PLANT))
3114         {
3115             mprf(MSGCH_MONSTER_ENCHANT, "The plants of the dungeon turn on you.");
3116             add_daction(DACT_ALLY_PLANT);
3117         }
3118         break;
3119 
3120     case GOD_ASHENZARI:
3121         you.exp_docked[old_god] = excom_xp_docked();
3122         you.exp_docked_total[old_god] = you.exp_docked[old_god];
3123         _ash_uncurse();
3124         break;
3125 
3126     case GOD_DITHMENOS:
3127         if (you.form == transformation::shadow)
3128             untransform();
3129         break;
3130 
3131     case GOD_GOZAG:
3132         if (you.attribute[ATTR_GOZAG_SHOPS_CURRENT])
3133         {
3134             mprf(MSGCH_GOD, old_god, "Your funded stores close, unable to pay "
3135                                      "their debts without your funds.");
3136             you.attribute[ATTR_GOZAG_SHOPS_CURRENT] = 0;
3137         }
3138         you.duration[DUR_GOZAG_GOLD_AURA] = 0;
3139         for (branch_iterator it; it; ++it)
3140             branch_bribe[it->id] = 0;
3141         add_daction(DACT_BRIBE_TIMEOUT);
3142         add_daction(DACT_REMOVE_GOZAG_SHOPS);
3143         shopping_list.remove_dead_shops();
3144         you.exp_docked[old_god] = excom_xp_docked();
3145         you.exp_docked_total[old_god] = you.exp_docked[old_god];
3146         break;
3147 
3148     case GOD_QAZLAL:
3149         if (old_piety >= piety_breakpoint(0))
3150         {
3151             mprf(MSGCH_GOD, old_god, "Your storm instantly dissipates.");
3152             you.redraw_armour_class = true;
3153         }
3154         if (you.duration[DUR_QAZLAL_FIRE_RES])
3155         {
3156             mprf(MSGCH_DURATION, "Your resistance to fire fades away.");
3157             you.duration[DUR_QAZLAL_FIRE_RES] = 0;
3158         }
3159         if (you.duration[DUR_QAZLAL_COLD_RES])
3160         {
3161             mprf(MSGCH_DURATION, "Your resistance to cold fades away.");
3162             you.duration[DUR_QAZLAL_COLD_RES] = 0;
3163         }
3164         if (you.duration[DUR_QAZLAL_ELEC_RES])
3165         {
3166             mprf(MSGCH_DURATION,
3167                  "Your resistance to electricity fades away.");
3168             you.duration[DUR_QAZLAL_ELEC_RES] = 0;
3169         }
3170         if (you.duration[DUR_QAZLAL_AC])
3171         {
3172             mprf(MSGCH_DURATION,
3173                  "Your resistance to physical damage fades away.");
3174             you.duration[DUR_QAZLAL_AC] = 0;
3175             you.redraw_armour_class = true;
3176         }
3177         break;
3178 
3179 #if TAG_MAJOR_VERSION == 34
3180     case GOD_PAKELLAS:
3181         simple_god_message(" continues to block your magic from regenerating.",
3182                            old_god);
3183         you.exp_docked[old_god] = excom_xp_docked();
3184         you.exp_docked_total[old_god] = you.exp_docked[old_god];
3185         break;
3186 #endif
3187 
3188     case GOD_CHEIBRIADOS:
3189         simple_god_message(" continues to slow your movements.", old_god);
3190         break;
3191 
3192     case GOD_HEPLIAKLQANA:
3193         add_daction(DACT_ALLY_HEPLIAKLQANA);
3194         remove_all_companions(GOD_HEPLIAKLQANA);
3195 
3196         you.exp_docked[old_god] = excom_xp_docked();
3197         you.exp_docked_total[old_god] = you.exp_docked[old_god];
3198         break;
3199 
3200     case GOD_WU_JIAN:
3201         you.attribute[ATTR_SERPENTS_LASH] = 0;
3202         if (you.props.exists(WU_JIAN_HEAVENLY_STORM_KEY))
3203             wu_jian_end_heavenly_storm();
3204         break;
3205 
3206     case GOD_OKAWARU:
3207         if (you.duration[DUR_HEROISM])
3208             okawaru_remove_heroism();
3209         if (you.duration[DUR_FINESSE])
3210             okawaru_remove_finesse();
3211         break;
3212 
3213     default:
3214         break;
3215     }
3216 
3217     _set_wrath_penance(old_god);
3218 
3219 #ifdef USE_TILE_LOCAL
3220     tiles.layout_statcol();
3221     redraw_screen();
3222     update_screen();
3223 #endif
3224 
3225     // Evil hack.
3226     learned_something_new(HINT_EXCOMMUNICATE,
3227                           coord_def((int)new_god, old_piety));
3228 
3229     for (ability_type abil : get_god_abilities())
3230         you.skills_to_hide.insert(abil_skill(abil));
3231 
3232     update_can_currently_train();
3233     reset_training();
3234 
3235     // Perhaps we abandoned Trog with everything but Spellcasting maxed out.
3236     check_selected_skills();
3237 }
3238 
nemelex_death_message()3239 void nemelex_death_message()
3240 {
3241     const int rank = min(random2(you.piety) / 30, 2);
3242 
3243     static const char *messages[NUM_PIETY_GAIN] =
3244     {
3245         "<lightgrey>Your body disappears without a glow.</lightgrey>",
3246         "Your body glows slightly and disappears.",
3247         "<white>Your body glows with a rainbow of weird colours and disappears.</white>",
3248     };
3249 
3250     static const char *glowing_messages[NUM_PIETY_GAIN] =
3251     {
3252         "<lightgrey>Your body disappears without additional glow.</lightgrey>",
3253         "Your body glows slightly brighter and disappears.",
3254         "<white>Your body glows with a rainbow of weird colours and disappears.</white>",
3255     };
3256 
3257     mpr((you.backlit() ? glowing_messages : messages)[rank]);
3258 }
3259 
god_hates_attacking_friend(god_type god,const monster & fr)3260 bool god_hates_attacking_friend(god_type god, const monster& fr)
3261 {
3262     if (fr.kill_alignment() != KC_FRIENDLY)
3263         return false;
3264 
3265     monster_type species = fr.mons_species();
3266 
3267     if (mons_is_object(species))
3268         return false;
3269     switch (god)
3270     {
3271         case GOD_ZIN:
3272         case GOD_SHINING_ONE:
3273         case GOD_ELYVILON:
3274             return true;
3275         case GOD_BEOGH: // added penance to avoid killings for loot
3276             return mons_genus(species) == MONS_ORC;
3277         case GOD_JIYVA:
3278             return mons_class_is_slime(species);
3279         case GOD_FEDHAS:
3280             return _fedhas_protects_species(species);
3281         default:
3282             return false;
3283     }
3284 }
3285 
_transformed_player_can_join_god(god_type which_god)3286 static bool _transformed_player_can_join_god(god_type which_god)
3287 {
3288     if (which_god == GOD_ZIN && you.form != transformation::none)
3289         return false; // zin hates everything
3290 
3291     if (is_good_god(which_god) && you.form == transformation::lich)
3292         return false;
3293 
3294     return true;
3295 }
3296 
gozag_service_fee()3297 int gozag_service_fee()
3298 {
3299     if (you.char_class == JOB_MONK && had_gods() == 0)
3300         return 0;
3301 
3302     if (crawl_state.game_is_sprint())
3303         return 0;
3304 
3305     const int gold = you.attribute[ATTR_GOLD_GENERATED];
3306     int fee = (int)(gold - gold / log10(gold + 10.0))/2;
3307 
3308     dprf("found %d gold, fee %d", gold, fee);
3309     return fee;
3310 }
3311 
_god_rejects_loveless(god_type god)3312 static bool _god_rejects_loveless(god_type god)
3313 {
3314     switch (god)
3315     {
3316     case GOD_BEOGH:
3317     case GOD_JIYVA:
3318     case GOD_HEPLIAKLQANA:
3319     case GOD_FEDHAS:
3320     case GOD_YREDELEMNUL:
3321         return true;
3322     default:
3323         return false;
3324     }
3325 }
3326 
3327 /**
3328  * Return true if the player can worship which_god.
3329  *
3330  * @param which_god  god to query
3331  * @param temp       If true (default), test if you can worship which_god now.
3332  *                   If false, test if you may ever be able to worship the god.
3333  * @return           Whether you can worship which_god.
3334  */
player_can_join_god(god_type which_god,bool temp)3335 bool player_can_join_god(god_type which_god, bool temp)
3336 {
3337     if (you.has_mutation(MUT_FORLORN))
3338         return false;
3339 
3340     if (is_good_god(which_god) && you.undead_or_demonic(temp))
3341         return false;
3342 
3343     if (you.has_mutation(MUT_INNATE_CASTER)
3344         && (which_god == GOD_SIF_MUNA
3345             || which_god == GOD_VEHUMET
3346             || which_god == GOD_KIKUBAAQUDGHA))
3347     {
3348         return false;
3349     }
3350 
3351     if (which_god == GOD_BEOGH && !species::is_orcish(you.species))
3352         return false;
3353 
3354     if (which_god == GOD_GOZAG && temp && you.gold < gozag_service_fee())
3355         return false;
3356 
3357     if (you.get_base_mutation_level(MUT_NO_LOVE, true, temp, temp)
3358         && _god_rejects_loveless(which_god))
3359     {
3360         return false;
3361     }
3362 
3363 #if TAG_MAJOR_VERSION == 34
3364     if (you.get_base_mutation_level(MUT_NO_ARTIFICE, true, temp, temp)
3365         && which_god == GOD_PAKELLAS)
3366     {
3367         return false;
3368     }
3369 #endif
3370 
3371     return !temp || _transformed_player_can_join_god(which_god);
3372 }
3373 
3374 // Handle messaging and identification for items/equipment on conversion.
_god_welcome_handle_gear()3375 static void _god_welcome_handle_gear()
3376 {
3377     // Check for amulets of faith.
3378     item_def *amulet = you.slot_item(EQ_AMULET, false);
3379     if (amulet && amulet->sub_type == AMU_FAITH && !is_useless_item(*amulet))
3380     {
3381         mprf(MSGCH_GOD, "Your amulet flashes!");
3382         flash_view_delay(UA_PLAYER, god_colour(you.religion), 300);
3383     }
3384 
3385     if (have_passive(passive_t::identify_items))
3386         auto_id_inventory();
3387 
3388     if (have_passive(passive_t::detect_portals))
3389         ash_detect_portals(true);
3390 
3391     // Give a reminder to remove any disallowed equipment.
3392     for (int i = EQ_FIRST_EQUIP; i < NUM_EQUIP; i++)
3393     {
3394         const item_def* item = you.slot_item(static_cast<equipment_type>(i));
3395         if (item && god_hates_item(*item))
3396         {
3397             mprf(MSGCH_GOD, "%s warns you to remove %s.",
3398                  uppercase_first(god_name(you.religion)).c_str(),
3399                  item->name(DESC_YOUR, false, false, false).c_str());
3400         }
3401     }
3402 
3403     // Refresh wielded/quivered weapons in case we have a new conduct
3404     // on them.
3405     you.wield_change = true;
3406     quiver::set_needs_redraw();
3407 }
3408 
3409 /* Make a CrawlStoreValue an empty vector with the requested item type.
3410  * It is an error if the value already had a different type.
3411  */
_make_empty_vec(CrawlStoreValue & v,store_val_type vectype)3412 static void _make_empty_vec(CrawlStoreValue &v, store_val_type vectype)
3413 {
3414     const store_val_type currtype = v.get_type();
3415     ASSERT(currtype == SV_NONE || currtype == SV_VEC);
3416 
3417     if (currtype == SV_NONE)
3418         v.new_vector(vectype);
3419     else
3420     {
3421         CrawlVector &vec = v.get_vector();
3422         const store_val_type old_vectype = vec.get_type();
3423         ASSERT(old_vectype == SV_NONE || old_vectype == vectype);
3424         vec.clear();
3425     }
3426 }
3427 
3428 // Note: we're trying for a behaviour where the player gets
3429 // to keep their assigned invocation slots if they get excommunicated
3430 // and then rejoin (but if they spend time with another god we consider
3431 // the old invocation slots void and erase them). We also try to
3432 // protect any bindings the character might have made into the
3433 // traditional invocation slots (a-e and X). -- bwr
set_god_ability_slots()3434 void set_god_ability_slots()
3435 {
3436     ASSERT(!you_worship(GOD_NO_GOD));
3437 
3438     if (find(begin(you.ability_letter_table), end(you.ability_letter_table),
3439              ABIL_RENOUNCE_RELIGION) == end(you.ability_letter_table)
3440         && you.ability_letter_table[letter_to_index('X')] == ABIL_NON_ABILITY)
3441     {
3442         you.ability_letter_table[letter_to_index('X')] = ABIL_RENOUNCE_RELIGION;
3443     }
3444 
3445     // Clear out other god invocations.
3446     for (ability_type& slot : you.ability_letter_table)
3447     {
3448         for (god_iterator it; it; ++it)
3449         {
3450             if (slot == ABIL_NON_ABILITY)
3451                 break;
3452             if (*it == you.religion)
3453                 continue;
3454             for (const god_power& power : god_powers[*it])
3455                 if (slot == power.abil)
3456                     slot = ABIL_NON_ABILITY;
3457         }
3458     }
3459 
3460     int num = letter_to_index('a');
3461     // Not using get_god_powers, so that hotkeys remain stable across games
3462     // even if you can't use a particular ability in a given game.
3463     for (const god_power& power : god_powers[you.religion])
3464     {
3465         if (power.abil != ABIL_NON_ABILITY
3466             // Animate Dead doesn't have its own hotkey; it steals
3467             // Animate Remains'
3468             && power.abil != ABIL_YRED_ANIMATE_DEAD
3469             // hep ident goes to G, so don't take b for it (hack alert)
3470             && power.abil != ABIL_HEPLIAKLQANA_IDENTITY
3471             && find(begin(you.ability_letter_table),
3472                     end(you.ability_letter_table), power.abil)
3473                == end(you.ability_letter_table)
3474             && you.ability_letter_table[num] == ABIL_NON_ABILITY)
3475         {
3476             // Assign sequentially: first ability 'a', third ability 'c',
3477             // etc., even if one is remapped.
3478             if (find_ability_slot(power.abil, index_to_letter(num)) < 0)
3479             {
3480                 you.ability_letter_table[num] = power.abil;
3481                 auto_assign_ability_slot(num);
3482             }
3483             ++num;
3484         }
3485     }
3486 }
3487 
3488 /// Check if the monk's joining bonus should be given. (Except Gozag's.)
_apply_monk_bonus()3489 static void _apply_monk_bonus()
3490 {
3491     if (you.char_class != JOB_MONK || had_gods() > 0)
3492         return;
3493 
3494     // monks get bonus piety for first god
3495     if (you_worship(GOD_RU))
3496         you.props[RU_SACRIFICE_PROGRESS_KEY] = 9999;
3497     else if (you_worship(GOD_ASHENZARI))
3498     {
3499         // two curses in (somewhat) rapid succession
3500         ashenzari_offer_new_curse();
3501         you.props[ASHENZARI_CURSE_PROGRESS_KEY] = 19;
3502     }
3503     else if (you_worship(GOD_USKAYAW))  // Gaining piety past this point does nothing
3504         gain_piety(15, 1, false); // of value with this god and looks weird.
3505     else
3506         gain_piety(35, 1, false);
3507 }
3508 
3509 /// Transfer some piety from an old good god to a new one, if applicable.
_transfer_good_god_piety()3510 static void _transfer_good_god_piety()
3511 {
3512     if (!is_good_god(you.religion))
3513         return;
3514 
3515     const god_type old_god = you.previous_good_god;
3516     const uint8_t old_piety = you.saved_good_god_piety;
3517 
3518     if (!is_good_god(old_god))
3519         return;
3520 
3521     if (you.religion != old_god)
3522     {
3523         static const map<god_type, const char*> farewell_messages = {
3524             { GOD_ELYVILON, "aid the meek" },
3525             { GOD_SHINING_ONE, "vanquish evil" },
3526             { GOD_ZIN, "enforce order" },
3527         };
3528 
3529         // Some feedback that piety moved over.
3530         simple_god_message(make_stringf(" says: Farewell. Go and %s with %s.",
3531                                         lookup(farewell_messages, you.religion,
3532                                                "become a bug"),
3533                                         god_name(you.religion).c_str()).c_str(),
3534 
3535                            old_god);
3536     }
3537 
3538     // Give a piety bonus when switching between good gods, or back to the
3539     // same good god.
3540     if (old_piety > piety_breakpoint(0))
3541         gain_piety(old_piety - piety_breakpoint(0), 2, false);
3542 }
3543 
3544 
3545 /**
3546  * Give an appropriate message for the given good god to give in response to
3547  * the player joining a god that brings down their wrath.
3548  *
3549  * @param good_god    The good god in question.
3550  */
_good_god_wrath_message(god_type good_god)3551 static string _good_god_wrath_message(god_type good_god)
3552 {
3553     switch (good_god)
3554     {
3555         case GOD_ELYVILON:
3556             return "Your evil deeds will not go unpunished";
3557         case GOD_SHINING_ONE:
3558             return "You will pay for your evil ways, mortal";
3559         case GOD_ZIN:
3560             return make_stringf("You will suffer for embracing such %s",
3561                                 is_chaotic_god(you.religion) ? "chaos"
3562                                                              : "evil");
3563         default:
3564             return "You will be buggily punished for this";
3565     }
3566 }
3567 
3568 /**
3569  * Check if joining the current god will cause wrath for any previously-
3570  * worshipped good gods. If so, message & set penance timeouts.
3571  *
3572  * @param old_god    The previous god worshipped; may be GOD_NO_GOD.
3573  */
_check_good_god_wrath(god_type old_god)3574 static void _check_good_god_wrath(god_type old_god)
3575 {
3576     for (god_type good_god : { GOD_ELYVILON, GOD_SHINING_ONE, GOD_ZIN })
3577     {
3578         if (old_god == good_god || !you.penance[good_god]
3579             || !god_hates_your_god(good_god, you.religion))
3580         {
3581             continue;
3582         }
3583 
3584         const string wrath_message
3585             = make_stringf(" says: %s!",
3586                            _good_god_wrath_message(good_god).c_str());
3587         simple_god_message(wrath_message.c_str(), good_god);
3588         set_penance_xp_timeout();
3589     }
3590 }
3591 
initialize_ashenzari_props()3592 void initialize_ashenzari_props()
3593 {
3594     if (!you.props.exists(ASHENZARI_CURSE_PROGRESS_KEY))
3595         you.props[ASHENZARI_CURSE_PROGRESS_KEY] = 0;
3596     if (!you.props.exists(ASHENZARI_CURSE_DELAY_KEY))
3597     {
3598         int delay = 20;
3599         if (crawl_state.game_is_sprint())
3600             delay /= SPRINT_MULTIPLIER;
3601         you.props[ASHENZARI_CURSE_DELAY_KEY] = delay;
3602     }
3603 }
3604 
3605 /// Handle basic god piety & related setup for a new-joined god.
_set_initial_god_piety()3606 static void _set_initial_god_piety()
3607 {
3608     // Currently, penance is just zeroed. This could be much more
3609     // interesting.
3610     you.penance[you.religion] = 0;
3611 
3612     switch (you.religion)
3613     {
3614     case GOD_XOM:
3615         // Xom uses piety and gift_timeout differently.
3616         you.piety = HALF_MAX_PIETY;
3617         you.gift_timeout = random2(40) + random2(40);
3618         break;
3619 
3620     case GOD_ASHENZARI:
3621         you.piety = ASHENZARI_BASE_PIETY;
3622         you.piety_hysteresis = 0;
3623         you.gift_timeout = 0;
3624         initialize_ashenzari_props();
3625         break;
3626 
3627     case GOD_RU:
3628         you.piety = 10; // one moderate sacrifice should get you to *.
3629         you.piety_hysteresis = 0;
3630         you.gift_timeout = 0;
3631 
3632         // I'd rather this be in on_join(), but then it overrides the
3633         // monk bonus...
3634         you.props[RU_SACRIFICE_PROGRESS_KEY] = 0;
3635         // offer the first sacrifice faster than normal
3636         {
3637             int delay = 50;
3638             if (crawl_state.game_is_sprint())
3639                 delay /= SPRINT_MULTIPLIER;
3640             you.props[RU_SACRIFICE_DELAY_KEY] = delay;
3641         }
3642         you.props[RU_SACRIFICE_PENALTY_KEY] = 0;
3643         break;
3644 
3645     default:
3646         you.piety = 15; // to prevent near instant excommunication
3647         if (you.piety_max[you.religion] < 15)
3648             you.piety_max[you.religion] = 15;
3649         you.piety_hysteresis = 0;
3650         you.gift_timeout = 0;
3651         break;
3652     }
3653 
3654     // Tutorial needs berserk usable.
3655     if (crawl_state.game_is_tutorial())
3656         gain_piety(30, 1, false);
3657 
3658     _apply_monk_bonus();
3659     _transfer_good_god_piety();
3660 }
3661 
3662 /// Setup when joining the greedy magnates of Gozag.
_join_gozag()3663 static void _join_gozag()
3664 {
3665     // Handle the fee.
3666     const int fee = gozag_service_fee();
3667     if (fee > 0)
3668     {
3669         ASSERT(you.gold >= fee);
3670         mprf(MSGCH_GOD, "You pay a service fee of %d gold.", fee);
3671         you.gold -= fee;
3672         you.attribute[ATTR_GOZAG_GOLD_USED] += fee;
3673     }
3674     else
3675         simple_god_message(" waives the service fee.");
3676 
3677     // Note relevant powers.
3678     bool needs_redraw = false;
3679     for (const auto& power : get_god_powers(you.religion))
3680     {
3681         if (you.gold >= get_gold_cost(power.abil))
3682         {
3683             power.display(true, "You have enough gold to %s.");
3684             needs_redraw = true;
3685         }
3686     }
3687 
3688     if (needs_redraw)
3689     {
3690 #ifdef USE_TILE_LOCAL
3691         tiles.layout_statcol();
3692         redraw_screen();
3693         update_screen();
3694 #else
3695         ;
3696 #endif
3697     }
3698 
3699     // Move gold to top of piles & detect it.
3700     add_daction(DACT_GOLD_ON_TOP);
3701 }
3702 
3703 /// Setup when joining the gelatinous groupies of Jiyva.
_join_jiyva()3704 static void _join_jiyva()
3705 {
3706     // Complimentary jelly upon joining.
3707     if (_has_jelly())
3708         return;
3709 
3710     mgen_data mg(MONS_JELLY, BEH_STRICT_NEUTRAL, you.pos());
3711     mg.set_summoned(&you, 0, 0, GOD_JIYVA);
3712 
3713     delayed_monster(mg);
3714     simple_god_message(" grants you a jelly!");
3715 }
3716 
3717 /// Setup when joining the sacred cult of Ru.
_join_ru()3718 static void _join_ru()
3719 {
3720     _make_empty_vec(you.props[AVAILABLE_SAC_KEY], SV_INT);
3721     _make_empty_vec(you.props[HEALTH_SAC_KEY], SV_INT);
3722     _make_empty_vec(you.props[ESSENCE_SAC_KEY], SV_INT);
3723     _make_empty_vec(you.props[PURITY_SAC_KEY], SV_INT);
3724     _make_empty_vec(you.props[ARCANA_SAC_KEY], SV_INT);
3725 }
3726 
3727 /// Setup for joining the furious barbarians of Trog.
join_trog_skills()3728 void join_trog_skills()
3729 {
3730     if (!you.has_mutation(MUT_DISTRIBUTED_TRAINING))
3731         for (int sk = SK_SPELLCASTING; sk <= SK_LAST_MAGIC; ++sk)
3732             you.train[sk] = you.train_alt[sk] = TRAINING_DISABLED;
3733 }
3734 
3735 // Setup for joining the orderly ascetics of Zin.
_join_zin()3736 static void _join_zin()
3737 {
3738     // Need to pay St. Peters.
3739     if (you.attribute[ATTR_DONATIONS] * 9 < you.gold)
3740     {
3741         item_def lucre;
3742         lucre.base_type = OBJ_GOLD;
3743         // If you worshipped Zin before, the already tithed for part is fine.
3744         lucre.quantity = you.gold - you.attribute[ATTR_DONATIONS] * 9;
3745         // Use the harsh acquirement pricing -- with a cap at +50 piety.
3746         // We don't want you get max piety at start just because you're filthy
3747         // rich. In that case, you have to donate again more... That the poor
3748         // widow is not spared doesn't mean the rich can't be milked for more.
3749         lucre.props[ACQUIRE_KEY] = 0;
3750         you.gold -= zin_tithe(lucre, lucre.quantity, true);
3751     }
3752 }
3753 
3754 #if TAG_MAJOR_VERSION == 34
3755 // Setup when becoming an overworked assistant to Pakellas.
_join_pakellas()3756 static void _join_pakellas()
3757 {
3758     mprf(MSGCH_GOD, "You stop regenerating magic.");
3759     you.attribute[ATTR_PAKELLAS_EXTRA_MP] = POT_MAGIC_MP;
3760 }
3761 #endif
3762 
3763 // Setup for joining the easygoing followers of Cheibriados.
_join_cheibriados()3764 static void _join_cheibriados()
3765 {
3766     simple_god_message(" begins to support your attributes as your "
3767                        "movement slows.");
3768     notify_stat_change();
3769 }
3770 
3771 /// What special things happen when you join a god?
3772 static const map<god_type, function<void ()>> on_join = {
3773     { GOD_BEOGH, update_player_symbol },
3774     { GOD_CHEIBRIADOS, _join_cheibriados },
__anon576266bf0202() 3775     { GOD_FEDHAS, []() {
3776         mprf(MSGCH_MONSTER_ENCHANT, "The plants of the dungeon cease their "
3777              "hostilities.");
3778         if (env.forest_awoken_until)
3779             for (monster_iterator mi; mi; ++mi)
3780                 mi->del_ench(ENCH_AWAKEN_FOREST);
3781     }},
3782     { GOD_GOZAG, _join_gozag },
3783     { GOD_JIYVA, _join_jiyva },
__anon576266bf0302() 3784     { GOD_LUGONU, []() {
3785         if (you.worshipped[GOD_LUGONU] == 0)
3786             gain_piety(20, 1, false);  // allow instant access to first power
3787     }},
3788 #if TAG_MAJOR_VERSION == 34
3789     { GOD_PAKELLAS, _join_pakellas },
3790 #endif
3791     { GOD_RU, _join_ru },
3792     { GOD_TROG, join_trog_skills },
3793     { GOD_ZIN, _join_zin },
3794 };
3795 
join_religion(god_type which_god)3796 void join_religion(god_type which_god)
3797 {
3798     ASSERT(which_god != GOD_NO_GOD);
3799     ASSERT(which_god != GOD_ECUMENICAL);
3800     ASSERT(!you.has_mutation(MUT_FORLORN));
3801 
3802     redraw_screen();
3803     update_screen();
3804 
3805     const god_type old_god = you.religion;
3806     if (you.previous_good_god == GOD_NO_GOD)
3807     {
3808         you.previous_good_god = old_god;
3809         you.saved_good_god_piety = you.piety;
3810         // doesn't matter if old_god isn't actually a good god; we check later
3811         // and then wipe it at the end of the function regardless
3812     }
3813 
3814     // Leave your prior religion first.
3815     if (!you_worship(GOD_NO_GOD))
3816         excommunication(true, which_god);
3817 
3818     // Welcome to the fold!
3819     you.religion = static_cast<god_type>(which_god);
3820     set_god_ability_slots();    // remove old god's slots, reserve new god's
3821 
3822     mark_milestone("god.worship", "became a worshipper of "
3823                    + god_name(you.religion) + ".");
3824     take_note(Note(NOTE_GET_GOD, you.religion));
3825 
3826     simple_god_message(make_stringf(" welcomes you%s!",
3827                                     you.worshipped[which_god] ? " back"
3828                                                               : "").c_str());
3829     // included in default force_more_message
3830 #ifdef DGL_WHEREIS
3831     whereis_record();
3832 #endif
3833 
3834     _set_initial_god_piety();
3835 
3836     const function<void ()> *join_effect = map_find(on_join, you.religion);
3837     if (join_effect != nullptr)
3838         (*join_effect)();
3839 
3840     // after join_effect() so that gozag's service fee is right for monks
3841     if (you.worshipped[you.religion] < 100)
3842         you.worshipped[you.religion]++;
3843 
3844     // after join_effect so that ru is initialized correctly for get_abilities
3845     // when flash_view_delay redraws the screen in local tiles
3846     _god_welcome_handle_gear();
3847 
3848     // Warn if a good god is starting wrath now.
3849     _check_good_god_wrath(old_god);
3850 
3851     if (!you_worship(GOD_GOZAG))
3852         for (const auto& power : get_god_powers(you.religion))
3853             if (power.rank <= 0)
3854                 power.display(true, "You can now %s.");
3855 
3856     // Allow training all divine ability skills immediately.
3857     vector<ability_type> abilities = get_god_abilities();
3858     for (ability_type abil : abilities)
3859         you.skills_to_show.insert(abil_skill(abil));
3860     update_can_currently_train();
3861 
3862     // now that you have a god, you can't save any piety from your prev god
3863     you.previous_good_god = GOD_NO_GOD;
3864     you.saved_good_god_piety = 0;
3865 
3866     you.redraw_title = true;
3867 
3868 #ifdef USE_TILE_LOCAL
3869     tiles.layout_statcol();
3870     redraw_screen();
3871     update_screen();
3872 #endif
3873 
3874     learned_something_new(HINT_CONVERT);
3875 }
3876 
god_pitch(god_type which_god)3877 void god_pitch(god_type which_god)
3878 {
3879     if (which_god == GOD_BEOGH && env.grid(you.pos()) != DNGN_ALTAR_BEOGH)
3880         mpr("You bow before the missionary of Beogh.");
3881     else
3882     {
3883         mprf("You %s the altar of %s.",
3884              get_form()->player_prayer_action().c_str(),
3885              god_name(which_god).c_str());
3886     }
3887     // these are included in default force_more_message
3888 
3889     const int fee = (which_god == GOD_GOZAG) ? gozag_service_fee() : 0;
3890 
3891     // Note: using worship we could make some gods not allow followers to
3892     // return, or not allow worshippers from other religions. - bwr
3893 
3894     // Gods can be racist...
3895     if (!player_can_join_god(which_god))
3896     {
3897         you.turn_is_over = false;
3898         if (which_god == GOD_GOZAG)
3899         {
3900             simple_god_message(" does not accept service from beggars like you!",
3901                                which_god);
3902             if (you.gold == 0)
3903             {
3904                 mprf("The service fee for joining is currently %d gold; you have"
3905                      " none.", fee);
3906             }
3907             else
3908             {
3909                 mprf("The service fee for joining is currently %d gold; you only"
3910                      " have %d.", fee, you.gold);
3911             }
3912         }
3913         else if (you.get_mutation_level(MUT_NO_LOVE)
3914                  && _god_rejects_loveless(which_god))
3915         {
3916             simple_god_message(" does not accept worship from the loveless!",
3917                                which_god);
3918         }
3919 #if TAG_MAJOR_VERSION == 34
3920         else if (you.get_mutation_level(MUT_NO_ARTIFICE)
3921                  && which_god == GOD_PAKELLAS)
3922         {
3923             simple_god_message(" does not accept worship from those who are "
3924                                "unable to use magical devices!", which_god);
3925         }
3926 #endif
3927         else if (!_transformed_player_can_join_god(which_god))
3928         {
3929             simple_god_message(" says: How dare you approach in such a "
3930                                "loathsome form!",
3931                                which_god);
3932         }
3933         else
3934         {
3935             simple_god_message(" does not accept worship from those such as"
3936                                " you!",
3937                                which_god);
3938         }
3939         return;
3940     }
3941 
3942     if (which_god == GOD_LUGONU && you.penance[GOD_LUGONU])
3943     {
3944         you.turn_is_over = false;
3945         simple_god_message(" refuses to forgive you so easily!", which_god);
3946         return;
3947     }
3948 
3949     if (describe_god_with_join(which_god))
3950         join_religion(which_god);
3951     else
3952     {
3953         you.turn_is_over = false;
3954         redraw_screen();
3955         update_screen();
3956     }
3957 }
3958 
3959 /** Ask the user for a god by name.
3960  *
3961  * @param def_god The god to use if the user presses just ENTER
3962  *                (default NUM_GODS).
3963  * @return the best match for the user's input, or def_god if the user
3964  *         pressed ENTER without providing input, or NUM_GODS if the
3965  *         user cancelled or there was no match.
3966  */
choose_god(god_type def_god)3967 god_type choose_god(god_type def_god)
3968 {
3969     char specs[80];
3970 
3971     string help = def_god == NUM_GODS ? "by name"
3972                                       : "default " + god_name(def_god);
3973     string prompt = make_stringf("Which god (%s)? ", help.c_str());
3974 
3975     if (msgwin_get_line(prompt, specs, sizeof(specs)) != 0)
3976         return NUM_GODS; // FIXME: distinguish cancellation from no match
3977 
3978     // If they pressed enter with no input.
3979     if (specs[0] == '\0')
3980         return def_god;
3981 
3982     string spec = lowercase_string(specs);
3983 
3984     return find_earliest_match(spec, GOD_NO_GOD, NUM_GODS,
3985                                always_true<god_type>,
3986                                bind(god_name, placeholders::_1, false));
3987 }
3988 
had_gods()3989 int had_gods()
3990 {
3991     int count = 0;
3992     for (god_iterator it; it; ++it)
3993         count += you.worshipped[*it];
3994     return count;
3995 }
3996 
god_likes_your_god(god_type god,god_type your_god)3997 bool god_likes_your_god(god_type god, god_type your_god)
3998 {
3999     return is_good_god(god) && is_good_god(your_god);
4000 }
4001 
god_hates_your_god(god_type god,god_type your_god)4002 bool god_hates_your_god(god_type god, god_type your_god)
4003 {
4004     // Ru doesn't care.
4005     if (god == GOD_RU)
4006         return false;
4007 
4008     // Gods do not hate themselves.
4009     if (god == your_god)
4010         return false;
4011 
4012     // Non-good gods always hate your current god.
4013     if (!is_good_god(god))
4014         return true;
4015 
4016     // Zin hates chaotic gods.
4017     if (god == GOD_ZIN && is_chaotic_god(your_god))
4018         return true;
4019 
4020     return is_evil_god(your_god);
4021 }
4022 
god_hates_killing(god_type god,const monster & mon)4023 bool god_hates_killing(god_type god, const monster& mon)
4024 {
4025     if (invalid_monster(&mon))
4026         return false;
4027     // Must be at least a creature of sorts. Smacking down an enchanted
4028     // weapon or disrupting a lightning doesn't count. Technically, this
4029     // might raise a concern about necromancy but zombies traditionally
4030     // count as creatures and that's the average person's (even if not ours)
4031     // intuition.
4032     if (mons_is_object(mon.type))
4033         return false;
4034 
4035     // kill as many illusions as you want.
4036     if (mon.is_illusion())
4037         return false;
4038 
4039     bool retval = false;
4040     const mon_holy_type holiness = mon.holiness();
4041 
4042     if (holiness & MH_HOLY)
4043         retval = (is_good_god(god));
4044     else if (holiness & MH_NATURAL)
4045         retval = (god == GOD_ELYVILON);
4046 
4047     if (god == GOD_FEDHAS)
4048         retval = (fedhas_protects(&mon));
4049 
4050     return retval;
4051 }
4052 
god_likes_spell(spell_type spell,god_type god)4053 bool god_likes_spell(spell_type spell, god_type god)
4054 {
4055     switch (god)
4056     {
4057     case GOD_VEHUMET:
4058         return vehumet_supports_spell(spell);
4059     case GOD_KIKUBAAQUDGHA:
4060         return spell_typematch(spell, spschool::necromancy);
4061     default: // quash unhandled constants warnings
4062         return false;
4063     }
4064 }
4065 
4066 /**
4067  * Does your god hate spellcasting?
4068  *
4069  * @param god           The god to check against
4070  * @return              Whether the god hates spellcasting
4071  */
god_hates_spellcasting(god_type god)4072 bool god_hates_spellcasting(god_type god)
4073 {
4074     return god == GOD_TROG;
4075 }
4076 
4077 /**
4078  * Will your god put you under penance if you actually cast spell?
4079  *
4080  * @param spell         The spell to check against
4081  * @param god           The god to check against
4082  * @param fake_spell    true if the spell is evoked or from an innate or divine ability
4083  *                      false if it is a spell being cast normally.
4084  * @return              true if the god hates the spell
4085  */
god_hates_spell(spell_type spell,god_type god,bool fake_spell)4086 bool god_hates_spell(spell_type spell, god_type god, bool fake_spell)
4087 {
4088     if (god_hates_spellcasting(god))
4089         return !fake_spell;
4090 
4091     if (god_punishes_spell(spell, god))
4092         return true;
4093 
4094     switch (god)
4095     {
4096     case GOD_CHEIBRIADOS:
4097         if (is_hasty_spell(spell))
4098             return true;
4099         break;
4100 #if TAG_MAJOR_VERSION == 34
4101     case GOD_PAKELLAS:
4102         if (spell == SPELL_SUBLIMATION_OF_BLOOD)
4103             return true;
4104         break;
4105 #endif
4106     default:
4107         break;
4108     }
4109     return false;
4110 }
4111 
4112 /**
4113  * Will your god excommunicate you if you actually cast spell?
4114  *
4115  * @param spell         The spell to check against
4116  * @param god           The god to check against
4117  * @return              Whether the god loathes the spell
4118  */
god_loathes_spell(spell_type spell,god_type god)4119 bool god_loathes_spell(spell_type spell, god_type god)
4120 {
4121     if (spell == SPELL_NECROMUTATION && is_good_god(god))
4122         return true;
4123     return false;
4124 }
4125 
4126 /**
4127  * Checks to see if your god hates or loathes this spell,
4128  * or just hates spellcasting in general, and returns a warning string
4129  *
4130  * @param spell         The spell to check against
4131  * @param god           The god to check against
4132  * @return              Warning string if god has strong opinions on spell
4133  *                      Empty string if god doesn't care about spell
4134  */
god_spell_warn_string(spell_type spell,god_type god)4135 string god_spell_warn_string(spell_type spell, god_type god)
4136 {
4137     if (god_loathes_spell(spell, god))
4138         return "Your god extremely despises this spell!";
4139     else if (god_hates_spellcasting(god))
4140         return "Your god hates spellcasting!";
4141     else if (god_hates_spell(spell, god))
4142         return "Your god hates this spell!";
4143     else
4144         return "";
4145 }
4146 
god_hates_ability(ability_type ability,god_type god)4147 bool god_hates_ability(ability_type ability, god_type god)
4148 {
4149     switch (ability)
4150     {
4151         case ABIL_EVOKE_BERSERK:
4152             return god == GOD_CHEIBRIADOS;
4153         default:
4154             break;
4155     }
4156     return false;
4157 }
4158 
elyvilon_lifesaving()4159 lifesaving_chance elyvilon_lifesaving()
4160 {
4161     if (!you_worship(GOD_ELYVILON))
4162         return lifesaving_chance::never;
4163 
4164     if (you.piety < piety_breakpoint(0))
4165         return lifesaving_chance::never;
4166 
4167     return you.piety >= piety_breakpoint(4) ? lifesaving_chance::always
4168                            : lifesaving_chance::sometimes;
4169 }
4170 
god_protects_from_harm()4171 bool god_protects_from_harm()
4172 {
4173     if (you.duration[DUR_LIFESAVING])
4174     {
4175         switch (elyvilon_lifesaving())
4176         {
4177         case lifesaving_chance::sometimes:
4178             if (random2(you.piety) >= piety_breakpoint(0))
4179                 return true;
4180             break;
4181         case lifesaving_chance::always:
4182             // Reliable lifesaving is costly.
4183             lose_piety(21 + random2(20));
4184             return true;
4185         default:
4186             break;
4187         }
4188     }
4189 
4190     if (have_passive(passive_t::protect_from_harm)
4191         && (one_chance_in(10) || x_chance_in_y(you.piety, 1000)))
4192     {
4193         return true;
4194     }
4195 
4196     return false;
4197 }
4198 
handle_god_time(int)4199 void handle_god_time(int /*time_delta*/)
4200 {
4201     if (you.attribute[ATTR_GOD_WRATH_COUNT] > 0)
4202     {
4203         vector<god_type> angry_gods;
4204         // First count the number of gods to whom we owe penance.
4205         for (god_iterator it; it; ++it)
4206         {
4207             if (active_penance(*it))
4208                 angry_gods.push_back(*it);
4209         }
4210         if (x_chance_in_y(angry_gods.size(), 20))
4211         {
4212             // This should be guaranteed; otherwise the god wouldn't have
4213             // appeared in the angry_gods list.
4214             const bool succ = divine_retribution(*random_iterator(angry_gods));
4215             ASSERT(succ);
4216         }
4217         you.attribute[ATTR_GOD_WRATH_COUNT]--;
4218     }
4219 
4220     // Update the god's opinion of the player.
4221     if (!you_worship(GOD_NO_GOD))
4222     {
4223         int delay;
4224         int sacrifice_count;
4225         switch (you.religion)
4226         {
4227         case GOD_TROG:
4228         case GOD_OKAWARU:
4229         case GOD_MAKHLEB:
4230         case GOD_BEOGH:
4231         case GOD_LUGONU:
4232         case GOD_DITHMENOS:
4233         case GOD_QAZLAL:
4234         case GOD_YREDELEMNUL:
4235         case GOD_KIKUBAAQUDGHA:
4236         case GOD_VEHUMET:
4237         case GOD_ZIN:
4238 #if TAG_MAJOR_VERSION == 34
4239         case GOD_PAKELLAS:
4240 #endif
4241         case GOD_JIYVA:
4242         case GOD_WU_JIAN:
4243         case GOD_SIF_MUNA:
4244             if (one_chance_in(17))
4245                 lose_piety(1);
4246             break;
4247 
4248         case GOD_ELYVILON:
4249         case GOD_HEPLIAKLQANA:
4250         case GOD_FEDHAS:
4251         case GOD_CHEIBRIADOS:
4252         case GOD_SHINING_ONE:
4253         case GOD_NEMELEX_XOBEH:
4254             if (one_chance_in(35))
4255                 lose_piety(1);
4256             break;
4257 
4258         case GOD_ASHENZARI:
4259             ASSERT(you.props.exists(ASHENZARI_CURSE_PROGRESS_KEY));
4260             ASSERT(you.props.exists(ASHENZARI_CURSE_DELAY_KEY));
4261 
4262             if (you.props[ASHENZARI_CURSE_PROGRESS_KEY].get_int()
4263                 >= you.props[ASHENZARI_CURSE_DELAY_KEY].get_int())
4264             {
4265                 ashenzari_offer_new_curse();
4266             }
4267             break;
4268 
4269         case GOD_RU:
4270             ASSERT(you.props.exists(RU_SACRIFICE_PROGRESS_KEY));
4271             ASSERT(you.props.exists(RU_SACRIFICE_DELAY_KEY));
4272             ASSERT(you.props.exists(AVAILABLE_SAC_KEY));
4273 
4274             delay = you.props[RU_SACRIFICE_DELAY_KEY].get_int();
4275             sacrifice_count = you.props[AVAILABLE_SAC_KEY].get_vector().size();
4276 
4277             // 6* is max piety for Ru
4278             if (sacrifice_count == 0 && you.piety < piety_breakpoint(5)
4279                 && you.props[RU_SACRIFICE_PROGRESS_KEY].get_int() >= delay)
4280             {
4281               ru_offer_new_sacrifices();
4282             }
4283 
4284             break;
4285 
4286         case GOD_USKAYAW:
4287             // We handle Uskayaw elsewhere because this func gets called rarely
4288         case GOD_GOZAG:
4289         case GOD_XOM:
4290             // Gods without normal piety do nothing each tick.
4291             return;
4292 
4293         case GOD_NO_GOD:
4294         case GOD_RANDOM:
4295         case GOD_ECUMENICAL:
4296         case GOD_NAMELESS:
4297         case NUM_GODS:
4298             die("Bad god, no bishop!");
4299             return;
4300 
4301         }
4302 
4303         if (you.piety < 1)
4304             excommunication();
4305     }
4306 }
4307 
god_colour(god_type god)4308 int god_colour(god_type god) // mv - added
4309 {
4310     switch (god)
4311     {
4312     case GOD_ZIN:
4313     case GOD_SHINING_ONE:
4314     case GOD_ELYVILON:
4315     case GOD_OKAWARU:
4316     case GOD_FEDHAS:
4317         return CYAN;
4318 
4319     case GOD_YREDELEMNUL:
4320     case GOD_KIKUBAAQUDGHA:
4321     case GOD_MAKHLEB:
4322     case GOD_VEHUMET:
4323     case GOD_TROG:
4324     case GOD_BEOGH:
4325     case GOD_LUGONU:
4326     case GOD_ASHENZARI:
4327     case GOD_WU_JIAN:
4328         return LIGHTRED;
4329 
4330     case GOD_GOZAG:
4331     case GOD_XOM:
4332         return YELLOW;
4333 
4334     case GOD_NEMELEX_XOBEH:
4335         return LIGHTMAGENTA;
4336 
4337     case GOD_SIF_MUNA:
4338         return LIGHTBLUE;
4339 
4340     case GOD_JIYVA:
4341         return GREEN;
4342 
4343     case GOD_CHEIBRIADOS:
4344     case GOD_HEPLIAKLQANA:
4345         return LIGHTCYAN;
4346 
4347     case GOD_DITHMENOS:
4348     case GOD_USKAYAW:
4349         return MAGENTA;
4350 
4351     case GOD_QAZLAL:
4352     case GOD_RU:
4353         return BROWN;
4354 
4355 #if TAG_MAJOR_VERSION == 34
4356     case GOD_PAKELLAS:
4357         return LIGHTGREEN;
4358 #endif
4359 
4360     case GOD_NO_GOD:
4361     case NUM_GODS:
4362     case GOD_RANDOM:
4363     case GOD_NAMELESS:
4364     default:
4365         break;
4366     }
4367 
4368     return YELLOW;
4369 }
4370 
god_message_altar_colour(god_type god)4371 colour_t god_message_altar_colour(god_type god)
4372 {
4373     int rnd;
4374 
4375     switch (god)
4376     {
4377     case GOD_SHINING_ONE:
4378         return YELLOW;
4379 
4380     case GOD_ZIN:
4381         return WHITE;
4382 
4383     case GOD_ELYVILON:
4384         return LIGHTBLUE;     // Really, LIGHTGREY but that's plain text.
4385 
4386     case GOD_OKAWARU:
4387         return CYAN;
4388 
4389     case GOD_YREDELEMNUL:
4390         return random_choose(DARKGREY, RED);
4391 
4392     case GOD_BEOGH:
4393         return random_choose(BROWN, LIGHTRED);
4394 
4395     case GOD_KIKUBAAQUDGHA:
4396         return DARKGREY;
4397 
4398     case GOD_FEDHAS:
4399         return random_choose(BROWN, GREEN);
4400 
4401     case GOD_XOM:
4402         return random2(15) + 1;
4403 
4404     case GOD_VEHUMET:
4405         rnd = random2(3);
4406         return (rnd == 0) ? LIGHTMAGENTA :
4407                (rnd == 1) ? LIGHTRED
4408                           : LIGHTBLUE;
4409 
4410     case GOD_MAKHLEB:
4411         rnd = random2(3);
4412         return (rnd == 0) ? RED :
4413                (rnd == 1) ? LIGHTRED
4414                           : YELLOW;
4415 
4416     case GOD_TROG:
4417         return RED;
4418 
4419     case GOD_NEMELEX_XOBEH:
4420         return LIGHTMAGENTA;
4421 
4422     case GOD_SIF_MUNA:
4423         return BLUE;
4424 
4425     case GOD_LUGONU:
4426     case GOD_WU_JIAN:
4427         return LIGHTRED;
4428 
4429     case GOD_CHEIBRIADOS:
4430         return LIGHTCYAN;
4431 
4432     case GOD_JIYVA:
4433         return random_choose(GREEN, LIGHTGREEN);
4434 
4435     case GOD_DITHMENOS:
4436         return MAGENTA;
4437 
4438     case GOD_GOZAG:
4439         return random_choose(YELLOW, BROWN);
4440 
4441     case GOD_QAZLAL:
4442     case GOD_RU:
4443         return BROWN;
4444 
4445 #if TAG_MAJOR_VERSION == 34
4446     case GOD_PAKELLAS:
4447         return random_choose(LIGHTMAGENTA, LIGHTGREEN, LIGHTCYAN);
4448 #endif
4449 
4450     case GOD_USKAYAW:
4451         return random_choose(RED, MAGENTA);
4452 
4453     case GOD_HEPLIAKLQANA:
4454         return random_choose(LIGHTGREEN, LIGHTBLUE);
4455 
4456     default:
4457         return YELLOW;
4458     }
4459 }
4460 
piety_rank(int piety)4461 int piety_rank(int piety)
4462 {
4463     // XXX: this seems to be used only in dat/database/godspeak.txt?
4464     if (you_worship(GOD_XOM))
4465     {
4466         const int breakpoints[] = { 20, 50, 80, 120, 180, INT_MAX };
4467         for (unsigned int i = 0; i < ARRAYSZ(breakpoints); ++i)
4468             if (piety <= breakpoints[i])
4469                 return i + 1;
4470         die("INT_MAX is no good");
4471     }
4472 
4473     for (int i = NUM_PIETY_STARS; i >= 1; --i)
4474         if (piety >= piety_breakpoint(i - 1))
4475             return i;
4476 
4477     return 0;
4478 }
4479 
piety_breakpoint(int i)4480 int piety_breakpoint(int i)
4481 {
4482     int breakpoints[NUM_PIETY_STARS] = { 30, 50, 75, 100, 120, 160 };
4483     if (i >= NUM_PIETY_STARS || i < 0)
4484         return 255;
4485     else
4486         return breakpoints[i];
4487 }
4488 
get_monster_tension(const monster & mons,god_type god)4489 int get_monster_tension(const monster& mons, god_type god)
4490 {
4491     if (!mons.alive())
4492         return 0;
4493 
4494     if (you.see_cell(mons.pos()))
4495     {
4496         if (!mons_can_hurt_player(&mons))
4497             return 0;
4498     }
4499 
4500     const mon_attitude_type att = mons_attitude(mons);
4501     if (att == ATT_GOOD_NEUTRAL || att == ATT_NEUTRAL)
4502         return 0;
4503 
4504     if (mons.cannot_act() || mons.asleep() || mons_is_fleeing(mons))
4505         return 0;
4506 
4507     int exper = exper_value(mons);
4508     if (exper <= 0)
4509         return 0;
4510 
4511     // Almost dead monsters don't count as much.
4512     exper *= mons.hit_points;
4513     exper /= mons.max_hit_points;
4514 
4515     bool gift = false;
4516 
4517     if (god != GOD_NO_GOD)
4518         gift = mons_is_god_gift(mons, god);
4519 
4520     if (att == ATT_HOSTILE)
4521     {
4522         // God is punishing you with a hostile gift, so it doesn't
4523         // count towards tension.
4524         if (gift)
4525             return 0;
4526     }
4527     else if (att == ATT_FRIENDLY)
4528     {
4529         // Friendly monsters being around to help you reduce
4530         // tension.
4531         exper = -exper;
4532 
4533         // If it's a god gift, it reduces tension even more, since
4534         // the god is already helping you out.
4535         if (gift)
4536             exper *= 2;
4537     }
4538 
4539     if (att != ATT_FRIENDLY)
4540     {
4541         if (!you.visible_to(&mons))
4542             exper /= 2;
4543         if (!mons.visible_to(&you))
4544             exper *= 2;
4545     }
4546 
4547     if (mons.confused() || mons.caught())
4548         exper /= 2;
4549 
4550     if (mons.has_ench(ENCH_SLOW))
4551     {
4552         exper *= 2;
4553         exper /= 3;
4554     }
4555 
4556     if (mons.has_ench(ENCH_HASTE))
4557     {
4558         exper *= 3;
4559         exper /= 2;
4560     }
4561 
4562     if (mons.has_ench(ENCH_MIGHT))
4563     {
4564         exper *= 5;
4565         exper /= 4;
4566     }
4567 
4568     if (mons.berserk_or_insane())
4569     {
4570         // in addition to haste and might bonuses above
4571         exper *= 3;
4572         exper /= 2;
4573     }
4574 
4575     return exper;
4576 }
4577 
get_tension(god_type god)4578 int get_tension(god_type god)
4579 {
4580     int total = 0;
4581 
4582     bool nearby_monster = false;
4583     for (radius_iterator ri(you.pos(), LOS_NO_TRANS); ri; ++ri)
4584     {
4585         const monster* mon = monster_at(*ri);
4586 
4587         if (mon && mon->alive() && you.can_see(*mon))
4588         {
4589             int exper = get_monster_tension(*mon, god);
4590 
4591             if (!mon->wont_attack())
4592                 nearby_monster = true;
4593 
4594             total += exper;
4595         }
4596     }
4597 
4598     // At least one monster has to be nearby, for tension to count.
4599     if (!nearby_monster)
4600         return 0;
4601 
4602     const int scale = 1;
4603 
4604     int tension = total;
4605 
4606     // Tension goes up inversely proportional to the percentage of max
4607     // hp you have.
4608     tension *= (scale + 1) * you.hp_max;
4609     tension /= max(you.hp_max + scale * you.hp, 1);
4610 
4611     // Divides by 1 at level 1, 200 at level 27.
4612     const int exp_lev  = you.get_experience_level();
4613     const int exp_need = exp_needed(exp_lev);
4614     const int factor   = (int)ceil(sqrt(exp_need / 30.0));
4615     const int div      = 1 + factor;
4616 
4617     tension /= div;
4618 
4619     if (player_in_branch(BRANCH_ABYSS))
4620     {
4621         if (tension < 2)
4622             tension = 2;
4623         else
4624         {
4625             tension *= 3;
4626             tension /= 2;
4627         }
4628     }
4629 
4630     if (you.cannot_act())
4631     {
4632         tension *= 10;
4633         tension  = max(1, tension);
4634 
4635         return tension;
4636     }
4637 
4638     if (you.confused())
4639         tension *= 2;
4640 
4641     if (you.caught())
4642         tension *= 2;
4643 
4644     if (you.duration[DUR_SLOW])
4645     {
4646         tension *= 3;
4647         tension /= 2;
4648     }
4649 
4650     if (you.duration[DUR_HASTE])
4651     {
4652         tension *= 2;
4653         tension /= 3;
4654     }
4655 
4656     return max(0, tension);
4657 }
4658 
get_fuzzied_monster_difficulty(const monster & mons)4659 int get_fuzzied_monster_difficulty(const monster& mons)
4660 {
4661     double factor = sqrt(exp_needed(you.experience_level) / 30.0);
4662     int exp = exper_value(mons) * 100;
4663     exp = random2(exp) + random2(exp);
4664     return exp / (1 + factor);
4665 }
4666 
4667 /////////////////////////////////////////////////////////////////////////////
4668 // Stuff for placing god gift monsters after the player's turn has ended.
4669 /////////////////////////////////////////////////////////////////////////////
4670 
4671 static vector<mgen_data>       _delayed_data;
4672 static deque<delayed_callback> _delayed_callbacks;
4673 static deque<unsigned int>     _delayed_done_trigger_pos;
4674 static deque<delayed_callback> _delayed_done_callbacks;
4675 static deque<string>      _delayed_success;
4676 
delayed_monster(const mgen_data & mg,delayed_callback callback)4677 void delayed_monster(const mgen_data &mg, delayed_callback callback)
4678 {
4679     _delayed_data.push_back(mg);
4680     _delayed_callbacks.push_back(callback);
4681 }
4682 
delayed_monster_done(string success,delayed_callback callback)4683 void delayed_monster_done(string success, delayed_callback callback)
4684 {
4685     const unsigned int size = _delayed_data.size();
4686     ASSERT(size > 0);
4687 
4688     _delayed_done_trigger_pos.push_back(size - 1);
4689     _delayed_success.push_back(success);
4690     _delayed_done_callbacks.push_back(callback);
4691 }
4692 
_place_delayed_monsters()4693 static void _place_delayed_monsters()
4694 {
4695     // Last monster that was successfully placed (so far).
4696     monster *lastmon  = nullptr;
4697     int      placed   = 0;
4698     god_type prev_god = GOD_NO_GOD;
4699 
4700     for (unsigned int i = 0; i < _delayed_data.size(); i++)
4701     {
4702         mgen_data &mg          = _delayed_data[i];
4703         delayed_callback cback = _delayed_callbacks[i];
4704 
4705         if (prev_god != mg.god)
4706         {
4707             lastmon  = nullptr;
4708             placed   = 0;
4709             prev_god = mg.god;
4710         }
4711 
4712         monster *mon = create_monster(mg);
4713 
4714         if (cback)
4715             (*cback)(mg, mon, placed);
4716 
4717         if (mon)
4718         {
4719             if (you_worship(GOD_YREDELEMNUL)
4720                 || you_worship(GOD_HEPLIAKLQANA)
4721                 || have_passive(passive_t::convert_orcs))
4722             {
4723                 add_companion(mon);
4724             }
4725             lastmon = mon;
4726             placed++;
4727         }
4728 
4729         if (!_delayed_done_trigger_pos.empty()
4730             && _delayed_done_trigger_pos[0] == i)
4731         {
4732             cback = _delayed_done_callbacks[0];
4733 
4734             string msg;
4735             if (lastmon)
4736             {
4737                 ASSERT(placed > 0);
4738                 msg = replace_all(_delayed_success[0], "@servant@",
4739                                   placed == 1
4740                                       ? lastmon->name(DESC_A)
4741                                       : pluralise(lastmon->name(DESC_PLAIN)));
4742             }
4743             else
4744                 ASSERT(placed == 0);
4745 
4746             prev_god = GOD_NO_GOD;
4747             _delayed_done_trigger_pos.pop_front();
4748             _delayed_success.pop_front();
4749             _delayed_done_callbacks.pop_front();
4750 
4751             if (msg.empty())
4752             {
4753                 if (cback)
4754                     (*cback)(mg, lastmon, placed);
4755                 continue;
4756             }
4757 
4758             // Fake its coming from simple_god_message().
4759             if (msg[0] == ' ' || msg[0] == '\'')
4760                 msg = uppercase_first(god_name(mg.god)) + msg;
4761 
4762             trim_string(msg);
4763 
4764             god_speaks(mg.god, msg.c_str());
4765 
4766             if (cback)
4767                 (*cback)(mg, lastmon, placed);
4768         }
4769     }
4770 
4771     _delayed_data.clear();
4772     _delayed_callbacks.clear();
4773     _delayed_done_trigger_pos.clear();
4774     _delayed_success.clear();
4775 }
4776 
_is_god(god_type god)4777 static bool _is_god(god_type god)
4778 {
4779     return god > GOD_NO_GOD && god < NUM_GODS;
4780 }
4781 
_is_temple_god(god_type god)4782 static bool _is_temple_god(god_type god)
4783 {
4784     if (!_is_god(god) || _is_disabled_god(god))
4785         return false;
4786 
4787     switch (god)
4788     {
4789     case GOD_NO_GOD:
4790     case GOD_LUGONU:
4791     case GOD_BEOGH:
4792     case GOD_JIYVA:
4793         return false;
4794 
4795     default:
4796         return true;
4797     }
4798 }
4799 
_is_nontemple_god(god_type god)4800 static bool _is_nontemple_god(god_type god)
4801 {
4802     return _is_god(god) && !_is_temple_god(god) && !_is_disabled_god(god);
4803 }
4804 
_cmp_god_by_name(god_type god1,god_type god2)4805 static bool _cmp_god_by_name(god_type god1, god_type god2)
4806 {
4807     return god_name(god1, false) < god_name(god2, false);
4808 }
4809 
4810 // Vector of temple gods.
4811 // Sorted by name for the benefit of the overview.
temple_god_list()4812 vector<god_type> temple_god_list()
4813 {
4814     vector<god_type> god_list;
4815     for (god_iterator it; it; ++it)
4816         if (_is_temple_god(*it))
4817             god_list.push_back(*it);
4818     sort(god_list.begin(), god_list.end(), _cmp_god_by_name);
4819     return god_list;
4820 }
4821 
4822 // Vector of non-temple gods.
4823 // Sorted by name for the benefit of the overview.
nontemple_god_list()4824 vector<god_type> nontemple_god_list()
4825 {
4826     vector<god_type> god_list;
4827     for (god_iterator it; it; ++it)
4828         if (_is_nontemple_god(*it))
4829             god_list.push_back(*it);
4830     sort(god_list.begin(), god_list.end(), _cmp_god_by_name);
4831     return god_list;
4832 }
4833 
god_power_usable(const god_power & power,bool ignore_piety,bool ignore_penance)4834 bool god_power_usable(const god_power& power, bool ignore_piety, bool ignore_penance)
4835 {
4836     // not an activated power
4837     if (power.abil == ABIL_NON_ABILITY)
4838         return false;
4839     const ability_type abil = fixup_ability(power.abil);
4840     ASSERT(abil != ABIL_NON_ABILITY);
4841     return (power.rank <= 0
4842             || power.rank == 7 && can_do_capstone_ability(you.religion)
4843             || piety_rank() >= power.rank
4844             || ignore_piety)
4845            && (!player_under_penance()
4846                || power.rank == -1
4847                || ignore_penance);
4848 }
4849 
god_power_from_ability(ability_type abil)4850 const god_power* god_power_from_ability(ability_type abil)
4851 {
4852     for (int god = GOD_NO_GOD; god < NUM_GODS; god++)
4853     {
4854         for (const auto& power : god_powers[god])
4855         {
4856             if (power.abil == abil)
4857                 return &power;
4858         }
4859     }
4860     return nullptr;
4861 }
4862