From a6a6af9550285fa15efbb7a1dd97c86721058a39 Mon Sep 17 00:00:00 2001 From: jwalz Date: Sat, 5 Jan 2002 21:05:52 +0000 Subject: [PATCH] *** empty log message *** --- src/pray.c | 1773 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1773 insertions(+) create mode 100644 src/pray.c diff --git a/src/pray.c b/src/pray.c new file mode 100644 index 000000000..c630ad4f1 --- /dev/null +++ b/src/pray.c @@ -0,0 +1,1773 @@ +/* SCCS Id: @(#)pray.c 3.3 2001/11/29 */ +/* Copyright (c) Benson I. Margulies, Mike Stephenson, Steve Linhart, 1989. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "hack.h" +#include "epri.h" + +STATIC_PTR int NDECL(prayer_done); +STATIC_DCL int NDECL(in_trouble); +STATIC_DCL void FDECL(fix_worst_trouble,(int)); +STATIC_DCL void FDECL(angrygods,(ALIGNTYP_P)); +#ifdef ELBERETH +STATIC_DCL void NDECL(gcrownu); +#endif /*ELBERETH*/ +STATIC_DCL void FDECL(pleased,(ALIGNTYP_P)); +STATIC_DCL void FDECL(godvoice,(ALIGNTYP_P,const char*)); +STATIC_DCL void FDECL(god_zaps_you,(ALIGNTYP_P)); +STATIC_DCL void FDECL(fry_by_god,(ALIGNTYP_P)); +STATIC_DCL void FDECL(gods_angry,(ALIGNTYP_P)); +STATIC_DCL void FDECL(gods_upset,(ALIGNTYP_P)); +STATIC_DCL void FDECL(consume_offering,(struct obj *)); +STATIC_DCL boolean FDECL(water_prayer,(BOOLEAN_P)); +STATIC_DCL boolean FDECL(blocked_boulder,(int,int)); + +/* + * Logic behind deities and altars and such: + * + prayers are made to your god if not on an altar, and to the altar's god + * if you are on an altar + * + If possible, your god answers all prayers, which is why bad things happen + * if you try to pray on another god's altar + * + sacrifices work basically the same way, but the other god may decide to + * accept your allegiance, after which they are your god. If rejected, + * your god takes over with your punishment. + * + if you're in Gehennom, all messages come from Moloch + */ + +/* + * Moloch, who dwells in Gehennom, is the "renegade" cruel god + * responsible for the theft of the Amulet from Marduk, the Creator. + * Moloch is unaligned. + */ +static const char *Moloch = "Moloch"; + +static const char *godvoices[] = { + "booms out", + "thunders", + "rings out", + "booms", +}; + +/* values calculated when prayer starts, and used when completed */ +static aligntyp p_aligntyp; +static int p_trouble; +static int p_type; /* (-1)-3: (-1)=really naughty, 3=really good */ + +#define PIOUS 20 +#define DEVOUT 14 +#define FERVENT 9 +#define STRIDENT 4 + +#define TROUBLE_STONED 12 +#define TROUBLE_SLIMED 11 +#define TROUBLE_STRANGLED 10 +#define TROUBLE_LAVA 9 +#define TROUBLE_SICK 8 +#define TROUBLE_STARVING 7 +#define TROUBLE_HIT 6 +#define TROUBLE_LYCANTHROPE 5 +#define TROUBLE_COLLAPSING 4 +#define TROUBLE_STUCK_IN_WALL 3 +#define TROUBLE_CURSED_BLINDFOLD 2 +#define TROUBLE_CURSED_LEVITATION 1 + +#define TROUBLE_PUNISHED (-1) +#define TROUBLE_CURSED_ITEMS (-2) +#define TROUBLE_BLIND (-3) +#define TROUBLE_POISONED (-4) +#define TROUBLE_WOUNDED_LEGS (-5) +#define TROUBLE_HUNGRY (-6) +#define TROUBLE_STUNNED (-7) +#define TROUBLE_CONFUSED (-8) +#define TROUBLE_HALLUCINATION (-9) + +/* We could force rehumanize of polyselfed people, but we can't tell + unintentional shape changes from the other kind. Oh well. */ + +/* Return 0 if nothing particular seems wrong, positive numbers for + serious trouble, and negative numbers for comparative annoyances. This + returns the worst problem. There may be others, and the gods may fix + more than one. + +This could get as bizarre as noting surrounding opponents, (or hostile dogs), +but that's really hard. + */ + +#define ugod_is_angry() (u.ualign.record < 0) +#define on_altar() IS_ALTAR(levl[u.ux][u.uy].typ) +#define on_shrine() ((levl[u.ux][u.uy].altarmask & AM_SHRINE) != 0) +#define a_align(x,y) ((aligntyp)Amask2align(levl[x][y].altarmask & AM_MASK)) + +STATIC_OVL int +in_trouble() +{ + register struct obj *otmp; + int i, j, count=0; + +/* Borrowed from eat.c */ + +#define SATIATED 0 +#define NOT_HUNGRY 1 +#define HUNGRY 2 +#define WEAK 3 +#define FAINTING 4 +#define FAINTED 5 +#define STARVED 6 + + if(Stoned) return(TROUBLE_STONED); + if(Slimed) return(TROUBLE_SLIMED); + if(Strangled) return(TROUBLE_STRANGLED); + if(u.utrap && u.utraptype == TT_LAVA) return(TROUBLE_LAVA); + if(Sick) return(TROUBLE_SICK); + if(u.uhs >= WEAK) return(TROUBLE_STARVING); + if (Upolyd ? (u.mh <= 5 || u.mh*7 <= u.mhmax) : + (u.uhp <= 5 || u.uhp*7 <= u.uhpmax)) return TROUBLE_HIT; + if(u.ulycn >= LOW_PM) return(TROUBLE_LYCANTHROPE); + if(near_capacity() >= EXT_ENCUMBER && AMAX(A_STR)-ABASE(A_STR) > 3) + return(TROUBLE_COLLAPSING); + + for (i= -1; i<=1; i++) for(j= -1; j<=1; j++) { + if (!i && !j) continue; + if (!isok(u.ux+i, u.uy+j) || IS_ROCK(levl[u.ux+i][u.uy+j].typ) + || (blocked_boulder(i,j) && !throws_rocks(youmonst.data))) + count++; + } + if (count == 8 && !Passes_walls) + return(TROUBLE_STUCK_IN_WALL); + + if((uarmf && uarmf->otyp==LEVITATION_BOOTS && uarmf->cursed) || + (uleft && uleft->otyp==RIN_LEVITATION && uleft->cursed) || + (uright && uright->otyp==RIN_LEVITATION && uright->cursed)) + return(TROUBLE_CURSED_LEVITATION); + if(Blindfolded && ublindf->cursed) return(TROUBLE_CURSED_BLINDFOLD); + + if(Punished) return(TROUBLE_PUNISHED); + for(otmp=invent; otmp; otmp=otmp->nobj) + if((otmp->otyp==LOADSTONE || otmp->otyp==LUCKSTONE) && + otmp->cursed) + return(TROUBLE_CURSED_ITEMS); + if((uarmh && uarmh->cursed) || /* helmet */ + (uarms && uarms->cursed) || /* shield */ + (uarmg && uarmg->cursed) || /* gloves */ + (uarm && uarm->cursed) || /* armor */ + (uarmc && uarmc->cursed) || /* cloak */ + (uarmf && uarmf->cursed && uarmf->otyp != LEVITATION_BOOTS) || + /* boots */ + (ublindf && ublindf->otyp == LENSES && ublindf->cursed) || + /* lenses: blindfold is TROUBLE_CURSED_BLINDFOLD */ +#ifdef TOURIST + (uarmu && uarmu->cursed) || /* shirt */ +#endif + (welded(uwep)) || + (uleft && uleft->cursed && uleft->otyp != RIN_LEVITATION) || + (uright && uright->cursed && uright->otyp != RIN_LEVITATION) || + (uamul && uamul->cursed)) + return(TROUBLE_CURSED_ITEMS); + + if(Blinded > 1) return(TROUBLE_BLIND); + for(i=0; i= HUNGRY) return(TROUBLE_HUNGRY); + if(HStun) return (TROUBLE_STUNNED); + if(HConfusion) return (TROUBLE_CONFUSED); + if(Hallucination) return(TROUBLE_HALLUCINATION); + + return(0); +} + +const char leftglow[] = "left ring softly glows"; +const char rightglow[] = "right ring softly glows"; + +STATIC_OVL void +fix_worst_trouble(trouble) +register int trouble; +{ + int i; + struct obj *otmp; + const char *what = (const char *)0; + + switch (trouble) { + case TROUBLE_STONED: + You_feel("more limber."); + Stoned = 0; + flags.botl = 1; + delayed_killer = 0; + break; + case TROUBLE_SLIMED: + pline_The("slime disappears."); + Slimed = 0; + flags.botl = 1; + delayed_killer = 0; + break; + case TROUBLE_STRANGLED: + if (uamul && uamul->otyp == AMULET_OF_STRANGULATION) { + Your("amulet vanishes!"); + useup(uamul); + } + You("can breathe again."); + Strangled = 0; + flags.botl = 1; + break; + case TROUBLE_LAVA: + You("are back on solid ground."); + /* teleport should always succeed, but if not, + * just untrap them. + */ + if(!safe_teleds()) + u.utrap = 0; + break; + case TROUBLE_STARVING: + losestr(-1); + /* fall into... */ + case TROUBLE_HUNGRY: + Your("%s feels content.", body_part(STOMACH)); + init_uhunger(); + flags.botl = 1; + break; + case TROUBLE_SICK: + You_feel("better."); + make_sick(0L, (char *) 0, FALSE, SICK_ALL); + break; + case TROUBLE_HIT: + /* "fix all troubles" will keep trying if hero has + 5 or less hit points, so make sure they're always + boosted to be more than that */ + You_feel("much better."); + if (Upolyd) { + u.mhmax += rnd(5); + if (u.mhmax <= 5) u.mhmax = 5+1; + u.mh = u.mhmax; + } + if (u.uhpmax < u.ulevel * 5 + 11) u.uhpmax += rnd(5); + if (u.uhpmax <= 5) u.uhpmax = 5+1; + u.uhp = u.uhpmax; + flags.botl = 1; + break; + case TROUBLE_COLLAPSING: + ABASE(A_STR) = AMAX(A_STR); + flags.botl = 1; + break; + case TROUBLE_STUCK_IN_WALL: + Your("surroundings change."); + /* no control, but works on no-teleport levels */ + (void) safe_teleds(); + break; + case TROUBLE_CURSED_LEVITATION: + if (uarmf && uarmf->otyp==LEVITATION_BOOTS + && uarmf->cursed) + otmp = uarmf; + else if (uleft && uleft->otyp==RIN_LEVITATION + && uleft->cursed) { + otmp = uleft; + what = leftglow; + } else { + otmp = uright; + what = rightglow; + } + goto decurse; + case TROUBLE_CURSED_BLINDFOLD: + otmp = ublindf; + goto decurse; + case TROUBLE_LYCANTHROPE: + you_unwere(TRUE); + break; + case TROUBLE_PUNISHED: + Your("chain disappears."); + unpunish(); + break; + case TROUBLE_CURSED_ITEMS: + /* weapon takes precedence if it interferes + with taking off a ring or shield */ + if (welded(uwep) && /* weapon */ + (uright || (bimanual(uwep) && (uleft || uarms)))) + otmp = uwep; + /* gloves come next, due to rings */ + else if (uarmg && uarmg->cursed) /* gloves */ + otmp = uarmg; + /* then shield due to two handed weapons and spells */ + else if (uarms && uarms->cursed) /* shield */ + otmp = uarms; + /* then cloak due to body armor */ + else if (uarmc && uarmc->cursed) /* cloak */ + otmp = uarmc; + else if (uarm && uarm->cursed) /* armor */ + otmp = uarm; + else if (uarmh && uarmh->cursed) /* helmet */ + otmp = uarmh; + else if (uarmf && uarmf->cursed) /* boots */ + otmp = uarmf; +#ifdef TOURIST + else if (uarmu && uarmu->cursed) /* shirt */ + otmp = uarmu; +#endif + /* (perhaps amulet should take precedence over rings?) */ + else if (uleft && uleft->cursed) { + otmp = uleft; + what = leftglow; + } else if (uright && uright->cursed) { + otmp = uright; + what = rightglow; + } else if (uamul && uamul->cursed) /* amulet */ + otmp = uamul; + else if (ublindf && ublindf->cursed) /* eyewear */ + otmp = ublindf; /* must be non-blinding lenses */ + /* if weapon wasn't handled above, do it now */ + else if (welded(uwep)) /* weapon */ + otmp = uwep; + else { + for(otmp=invent; otmp; otmp=otmp->nobj) + if ((otmp->otyp==LOADSTONE || + otmp->otyp==LUCKSTONE) && otmp->cursed) + break; + } +decurse: + if (!otmp) { + impossible("fix_worst_trouble: nothing to uncurse."); + return; + } + uncurse(otmp); + otmp->bknown = TRUE; + if (!Blind) + Your("%s %s.", + what ? what : + (const char *)aobjnam (otmp, "softly glow"), + hcolor(amber)); + break; + case TROUBLE_POISONED: + if (Hallucination) + pline("There's a tiger in your tank."); + else + You_feel("in good health again."); + for(i=0; i 0 ? -Luck/3 : -Luck); + else + maxanger = 3*u.ugangr + + ((Luck > 0 || u.ualign.record >= STRIDENT) ? -Luck/3 : -Luck); + if (maxanger < 1) maxanger = 1; /* possible if bad align & good luck */ + else if (maxanger > 15) maxanger = 15; /* be reasonable */ + + switch (rn2(maxanger)) { + case 0: + case 1: You_feel("that %s is %s.", align_gname(resp_god), + Hallucination ? "bummed" : "displeased"); + break; + case 2: + case 3: + godvoice(resp_god,(char *)0); + pline("\"Thou %s, %s.\"", + (ugod_is_angry() && resp_god == u.ualign.type) + ? "hast strayed from the path" : + "art arrogant", + youmonst.data->mlet == S_HUMAN ? "mortal" : "creature"); + verbalize("Thou must relearn thy lessons!"); + (void) adjattrib(A_WIS, -1, FALSE); + losexp((char *)0); + break; + case 6: if (!Punished) { + gods_angry(resp_god); + punish((struct obj *)0); + break; + } /* else fall thru */ + case 4: + case 5: gods_angry(resp_god); + if (!Blind && !Antimagic) + pline("%s glow surrounds you.", + An(hcolor(Black))); + rndcurse(); + break; + case 7: + case 8: godvoice(resp_god,(char *)0); + verbalize("Thou durst %s me?", + (on_altar() && + (a_align(u.ux,u.uy) != resp_god)) ? + "scorn":"call upon"); + pline("\"Then die, %s!\"", + youmonst.data->mlet == S_HUMAN ? "mortal" : "creature"); + summon_minion(resp_god, FALSE); + break; + + default: gods_angry(resp_god); + god_zaps_you(resp_god); + break; + } + u.ublesscnt = rnz(300); + return; +} + +/* helper to print "str appears at your feet", or appropriate */ +static void +at_your_feet(str) + const char *str; +{ + if (Blind) str = Something; + if (u.uswallow) { + /* barrier between you and the floor */ + pline("%s drops into %s %s.", str, + s_suffix(mon_nam(u.ustuck)), mbodypart(u.ustuck, STOMACH)); + } else { + pline("%s %s %s your %s!", str, + Blind ? "lands" : "appears", + Levitation ? "beneath" : "at", + makeplural(body_part(FOOT))); + } +} + +#ifdef ELBERETH +STATIC_OVL void +gcrownu() +{ + struct obj *obj; + boolean already_exists, in_hand; + short class_gift; + int sp_no; +#define ok_wep(o) ((o) && ((o)->oclass == WEAPON_CLASS || is_weptool(o))) + + HSee_invisible |= FROMOUTSIDE; + HFire_resistance |= FROMOUTSIDE; + HCold_resistance |= FROMOUTSIDE; + HShock_resistance |= FROMOUTSIDE; + HSleep_resistance |= FROMOUTSIDE; + HPoison_resistance |= FROMOUTSIDE; + godvoice(u.ualign.type, (char *)0); + + obj = ok_wep(uwep) ? uwep : 0; + already_exists = in_hand = FALSE; /* lint suppression */ + switch (u.ualign.type) { + case A_LAWFUL: + u.uevent.uhand_of_elbereth = 1; + verbalize("I crown thee... The Hand of Elbereth!"); + break; + case A_NEUTRAL: + u.uevent.uhand_of_elbereth = 2; + in_hand = (uwep && uwep->oartifact == ART_VORPAL_BLADE); + already_exists = exist_artifact(LONG_SWORD, artiname(ART_VORPAL_BLADE)); + verbalize("Thou shalt be my Envoy of Balance!"); + break; + case A_CHAOTIC: + u.uevent.uhand_of_elbereth = 3; + in_hand = (uwep && uwep->oartifact == ART_STORMBRINGER); + already_exists = exist_artifact(RUNESWORD, artiname(ART_STORMBRINGER)); + verbalize("Thou art chosen to %s for My Glory!", + already_exists && !in_hand ? "take lives" : "steal souls"); + break; + } + + class_gift = STRANGE_OBJECT; + /* 3.3.[01] had this in the A_NEUTRAL case below, + preventing chaotic wizards from receiving a spellbook */ + if (Role_if(PM_WIZARD) && + (!uwep || (uwep->oartifact != ART_VORPAL_BLADE && + uwep->oartifact != ART_STORMBRINGER)) && + !carrying(SPE_FINGER_OF_DEATH)) { + class_gift = SPE_FINGER_OF_DEATH; + make_splbk: + obj = mksobj(class_gift, TRUE, FALSE); + bless(obj); + obj->bknown = TRUE; + at_your_feet("A spellbook"); + dropy(obj); + u.ugifts++; + /* when getting a new book for known spell, enhance + currently wielded weapon rather than the book */ + for (sp_no = 0; sp_no < MAXSPELL; sp_no++) + if (spl_book[sp_no].sp_id == class_gift) { + if (ok_wep(uwep)) obj = uwep; /* to be blessed,&c */ + break; + } + } else if (Role_if(PM_MONK) && + (!uwep || !uwep->oartifact) && + !carrying(SPE_RESTORE_ABILITY)) { + /* monks rarely wield a weapon */ + class_gift = SPE_RESTORE_ABILITY; + goto make_splbk; + } + + switch (u.ualign.type) { + case A_LAWFUL: + if (class_gift != STRANGE_OBJECT) { + ; /* already got bonus above */ + } else if (obj && obj->otyp == LONG_SWORD && !obj->oartifact) { + if (!Blind) Your("sword shines brightly for a moment."); + obj = oname(obj, artiname(ART_EXCALIBUR)); + if (obj && obj->oartifact == ART_EXCALIBUR) u.ugifts++; + } + /* acquire Excalibur's skill regardless of weapon or gift */ + unrestrict_weapon_skill(P_LONG_SWORD); + if (obj && obj->oartifact == ART_EXCALIBUR) + discover_artifact(ART_EXCALIBUR); + break; + case A_NEUTRAL: + if (class_gift != STRANGE_OBJECT) { + ; /* already got bonus above */ + } else if (in_hand) { + Your("%s goes snicker-snack!", xname(obj)); + obj->dknown = TRUE; + } else if (!already_exists) { + obj = mksobj(LONG_SWORD, FALSE, FALSE); + obj = oname(obj, artiname(ART_VORPAL_BLADE)); + obj->spe = 1; + at_your_feet("A sword"); + dropy(obj); + u.ugifts++; + } + /* acquire Vorpal Blade's skill regardless of weapon or gift */ + unrestrict_weapon_skill(P_LONG_SWORD); + if (obj && obj->oartifact == ART_VORPAL_BLADE) + discover_artifact(ART_VORPAL_BLADE); + break; + case A_CHAOTIC: + { + char swordbuf[BUFSZ]; + + Sprintf(swordbuf, "%s sword", hcolor(Black)); + if (class_gift != STRANGE_OBJECT) { + ; /* already got bonus above */ + } else if (in_hand) { + Your("%s hums ominously!", swordbuf); + obj->dknown = TRUE; + } else if (!already_exists) { + obj = mksobj(RUNESWORD, FALSE, FALSE); + obj = oname(obj, artiname(ART_STORMBRINGER)); + at_your_feet(An(swordbuf)); + obj->spe = 1; + dropy(obj); + u.ugifts++; + } + /* acquire Stormbringer's skill regardless of weapon or gift */ + unrestrict_weapon_skill(P_BROAD_SWORD); + if (obj && obj->oartifact == ART_STORMBRINGER) + discover_artifact(ART_STORMBRINGER); + break; + } + default: + obj = 0; /* lint */ + break; + } + + /* enhance weapon regardless of alignment or artifact status */ + if (ok_wep(obj)) { + bless(obj); + obj->oeroded = obj->oeroded2 = 0; + obj->oerodeproof = TRUE; + obj->bknown = obj->rknown = TRUE; + if (obj->spe < 1) obj->spe = 1; + /* acquire skill in this weapon */ + unrestrict_weapon_skill(weapon_type(obj)); + } else if (class_gift == STRANGE_OBJECT) { + /* opportunity knocked, but there was nobody home... */ + You_feel("unworthy."); + } + update_inventory(); + return; +} +#endif /*ELBERETH*/ + +STATIC_OVL void +pleased(g_align) + aligntyp g_align; +{ + /* don't use p_trouble, worst trouble may get fixed while praying */ + int trouble = in_trouble(); /* what's your worst difficulty? */ + int pat_on_head = 0, kick_on_butt; + + You_feel("that %s is %s.", align_gname(g_align), + u.ualign.record >= DEVOUT ? + Hallucination ? "pleased as punch" : "well-pleased" : + u.ualign.record >= STRIDENT ? + Hallucination ? "ticklish" : "pleased" : + Hallucination ? "full" : "satisfied"); + + /* not your deity */ + if (on_altar() && p_aligntyp != u.ualign.type) { + adjalign(-1); + return; + } else if (u.ualign.record < 2 && trouble <= 0) adjalign(1); + + /* depending on your luck & align level, the god you prayed to will: + - fix your worst problem if it's major. + - fix all your major problems. + - fix your worst problem if it's minor. + - fix all of your problems. + - do you a gratuitous favor. + + if you make it to the the last category, you roll randomly again + to see what they do for you. + + If your luck is at least 0, then you are guaranteed rescued + from your worst major problem. */ + + if (!trouble && u.ualign.record >= DEVOUT) { + /* if hero was in trouble, but got better, no special favor */ + if (p_trouble == 0) pat_on_head = 1; + } else { + int action = rn1(on_altar() ? 3 + on_shrine() : 2, Luck+1); + + if (!on_altar()) action = max(action,2); + if (u.ualign.record < STRIDENT) + action = (u.ualign.record > 0 || !rnl(2)) ? 1 : 0; + + switch(min(action,5)) { + case 5: pat_on_head = 1; + case 4: do fix_worst_trouble(trouble); + while ((trouble = in_trouble()) != 0); + break; + + case 3: fix_worst_trouble(trouble); + case 2: while ((trouble = in_trouble()) > 0) + fix_worst_trouble(trouble); + break; + + case 1: if (trouble > 0) fix_worst_trouble(trouble); + case 0: break; /* your god blows you off, too bad */ + } + } + + if(pat_on_head) + switch(rn2((Luck + 6)>>1)) { + case 0: break; + case 1: + if (uwep && (welded(uwep) || uwep->oclass == WEAPON_CLASS || + is_weptool(uwep))) { + char repair_buf[BUFSZ]; + + *repair_buf = '\0'; + if (uwep->oeroded || uwep->oeroded2) + Sprintf(repair_buf, " and %s now as good as new", + uwep->quan == 1L ? "is" : "are"); + + if (uwep->cursed) { + uncurse(uwep); + uwep->bknown = TRUE; + if (!Blind) + Your("%s %s%s.", aobjnam(uwep, "softly glow"), + hcolor(amber), repair_buf); + else You_feel("the power of %s over your %s.", + u_gname(), xname(uwep)); + *repair_buf = '\0'; + } else if (!uwep->blessed) { + bless(uwep); + uwep->bknown = TRUE; + if (!Blind) + Your("%s with %s aura%s.", + aobjnam(uwep, "softly glow"), + an(hcolor(light_blue)), repair_buf); + else You_feel("the blessing of %s over your %s.", + u_gname(), xname(uwep)); + *repair_buf = '\0'; + } + + /* fix any rust/burn/rot damage, but don't protect + against future damage */ + if (uwep->oeroded || uwep->oeroded2) { + uwep->oeroded = uwep->oeroded2 = 0; + /* only give this message if we didn't just bless + or uncurse (which has already given a message) */ + if (*repair_buf) + Your("%s as good as new!", + aobjnam(uwep, Blind ? "feel" : "look")); + } + update_inventory(); + } + break; + case 3: + /* takes 2 hints to get the music to enter the stronghold */ + if (flags.soundok && !u.uevent.uopened_dbridge) { + if(u.uevent.uheard_tune < 1) { + godvoice(g_align,(char *)0); + verbalize("Hark, %s!", + youmonst.data->mlet == S_HUMAN ? "mortal" : "creature"); + verbalize( + "To enter the castle, thou must play the right tune!"); + u.uevent.uheard_tune++; + break; + } else if (u.uevent.uheard_tune < 2) { + You_hear(Hallucination ? "a funeral march..." : "a divine music..."); + pline("It sounds like: \"%s\".", tune); + u.uevent.uheard_tune++; + break; + } + } + /* Otherwise, falls into next case */ + case 2: + if (!Blind) + You("are surrounded by %s glow.", + an(hcolor(golden))); + if (Upolyd) u.mh = u.mhmax += 5; + u.uhp = u.uhpmax += 5; + ABASE(A_STR) = AMAX(A_STR); + if (u.uhunger < 900) init_uhunger(); + if (u.uluck < 0) u.uluck = 0; + make_blinded(0L,TRUE); + flags.botl = 1; + break; + case 4: { + register struct obj *otmp; + + if (Blind) + You_feel("the power of %s.", u_gname()); + else You("are surrounded by %s aura.", + an(hcolor(light_blue))); + for(otmp=invent; otmp; otmp=otmp->nobj) { + if (otmp->cursed) { + uncurse(otmp); + if (!Blind) { + Your("%s %s.", aobjnam(otmp, "softly glow"), + hcolor(amber)); + otmp->bknown = TRUE; + } + } + } + break; + } + case 5: { + const char *msg="\"and thus I grant thee the gift of %s!\""; + godvoice(u.ualign.type, "Thou hast pleased me with thy progress,"); + if (!(HTelepat & INTRINSIC)) { + HTelepat |= FROMOUTSIDE; + pline(msg, "Telepathy"); + if (Blind) see_monsters(); + } else if (!(HFast & INTRINSIC)) { + HFast |= FROMOUTSIDE; + pline(msg, "Speed"); + } else if (!(HStealth & INTRINSIC)) { + HStealth |= FROMOUTSIDE; + pline(msg, "Stealth"); + } else { + if (!(HProtection & INTRINSIC)) { + HProtection |= FROMOUTSIDE; + if (!u.ublessed) u.ublessed = rn1(3, 2); + } else u.ublessed++; + pline(msg, "my protection"); + } + verbalize("Use it wisely in my name!"); + break; + } + case 7: + case 8: + case 9: /* KMH -- can occur during full moons */ +#ifdef ELBERETH + if (u.ualign.record >= PIOUS && !u.uevent.uhand_of_elbereth) { + gcrownu(); + break; + } /* else FALLTHRU */ +#endif /*ELBERETH*/ + case 6: { + struct obj *otmp; + int sp_no, trycnt = u.ulevel + 1; + + at_your_feet("An object"); + /* not yet known spells given preference over already known ones */ + /* Also, try to grant a spell for which there is a skill slot */ + otmp = mkobj(SPBOOK_CLASS, TRUE); + while (--trycnt > 0) { + if (otmp->otyp != SPE_BLANK_PAPER) { + for (sp_no = 0; sp_no < MAXSPELL; sp_no++) + if (spl_book[sp_no].sp_id == otmp->otyp) break; + if (sp_no == MAXSPELL && + !P_RESTRICTED(spell_skilltype(otmp->otyp))) + break; /* usable, but not yet known */ + } else { + if (!objects[SPE_BLANK_PAPER].oc_name_known || + carrying(MAGIC_MARKER)) break; + } + otmp->otyp = rnd_class(bases[SPBOOK_CLASS], SPE_BLANK_PAPER); + } + bless(otmp); + place_object(otmp, u.ux, u.uy); + break; + } + default: impossible("Confused deity!"); + break; + } + + u.ublesscnt = rnz(350); + kick_on_butt = u.uevent.udemigod ? 1 : 0; +#ifdef ELBERETH + if (u.uevent.uhand_of_elbereth) kick_on_butt++; +#endif + if (kick_on_butt) u.ublesscnt += kick_on_butt * rnz(1000); + + return; +} + +/* either blesses or curses water on the altar, + * returns true if it found any water here. + */ +STATIC_OVL boolean +water_prayer(bless_water) + boolean bless_water; +{ + register struct obj* otmp; + register long changed = 0; + boolean other = FALSE, bc_known = !(Blind || Hallucination); + + for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere) { + /* turn water into (un)holy water */ + if (otmp->otyp == POT_WATER && + (bless_water ? !otmp->blessed : !otmp->cursed)) { + otmp->blessed = bless_water; + otmp->cursed = !bless_water; + otmp->bknown = bc_known; + changed += otmp->quan; + } else if(otmp->oclass == POTION_CLASS) + other = TRUE; + } + if(!Blind && changed) { + pline("%s potion%s on the altar glow%s %s for a moment.", + ((other && changed > 1L) ? "Some of the" : + (other ? "One of the" : "The")), + ((other || changed > 1L) ? "s" : ""), (changed > 1L ? "" : "s"), + (bless_water ? hcolor(light_blue) : hcolor(Black))); + } + return((boolean)(changed > 0L)); +} + +STATIC_OVL void +godvoice(g_align, words) + aligntyp g_align; + const char *words; +{ + const char *quot = ""; + if(words) + quot = "\""; + else + words = ""; + + pline_The("voice of %s %s: %s%s%s", align_gname(g_align), + godvoices[rn2(SIZE(godvoices))], quot, words, quot); +} + +STATIC_OVL void +gods_angry(g_align) + aligntyp g_align; +{ + godvoice(g_align, "Thou hast angered me."); +} + +/* The g_align god is upset with you. */ +STATIC_OVL void +gods_upset(g_align) + aligntyp g_align; +{ + if(g_align == u.ualign.type) u.ugangr++; + else if(u.ugangr) u.ugangr--; + angrygods(g_align); +} + +static NEARDATA const char sacrifice_types[] = { FOOD_CLASS, AMULET_CLASS, 0 }; + +STATIC_OVL void +consume_offering(otmp) +register struct obj *otmp; +{ + if (Hallucination) + switch (rn2(3)) { + case 0: + Your("sacrifice sprouts wings and a propeller and roars away!"); + break; + case 1: + Your("sacrifice puffs up, swelling bigger and bigger, and pops!"); + break; + case 2: + Your("sacrifice collapses into a cloud of dancing particles and fades away!"); + break; + } + else if (Blind && u.ualign.type == A_LAWFUL) + Your("sacrifice disappears!"); + else Your("sacrifice is consumed in a %s!", + u.ualign.type == A_LAWFUL ? "flash of light" : "burst of flame"); + if (carried(otmp)) useup(otmp); + else useupf(otmp, 1L); + exercise(A_WIS, TRUE); +} + +int +dosacrifice() +{ + register struct obj *otmp; + int value = 0; + int pm; + aligntyp altaralign = a_align(u.ux,u.uy); + + if (!on_altar()) { + You("are not standing on an altar."); + return 0; + } + + if (In_endgame(&u.uz)) { + if (!(otmp = getobj(sacrifice_types, "sacrifice"))) return 0; + } else { + if (!(otmp = floorfood("sacrifice", 1))) return 0; + } + /* + Was based on nutritional value and aging behavior (< 50 moves). + Sacrificing a food ration got you max luck instantly, making the + gods as easy to please as an angry dog! + + Now only accepts corpses, based on the game's evaluation of their + toughness. Human and pet sacrifice, as well as sacrificing unicorns + of your alignment, is strongly discouraged. + */ + +#define MAXVALUE 24 /* Highest corpse value (besides Wiz) */ + + if (otmp->otyp == CORPSE) { + register struct permonst *ptr = &mons[otmp->corpsenm]; + struct monst *mtmp; + extern const int monstr[]; + + /* KMH, conduct */ + u.uconduct.gnostic++; + + /* you're handling this corpse, even if it was killed upon the altar */ + feel_cockatrice(otmp, TRUE); + + if (otmp->corpsenm == PM_ACID_BLOB + || (monstermoves <= peek_at_iced_corpse_age(otmp) + 50)) { + value = monstr[otmp->corpsenm] + 1; + if (otmp->oeaten) + value = eaten_stat(value, otmp); + } + + if (your_race(ptr)) { + if (is_demon(youmonst.data)) { + You("find the idea very satisfying."); + exercise(A_WIS, TRUE); + } else if (u.ualign.type != A_CHAOTIC) { + pline("You'll regret this infamous offense!"); + exercise(A_WIS, FALSE); + } + + if (altaralign != A_CHAOTIC && altaralign != A_NONE) { + /* curse the lawful/neutral altar */ + pline_The("altar is stained with %s blood.", urace.adj); + if(!Is_astralevel(&u.uz)) + levl[u.ux][u.uy].altarmask = AM_CHAOTIC; + angry_priest(); + } else { + struct monst *dmon; + const char *demonless_msg; + + /* Human sacrifice on a chaotic or unaligned altar */ + /* is equivalent to demon summoning */ + if (altaralign == A_CHAOTIC && u.ualign.type != A_CHAOTIC) { + pline( + "The blood floods the altar, which vanishes in %s cloud!", + an(hcolor(Black))); + levl[u.ux][u.uy].typ = ROOM; + levl[u.ux][u.uy].altarmask = 0; + if(Invisible) newsym(u.ux, u.uy); + angry_priest(); + demonless_msg = "cloud dissipates"; + } else { + /* either you're chaotic or altar is Moloch's or both */ + pline_The("blood covers the altar!"); + change_luck(altaralign == A_NONE ? -2 : 2); + demonless_msg = "blood coagulates"; + } + if ((pm = dlord(altaralign)) != NON_PM && + (dmon = makemon(&mons[pm], u.ux, u.uy, NO_MM_FLAGS))) { + You("have summoned %s!", a_monnam(dmon)); + if (sgn(u.ualign.type) == sgn(dmon->data->maligntyp)) + dmon->mpeaceful = TRUE; + You("are terrified, and unable to move."); + nomul(-3); + } else pline_The("%s.", demonless_msg); + } + + if (u.ualign.type != A_CHAOTIC) { + adjalign(-5); + u.ugangr += 3; + (void) adjattrib(A_WIS, -1, TRUE); + if (!Inhell) angrygods(u.ualign.type); + change_luck(-5); + } else adjalign(5); + if (carried(otmp)) useup(otmp); + else useupf(otmp, 1L); + return(1); + } else if (otmp->oxlth && otmp->oattached == OATTACHED_MONST + && ((mtmp = get_mtraits(otmp, FALSE)) != (struct monst *)0) + && mtmp->mtame) { + /* mtmp is a temporary pointer to a tame monster's attributes, + * not a real monster */ + pline("So this is how you repay loyalty?"); + adjalign(-3); + value = -1; + HAggravate_monster |= FROMOUTSIDE; + } else if (is_undead(ptr)) { /* Not demons--no demon corpses */ + if (u.ualign.type != A_CHAOTIC) + value += 1; + } else if (is_unicorn(ptr)) { + int unicalign = sgn(ptr->maligntyp); + + /* If same as altar, always a very bad action. */ + if (unicalign == altaralign) { + pline("Such an action is an insult to %s!", + (unicalign == A_CHAOTIC) + ? "chaos" : unicalign ? "law" : "balance"); + (void) adjattrib(A_WIS, -1, TRUE); + value = -5; + } else if (u.ualign.type == altaralign) { + /* If different from altar, and altar is same as yours, */ + /* it's a very good action */ + if (u.ualign.record < ALIGNLIM) + You_feel("appropriately %s.", align_str(u.ualign.type)); + else You_feel("you are thoroughly on the right path."); + adjalign(5); + value += 3; + } else + /* If sacrificing unicorn of your alignment to altar not of */ + /* your alignment, your god gets angry and it's a conversion */ + if (unicalign == u.ualign.type) { + u.ualign.record = -1; + value = 1; + } else value += 3; + } + } /* corpse */ + + if (otmp->otyp == AMULET_OF_YENDOR) { + if (!In_endgame(&u.uz)) { + if (Hallucination) + You_feel("homesick."); + else + You_feel("an urge to return to the surface."); + return 1; + } else { + /* The final Test. Did you win? */ + if(uamul == otmp) Amulet_off(); + u.uevent.ascended = 1; + if(carried(otmp)) useup(otmp); /* well, it's gone now */ + else useupf(otmp, 1L); + You("offer the Amulet of Yendor to %s...", a_gname()); + if (u.ualign.type != altaralign) { + /* And the opposing team picks you up and + carries you off on their shoulders */ + adjalign(-99); + pline("%s accepts your gift, and gains dominion over %s...", + a_gname(), u_gname()); + pline("%s is enraged...", u_gname()); + pline("Fortunately, %s permits you to live...", a_gname()); + pline("A cloud of %s smoke surrounds you...", + hcolor((const char *)"orange")); + done(ESCAPED); + } else { /* super big win */ + adjalign(10); +pline("An invisible choir sings, and you are bathed in radiance..."); + godvoice(altaralign, "Congratulations, mortal!"); + display_nhwindow(WIN_MESSAGE, FALSE); +verbalize("In return for thy service, I grant thee the gift of Immortality!"); + You("ascend to the status of Demigod%s...", + flags.female ? "dess" : ""); + done(ASCENDED); + } + } + } /* real Amulet */ + + if (otmp->otyp == FAKE_AMULET_OF_YENDOR) { + if (flags.soundok) + You_hear("a nearby thunderclap."); + if (!otmp->known) { + You("realize you have made a %s.", + Hallucination ? "boo-boo" : "mistake"); + otmp->known = TRUE; + change_luck(-1); + return 1; + } else { + /* don't you dare try to fool the gods */ + change_luck(-3); + adjalign(-1); + u.ugangr += 3; + value = -3; + } + } /* fake Amulet */ + + if (value == 0) { + pline(nothing_happens); + return (1); + } + + if (altaralign != u.ualign.type && + (Is_astralevel(&u.uz) || Is_sanctum(&u.uz))) { + /* + * REAL BAD NEWS!!! High altars cannot be converted. Even an attempt + * gets the god who owns it truely pissed off. + */ + You_feel("the air around you grow charged..."); + pline("Suddenly, you realize that %s has noticed you...", a_gname()); + godvoice(altaralign, "So, mortal! You dare desecrate my High Temple!"); + /* Throw everything we have at the player */ + god_zaps_you(altaralign); + } else if (value < 0) { /* I don't think the gods are gonna like this... */ + gods_upset(altaralign); + } else { + int saved_anger = u.ugangr; + int saved_cnt = u.ublesscnt; + int saved_luck = u.uluck; + + /* Sacrificing at an altar of a different alignment */ + if (u.ualign.type != altaralign) { + /* Is this a conversion ? */ + /* An unaligned altar in Gehennom will always elicit rejection. */ + if (ugod_is_angry() || (altaralign == A_NONE && Inhell)) { + if(u.ualignbase[A_CURRENT] == u.ualignbase[A_ORIGINAL] && + altaralign != A_NONE) { + You("have a strong feeling that %s is angry...", u_gname()); + consume_offering(otmp); + pline("%s accepts your allegiance.", a_gname()); + + /* The player wears a helm of opposite alignment? */ + if (uarmh && uarmh->otyp == HELM_OF_OPPOSITE_ALIGNMENT) + u.ualignbase[A_CURRENT] = altaralign; + else + u.ualign.type = u.ualignbase[A_CURRENT] = altaralign; + u.ublessed = 0; + flags.botl = 1; + + You("have a sudden sense of a new direction."); + /* Beware, Conversion is costly */ + change_luck(-3); + u.ublesscnt += 300; + adjalign((int)(u.ualignbase[A_ORIGINAL] * (ALIGNLIM / 2))); + } else { + u.ugangr += 3; + adjalign(-5); + pline("%s rejects your sacrifice!", a_gname()); + godvoice(altaralign, "Suffer, infidel!"); + change_luck(-5); + (void) adjattrib(A_WIS, -2, TRUE); + if (!Inhell) angrygods(u.ualign.type); + } + return(1); + } else { + consume_offering(otmp); + You("sense a conflict between %s and %s.", + u_gname(), a_gname()); + if (rn2(8 + u.ulevel) > 5) { + struct monst *pri; + You_feel("the power of %s increase.", u_gname()); + exercise(A_WIS, TRUE); + change_luck(1); + /* Yes, this is supposed to be &=, not |= */ + levl[u.ux][u.uy].altarmask &= AM_SHRINE; + /* the following accommodates stupid compilers */ + levl[u.ux][u.uy].altarmask = + levl[u.ux][u.uy].altarmask | (Align2amask(u.ualign.type)); + if (!Blind) + pline_The("altar glows %s.", + hcolor( + u.ualign.type == A_LAWFUL ? White : + u.ualign.type ? Black : (const char *)"gray")); + + if (rnl(u.ulevel) > 6 && u.ualign.record > 0 && + rnd(u.ualign.record) > (3*ALIGNLIM)/4) + summon_minion(altaralign, TRUE); + /* anger priest; test handles bones files */ + if((pri = findpriest(temple_occupied(u.urooms))) && + !p_coaligned(pri)) + angry_priest(); + } else { + pline("Unluckily, you feel the power of %s decrease.", + u_gname()); + change_luck(-1); + exercise(A_WIS, FALSE); + if (rnl(u.ulevel) > 6 && u.ualign.record > 0 && + rnd(u.ualign.record) > (7*ALIGNLIM)/8) + summon_minion(altaralign, TRUE); + } + return(1); + } + } + + consume_offering(otmp); + /* OK, you get brownie points. */ + if(u.ugangr) { + u.ugangr -= + ((value * (u.ualign.type == A_CHAOTIC ? 2 : 3)) / MAXVALUE); + if(u.ugangr < 0) u.ugangr = 0; + if(u.ugangr != saved_anger) { + if (u.ugangr) { + pline("%s seems %s.", u_gname(), + Hallucination ? "groovy" : "slightly mollified"); + + if ((int)u.uluck < 0) change_luck(1); + } else { + pline("%s seems %s.", u_gname(), Hallucination ? + "cosmic (not a new fact)" : "mollified"); + + if ((int)u.uluck < 0) u.uluck = 0; + } + } else { /* not satisfied yet */ + if (Hallucination) + pline_The("gods seem tall."); + else You("have a feeling of inadequacy."); + } + } else if(ugod_is_angry()) { + if(value > MAXVALUE) value = MAXVALUE; + if(value > -u.ualign.record) value = -u.ualign.record; + adjalign(value); + You_feel("partially absolved."); + } else if (u.ublesscnt > 0) { + u.ublesscnt -= + ((value * (u.ualign.type == A_CHAOTIC ? 500 : 300)) / MAXVALUE); + if(u.ublesscnt < 0) u.ublesscnt = 0; + if(u.ublesscnt != saved_cnt) { + if (u.ublesscnt) { + if (Hallucination) + You("realize that the gods are not like you and I."); + else + You("have a hopeful feeling."); + if ((int)u.uluck < 0) change_luck(1); + } else { + if (Hallucination) + pline("Overall, there is a smell of fried onions."); + else + You("have a feeling of reconciliation."); + if ((int)u.uluck < 0) u.uluck = 0; + } + } + } else { + int nartifacts = nartifact_exist(); + + /* you were already in pretty good standing */ + /* The player can gain an artifact */ + /* The chance goes down as the number of artifacts goes up */ + if (u.ulevel > 2 && !rn2(10 + (2 * u.ugifts * nartifacts))) { + otmp = mk_artifact((struct obj *)0, a_align(u.ux,u.uy)); + if (otmp) { + if (otmp->spe < 0) otmp->spe = 0; + if (otmp->cursed) uncurse(otmp); + otmp->oerodeproof = TRUE; + dropy(otmp); + at_your_feet("An object"); + godvoice(u.ualign.type, "Use my gift wisely!"); + u.ugifts++; + u.ublesscnt = rnz(300 + (50 * nartifacts)); + exercise(A_WIS, TRUE); + /* make sure we can use this weapon */ + unrestrict_weapon_skill(weapon_type(otmp)); + discover_artifact(otmp->oartifact); + return(1); + } + } + change_luck((value * LUCKMAX) / (MAXVALUE * 2)); + if (u.uluck != saved_luck) { + if (Blind) + You("think %s brushed your %s.",something, body_part(FOOT)); + else You(Hallucination ? + "see crabgrass at your %s. A funny thing in a dungeon." : + "glimpse a four-leaf clover at your %s.", + makeplural(body_part(FOOT))); + } + } + } + return(1); +} + + +/* determine prayer results in advance; also used for enlightenment */ +boolean +can_pray(praying) +boolean praying; /* false means no messages should be given */ +{ + int alignment; + + p_aligntyp = on_altar() ? a_align(u.ux,u.uy) : u.ualign.type; + p_trouble = in_trouble(); + + if (is_demon(youmonst.data) && (p_aligntyp != A_CHAOTIC)) { + if (praying) + pline_The("very idea of praying to a %s god is repugnant to you.", + p_aligntyp ? "lawful" : "neutral"); + return FALSE; + } + + if (praying) + You("begin praying to %s.", align_gname(p_aligntyp)); + + if (u.ualign.type && u.ualign.type == -p_aligntyp) + alignment = -u.ualign.record; /* Opposite alignment altar */ + else if (u.ualign.type != p_aligntyp) + alignment = u.ualign.record / 2; /* Different alignment altar */ + else alignment = u.ualign.record; + + if ((p_trouble > 0) ? (u.ublesscnt > 200) : /* big trouble */ + (p_trouble < 0) ? (u.ublesscnt > 100) : /* minor difficulties */ + (u.ublesscnt > 0)) /* not in trouble */ + p_type = 0; /* too soon... */ + else if ((int)Luck < 0 || u.ugangr || alignment < 0) + p_type = 1; /* too naughty... */ + else /* alignment >= 0 */ { + if(on_altar() && u.ualign.type != p_aligntyp) + p_type = 2; + else + p_type = 3; + } + + if (is_undead(youmonst.data) && !Inhell && + (p_aligntyp == A_LAWFUL || (p_aligntyp == A_NEUTRAL && !rn2(10)))) + p_type = -1; + /* Note: when !praying, the random factor for neutrals makes the + return value a non-deterministic approximation for enlightenment. + This case should be uncommon enough to live with... */ + + return !praying ? (boolean)(p_type == 3 && !Inhell) : TRUE; +} + +int +dopray() +{ + /* Confirm accidental slips of Alt-P */ + if (flags.prayconfirm) + if (yn("Are you sure you want to pray?") == 'n') + return 0; + + u.uconduct.gnostic++; + /* Praying implies that the hero is conscious and since we have + no deafness attribute this implies that all verbalized messages + can be heard. So, in case the player has used the 'O' command + to toggle this accessible flag off, force it to be on. */ + flags.soundok = 1; + + /* set up p_type and p_alignment */ + if (!can_pray(TRUE)) return 0; + +#ifdef WIZARD + if (wizard && p_type >= 0) { + if (yn("Force the gods to be pleased?") == 'y') { + u.ublesscnt = 0; + if (u.uluck < 0) u.uluck = 0; + if (u.ualign.record <= 0) u.ualign.record = 1; + u.ugangr = 0; + if(p_type < 2) p_type = 3; + } + } +#endif + nomul(-3); + nomovemsg = "You finish your prayer."; + afternmv = prayer_done; + + if(p_type == 3 && !Inhell) { + /* if you've been true to your god you can't die while you pray */ + if (!Blind) + You("are surrounded by a shimmering light."); + u.uinvulnerable = TRUE; + } + + return(1); +} + +STATIC_PTR int +prayer_done() /* M. Stephenson (1.0.3b) */ +{ + aligntyp alignment = p_aligntyp; + + u.uinvulnerable = FALSE; + if(p_type == -1) { + godvoice(alignment, + alignment == A_LAWFUL ? + "Vile creature, thou durst call upon me?" : + "Walk no more, perversion of nature!"); + You_feel("like you are falling apart."); + /* KMH -- Gods have mastery over unchanging */ + rehumanize(); + losehp(rnd(20), "residual undead turning effect", KILLED_BY_AN); + exercise(A_CON, FALSE); + return(1); + } + if (Inhell) { + pline("Since you are in Gehennom, %s won't help you.", + align_gname(alignment)); + /* haltingly aligned is least likely to anger */ + if (u.ualign.record <= 0 || rnl(u.ualign.record)) + angrygods(u.ualign.type); + return(0); + } + + if (p_type == 0) { + if(on_altar() && u.ualign.type != alignment) + (void) water_prayer(FALSE); + u.ublesscnt += rnz(250); + change_luck(-3); + gods_upset(u.ualign.type); + } else if(p_type == 1) { + if(on_altar() && u.ualign.type != alignment) + (void) water_prayer(FALSE); + angrygods(u.ualign.type); /* naughty */ + } else if(p_type == 2) { + if(water_prayer(FALSE)) { + /* attempted water prayer on a non-coaligned altar */ + u.ublesscnt += rnz(250); + change_luck(-3); + gods_upset(u.ualign.type); + } else pleased(alignment); + } else { + /* coaligned */ + if(on_altar()) + (void) water_prayer(TRUE); + pleased(alignment); /* nice */ + } + return(1); +} + +int +doturn() +{ /* Knights & Priest(esse)s only please */ + + struct monst *mtmp, *mtmp2; + int once, range, xlev; + + if (!Role_if(PM_PRIEST) && !Role_if(PM_KNIGHT)) { + /* Try to use turn undead spell. */ + if (objects[SPE_TURN_UNDEAD].oc_name_known) { + register int sp_no; + for (sp_no = 0; sp_no < MAXSPELL && + spl_book[sp_no].sp_id != NO_SPELL && + spl_book[sp_no].sp_id != SPE_TURN_UNDEAD; sp_no++); + + if (sp_no < MAXSPELL && + spl_book[sp_no].sp_id == SPE_TURN_UNDEAD) + return spelleffects(sp_no, TRUE); + } + + You("don't know how to turn undead!"); + return(0); + } + u.uconduct.gnostic++; + + if ((u.ualign.type != A_CHAOTIC && + (is_demon(youmonst.data) || is_undead(youmonst.data))) || + u.ugangr > 6 /* "Die, mortal!" */) { + + pline("For some reason, %s seems to ignore you.", u_gname()); + aggravate(); + exercise(A_WIS, FALSE); + return(0); + } + + if (Inhell) { + pline("Since you are in Gehennom, %s won't help you.", u_gname()); + aggravate(); + return(0); + } + pline("Calling upon %s, you chant an arcane formula.", u_gname()); + exercise(A_WIS, TRUE); + + /* note: does not perform unturn_dead() on victims' inventories */ + range = BOLT_LIM + (u.ulevel / 5); /* 5 to 11 */ + range *= range; + once = 0; + for(mtmp = fmon; mtmp; mtmp = mtmp2) { + mtmp2 = mtmp->nmon; + + if (DEADMONSTER(mtmp)) continue; + if (!cansee(mtmp->mx,mtmp->my) || + distu(mtmp->mx,mtmp->my) > range) continue; + + if (!mtmp->mpeaceful && (is_undead(mtmp->data) || + (is_demon(mtmp->data) && (u.ulevel > (MAXULEV/2))))) { + + mtmp->msleeping = 0; + if (Confusion) { + if (!once++) + pline("Unfortunately, your voice falters."); + mtmp->mflee = 0; + mtmp->mfrozen = 0; + mtmp->mcanmove = 1; + } else if (!resist(mtmp, '\0', 0, TELL)) { + xlev = 6; + switch (mtmp->data->mlet) { + /* this is intentional, lichs are tougher + than zombies. */ + case S_LICH: xlev += 2; + case S_GHOST: xlev += 2; + case S_VAMPIRE: xlev += 2; + case S_WRAITH: xlev += 2; + case S_MUMMY: xlev += 2; + case S_ZOMBIE: + monflee(mtmp, 0, FALSE, TRUE); /* at least */ + if(u.ulevel >= xlev && + !resist(mtmp, '\0', 0, NOTELL)) { + if(u.ualign.type == A_CHAOTIC) { + mtmp->mpeaceful = 1; + } else { /* damn them */ + killed(mtmp); + } + } + break; + default: + monflee(mtmp, 0, FALSE, TRUE); + break; + } + } + } + } + nomul(-5); + return(1); +} + +const char * +a_gname() +{ + return(a_gname_at(u.ux, u.uy)); +} + +const char * +a_gname_at(x,y) /* returns the name of an altar's deity */ +xchar x, y; +{ + if(!IS_ALTAR(levl[x][y].typ)) return((char *)0); + + return align_gname(a_align(x,y)); +} + +const char * +u_gname() /* returns the name of the player's deity */ +{ + return align_gname(u.ualign.type); +} + +const char * +align_gname(alignment) +aligntyp alignment; +{ + const char *gnam; + + switch (alignment) { + case A_NONE: gnam = Moloch; break; + case A_LAWFUL: gnam = urole.lgod; break; + case A_NEUTRAL: gnam = urole.ngod; break; + case A_CHAOTIC: gnam = urole.cgod; break; + default: impossible("unknown alignment."); + gnam = "someone"; break; + } + if (*gnam == '_') ++gnam; + return gnam; +} + +/* hallucination handling for priest/minion names: select a random god + iff character is hallucinating */ +const char * +halu_gname(alignment) +aligntyp alignment; +{ + const char *gnam; + int which; + + if (!Hallucination) return align_gname(alignment); + + which = randrole(); + switch (rn2(3)) { + case 0: gnam = roles[which].lgod; break; + case 1: gnam = roles[which].ngod; break; + case 2: gnam = roles[which].cgod; break; + default: gnam = 0; break; /* lint suppression */ + } + if (!gnam) gnam = Moloch; + if (*gnam == '_') ++gnam; + return gnam; +} + +/* deity's title */ +const char * +align_gtitle(alignment) +aligntyp alignment; +{ + const char *gnam, *result = "god"; + + switch (alignment) { + case A_LAWFUL: gnam = urole.lgod; break; + case A_NEUTRAL: gnam = urole.ngod; break; + case A_CHAOTIC: gnam = urole.cgod; break; + default: gnam = 0; break; + } + if (gnam && *gnam == '_') result = "goddess"; + return result; +} + +void +altar_wrath(x, y) +register int x, y; +{ + aligntyp altaralign = a_align(x,y); + + if(!strcmp(align_gname(altaralign), u_gname())) { + godvoice(altaralign, "How darest thou desecrate my altar!"); + (void) adjattrib(A_WIS, -1, FALSE); + } else { + pline("A voice (could it be %s?) whispers:", + align_gname(altaralign)); + verbalize("Thou shalt pay, infidel!"); + change_luck(-1); + } +} + +/* assumes isok() at one space away, but not necessarily at two */ +STATIC_OVL boolean +blocked_boulder(dx,dy) +int dx,dy; +{ + register struct obj *otmp; + long count = 0L; + + for(otmp = level.objects[u.ux+dx][u.uy+dy]; otmp; otmp = otmp->nexthere) { + if(otmp->otyp == BOULDER) + count += otmp->quan; + } + + switch(count) { + case 0: return FALSE; /* no boulders--not blocked */ + case 1: break; /* possibly blocked depending on if it's pushable */ + default: return TRUE; /* >1 boulder--blocked after they push the top + one; don't force them to push it first to find out */ + } + + if (!isok(u.ux+2*dx, u.uy+2*dy)) + return TRUE; + if (IS_ROCK(levl[u.ux+2*dx][u.uy+2*dy].typ)) + return TRUE; + if (sobj_at(BOULDER, u.ux+2*dx, u.uy+2*dy)) + return TRUE; + + return FALSE; +} + +/*pray.c*/