Source:NetHack 3.4.3/src/pray.c
Below is the full text to src/pray.c from NetHack 3.4.3. To link to a particular line, write Source:NetHack 3.4.3/src/pray.c#line123, for example.
Contents
- 1 Top of file
- 2 in_trouble
- 3 worst_cursed_item
- 4 fix_worst_trouble
- 5 god_zaps_you
- 6 fry_by_god
- 7 angrygods
- 8 at_your_feet
- 9 gcrownu
- 10 pleased
- 11 water_prayer
- 12 godvoice
- 13 consume_offering
- 14 dosacrifice
- 15 can_pray
- 16 dopray
- 17 prayer_done
- 18 doturn
- 19 a_gname
- 20 a_gname_at
- 21 u_gname
- 22 align_gname
- 23 hallu_gname
- 24 align_gtitle
- 25 altar_wrath
- 26 blocked_boulder
Top of file
/* SCCS Id: @(#)pray.c 3.4 2003/03/23 */
/* Copyright (c) Benson I. Margulies, Mike Stephenson, Steve Linhart, 1989. */
/* NetHack may be freely redistributed. See license for details. */
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
#include "hack.h"
#include "epri.h"
STATIC_PTR int NDECL(prayer_done);
STATIC_DCL struct obj *NDECL(worst_cursed_item);
STATIC_DCL int NDECL(in_trouble);
STATIC_DCL void FDECL(fix_worst_trouble,(int));
STATIC_DCL void FDECL(angrygods,(ALIGNTYP_P));
STATIC_DCL void FDECL(at_your_feet, (const char *));
#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));
/* simplify a few tests */
#define Cursed_obj(obj,typ) ((obj) && (obj)->otyp == (typ) && (obj)->cursed)
/*
* 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
/*
* The actual trouble priority is determined by the order of the
* checks performed in in_trouble() rather than by these numeric
* values, so keep that code and these values synchronized in
* order to have the values be meaningful.
*/
#define TROUBLE_STONED 13
#define TROUBLE_SLIMED 12
#define TROUBLE_STRANGLED 11
#define TROUBLE_LAVA 10
#define TROUBLE_SICK 9
#define TROUBLE_STARVING 8
#define TROUBLE_HIT 7
#define TROUBLE_LYCANTHROPE 6
#define TROUBLE_COLLAPSING 5
#define TROUBLE_STUCK_IN_WALL 4
#define TROUBLE_CURSED_LEVITATION 3
#define TROUBLE_UNUSEABLE_HANDS 2
#define TROUBLE_CURSED_BLINDFOLD 1
#define TROUBLE_PUNISHED (-1)
#define TROUBLE_FUMBLING (-2)
#define TROUBLE_CURSED_ITEMS (-3)
#define TROUBLE_SADDLE (-4)
#define TROUBLE_BLIND (-5)
#define TROUBLE_POISONED (-6)
#define TROUBLE_WOUNDED_LEGS (-7)
#define TROUBLE_HUNGRY (-8)
#define TROUBLE_STUNNED (-9)
#define TROUBLE_CONFUSED (-10)
#define TROUBLE_HALLUCINATION (-11)
/* We could force rehumanize of polyselfed people, but we can't tell
unintentional shape changes from the other kind. Oh well.
3.4.2: make an exception if polymorphed into a form which lacks
hands; that's a case where the ramifications override this doubt.
*/
in_trouble
/* 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()
{
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
/*
* major troubles
*/
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 (Cursed_obj(uarmf, LEVITATION_BOOTS) ||
stuck_ring(uleft, RIN_LEVITATION) ||
stuck_ring(uright, RIN_LEVITATION))
return(TROUBLE_CURSED_LEVITATION);
if (nohands(youmonst.data) || !freehand()) {
/* for bag/box access [cf use_container()]...
make sure it's a case that we know how to handle;
otherwise "fix all troubles" would get stuck in a loop */
if (welded(uwep)) return TROUBLE_UNUSEABLE_HANDS;
if (Upolyd && nohands(youmonst.data) && (!Unchanging ||
((otmp = unchanger()) != 0 && otmp->cursed)))
return TROUBLE_UNUSEABLE_HANDS;
}
if(Blindfolded && ublindf->cursed) return(TROUBLE_CURSED_BLINDFOLD);
/*
* minor troubles
*/
if(Punished) return(TROUBLE_PUNISHED);
if (Cursed_obj(uarmg, GAUNTLETS_OF_FUMBLING) ||
Cursed_obj(uarmf, FUMBLE_BOOTS))
return TROUBLE_FUMBLING;
if (worst_cursed_item()) return TROUBLE_CURSED_ITEMS;
#ifdef STEED
if (u.usteed) { /* can't voluntarily dismount from a cursed saddle */
otmp = which_armor(u.usteed, W_SADDLE);
if (Cursed_obj(otmp, SADDLE)) return TROUBLE_SADDLE;
}
#endif
if (Blinded > 1 && haseyes(youmonst.data)) return(TROUBLE_BLIND);
for(i=0; i<A_MAX; i++)
if(ABASE(i) < AMAX(i)) return(TROUBLE_POISONED);
if(Wounded_legs
#ifdef STEED
&& !u.usteed
#endif
) return (TROUBLE_WOUNDED_LEGS);
if(u.uhs >= HUNGRY) return(TROUBLE_HUNGRY);
if(HStun) return (TROUBLE_STUNNED);
if(HConfusion) return (TROUBLE_CONFUSED);
if(Hallucination) return(TROUBLE_HALLUCINATION);
return(0);
}
worst_cursed_item
/* select an item for TROUBLE_CURSED_ITEMS */
STATIC_OVL struct obj *
worst_cursed_item()
{
register struct obj *otmp;
/* if strained or worse, check for loadstone first */
if (near_capacity() >= HVY_ENCUMBER) {
for (otmp = invent; otmp; otmp = otmp->nobj)
if (Cursed_obj(otmp, LOADSTONE)) return otmp;
}
/* weapon takes precedence if it is interfering
with taking off a ring or putting on a shield */
if (welded(uwep) && (uright || bimanual(uwep))) { /* weapon */
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) { /* suit */
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
} else if (uamul && uamul->cursed) { /* amulet */
otmp = uamul;
} else if (uleft && uleft->cursed) { /* left ring */
otmp = uleft;
} else if (uright && uright->cursed) { /* right ring */
otmp = uright;
} 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;
/* active secondary weapon even though it isn't welded */
} else if (uswapwep && uswapwep->cursed && u.twoweap) {
otmp = uswapwep;
/* all worn items ought to be handled by now */
} else {
for (otmp = invent; otmp; otmp = otmp->nobj) {
if (!otmp->cursed) continue;
if (otmp->otyp == LOADSTONE || confers_luck(otmp))
break;
}
}
return otmp;
}
fix_worst_trouble
STATIC_OVL void
fix_worst_trouble(trouble)
register int trouble;
{
int i;
struct obj *otmp = 0;
const char *what = (const char *)0;
static NEARDATA const char leftglow[] = "left ring softly glows",
rightglow[] = "right ring softly glows";
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(FALSE))
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(FALSE);
break;
case TROUBLE_CURSED_LEVITATION:
if (Cursed_obj(uarmf, LEVITATION_BOOTS)) {
otmp = uarmf;
} else if ((otmp = stuck_ring(uleft,RIN_LEVITATION)) !=0) {
if (otmp == uleft) what = leftglow;
} else if ((otmp = stuck_ring(uright,RIN_LEVITATION))!=0) {
if (otmp == uright) what = rightglow;
}
goto decurse;
case TROUBLE_UNUSEABLE_HANDS:
if (welded(uwep)) {
otmp = uwep;
goto decurse;
}
if (Upolyd && nohands(youmonst.data)) {
if (!Unchanging) {
Your("shape becomes uncertain.");
rehumanize(); /* "You return to {normal} form." */
} else if ((otmp = unchanger()) != 0 && otmp->cursed) {
/* otmp is an amulet of unchanging */
goto decurse;
}
}
if (nohands(youmonst.data) || !freehand())
impossible("fix_worst_trouble: couldn't cure hands.");
break;
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_FUMBLING:
if (Cursed_obj(uarmg, GAUNTLETS_OF_FUMBLING))
otmp = uarmg;
else if (Cursed_obj(uarmf, FUMBLE_BOOTS))
otmp = uarmf;
goto decurse;
/*NOTREACHED*/
break;
case TROUBLE_CURSED_ITEMS:
otmp = worst_cursed_item();
if (otmp == uright) what = rightglow;
else if (otmp == uleft) what = leftglow;
decurse:
if (!otmp) {
impossible("fix_worst_trouble: nothing to uncurse.");
return;
}
uncurse(otmp);
if (!Blind) {
Your("%s %s.", what ? what :
(const char *)aobjnam(otmp, "softly glow"),
hcolor(NH_AMBER));
otmp->bknown = TRUE;
}
update_inventory();
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<A_MAX; i++) {
if(ABASE(i) < AMAX(i)) {
ABASE(i) = AMAX(i);
flags.botl = 1;
}
}
(void) encumber_msg();
break;
case TROUBLE_BLIND:
{
int num_eyes = eyecount(youmonst.data);
const char *eye = body_part(EYE);
Your("%s feel%s better.",
(num_eyes == 1) ? eye : makeplural(eye),
(num_eyes == 1) ? "s" : "");
u.ucreamed = 0;
make_blinded(0L,FALSE);
break;
}
case TROUBLE_WOUNDED_LEGS:
heal_legs();
break;
case TROUBLE_STUNNED:
make_stunned(0L,TRUE);
break;
case TROUBLE_CONFUSED:
make_confused(0L,TRUE);
break;
case TROUBLE_HALLUCINATION:
pline ("Looks like you are back in Kansas.");
(void) make_hallucinated(0L,FALSE,0L);
break;
#ifdef STEED
case TROUBLE_SADDLE:
otmp = which_armor(u.usteed, W_SADDLE);
uncurse(otmp);
if (!Blind) {
pline("%s %s %s.",
s_suffix(upstart(y_monnam(u.usteed))),
aobjnam(otmp, "softly glow"),
hcolor(NH_AMBER));
otmp->bknown = TRUE;
}
break;
#endif
}
}
god_zaps_you
/* "I am sometimes shocked by... the nuns who never take a bath without
* wearing a bathrobe all the time. When asked why, since no man can see them,
* they reply 'Oh, but you forget the good God'. Apparently they conceive of
* the Deity as a Peeping Tom, whose omnipotence enables Him to see through
* bathroom walls, but who is foiled by bathrobes." --Bertrand Russell, 1943
* Divine wrath, dungeon walls, and armor follow the same principle.
*/
STATIC_OVL void
god_zaps_you(resp_god)
aligntyp resp_god;
{
if (u.uswallow) {
pline("Suddenly a bolt of lightning comes down at you from the heavens!");
pline("It strikes %s!", mon_nam(u.ustuck));
if (!resists_elec(u.ustuck)) {
pline("%s fries to a crisp!", Monnam(u.ustuck));
/* Yup, you get experience. It takes guts to successfully
* pull off this trick on your god, anyway.
*/
xkilled(u.ustuck, 0);
} else
pline("%s seems unaffected.", Monnam(u.ustuck));
} else {
pline("Suddenly, a bolt of lightning strikes you!");
if (Reflecting) {
shieldeff(u.ux, u.uy);
if (Blind)
pline("For some reason you're unaffected.");
else
(void) ureflects("%s reflects from your %s.", "It");
} else if (Shock_resistance) {
shieldeff(u.ux, u.uy);
pline("It seems not to affect you.");
} else
fry_by_god(resp_god);
}
pline("%s is not deterred...", align_gname(resp_god));
if (u.uswallow) {
pline("A wide-angle disintegration beam aimed at you hits %s!",
mon_nam(u.ustuck));
if (!resists_disint(u.ustuck)) {
pline("%s fries to a crisp!", Monnam(u.ustuck));
xkilled(u.ustuck, 2); /* no corpse */
} else
pline("%s seems unaffected.", Monnam(u.ustuck));
} else {
pline("A wide-angle disintegration beam hits you!");
/* disintegrate shield and body armor before disintegrating
* the impudent mortal, like black dragon breath -3.
*/
if (uarms && !(EReflecting & W_ARMS) &&
!(EDisint_resistance & W_ARMS))
(void) destroy_arm(uarms);
if (uarmc && !(EReflecting & W_ARMC) &&
!(EDisint_resistance & W_ARMC))
(void) destroy_arm(uarmc);
if (uarm && !(EReflecting & W_ARM) &&
!(EDisint_resistance & W_ARM) && !uarmc)
(void) destroy_arm(uarm);
#ifdef TOURIST
if (uarmu && !uarm && !uarmc) (void) destroy_arm(uarmu);
#endif
if (!Disint_resistance)
fry_by_god(resp_god);
else {
You("bask in its %s glow for a minute...", NH_BLACK);
godvoice(resp_god, "I believe it not!");
}
if (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)) {
/* one more try for high altars */
verbalize("Thou cannot escape my wrath, mortal!");
summon_minion(resp_god, FALSE);
summon_minion(resp_god, FALSE);
summon_minion(resp_god, FALSE);
verbalize("Destroy %s, my servants!", uhim());
}
}
}
fry_by_god
STATIC_OVL void
fry_by_god(resp_god)
aligntyp resp_god;
{
char killerbuf[64];
You("fry to a crisp.");
killer_format = KILLED_BY;
Sprintf(killerbuf, "the wrath of %s", align_gname(resp_god));
killer = killerbuf;
done(DIED);
}
angrygods
STATIC_OVL void
angrygods(resp_god)
aligntyp resp_god;
{
register int maxanger;
if(Inhell) resp_god = A_NONE;
u.ublessed = 0;
/* changed from tmp = u.ugangr + abs (u.uluck) -- rph */
/* added test for alignment diff -dlc */
if(resp_god != u.ualign.type)
maxanger = u.ualign.record/2 + (Luck > 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(NH_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;
}
at_your_feet
/* 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 %s into %s %s.", str, vtense(str, "drop"),
s_suffix(mon_nam(u.ustuck)), mbodypart(u.ustuck, STOMACH));
} else {
pline("%s %s %s your %s!", str,
Blind ? "lands" : vtense(str, "appear"),
Levitation ? "beneath" : "at",
makeplural(body_part(FOOT)));
}
}
#ifdef ELBERETH
gcrownu
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(NH_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*/
pleased
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(Luck + (on_altar() ? 3 + on_shrine() : 2), 1);
if (!on_altar()) action = min(action, 3);
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 */
}
}
/* note: can't get pat_on_head unless all troubles have just been
fixed or there were no troubles to begin with; hallucination
won't be in effect so special handling for it is superfluous */
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",
otense(uwep, "are"));
if (uwep->cursed) {
uncurse(uwep);
uwep->bknown = TRUE;
if (!Blind)
Your("%s %s%s.", aobjnam(uwep, "softly glow"),
hcolor(NH_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(NH_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 (!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("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(NH_GOLDEN)));
/* if any levels have been lost (and not yet regained),
treat this effect like blessed full healing */
if (u.ulevel < u.ulevelmax) {
u.ulevelmax -= 1; /* see potion.c */
pluslvl(FALSE);
} else {
u.uhpmax += 5;
if (Upolyd) u.mhmax += 5;
}
u.uhp = u.uhpmax;
if (Upolyd) u.mh = u.mhmax;
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;
int any = 0;
if (Blind)
You_feel("the power of %s.", u_gname());
else You("are surrounded by %s aura.",
an(hcolor(NH_LIGHT_BLUE)));
for(otmp=invent; otmp; otmp=otmp->nobj) {
if (otmp->cursed) {
uncurse(otmp);
if (!Blind) {
Your("%s %s.", aobjnam(otmp, "softly glow"),
hcolor(NH_AMBER));
otmp->bknown = TRUE;
++any;
}
}
}
if (any) update_inventory();
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;
}
water_prayer
/* 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(NH_LIGHT_BLUE) : hcolor(NH_BLACK)));
}
return((boolean)(changed > 0L));
}
godvoice
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 };
consume_offering
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);
}
dosacrifice
int
dosacrifice()
{
register struct obj *otmp;
int value = 0;
int pm;
aligntyp altaralign = a_align(u.ux,u.uy);
if (!on_altar() || u.uswallow) {
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++;
Obviously, you're no longer an atheist.
/* you're handling this corpse, even if it was killed upon the altar */
feel_cockatrice(otmp, TRUE);
Cockatrices will kill you if you aren't careful!
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);
}
The value of a monster is given by monstr[otmp->corpsenm] + 1
, which if the monster difficulty level from monst.c; it is also the number that determines which monsters the RNG generates. If it's partially eaten, that's multiplied by (roughly) the percentage remaining. If it's more than fifty moves old, adjusted for ice, it's worthless, unless it's an acid blob. These never expire (although they may, of course, rot).
Sacrificing your own race
Note that your_race() returns true based on your actual race chosen at the start of the game, i.e. polymorphing counts you as that race alongside any race applicable to your current form.
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);
}
Characters in the form of demonss exercise wisdom by sacrificing their own race, while non-chaotic characters will abuse it. Chaotic non-demons do neither.
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();
A lawful or neutral altar will immediately be converted to chaos (outside the astral level). This will, obviously, anger any attendant priests.
} 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(NH_BLACK)));
levl[u.ux][u.uy].typ = ROOM;
levl[u.ux][u.uy].altarmask = 0;
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 the altar is Moloch's, you lose two luck. If you're chaotic and the altar is chaotic (i.e., not Moloch's), you gain two. If it's not Moloch's altar and you're not chaotic, your luck is unaffected (so far), but you've destroyed the altar and angered the priest. Thus any attempt by a non-chaotic character to sacrifice a character of their own race will anger the priest, if any, except at Moloch's altar.
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);
}
A random demon lord between Juiblex and Yeenoghu inclusive is chosen up to 20 times, in an attempt to find one that has not been created already. Unless the altar is unaligned, the alignment of the demon lord must match the alignment of the altar. Currently, Yeenoghu follows Juiblex in monst.c. Thus only these two demon lords are eligible to appear. They are both chaotic.
Otherwise a random demon is chosen up to 20 times, respecting extinction and with the same alignment requirements.
If there is space for it adjacent to you, the chosen demon appears, peaceful if it matches your alignment and hostile otherwise. Three turns pass. If no matching demon is found, none appears.
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);
If you aren't chaotic, you lose 5 alignment, your god's anger increases by three, your wisdom decreases by one point, your luck decreases by 5, and unless you're in Gehennom, your god potentially punishes you as for praying too much. If you are chaotic, instead your alignment increases by 5. The corpse disappears, and nothing more happens for the case of sacrificing a creature of your own race. The value of the sacrifice (calculated immediately preceding this section) is ignored, so sacrificing a rotten corpse of your own race (e.g. from a zombie of your race) has the same effect as sacrificing a fresh one.
Sacrificing pets
} 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;
If you try to sacrifice a pet, you lose three alignment and gain the aggravate monster intrinsic. The pet's corpse has a value of -1. This does not apply if the pet is of your own race, in which case the code doesn't reach this point (bug?).
Yes, that entire conditional is to see if it's a former pet's corpse. In order, it does the following: (Note that if any step returns false, the if fails immediately and the remaining steps are not executed, which prevents lots of nasty invalid pointer dereferencing)
- Does the object have extra data? (oxlth is "Object eXtra data LengTH")
- Is the extra data that of a monster?
- Get a pointer to an object containing the traits of that monster and put it in a temporary variable
- Is the pointer non-null?
- Was the monster tame?
Sacrificing undead
} else if (is_undead(ptr)) { /* Not demons--no demon corpses */
if (u.ualign.type != A_CHAOTIC)
value += 1;
The corpse of an undead creature has an additional +1 value for non-chaotic characters.
Sacrificing unicorns
} 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;
Sacrificing a unicorn on an altar aligned with it will set its sacrifice value to -5 and reduce your wisdom by 1. But sacrificing a non-aligned unicorn on a coaligned altar gives you +5 alignment, and gives it +3 value. Sacrificing a unicorn of your alignment on an altar not of your alignment sets the value to one and your alignment to -1 (actually worse than sacrificing on a coaligned altar). Finally, sacrificing a unicorn not aligned with either you or the altar increases its value by 3 and has no other effects.
}
} /* corpse */
Sacrificing the Amulet of Yendor
if (otmp->otyp == AMULET_OF_YENDOR) {
if (!Is_astralevel(&u.uz)) {
if (Hallucination)
You_feel("homesick.");
else
You_feel("an urge to return to the surface.");
return 1;
This code is supposed to give a hint if you try to sacrifice the Amulet of Yendor on an ordinary altar in the dungeon; however, it seems it can never run, because floorfood() (called on line 1135 above) won't let the player even select the amulet for sacrifice. (All you get if you try is "You don't have anything to sacrifice," or, if also carrying a corpse and selecting the amulet instead, "That is a silly thing to sacrifice.") The message above can be triggered in wizard mode by wishing for an altar on the elemental planes (other than Astral) and trying to sacrifice the amulet there, but no altars are normally generated on those levels.
} 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);
You sacrificed the Amulet on the wrong altar, and so escaped the Dungeon "in celestial disgrace".
} 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 */
You ascended. Congrats, welcome to the demigod bar.
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;
Sacrificing a fake Amulet: if un-ID'd, you simply lose 1 luck.
} else {
/* don't you dare try to fool the gods */
change_luck(-3);
adjalign(-1);
u.ugangr += 3;
value = -3;
}
} /* fake Amulet */
Offering a known fake amulet, however, costs you 3 luck and 1 alignment; and angers your god.
Worthless sacrifice
if (value == 0) {
pline(nothing_happens);
return (1);
}
If the value is zero, "nothing happens".
Converting altars
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;
Altars on the Astral Plane cannot be converted.
/* 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());
Your alignment record was negative, and you converted your alignment to that of the altar. (Note: this cannot happen on an altar to Moloch.)
/* The player wears a helm of opposite alignment? */
if (uarmh && uarmh->otyp == HELM_OF_OPPOSITE_ALIGNMENT)
u.ualignbase[A_CURRENT] = altaralign;
Handle conversion whilst wearing a Helm of opposite alignment.
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)));
Whether wearing the Helm or not, you lose 3 luck, half your alignment record and any intrinsic protection; and your prayer timeout is increased.
} 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);
Attempting to convert yourself a second time will anger your god. This code also handles attempted sacrifice to Moloch, which is always rejected.
} 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 ? NH_WHITE :
u.ualign.type ? NH_BLACK : (const char *)"gray"));
Otherwise, attempt to convert the altar. If successful (random number between 0 and level+8 is greater than 5), you get +1 luck and exercise wisdom...
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();
... but may summon a random minion of the altar's original god, and will anger any attendant 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);
Failed conversion results in -1 luck and abusing wisdom, and may still summon a minion.
}
}
Normal, successful offering
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 your god is angry, their anger is reduced by 1/12 the value of the sacrifice (rounded down) if chaotic, and 1/8 of its value if lawful or neutral. If this would reduce it below 0; set it to 0 instead.
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);
The sacrifice has reduced your god's anger, but it is not yet zero. If your luck is negative, increase it by one point.
} else {
pline("%s seems %s.", u_gname(), Hallucination ?
"cosmic (not a new fact)" : "mollified");
if ((int)u.uluck < 0) u.uluck = 0;
}
The sacrifice has reduced your god's anger to zero. If your luck is negative, it is also set to zero.
} else { /* not satisfied yet */
if (Hallucination)
pline_The("gods seem tall.");
else You("have a feeling of inadequacy.");
}
The sacrifice has not affected your god's anger.
} 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.");
Your god was not angry, but your alignment is negative. It is increased by the least of:
- The value of the sacrifice,
- 24 points, or
- To zero.
} else if (u.ublesscnt > 0) {
u.ublesscnt -=
((value * (u.ualign.type == A_CHAOTIC ? 500 : 300)) / MAXVALUE);
if(u.ublesscnt < 0) u.ublesscnt = 0;
Your god was not angry and your alignment is at least zero, but your prayer timeout has not yet expired. Reduce it by 20.83 times the value of the sacrifice (again, rounded down) if chaotic, or 12.5 times its value otherwise. If this would reduce it to 0; set it to 0 instead.
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);
The sacrifice has reduced your prayer timeout, but it is not yet zero. Your luck is increased by one if negative, but you may not yet pray.
} 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;
Your prayer timeout has been reduced to zero by the sacrifice. Your luck is set to zero if negative, and it is safe to pray.
}
}
} 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 && u.uluck >= 0 &&
!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);
}
}
If you are in generally good standing, have non-negative Luck, and are at least level 3, you may get an artifact as a gift. The odds of this decrease with both the number of artifacts already existing and the number of gifts previously granted.
The artifact you receive is guaranteed to be non-cursed, erodeproof, and have a non-negative enchantment; you will be unrestricted in the needed weapon skill if necessary; and your wisdom is exercised. Your prayer timeout is reset to rnz(300 + 50 * number of artifacts already existing).
change_luck((value * LUCKMAX) / (MAXVALUE * 2));
if ((int)u.uluck < 0) u.uluck = 0;
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);
}
If none of the other cases apply, your luck is increased by 10/48 of the value of the sacrifice (again, rounded down), and set to zero if it is still negative after this.
can_pray
/* 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;
}
dopray
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);
}
prayer_done
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);
}
doturn
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; /*FALLTHRU*/
case S_GHOST: xlev += 2; /*FALLTHRU*/
case S_VAMPIRE: xlev += 2; /*FALLTHRU*/
case S_WRAITH: xlev += 2; /*FALLTHRU*/
case S_MUMMY: xlev += 2; /*FALLTHRU*/
case S_ZOMBIE:
if (u.ulevel >= xlev &&
!resist(mtmp, '\0', 0, NOTELL)) {
if (u.ualign.type == A_CHAOTIC) {
mtmp->mpeaceful = 1;
set_malign(mtmp);
} else { /* damn them */
killed(mtmp);
}
break;
} /* else flee */
/*FALLTHRU*/
default:
monflee(mtmp, 0, FALSE, TRUE);
break;
}
}
}
}
nomul(-5);
return(1);
}
a_gname
const char *
a_gname()
{
return(a_gname_at(u.ux, u.uy));
}
a_gname_at
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));
}
u_gname
const char *
u_gname() /* returns the name of the player's deity */
{
return align_gname(u.ualign.type);
}
align_gname
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;
}
hallu_gname
/* 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;
}
align_gtitle
/* 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;
}
altar_wrath
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);
}
}
blocked_boulder
/* 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*/