diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 3cc5261f6..cc6cf57a7 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -79,6 +79,8 @@ when a pet moves reluctantly, name the top item of the pile it is reluctant to step on if the hero sees or remembers any object(s) at that spot ensure sufficient messages are given to clarify the transition from detected vampire bats to fog clouds in Vlad's tower +fix "killing by kicking something weird" when kicking an object causes death +guard macros available for mextra fields similar to those for oextra fields Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index c25c634b6..3bba9fe1d 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1190,6 +1190,7 @@ E void FDECL(remove_rooms, (int, int, int, int)); /* ### mkmaze.c ### */ E void FDECL(wallification, (int, int, int, int)); +E void FDECL(fix_wall_spines, (int, int, int, int)); E void FDECL(walkfrom, (int, int, SCHAR_P)); E void FDECL(makemaz, (const char *)); E void FDECL(mazexy, (coord *)); diff --git a/include/mextra.h b/include/mextra.h index e2cde882c..8a37a7483 100644 --- a/include/mextra.h +++ b/include/mextra.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 mextra.h $NHDT-Date: 1432512781 2015/05/25 00:13:01 $ $NHDT-Branch: master $:$NHDT-Revision: 1.16 $ */ +/* NetHack 3.6 mextra.h $NHDT-Date: 1451836000 2016/01/03 15:46:40 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.18 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -190,6 +190,11 @@ struct mextra { #define MCORPSENM(mon) ((mon)->mextra->mcorpsenm) #define has_mname(mon) ((mon)->mextra && MNAME(mon)) +#define has_egd(mon) ((mon)->mextra && EGD(mon)) +#define has_epri(mon) ((mon)->mextra && EPRI(mon)) +#define has_eshk(mon) ((mon)->mextra && ESHK(mon)) +#define has_emin(mon) ((mon)->mextra && EMIN(mon)) +#define has_edog(mon) ((mon)->mextra && EDOG(mon)) #define has_mcorpsenm(mon) ((mon)->mextra && MCORPSENM(mon) != NON_PM) #endif /* MEXTRA_H */ diff --git a/src/dokick.c b/src/dokick.c index ca4e2a6bc..7515f6fda 100644 --- a/src/dokick.c +++ b/src/dokick.c @@ -20,9 +20,9 @@ STATIC_DCL void FDECL(kickdmg, (struct monst *, BOOLEAN_P)); STATIC_DCL boolean FDECL(maybe_kick_monster, (struct monst *, XCHAR_P, XCHAR_P)); STATIC_DCL void FDECL(kick_monster, (struct monst *, XCHAR_P, XCHAR_P)); -STATIC_DCL int FDECL(kick_object, (XCHAR_P, XCHAR_P)); +STATIC_DCL int FDECL(kick_object, (XCHAR_P, XCHAR_P, char *)); STATIC_DCL int FDECL(really_kick_object, (XCHAR_P, XCHAR_P)); -STATIC_DCL char *FDECL(kickstr, (char *)); +STATIC_DCL char *FDECL(kickstr, (char *, const char *)); STATIC_DCL void FDECL(otransit_msg, (struct obj *, BOOLEAN_P, long)); STATIC_DCL void FDECL(drop_to, (coord *, SCHAR_P)); @@ -463,15 +463,18 @@ xchar x, y; /* coordinates where object was before the impact, not after */ /* jacket around really_kick_object */ STATIC_OVL int -kick_object(x, y) +kick_object(x, y, kickobjnam) xchar x, y; +char *kickobjnam; { int res = 0; + *kickobjnam = '\0'; /* if a pile, the "top" object gets kicked */ kickedobj = level.objects[x][y]; if (kickedobj) { /* kick object; if doing is fatal, done() will clean up kickedobj */ + Strcpy(kickobjnam, killer_xname(kickedobj)); /* matters iff res==0 */ res = really_kick_object(x, y); kickedobj = (struct obj *) 0; } @@ -707,13 +710,14 @@ xchar x, y; /* cause of death if kicking kills kicker */ STATIC_OVL char * -kickstr(buf) +kickstr(buf, kickobjnam) char *buf; +const char *kickobjnam; { const char *what; - if (kickedobj) - what = killer_xname(kickedobj); + if (*kickobjnam) + what = kickobjnam; else if (maploc == &nowhere) what = "nothing"; else if (IS_DOOR(maploc->typ)) @@ -755,8 +759,9 @@ dokick() int dmg = 0, glyph, oldglyph = -1; register struct monst *mtmp; boolean no_kick = FALSE; - char buf[BUFSZ]; + char buf[BUFSZ], kickobjnam[BUFSZ]; + kickobjnam[0] = '\0'; if (nolimbs(youmonst.data) || slithy(youmonst.data)) { You("have no legs to kick with."); no_kick = TRUE; @@ -948,7 +953,7 @@ dokick() if (OBJ_AT(x, y) && (!Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) || sobj_at(BOULDER, x, y))) { - if (kick_object(x, y)) { + if (kick_object(x, y, kickobjnam)) { if (Is_airlevel(&u.uz)) hurtle(-u.dx, -u.dy, 1, TRUE); /* assume it's light */ return 1; @@ -1211,7 +1216,7 @@ dokick() if (!rn2(3)) set_wounded_legs(RIGHT_SIDE, 5 + rnd(5)); dmg = rnd(ACURR(A_CON) > 15 ? 3 : 5); - losehp(Maybe_Half_Phys(dmg), kickstr(buf), KILLED_BY); + losehp(Maybe_Half_Phys(dmg), kickstr(buf, kickobjnam), KILLED_BY); if (Is_airlevel(&u.uz) || Levitation) hurtle(-u.dx, -u.dy, rn1(2, 4), TRUE); /* assume it's heavy */ return 1; diff --git a/src/mkmaze.c b/src/mkmaze.c index eddf6fbd1..100b0b525 100644 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@ -135,17 +135,6 @@ int x1, y1, x2, y2; uchar type; register int x, y; struct rm *lev; - int bits; - int locale[3][3]; /* rock or wall status surrounding positions */ - /* - * Value 0 represents a free-standing wall. It could be anything, - * so even though this table says VWALL, we actually leave whatever - * typ was there alone. - */ - static xchar spine_array[16] = { VWALL, HWALL, HWALL, HWALL, - VWALL, TRCORNER, TLCORNER, TDWALL, - VWALL, BRCORNER, BLCORNER, TUWALL, - VWALL, TLWALL, TRWALL, CROSSWALL }; /* sanity check on incoming variables */ if (x1 < 0 || x2 >= COLNO || x1 > x2 || y1 < 0 || y2 >= ROWNO || y1 > y2) @@ -165,6 +154,33 @@ int x1, y1, x2, y2; } } + fix_wall_spines(x1,y1,x2,y2); +} + +void +fix_wall_spines(x1, y1, x2, y2) +int x1, y1, x2, y2; +{ + uchar type; + register int x,y; + struct rm *lev; + int bits; + int locale[3][3]; /* rock or wall status surrounding positions */ + + /* + * Value 0 represents a free-standing wall. It could be anything, + * so even though this table says VWALL, we actually leave whatever + * typ was there alone. + */ + static xchar spine_array[16] = { VWALL, HWALL, HWALL, HWALL, + VWALL, TRCORNER, TLCORNER, TDWALL, + VWALL, BRCORNER, BLCORNER, TUWALL, + VWALL, TLWALL, TRWALL, CROSSWALL }; + + /* sanity check on incoming variables */ + if (x1<0 || x2>=COLNO || x1>x2 || y1<0 || y2>=ROWNO || y1>y2) + panic("wall_extends: bad bounds (%d,%d) to (%d,%d)",x1,y1,x2,y2); + /* * Step 2: set the correct wall type. We can't combine steps * 1 and 2 into a single sweep because we depend on knowing if diff --git a/src/monmove.c b/src/monmove.c index 33917864f..8fc93b745 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 monmove.c $NHDT-Date: 1451664819 2016/01/01 16:13:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.79 $ */ +/* NetHack 3.6 monmove.c $NHDT-Date: 1451866935 2016/01/04 00:22:15 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.80 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -571,7 +571,7 @@ toofar: case 0: /* no movement, but it can still attack you */ case 3: /* absolutely no movement */ /* vault guard might have vanished */ - if (mtmp->isgd && (mtmp->mhp < 1 || !mtmp->mx == 0)) + if (mtmp->isgd && (mtmp->mhp < 1 || mtmp->mx == 0)) return 1; /* behave as if it died */ /* During hallucination, monster appearance should * still change - even if it doesn't move. diff --git a/src/options.c b/src/options.c index 2dab20368..3e923e046 100644 --- a/src/options.c +++ b/src/options.c @@ -3487,6 +3487,7 @@ char ch; static char fmtstr_doset_add_menu[] = "%s%-15s [%s] "; static char fmtstr_doset_add_menu_tab[] = "%s\t[%s]"; +static char n_currently_set[] = "(%d currently set)"; STATIC_OVL void doset_add_menu(win, option, indexoffset) @@ -3528,6 +3529,38 @@ int indexoffset; /* value to add to index in compopt[], or zero add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); } +STATIC_OVL void +opts_add_others(win, name, id, bufx, nset) +winid win; +char *name; +int id; +char *bufx; +int nset; +{ + char buf[BUFSZ], buf2[BUFSZ]; + anything any = zeroany; + any.a_int = id; + if (!bufx) + Sprintf(buf2, n_currently_set, nset); + else + Sprintf(buf2, "%s", bufx); + if (!iflags.menu_tab_sep) + Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : " ", + name, buf2); + else + Sprintf(buf, fmtstr_doset_add_menu_tab, name, buf2); + add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); +} + +enum opt_other_enums { + OPT_OTHER_MSGTYPE = -4, + OPT_OTHER_MENUCOLOR = -3, + OPT_OTHER_STATHILITE = -2, + OPT_OTHER_APEXC = -1 + /* these must be < 0 */ +}; + + /* Changing options via menu by Per Liboriussen */ int doset() @@ -3541,7 +3574,6 @@ doset() int indexoffset, startpass, endpass; boolean setinitial = FALSE, fromfile = FALSE; int biggest_name = 0; - const char *n_currently_set = "(%d currently set)"; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin); @@ -3636,35 +3668,27 @@ doset() doset_add_menu(tmpwin, compopt[i].name, (pass == DISP_IN_GAME) ? 0 : indexoffset); } - any.a_int = -4; - Sprintf(buf2, n_currently_set, msgtype_count()); - Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : " ", - "message types", buf2); - add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); - any.a_int = -3; - Sprintf(buf2, n_currently_set, count_menucolors()); - Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : " ", - "menucolors", buf2); - add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); + + any = zeroany; + add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED); + add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings, + "Other settings:", + MENU_UNSELECTED); + + opts_add_others(tmpwin, "autopickup exceptions", OPT_OTHER_APEXC, + NULL, count_ape_maps((int *) 0, (int *) 0)); + opts_add_others(tmpwin, "menucolors", OPT_OTHER_MENUCOLOR, + NULL, count_menucolors()); + opts_add_others(tmpwin, "message types", OPT_OTHER_MSGTYPE, + NULL, msgtype_count()); #ifdef STATUS_VIA_WINDOWPORT #ifdef STATUS_HILITES - any.a_int = -2; get_status_hilites(buf2, 60); if (!*buf2) Sprintf(buf2, "%s", "(none)"); - if (!iflags.menu_tab_sep) - Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : " ", - "status_hilites", buf2); - else - Sprintf(buf, fmtstr_doset_add_menu_tab, "status_hilites", buf2); - add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); + opts_add_others(tmpwin, "status_hilites", OPT_OTHER_STATHILITE, buf2, 0); #endif #endif - any.a_int = -1; - Sprintf(buf2, n_currently_set, count_ape_maps((int *) 0, (int *) 0)); - Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : " ", - "autopickup exceptions", buf2); - add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); #ifdef PREFIXES_IN_USE any = zeroany; add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED); @@ -3684,14 +3708,13 @@ doset() */ for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) { opt_indx = pick_list[pick_idx].item.a_int - 1; - if (opt_indx == -2) { - /* -2 due to -1 offset for select_menu() */ + if (opt_indx < -1) opt_indx++; /* -1 offset for select_menu() */ + if (opt_indx == OPT_OTHER_APEXC) { (void) special_handling("autopickup_exception", setinitial, fromfile); #ifdef STATUS_VIA_WINDOWPORT #ifdef STATUS_HILITES - } else if (opt_indx == -3) { - /* -3 due to -1 offset for select_menu() */ + } else if (opt_indx == OPT_OTHER_STATHILITE) { if (!status_hilite_menu()) { pline("Bad status hilite(s) specified."); } else { @@ -3700,10 +3723,10 @@ doset() } #endif #endif - } else if (opt_indx == -4) { + } else if (opt_indx == OPT_OTHER_MENUCOLOR) { (void) special_handling("menucolors", setinitial, fromfile); - } else if (opt_indx == -5) { + } else if (opt_indx == OPT_OTHER_MSGTYPE) { (void) special_handling("msgtype", setinitial, fromfile); } else if (opt_indx < boolcount) { /* boolean option */ diff --git a/src/shk.c b/src/shk.c index c8123b74a..ca3893b1f 100644 --- a/src/shk.c +++ b/src/shk.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 shk.c $NHDT-Date: 1450604649 2015/12/20 09:44:09 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.117 $ */ +/* NetHack 3.6 shk.c $NHDT-Date: 1451838768 2016/01/03 16:32:48 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.119 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -759,13 +759,26 @@ register char rmno; rmno >= ROOMOFFSET ? rooms[rmno - ROOMOFFSET].resident : 0; if (shkp) { - if (NOTANGRY(shkp)) { - if (ESHK(shkp)->surcharge) - pacify_shk(shkp); + if (has_eshk(shkp)) { + if (NOTANGRY(shkp)) { + if (ESHK(shkp)->surcharge) + pacify_shk(shkp); + } else { + if (!ESHK(shkp)->surcharge) + rile_shk(shkp); + } } else { - if (!ESHK(shkp)->surcharge) - rile_shk(shkp); - } + /* would have segfaulted on ESHK dereference previously */ + impossible( + "shopkeeper career change? (rmno=%d, ROOMOFFSET=%d, mnum=%d, %s)", + (int)rmno, ROOMOFFSET, shkp->mnum, + has_mname(shkp) ? MNAME(shkp) : "anonymous" + ); + + /* not sure if this is appropriate, because it does nothing to + correct the underlying rooms[].resident issue but... */ + return (struct monst *)0; + } } return shkp; } diff --git a/src/zap.c b/src/zap.c index 26ddd757d..677921c2e 100644 --- a/src/zap.c +++ b/src/zap.c @@ -152,6 +152,8 @@ struct obj *otmp; /* fall through */ case SPE_FORCE_BOLT: reveal_invis = TRUE; + if (disguised_mimic) + seemimic(mtmp); if (resists_magm(mtmp)) { /* match effect on player */ shieldeff(mtmp->mx, mtmp->my); pline("Boing!"); @@ -171,6 +173,8 @@ struct obj *otmp; case WAN_SLOW_MONSTER: case SPE_SLOW_MONSTER: if (!resist(mtmp, otmp->oclass, 0, NOTELL)) { + if (disguised_mimic) + seemimic(mtmp); mon_adjust_speed(mtmp, -1, otmp); m_dowear(mtmp, FALSE); /* might want speed boots */ if (u.uswallow && (mtmp == u.ustuck) && is_whirly(mtmp->data)) { @@ -182,6 +186,8 @@ struct obj *otmp; break; case WAN_SPEED_MONSTER: if (!resist(mtmp, otmp->oclass, 0, NOTELL)) { + if (disguised_mimic) + seemimic(mtmp); mon_adjust_speed(mtmp, 1, otmp); m_dowear(mtmp, FALSE); /* might want speed boots */ } @@ -239,16 +245,22 @@ struct obj *otmp; break; case WAN_CANCELLATION: case SPE_CANCELLATION: + if (disguised_mimic) + seemimic(mtmp); (void) cancel_monst(mtmp, otmp, TRUE, TRUE, FALSE); break; case WAN_TELEPORTATION: case SPE_TELEPORT_AWAY: + if (disguised_mimic) + seemimic(mtmp); reveal_invis = !u_teleport_mon(mtmp, TRUE); break; case WAN_MAKE_INVISIBLE: { int oldinvis = mtmp->minvis; char nambuf[BUFSZ]; + if (disguised_mimic) + seemimic(mtmp); /* format monster's name before altering its visibility */ Strcpy(nambuf, Monnam(mtmp)); mon_set_minvis(mtmp); @@ -368,6 +380,8 @@ struct obj *otmp; wake = FALSE; break; case SPE_DRAIN_LIFE: + if (disguised_mimic) + seemimic(mtmp); dmg = monhp_per_lvl(mtmp); if (dbldam) dmg *= 2;