From 7b82fed49d10ff1bac671e36e4bc2711310c554d Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 30 Oct 2015 00:44:58 -0700 Subject: [PATCH] '#turn' for non-priests/non-knights Another code change while reformatting: '#turn' by non-priest/non-knight casts the "turn undead" spell if the hero has learned it, but it was forcing the spell code to aim at self rather than ask for a direction. Evidently nobody has ever used that while knowing the spell and able to cast it.... --- doc/fixes36.0 | 2 + src/pray.c | 231 +++++++++++++++++++++++++++----------------------- 2 files changed, 126 insertions(+), 107 deletions(-) diff --git a/doc/fixes36.0 b/doc/fixes36.0 index 913310ebd..dcfcad720 100644 --- a/doc/fixes36.0 +++ b/doc/fixes36.0 @@ -929,6 +929,8 @@ casting spell of protection when previous casting(s) hadn't time out yet remaining monsters continued to move after hero conceptually left the level when a monster knocked him onto a level-changing trap (this bug made it be feasible--but not practical--to level teleport with the Amulet) +#turn for non-priest/non-knight attempts to cast "turn undead" spell, but + was forcing the spell to target self rather than choose a direction Platform- and/or Interface-Specific Fixes diff --git a/src/pray.c b/src/pray.c index aa7893b2f..08242a02e 100644 --- a/src/pray.c +++ b/src/pray.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pray.c $NHDT-Date: 1445556883 2015/10/22 23:34:43 $ $NHDT-Branch: master $:$NHDT-Revision: 1.85 $ */ +/* NetHack 3.6 pray.c $NHDT-Date: 1446191091 2015/10/30 07:44:51 $ $NHDT-Branch: master $:$NHDT-Revision: 1.86 $ */ /* Copyright (c) Benson I. Margulies, Mike Stephenson, Steve Linhart, 1989. */ /* NetHack may be freely redistributed. See license for details. */ @@ -37,9 +37,9 @@ STATIC_DCL boolean FDECL(blocked_boulder, (int, int)); */ /* - * Moloch, who dwells in Gehennom, is the "renegade" cruel god - * responsible for the theft of the Amulet from Marduk, the Creator. - * Moloch is unaligned. + * 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"; @@ -91,20 +91,6 @@ static int p_type; /* (-1)-3: (-1)=really naughty, 3=really good */ #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. - */ - -/* 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) @@ -154,6 +140,20 @@ boolean only_if_injured; /* determines whether maxhp <= 5 matters */ return (boolean) (curhp <= 5 || curhp * divisor <= maxhp); } +/* + * 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. + * + * 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. + */ STATIC_OVL int in_trouble() { @@ -310,7 +310,7 @@ worst_cursed_item() STATIC_OVL void fix_worst_trouble(trouble) -register int trouble; +int trouble; { int i; struct obj *otmp = 0; @@ -344,7 +344,7 @@ register int trouble; break; case TROUBLE_STARVING: losestr(-1); - /* fall into... */ + /*FALLTHRU*/ case TROUBLE_HUNGRY: Your("%s feels content.", body_part(STOMACH)); init_uhunger(); @@ -533,8 +533,8 @@ 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( + "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)); @@ -618,7 +618,7 @@ STATIC_OVL void angrygods(resp_god) aligntyp resp_god; { - register int maxanger; + int maxanger; if (Inhell) resp_god = A_NONE; @@ -629,9 +629,9 @@ aligntyp resp_god; 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); + 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) @@ -872,9 +872,9 @@ aligntyp g_align; int pat_on_head = 0, kick_on_butt; You_feel("that %s is %s.", align_gname(g_align), - u.ualign.record >= DEVOUT + (u.ualign.record >= DEVOUT) ? Hallucination ? "pleased as punch" : "well-pleased" - : u.ualign.record >= STRIDENT + : (u.ualign.record >= STRIDENT) ? Hallucination ? "ticklish" : "pleased" : Hallucination ? "full" : "satisfied"); @@ -885,19 +885,20 @@ aligntyp g_align; } 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. */ - + /* + * 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) @@ -1193,6 +1194,7 @@ aligntyp g_align; const char *words; { const char *quot = ""; + if (words) quot = "\""; else @@ -1270,16 +1272,15 @@ dosacrifice() otmp = floorfood("sacrifice", 1); if (!otmp) 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. - */ - + /* + * 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) { @@ -1376,11 +1377,11 @@ dosacrifice() else useupf(otmp, 1L); return 1; - } else if (has_omonst(otmp) && ((mtmp = get_mtraits(otmp, FALSE)) - != (struct monst *) 0) + } else if (has_omonst(otmp) + && (mtmp = get_mtraits(otmp, FALSE)) != 0 && mtmp->mtame) { - /* mtmp is a temporary pointer to a tame monster's attributes, - * not a real monster */ + /* 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; @@ -1391,32 +1392,37 @@ dosacrifice() } else if (is_unicorn(ptr)) { int unicalign = sgn(ptr->maligntyp); - /* If same as altar, always a very bad action. */ if (unicalign == altaralign) { + /* When same as altar, always a very bad action. + */ pline("Such an action is an insult to %s!", - (unicalign == A_CHAOTIC) ? "chaos" : unicalign - ? "law" - : "balance"); + (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 */ + /* When 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) { + } else if (unicalign == u.ualign.type) { + /* When sacrificing unicorn of your alignment to altar not of + * your alignment, your god gets angry and it's a conversion. + */ u.ualign.record = -1; value = 1; - } else + } else { + /* Otherwise, unicorn's alignment is different from yours + * and different from the altar's. It's an ordinary (well, + * with a bonus) sacrifice on a cross-aligned altar. + */ value += 3; + } } } /* corpse */ @@ -1439,7 +1445,7 @@ dosacrifice() : "ashamed"); return 1; } else { - /* The final Test. Did you win? */ + /* The final Test. Did you win? */ if (uamul == otmp) Amulet_off(); u.uevent.ascended = 1; @@ -1581,11 +1587,11 @@ dosacrifice() | (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")); + hcolor((u.ualign.type == A_LAWFUL) + ? NH_WHITE + : u.ualign.type + ? NH_BLACK + : (const char *) "gray")); if (rnl(u.ulevel) > 6 && u.ualign.record > 0 && rnd(u.ualign.record) > (3 * ALIGNLIM) / 4) @@ -1610,8 +1616,8 @@ dosacrifice() consume_offering(otmp); /* OK, you get brownie points. */ if (u.ugangr) { - u.ugangr -= - ((value * (u.ualign.type == A_CHAOTIC ? 2 : 3)) / MAXVALUE); + u.ugangr -= ((value * (u.ualign.type == A_CHAOTIC ? 2 : 3)) + / MAXVALUE); if (u.ugangr < 0) u.ugangr = 0; if (u.ugangr != saved_anger) { @@ -1704,8 +1710,7 @@ dosacrifice() body_part(FOOT)); else You(Hallucination - ? "see crabgrass at your %s. A funny thing in a " - "dungeon." + ? "see crabgrass at your %s. A funny thing in a dungeon." : "glimpse a four-leaf clover at your %s.", makeplural(body_part(FOOT))); } @@ -1741,10 +1746,10 @@ boolean praying; /* false means no messages should be given */ 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... */ + 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 */ { @@ -1761,9 +1766,10 @@ boolean praying; /* false means no messages should be given */ 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; + return !praying ? (boolean) (p_type == 3 && !Inhell) : TRUE; } +/* #pray commmand */ int dopray() { @@ -1804,15 +1810,17 @@ dopray() return 1; } -STATIC_PTR int prayer_done() /* M. Stephenson (1.0.3b) */ +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!"); + 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(); @@ -1857,27 +1865,30 @@ STATIC_PTR int prayer_done() /* M. Stephenson (1.0.3b) */ return 1; } +/* #turn command */ int doturn() -{ /* Knights & Priest(esse)s only please */ - +{ + /* 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++) - ; + /* Try to use the "turn undead" spell. + * + * This used to be based on whether hero knows the name of the + * turn undead spellbook, but it's possible to know--and be able + * to cast--the spell while having lost the book ID to amnesia. + * (It also used to tell spelleffects() to cast at self?) + */ + int sp_no; - if (sp_no < MAXSPELL && spl_book[sp_no].sp_id == SPE_TURN_UNDEAD) - return spelleffects(sp_no, TRUE); + for (sp_no = 0; sp_no < MAXSPELL; ++sp_no) { + if (spl_book[sp_no].sp_id == NO_SPELL) + break; + else if (spl_book[sp_no].sp_id == SPE_TURN_UNDEAD) + return spelleffects(sp_no, FALSE); } - You("don't know how to turn undead!"); return 0; } @@ -1885,13 +1896,12 @@ doturn() if ((u.ualign.type != A_CHAOTIC && (is_demon(youmonst.data) || is_undead(youmonst.data))) - || u.ugangr > 6 /* "Die, mortal!" */) { + || 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(); @@ -1967,7 +1977,9 @@ 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 */ +/* returns the name of an altar's deity */ +const char * +a_gname_at(x, y) xchar x, y; { if (!IS_ALTAR(levl[x][y].typ)) @@ -1976,7 +1988,9 @@ xchar x, y; return align_gname(a_align(x, y)); } -const char *u_gname() /* returns the name of the player's deity */ +/* returns the name of the hero's deity */ +const char * +u_gname() { return align_gname(u.ualign.type); } @@ -2135,12 +2149,15 @@ int dx, dy; switch (count) { case 0: - return FALSE; /* no boulders--not blocked */ + /* no boulders--not blocked */ + return FALSE; case 1: - break; /* possibly blocked depending on if it's pushable */ + /* possibly blocked depending on if it's pushable */ + break; default: - return TRUE; /* >1 boulder--blocked after they push the top - one; don't force them to push it first to find out */ + /* more than one boulder--blocked after they push the top one; + don't force them to push it first to find out */ + return TRUE; } if (!isok(u.ux + 2 * dx, u.uy + 2 * dy))