diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 69724485b..d33e86598 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -492,6 +492,17 @@ hero poly'd into paper or straw golem reverts to human if burned up even when Unchanging without any explanation given hero polymorphed into form which can't wear armor via 'W' (eliciting "don't even bother") could wear it via 'P' +make multi-shot missiles fired by monsters be less verbose when they miss +can no longer play controlled notes on musical instrument if impaired +if a special level specified the appearance of a mimic and mimics had been + genocided prior to creating the level, whatever random monster took + the mimic's place got its intended appearance +redundant "hit by gush of water" message if poly'd into iron golem or gremlin +a shop object stolen from outside the shop (via grappling hook) would be left + marked as 'unpaid' after the shop robbery took place, resulting in + "unpaid_cost: object wasn't on any bill" when looking at inventory +a shop object stolen from outside the shop could trigger a crash if that shop + had never been entered by the hero Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository @@ -737,11 +748,14 @@ Master Key of Thievery always finds door and chest traps if used to lock or blessed (for non-rogues); player is offered the opportunity to disarm "Elbereth" must now be the only engraved text on a square to function "Elbereth" now erodes based on attacks by the player, not monsters scared -option herecmd_menu to make a mouse click on your character pop up +add option herecmd_menu to make a mouse click on your character pop up a context menu, and extended command #herecmdmenu to do the same change #adjust's behavior when collecting compatible stacks; that used to occur for any #adjust which lacked a split count, now it only happens when 'adjusting' into a stack's own inventory slot +a prayer result which results in uncursing some or all of the hero's items + won't uncurse a worn helm of opposite alignment since that would + facilitate the hero switching to another god by taking it off Platform- and/or Interface-Specific New Features diff --git a/include/extern.h b/include/extern.h index 175cee5cc..b152af29c 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1513130012 2017/12/13 01:53:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.621 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1514769568 2018/01/01 01:19:28 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.622 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1400,6 +1400,7 @@ E void FDECL(restore_cham, (struct monst *)); E boolean FDECL(hideunder, (struct monst *)); E void FDECL(hide_monst, (struct monst *)); E void FDECL(mon_animal_list, (BOOLEAN_P)); +E boolean FDECL(validvamp, (struct monst *, int *, int)); E int FDECL(select_newcham_form, (struct monst *)); E void FDECL(mgender_from_permonst, (struct monst *, struct permonst *)); E int FDECL(newcham, diff --git a/src/mon.c b/src/mon.c index a872b93a9..62fb34a8f 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1505266804 2017/09/13 01:40:04 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.244 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1514769571 2018/01/01 01:19:31 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.246 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -23,7 +23,6 @@ STATIC_DCL void FDECL(kill_eggs, (struct obj *)); STATIC_DCL int FDECL(pickvampshape, (struct monst *)); STATIC_DCL boolean FDECL(isspecmon, (struct monst *)); STATIC_DCL boolean FDECL(validspecmon, (struct monst *, int)); -STATIC_DCL boolean FDECL(validvamp, (struct monst *, int *, int)); STATIC_DCL struct permonst *FDECL(accept_newcham_form, (int)); STATIC_DCL struct obj *FDECL(make_corpse, (struct monst *, unsigned)); STATIC_DCL void FDECL(m_detach, (struct monst *, struct permonst *)); @@ -3162,7 +3161,7 @@ int mndx; } /* prevent wizard mode user from specifying invalid vampshifter shape */ -STATIC_OVL boolean +boolean validvamp(mon, mndx_p, monclass) struct monst *mon; int *mndx_p, monclass; diff --git a/src/mthrowu.c b/src/mthrowu.c index 3d2830b96..6806feef4 100644 --- a/src/mthrowu.c +++ b/src/mthrowu.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mthrowu.c $NHDT-Date: 1446887531 2015/11/07 09:12:11 $ $NHDT-Branch: master $:$NHDT-Revision: 1.63 $ */ +/* NetHack 3.6 mthrowu.c $NHDT-Date: 1514152830 2017/12/24 22:00:30 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.73 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -26,6 +26,7 @@ STATIC_OVL NEARDATA const char *breathwep[] = { }; extern boolean notonhead; /* for long worms */ +STATIC_VAR int mesg_given; /* for m_throw()/thitu() 'miss' message */ /* hero is hit by something other than a monster */ int @@ -37,7 +38,7 @@ const char *name; /* if null, then format `*objp' */ struct obj *obj = objp ? *objp : 0; const char *onm, *knm; boolean is_acid; - int kprefix = KILLED_BY_AN; + int kprefix = KILLED_BY_AN, dieroll; char onmbuf[BUFSZ], knmbuf[BUFSZ]; if (!name) { @@ -59,10 +60,15 @@ const char *name; /* if null, then format `*objp' */ : an(name); is_acid = (obj && obj->otyp == ACID_VENOM); - if (u.uac + tlev <= rnd(20)) { - if (Blind || !flags.verbose) + if (u.uac + tlev <= (dieroll = rnd(20))) { + ++mesg_given; + if (Blind || !flags.verbose) { pline("It misses."); - else + } else if (u.uac + tlev <= dieroll - 2) { + if (onm != onmbuf) + Strcpy(onmbuf, onm); /* [modifiable buffer for upstart()] */ + pline("%s %s you.", upstart(onmbuf), vtense(onmbuf, "miss")); + } else You("are almost hit by %s.", onm); return 0; } else { @@ -518,6 +524,7 @@ struct obj *obj; /* missile (or stack providing it) */ (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y); return; } + mesg_given = 0; /* a 'missile misses' message has not yet been shown */ /* Note: drop_throw may destroy singleobj. Since obj must be destroyed * early to avoid the dagger bug, anyone who modifies this code should @@ -646,8 +653,10 @@ struct obj *obj; /* missile (or stack providing it) */ if (!range /* reached end of path */ || MT_FLIGHTCHECK(FALSE)) { if (singleobj) { /* hits_bars might have destroyed it */ - if (m_shot.n > 1 && (cansee(bhitpos.x, bhitpos.y) - || (archer && canseemon(archer)))) + if (m_shot.n > 1 + && (!mesg_given || bhitpos.x != u.ux || bhitpos.y != u.uy) + && (cansee(bhitpos.x, bhitpos.y) + || (archer && canseemon(archer)))) pline("%s misses.", The(mshot_xname(singleobj))); (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y); } @@ -659,6 +668,7 @@ struct obj *obj; /* missile (or stack providing it) */ tmp_at(bhitpos.x, bhitpos.y); delay_output(); tmp_at(DISP_END, 0); + mesg_given = 0; /* reset */ if (blindinc) { u.ucreamed += blindinc; diff --git a/src/music.c b/src/music.c index 75ab39d4d..68c9e97d5 100644 --- a/src/music.c +++ b/src/music.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 music.c $NHDT-Date: 1452660194 2016/01/13 04:43:14 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.42 $ */ +/* NetHack 3.6 music.c $NHDT-Date: 1514504228 2017/12/28 23:37:08 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.46 $ */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -6,7 +6,7 @@ * This file contains the different functions designed to manipulate the * musical instruments and their various effects. * - * Actually the list of instruments / effects is : + * The list of instruments / effects is : * * (wooden) flute may calm snakes if player has enough dexterity * magic flute may put monsters to sleep: area of effect depends @@ -450,8 +450,7 @@ STATIC_OVL int do_improvisation(instr) struct obj *instr; { - int damage, do_spec = !Confusion; -#if defined(MAC) || defined(AMIGA) || defined(VPIX_MUSIC) || defined(PCMUSIC) + int damage, mode, do_spec = !(Stunned || Confusion); struct obj itmp; itmp = *instr; @@ -476,23 +475,55 @@ struct obj *instr; #ifdef PCMUSIC pc_speaker(&itmp, "C"); #endif -#endif /* MAC || AMIGA || VPIX_MUSIC || PCMUSIC */ - if (!do_spec) +#define PLAY_NORMAL 0 +#define PLAY_STUNNED 1 +#define PLAY_CONFUSED 2 +#define PLAY_HALLU 4 + mode = PLAY_NORMAL; + if (Stunned) + mode |= PLAY_STUNNED; + if (Confusion) + mode |= PLAY_CONFUSED; + if (Hallucination) + mode |= PLAY_HALLU; + + switch (mode) { + case PLAY_NORMAL: + You("start playing %s.", yname(instr)); + break; + case PLAY_STUNNED: + You("produce an obnoxious droning sound."); + break; + case PLAY_CONFUSED: + You("produce a raucous noise."); + break; + case PLAY_HALLU: + You("produce a kaleidoscopic display of floating butterfiles."); + break; + /* TODO? give some or all of these combinations their own feedback; + hallucination ones should reference senses other than hearing... */ + case PLAY_STUNNED | PLAY_CONFUSED: + case PLAY_STUNNED | PLAY_HALLU: + case PLAY_CONFUSED | PLAY_HALLU: + case PLAY_STUNNED | PLAY_CONFUSED | PLAY_HALLU: + default: pline("What you produce is quite far from music..."); - else - You("start playing %s.", the(xname(instr))); + break; + } +#undef PLAY_NORMAL +#undef PLAY_STUNNED +#undef PLAY_CONFUSED +#undef PLAY_HALLU - switch (instr->otyp) { + switch (itmp.otyp) { /* note: itmp.otyp might differ from instr->otyp */ case MAGIC_FLUTE: /* Make monster fall asleep */ - if (do_spec && instr->spe > 0) { - consume_obj_charge(instr, TRUE); + consume_obj_charge(instr, TRUE); - You("produce %s music.", Hallucination ? "piped" : "soft"); - put_monsters_to_sleep(u.ulevel * 5); - exercise(A_DEX, TRUE); - break; - } /* else FALLTHRU */ + You("produce %s music.", Hallucination ? "piped" : "soft"); + put_monsters_to_sleep(u.ulevel * 5); + exercise(A_DEX, TRUE); + break; case WOODEN_FLUTE: /* May charm snakes */ do_spec &= (rn2(ACURR(A_DEX)) + u.ulevel > 25); pline("%s.", Tobjnam(instr, do_spec ? "trill" : "toot")); @@ -502,66 +533,59 @@ struct obj *instr; break; case FIRE_HORN: /* Idem wand of fire */ case FROST_HORN: /* Idem wand of cold */ - if (do_spec && instr->spe > 0) { - consume_obj_charge(instr, TRUE); + consume_obj_charge(instr, TRUE); - if (!getdir((char *) 0)) { - pline("%s.", Tobjnam(instr, "vibrate")); - break; - } else if (!u.dx && !u.dy && !u.dz) { - if ((damage = zapyourself(instr, TRUE)) != 0) { - char buf[BUFSZ]; - - Sprintf(buf, "using a magical horn on %sself", uhim()); - losehp(damage, buf, KILLED_BY); /* fire or frost damage */ - } - } else { - buzz((instr->otyp == FROST_HORN) ? AD_COLD - 1 : AD_FIRE - 1, - rn1(6, 6), u.ux, u.uy, u.dx, u.dy); - } - makeknown(instr->otyp); + if (!getdir((char *) 0)) { + pline("%s.", Tobjnam(instr, "vibrate")); break; - } /* else FALLTHRU */ + } else if (!u.dx && !u.dy && !u.dz) { + if ((damage = zapyourself(instr, TRUE)) != 0) { + char buf[BUFSZ]; + + Sprintf(buf, "using a magical horn on %sself", uhim()); + losehp(damage, buf, KILLED_BY); /* fire or frost damage */ + } + } else { + buzz((instr->otyp == FROST_HORN) ? AD_COLD - 1 : AD_FIRE - 1, + rn1(6, 6), u.ux, u.uy, u.dx, u.dy); + } + makeknown(instr->otyp); + break; case TOOLED_HORN: /* Awaken or scare monsters */ You("produce a frightful, grave sound."); awaken_monsters(u.ulevel * 30); exercise(A_WIS, FALSE); break; case BUGLE: /* Awaken & attract soldiers */ - You("extract a loud noise from %s.", the(xname(instr))); + You("extract a loud noise from %s.", yname(instr)); awaken_soldiers(&youmonst); exercise(A_WIS, FALSE); break; case MAGIC_HARP: /* Charm monsters */ - if (do_spec && instr->spe > 0) { - consume_obj_charge(instr, TRUE); + consume_obj_charge(instr, TRUE); - pline("%s very attractive music.", Tobjnam(instr, "produce")); - charm_monsters((u.ulevel - 1) / 3 + 1); - exercise(A_DEX, TRUE); - break; - } /* else FALLTHRU */ + pline("%s very attractive music.", Tobjnam(instr, "produce")); + charm_monsters((u.ulevel - 1) / 3 + 1); + exercise(A_DEX, TRUE); + break; case WOODEN_HARP: /* May calm Nymph */ do_spec &= (rn2(ACURR(A_DEX)) + u.ulevel > 25); - pline("%s %s.", The(xname(instr)), + pline("%s %s.", Yname2(instr), do_spec ? "produces a lilting melody" : "twangs"); if (do_spec) calm_nymphs(u.ulevel * 3); exercise(A_DEX, TRUE); break; case DRUM_OF_EARTHQUAKE: /* create several pits */ - if (do_spec && instr->spe > 0) { - consume_obj_charge(instr, TRUE); + consume_obj_charge(instr, TRUE); - You("produce a heavy, thunderous rolling!"); - pline_The("entire %s is shaking around you!", - generic_lvl_desc()); - do_earthquake((u.ulevel - 1) / 3 + 1); - /* shake up monsters in a much larger radius... */ - awaken_monsters(ROWNO * COLNO); - makeknown(DRUM_OF_EARTHQUAKE); - break; - } /* else FALLTHRU */ + You("produce a heavy, thunderous rolling!"); + pline_The("entire %s is shaking around you!", generic_lvl_desc()); + do_earthquake((u.ulevel - 1) / 3 + 1); + /* shake up monsters in a much larger radius... */ + awaken_monsters(ROWNO * COLNO); + makeknown(DRUM_OF_EARTHQUAKE); + break; case LEATHER_DRUM: /* Awaken monsters */ You("beat a deafening row!"); awaken_monsters(u.ulevel * 40); @@ -571,7 +595,7 @@ struct obj *instr; break; default: impossible("What a weird instrument (%d)!", instr->otyp); - break; + return 0; } return 2; /* That takes time */ } @@ -598,11 +622,13 @@ struct obj *instr; You("are incapable of playing %s.", the(distant_name(instr, xname))); return 0; } - if (instr->otyp != LEATHER_DRUM && instr->otyp != DRUM_OF_EARTHQUAKE) { + if (instr->otyp != LEATHER_DRUM && instr->otyp != DRUM_OF_EARTHQUAKE + && !(Stunned || Confusion || Hallucination)) { c = ynq("Improvise?"); if (c == 'q') goto nevermind; } + if (c == 'n') { if (u.uevent.uheard_tune == 2) c = ynq("Play the passtune?"); diff --git a/src/pickup.c b/src/pickup.c index aa147080b..d09bbbfdb 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pickup.c $NHDT-Date: 1508549438 2017/10/21 01:30:38 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.192 $ */ +/* NetHack 3.6 pickup.c $NHDT-Date: 1515144225 2018/01/05 09:23:45 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.193 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1495,15 +1495,30 @@ struct obj * pick_obj(otmp) struct obj *otmp; { + struct obj *result; + int ox = otmp->ox, oy = otmp->oy; + boolean robshop = (!u.uswallow && otmp != uball && costly_spot(ox, oy)); + obj_extract_self(otmp); - if (!u.uswallow && otmp != uball && costly_spot(otmp->ox, otmp->oy)) { + otmp->nomerge = 1; + result = addinv(otmp); + otmp->nomerge = 0; + newsym(ox, oy); + + /* this used to be done before addinv(), but remote_burglary() + calls rob_shop() which calls setpaid() after moving costs of + unpaid items to shop debt; setpaid() calls clear_unpaid() for + lots of object chains, but 'otmp' wasn't on any of those so + remained flagged as an unpaid item in inventory, triggering + impossible() every time inventory was examined... */ + if (robshop) { char saveushops[5], fakeshop[2]; /* addtobill cares about your location rather than the object's; usually they'll be the same, but not when using telekinesis (if ever implemented) or a grappling hook */ Strcpy(saveushops, u.ushops); - fakeshop[0] = *in_rooms(otmp->ox, otmp->oy, SHOPBASE); + fakeshop[0] = *in_rooms(ox, oy, SHOPBASE); fakeshop[1] = '\0'; Strcpy(u.ushops, fakeshop); /* sets obj->unpaid if necessary */ @@ -1511,10 +1526,9 @@ struct obj *otmp; Strcpy(u.ushops, saveushops); /* if you're outside the shop, make shk notice */ if (!index(u.ushops, *fakeshop)) - remote_burglary(otmp->ox, otmp->oy); + remote_burglary(ox, oy); } - newsym(otmp->ox, otmp->oy); - return addinv(otmp); /* might merge it with other objects */ + return result; } /* diff --git a/src/pray.c b/src/pray.c index 51dfbb5bb..0e74bb98a 100644 --- a/src/pray.c +++ b/src/pray.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pray.c $NHDT-Date: 1450577672 2015/12/20 02:14:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.89 $ */ +/* NetHack 3.6 pray.c $NHDT-Date: 1514593198 2017/12/30 00:19:58 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.95 $ */ /* Copyright (c) Benson I. Margulies, Mike Stephenson, Steve Linhart, 1989. */ /* NetHack may be freely redistributed. See license for details. */ @@ -265,18 +265,21 @@ worst_cursed_item() 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 */ + /* gloves come next, due to rings */ } else if (uarmg && uarmg->cursed) { /* gloves */ otmp = uarmg; - /* then shield due to two handed weapons and spells */ + /* then shield due to two handed weapons and spells */ } else if (uarms && uarms->cursed) { /* shield */ otmp = uarms; - /* then cloak due to body armor */ + /* 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 */ + /* if worn helmet of opposite alignment is making you an adherent + of the current god, he/she/it won't uncurse that for you */ + } else if (uarmh && uarmh->cursed /* helmet */ + && uarmh->otyp != HELM_OF_OPPOSITE_ALIGNMENT) { otmp = uarmh; } else if (uarmf && uarmf->cursed) { /* boots */ otmp = uarmf; @@ -290,13 +293,13 @@ worst_cursed_item() otmp = uright; } else if (ublindf && ublindf->cursed) { /* eyewear */ otmp = ublindf; /* must be non-blinding lenses */ - /* if weapon wasn't handled above, do it now */ + /* 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 */ + /* 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 */ + /* all worn items ought to be handled by now */ } else { for (otmp = invent; otmp; otmp = otmp->nobj) { if (!otmp->cursed) @@ -336,9 +339,7 @@ int trouble; break; case TROUBLE_LAVA: You("are back on solid ground."); - /* teleport should always succeed, but if not, - * just untrap them. - */ + /* teleport should always succeed, but if not, just untrap them */ if (!safe_teleds(FALSE)) u.utrap = 0; break; @@ -386,8 +387,7 @@ int trouble; if ((otmp = stuck_ring(uleft, RIN_SUSTAIN_ABILITY)) != 0) { if (otmp == uleft) what = leftglow; - } else if ((otmp = stuck_ring(uright, RIN_SUSTAIN_ABILITY)) - != 0) { + } else if ((otmp = stuck_ring(uright, RIN_SUSTAIN_ABILITY)) != 0) { if (otmp == uright) what = rightglow; } @@ -1070,7 +1070,9 @@ aligntyp g_align; else You("are surrounded by %s aura.", an(hcolor(NH_LIGHT_BLUE))); for (otmp = invent; otmp; otmp = otmp->nobj) { - if (otmp->cursed) { + if (otmp->cursed + && (otmp != uarmh /* [see worst_cursed_item()] */ + || uarmh->otyp != HELM_OF_OPPOSITE_ALIGNMENT)) { if (!Blind) { pline("%s %s.", Yobjnam2(otmp, "softly glow"), hcolor(NH_AMBER)); diff --git a/src/read.c b/src/read.c index e452bf33a..34dd9a32e 100644 --- a/src/read.c +++ b/src/read.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 read.c $NHDT-Date: 1513130018 2017/12/13 01:53:38 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.149 $ */ +/* NetHack 3.6 read.c $NHDT-Date: 1515802375 2018/01/13 00:12:55 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.150 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -102,10 +102,10 @@ char *buf; "Go team ant!", "Got newt?", "Hello, my darlings!", /* Charlie Drake */ - "Hey! Nymphs! Steal This T-Shirt!", + "Hey! Nymphs! Steal This T-Shirt!", "I <3 Dungeon of Doom", "I <3 Maud", - "I am a Valkyrie. If you see me running, try to keep up.", + "I am a Valkyrie. If you see me running, try to keep up.", "I am not a pack rat - I am a collector", "I bounced off a rubber tree", /* Monkey Island */ "Plunder Island Brimstone Beach Club", /* Monkey Island */ @@ -141,6 +141,16 @@ char *buf; "Pudding farmer", "Vegetarian", "Hello, I'm War!", + "It is better to light a candle than to curse the darkness", + "It is easier to curse the darkness than to light a candle", + /* expanded "rock--paper--scissors" featured in TV show "Big Bang + Theory" although they didn't create it (and an actual T-shirt + with pentagonal diagram showing which choices defeat which) */ + "rock--paper--scissors--lizard--Spock!", + /* "All men must die -- all men must serve" challange and response + from book series _A_Song_of_Ice_and_Fire_ by George R.R. Martin, + TV show "Game of Thrones" (probably an actual T-shirt too...) */ + "/Valar morghulis/ -- /Valar dohaeris/", }; Strcpy(buf, shirt_msgs[tshirt->o_id % SIZE(shirt_msgs)]); @@ -191,7 +201,8 @@ doread() useup(scroll); return 1; } else if (scroll->otyp == T_SHIRT || scroll->otyp == ALCHEMY_SMOCK) { - char buf[BUFSZ]; + char buf[BUFSZ], *mesg; + const char *endpunct; if (Blind) { You_cant("feel any Braille writing."); @@ -205,15 +216,25 @@ doread() return 0; } u.uconduct.literate++; - if (flags.verbose) + /* populate 'buf[]' */ + mesg = (scroll->otyp == T_SHIRT) ? tshirt_text(scroll, buf) + : apron_text(scroll, buf); + endpunct = ""; + if (flags.verbose) { + int ln = (int) strlen(mesg); + + /* we will be displaying a sentence; need ending punctuation */ + if (ln > 0 && !index(".!?", mesg[ln - 1])) + endpunct = "."; pline("It reads:"); - pline("\"%s\"", (scroll->otyp == T_SHIRT) ? tshirt_text(scroll, buf) - : apron_text(scroll, buf)); + } + pline("\"%s\"%s", mesg, endpunct); return 1; } else if (scroll->otyp == CREDIT_CARD) { static const char *card_msgs[] = { "Leprechaun Gold Tru$t - Shamrock Card", - "Magic Memory Vault Charge Card", "Larn National Bank", /* Larn */ + "Magic Memory Vault Charge Card", + "Larn National Bank", /* Larn */ "First Bank of Omega", /* Omega */ "Bank of Zork - Frobozz Magic Card", /* Zork */ "Ankh-Morpork Merchant's Guild Barter Card", @@ -238,13 +259,14 @@ doread() : card_msgs[scroll->o_id % (SIZE(card_msgs) - 1)]); } /* Make a credit card number */ - pline("\"%d0%d %ld%d1 0%d%d0\"", + pline("\"%d0%d %ld%d1 0%d%d0\"%s", (((int) scroll->o_id % 89) + 10), ((int) scroll->o_id % 4), ((((long) scroll->o_id * 499L) % 899999L) + 100000L), ((int) scroll->o_id % 10), (!((int) scroll->o_id % 3)), - (((int) scroll->o_id * 7) % 10)); + (((int) scroll->o_id * 7) % 10), + (flags.verbose || Blind) ? "." : ""); u.uconduct.literate++; return 1; } else if (scroll->otyp == CAN_OF_GREASE) { @@ -257,7 +279,7 @@ doread() } if (flags.verbose) pline("It reads:"); - pline("\"Magic Marker(TM) Red Ink Marker Pen. Water Soluble.\""); + pline("\"Magic Marker(TM) Red Ink Marker Pen. Water Soluble.\""); u.uconduct.literate++; return 1; } else if (scroll->oclass == COIN_CLASS) { @@ -265,7 +287,7 @@ doread() You("feel the embossed words:"); else if (flags.verbose) You("read:"); - pline("\"1 Zorkmid. 857 GUE. In Frobs We Trust.\""); + pline("\"1 Zorkmid. 857 GUE. In Frobs We Trust.\""); u.uconduct.literate++; return 1; } else if (scroll->oartifact == ART_ORB_OF_FATE) { @@ -291,7 +313,7 @@ doread() You_cant("feel any Braille writing."); return 0; } - pline("The wrapper reads: \"%s\"", + pline("The wrapper reads: \"%s\".", wrapper_msgs[scroll->o_id % SIZE(wrapper_msgs)]); u.uconduct.literate++; return 1; diff --git a/src/shk.c b/src/shk.c index 62052fbe7..c81c788b2 100644 --- a/src/shk.c +++ b/src/shk.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 shk.c $NHDT-Date: 1464138042 2016/05/25 01:00:42 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.132 $ */ +/* NetHack 3.6 shk.c $NHDT-Date: 1515144230 2018/01/05 09:23:50 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.136 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2354,6 +2354,12 @@ struct monst *shkp; return; } + /* normally bill_p gets set up whenever you enter the shop, but obj + might be going onto the bill because hero just snagged it with + a grappling hook from outside without ever having been inside */ + if (!eshkp->bill_p) + eshkp->bill_p = &(eshkp->bill[0]); + bct = eshkp->billct; bp = &(eshkp->bill_p[bct]); bp->bo_id = obj->o_id; diff --git a/src/sp_lev.c b/src/sp_lev.c index f8f2a8d57..5fc103a1b 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 sp_lev.c $NHDT-Date: 1513879435 2017/12/21 18:03:55 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.93 $ */ +/* NetHack 3.6 sp_lev.c $NHDT-Date: 1514769572 2018/01/01 01:19:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.95 $ */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -1589,11 +1589,14 @@ struct mkroom *croom; mtmp = christen_monst(mtmp, m->name.str); /* - * This is currently hardwired for mimics only. It should - * eventually be expanded. + * This doesn't complain if an attempt is made to give a + * non-mimic/non-shapechanger an appearance or to give a + * shapechanger a non-monster shape, it just refuses to comply. */ if (m->appear_as.str - && ((mtmp->data->mlet == S_MIMIC) || mtmp->cham) + && ((mtmp->data->mlet == S_MIMIC) + /* shapechanger (chameleons, et al, and vampires) */ + || (mtmp->cham >= LOW_PM && m->appear == M_AP_MONSTER)) && !Protection_from_shape_changers) { int i; @@ -1658,7 +1661,29 @@ struct mkroom *croom; mndx = select_newcham_form(mtmp); else mndx = name_to_mon(m->appear_as.str); - if ((mndx != NON_PM) && (&mons[mndx] != mtmp->data)) { + + if (mndx == NON_PM || (is_vampshifter(mtmp) + && !validvamp(mtmp, &mndx, S_HUMAN))) { + impossible("create_monster: invalid %s (\"%s\")", + (mtmp->data->mlet == S_MIMIC) + ? "mimic appearance" + : (mtmp->data == &mons[PM_WIZARD_OF_YENDOR]) + ? "Wizard appearance" + : is_vampshifter(mtmp) + ? "vampire shape" + : "chameleon shape", + m->appear_as.str); + } else if (&mons[mndx] == mtmp->data) { + /* explicitly forcing a mimic to appear as itself */ + mtmp->m_ap_type = M_AP_NOTHING; + mtmp->mappearance = 0; + } else if (mtmp->data->mlet == S_MIMIC + || mtmp->data == &mons[PM_WIZARD_OF_YENDOR]) { + /* this is ordinarily only used for Wizard clones + and hasn't been exhaustively tested for mimics */ + mtmp->m_ap_type = M_AP_MONSTER; + mtmp->mappearance = mndx; + } else { /* chameleon or vampire */ struct permonst *mdat = &mons[mndx]; struct permonst *olddata = mtmp->data; diff --git a/src/trap.c b/src/trap.c index 401d5a7fc..1855a722a 100644 --- a/src/trap.c +++ b/src/trap.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 trap.c $NHDT-Date: 1494107206 2017/05/06 21:46:46 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.278 $ */ +/* NetHack 3.6 trap.c $NHDT-Date: 1514855666 2018/01/02 01:14:26 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.284 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1103,7 +1103,7 @@ unsigned trflags; if (uarmc) (void) water_damage(uarmc, cloak_simple_name(uarmc), TRUE); else if (uarm) - (void) water_damage(uarm, "armor", TRUE); + (void) water_damage(uarm, suit_simple_name(uarm), TRUE); else if (uarmu) (void) water_damage(uarmu, "shirt", TRUE); } @@ -1112,11 +1112,9 @@ unsigned trflags; if (u.umonnum == PM_IRON_GOLEM) { int dam = u.mhmax; - pline("%s you!", A_gush_of_water_hits); You("are covered with rust!"); losehp(Maybe_Half_Phys(dam), "rusting away", KILLED_BY); } else if (u.umonnum == PM_GREMLIN && rn2(3)) { - pline("%s you!", A_gush_of_water_hits); (void) split_mon(&youmonst, (struct monst *) 0); } @@ -2292,7 +2290,8 @@ register struct monst *mtmp; (void) water_damage(target, cloak_simple_name(target), TRUE); else if ((target = which_armor(mtmp, W_ARM)) != 0) - (void) water_damage(target, "armor", TRUE); + (void) water_damage(target, suit_simple_name(target), + TRUE); else if ((target = which_armor(mtmp, W_ARMU)) != 0) (void) water_damage(target, "shirt", TRUE); } @@ -3430,7 +3429,16 @@ boolean force; pline("Water gets into your %s!", ostr); water_damage_chain(obj->cobj, FALSE); - return ER_NOTHING; + return ER_DAMAGED; /* contents were damaged */ + } else if (obj->otyp == OILSKIN_SACK) { + if (carried(obj)) + pline("Some water slides right off your %s.", ostr); + makeknown(OILSKIN_SACK); + /* not actually damaged, but because we /didn't/ get the "water + gets into!" message, the player now has more information and + thus we need to waste any potion they may have used (also, + flavourwise the water is now on the floor) */ + return ER_DAMAGED; } else if (!force && (Luck + 5) > rn2(20)) { /* chance per item of sustaining damage: * max luck: 10% diff --git a/sys/unix/hints/macosx.sh b/sys/unix/hints/macosx.sh old mode 100755 new mode 100644 index df71033b8..2bf2360d9 --- a/sys/unix/hints/macosx.sh +++ b/sys/unix/hints/macosx.sh @@ -1,5 +1,5 @@ #!/bin/sh -# NetHack 3.6 macosx.sh $NHDT-Date: 1455930387 2016/02/20 01:06:27 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $ +# NetHack 3.6 macosx.sh $NHDT-Date: 1515549543 2018/01/10 01:59:03 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.18 $ # Copyright (c) Kenneth Lorber, Kensington, Maryland, 2007. # NetHack may be freely redistributed. See license for details. # @@ -94,16 +94,23 @@ xgroup2) xeditsysconf) src=$2 dest=$3 - # we should traverse the elements of $PATH instead - if [ -f /usr/bin/gdb ]; then + ptg=1 + # We don't need an LLDB module because any MacOSX new enough to + # have no Apple supported gdb is also new enough to get good + # stack traces through libc. + # NB: xcrun will check $PATH + if [[ -x /usr/bin/xcrun && `/usr/bin/xcrun -f gdb 2>/dev/null` ]] ; then + gdbpath="GDBPATH="`/usr/bin/xcrun -f gdb` + elif [ -f /usr/bin/gdb ]; then gdbpath='GDBPATH=/usr/bin/gdb' #traditional location elif [ -f /opt/local/bin/ggdb ]; then gdbpath='GDBPATH=/opt/local/bin/ggdb' #macports gdb elif [ -f /Developer/usr/bin/gdb ]; then # this one seems to be broken with Xcode 5.1.1 on Mountain Lion - gdbpath='GDBPATH=/Developer/usr/bin/gdb' #recent Xcode tools + gdbpath='GDBPATH=/Developer/usr/bin/gdb' #older Xcode tools else gdbpath='#GDBPATH' #none of the above + ptg=0 fi if [ -f /bin/grep ]; then greppath='GREPPATH=/bin/grep' @@ -116,7 +123,7 @@ xeditsysconf) if ! [ -e $dest ]; then sed -e "s:^GDBPATH=.*:$gdbpath:" \ -e "s:^GREPPATH=.*:$greppath:" \ - -e 's/^PANICTRACE_GDB=[12]/PANICTRACE_GDB=0/' \ + -e "s/^PANICTRACE_GDB=./PANICTRACE_GDB=$ptg/" \ -e 's/^#OPTIONS=.*/&\ OPTIONS=!use_darkgray/' \ $src > $dest diff --git a/sys/unix/hints/macosx10.10 b/sys/unix/hints/macosx10.10 index 19737f0c1..f320e25fb 100644 --- a/sys/unix/hints/macosx10.10 +++ b/sys/unix/hints/macosx10.10 @@ -1,5 +1,5 @@ # -# NetHack 3.6 macosx10.11 $NHDT-Date: 1445622451 2015/10/23 17:47:31 $ $NHDT-Branch: master $:$NHDT-Revision: 1.0 $ +# NetHack 3.6 macosx10.11 $NHDT-Date: 1515549543 2018/01/10 01:59:03 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.48 $ # Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. # NetHack may be freely redistributed. See license for details. # @@ -172,6 +172,7 @@ CHGRP=/usr/bin/true GAMEPERM = 0700 VARFILEPERM = 0600 VARDIRPERM = 0700 +POSTINSTALL+= sys/unix/hints/macosx.sh editsysconf sys/unix/sysconf $(HACKDIR)/sysconf; # We can use "make all" to build the whole thing - but it misses some things: MOREALL=$(MAKE) install CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" -DSECURE