diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 2f183811c..02bc07509 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,7 +1,9 @@ -$NHDT-Branch: master $:$NHDT-Revision: 1.2 $ $NHDT-Date: 1524945860 2018/04/28 20:04:20 $ +$NHDT-Branch: master $:$NHDT-Revision: 1.3 $ $NHDT-Date: 1525012578 2018/04/29 14:36:18 $ General Fixes and Modified Features ----------------------------------- +since return capability is purported to be because of an implicit + tether on the aklys, integrate that into display features Fixes to Post-3.7.0 Problems that Were Exposed Via git Repository diff --git a/include/display.h b/include/display.h index 4bd8cf924..a07b53634 100644 --- a/include/display.h +++ b/include/display.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 display.h $NHDT-Date: 1447729027 2015/11/17 02:57:07 $ $NHDT-Branch: master $:$NHDT-Revision: 1.26 $ */ +/* NetHack 3.6 display.h $NHDT-Date: 1525012585 2018/04/29 14:36:25 $ $NHDT-Branch: master $:$NHDT-Revision: 1.28 $ */ /* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */ /* and Dave Cohrs, 1990. */ /* NetHack may be freely redistributed. See license for details. */ @@ -179,14 +179,16 @@ */ #define DISP_BEAM (-1) /* Keep all glyphs showing & clean up at end. */ #define DISP_ALL (-2) /* Like beam, but still displayed if not visible. */ -#define DISP_FLASH (-3) /* Clean up each glyph before displaying new one. */ -#define DISP_ALWAYS (-4) /* Like flash, but still displayed if not visible. */ -#define DISP_CHANGE (-5) /* Change glyph. */ -#define DISP_END (-6) /* Clean up. */ -#define DISP_FREEMEM (-7) /* Free all memory during exit only. */ +#define DISP_TETHER (-3) /* Like beam, but tether glyph differs from final */ +#define DISP_FLASH (-4) /* Clean up each glyph before displaying new one. */ +#define DISP_ALWAYS (-5) /* Like flash, but still displayed if not visible. */ +#define DISP_CHANGE (-6) /* Change glyph. */ +#define DISP_END (-7) /* Clean up. */ +#define DISP_FREEMEM (-8) /* Free all memory during exit only. */ /* Total number of cmap indices in the shield_static[] array. */ #define SHIELD_COUNT 21 +#define BACKTRACK (-1) /* flag for DISP_END to display each prior location */ /* * display_self() diff --git a/include/extern.h b/include/extern.h index e8d850875..be57ba71d 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1518053385 2018/02/08 01:29:45 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.625 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1525012590 2018/04/29 14:36:30 $ $NHDT-Branch: master $:$NHDT-Revision: 1.629 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2879,7 +2879,8 @@ E int FDECL(spell_damage_bonus, (int)); E const char *FDECL(exclam, (int force)); E void FDECL(hit, (const char *, struct monst *, const char *)); E void FDECL(miss, (const char *, struct monst *)); -E struct monst *FDECL(bhit, (int, int, int, int, int (*)(MONST_P, OBJ_P), +E struct monst *FDECL(bhit, (int, int, int, enum bhit_call_types, + int (*)(MONST_P, OBJ_P), int (*)(OBJ_P, OBJ_P), struct obj **)); E struct monst *FDECL(boomhit, (struct obj *, int, int)); E int FDECL(zhitm, (struct monst *, int, int, struct obj **)); diff --git a/include/hack.h b/include/hack.h index af35c2c00..7d493e962 100644 --- a/include/hack.h +++ b/include/hack.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 hack.h $NHDT-Date: 1490908464 2017/03/30 21:14:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.76 $ */ +/* NetHack 3.6 hack.h $NHDT-Date: 1525012595 2018/04/29 14:36:35 $ $NHDT-Branch: master $:$NHDT-Revision: 1.82 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Pasi Kallinen, 2017. */ /* NetHack may be freely redistributed. See license for details. */ @@ -175,6 +175,7 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */ enum bhit_call_types { ZAPPED_WAND = 0, THROWN_WEAPON, + THROWN_TETHERED_WEAPON, KICKED_WEAPON, FLASHED_LIGHT, INVIS_BEAM diff --git a/src/display.c b/src/display.c index 5c98c8a99..2d3a272a7 100644 --- a/src/display.c +++ b/src/display.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 display.c $NHDT-Date: 1524780381 2018/04/26 22:06:21 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.90 $ */ +/* NetHack 3.6 display.c $NHDT-Date: 1525012604 2018/04/29 14:36:44 $ $NHDT-Branch: master $:$NHDT-Revision: 1.91 $ */ /* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */ /* and Dave Cohrs, 1990. */ /* NetHack may be freely redistributed. See license for details. */ @@ -892,6 +892,15 @@ xchar x, y; } } +int +tether_glyph(x, y) +{ + int tdx, tdy; + tdx = u.ux - x; + tdy = u.uy - y; + return zapdir_to_glyph(sgn(tdx),sgn(tdy), 2); +} + /* * tmp_at() * @@ -912,6 +921,9 @@ xchar x, y; * * DISP_BEAM - Display the given glyph at each location, but do not erase * any until the close call. + * DISP_TETHER- Display a tether glyph at each location, and the tethered + * object at the farthest location, but do not erase any + * until the return trip or close. * DISP_FLASH - Display the given glyph at each location, but erase the * previous location's glyph. * DISP_ALWAYS- Like DISP_FLASH, but vision is not taken into account. @@ -937,6 +949,7 @@ int x, y; switch (x) { case DISP_BEAM: case DISP_ALL: + case DISP_TETHER: case DISP_FLASH: case DISP_ALWAYS: if (!tglyph) @@ -979,6 +992,22 @@ int x, y; /* Erase (reset) from source to end */ for (i = 0; i < tglyph->sidx; i++) newsym(tglyph->saved[i].x, tglyph->saved[i].y); + } else if (tglyph->style == DISP_TETHER) { + int i; + + if (y == BACKTRACK && tglyph->sidx > 1) { + /* backtrack */ + for (i = tglyph->sidx - 1; i > 0; i--) { + newsym(tglyph->saved[i].x, tglyph->saved[i].y); + show_glyph(tglyph->saved[i - 1].x, + tglyph->saved[i - 1].y, tglyph->glyph); + flush_screen(0); /* make sure it shows up */ + delay_output(); + } + tglyph->sidx = 1; + } + for (i = 0; i < tglyph->sidx; i++) + newsym(tglyph->saved[i].x, tglyph->saved[i].y); } else { /* DISP_FLASH or DISP_ALWAYS */ if (tglyph->sidx) /* been called at least once */ newsym(tglyph->saved[0].x, tglyph->saved[0].y); @@ -1002,6 +1031,20 @@ int x, y; tglyph->saved[tglyph->sidx].x = x; tglyph->saved[tglyph->sidx].y = y; tglyph->sidx += 1; + } else if (tglyph->style == DISP_TETHER) { + if (tglyph->sidx >= TMP_AT_MAX_GLYPHS) + break; /* too many locations */ + if (tglyph->sidx) { + int px, py; + + px = tglyph->saved[tglyph->sidx-1].x; + py = tglyph->saved[tglyph->sidx-1].y; + show_glyph(px, py, tether_glyph(px, py)); + } + /* save pos for later use or erasure */ + tglyph->saved[tglyph->sidx].x = x; + tglyph->saved[tglyph->sidx].y = y; + tglyph->sidx += 1; } else { /* DISP_FLASH/ALWAYS */ if (tglyph->sidx) { /* not first call, so reset previous pos */ newsym(tglyph->saved[0].x, tglyph->saved[0].y); diff --git a/src/dothrow.c b/src/dothrow.c index 246a0d51b..81487a5b6 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 dothrow.c $NHDT-Date: 1522967321 2018/04/05 22:28:41 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.135 $ */ +/* NetHack 3.6 dothrow.c $NHDT-Date: 1525012611 2018/04/29 14:36:51 $ $NHDT-Branch: master $:$NHDT-Revision: 1.137 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1082,6 +1082,7 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ register int range, urange; boolean crossbowing, impaired = (Confusion || Stunned || Blind || Hallucination || Fumbling); + boolean tethered_weapon = (obj->otyp == AKLYS && (wep_mask & W_WEP) != 0); notonhead = FALSE; /* reset potentially stale value */ if ((obj->cursed || obj->greased) && (u.dx || u.dy) && !rn2(7)) { @@ -1131,8 +1132,7 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ if (u.dz < 0 /* Mjollnir must we wielded to be thrown--caller verifies this; aklys must we wielded as primary to return when thrown */ - && ((Role_if(PM_VALKYRIE) && obj->oartifact == ART_MJOLLNIR) - || (obj->otyp == AKLYS && (wep_mask & W_WEP) != 0)) + && ((Role_if(PM_VALKYRIE) && obj->oartifact == ART_MJOLLNIR) || tethered_weapon) && !impaired) { pline("%s the %s and returns to your hand!", Tobjnam(obj, "hit"), ceiling(u.ux, u.uy)); @@ -1217,7 +1217,7 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ range = 20; /* you must be giant */ else if (obj->oartifact == ART_MJOLLNIR) range = (range + 1) / 2; /* it's heavy */ - else if (obj->otyp == AKLYS && (wep_mask & W_WEP) != 0) + else if (tethered_weapon) /* primary weapon is aklys */ /* if an aklys is going to return, range is limited by the length of the attached cord [implicit aspect of item] */ range = min(range, BOLT_LIM / 2); @@ -1227,7 +1227,8 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ if (Underwater) range = 1; - mon = bhit(u.dx, u.dy, range, THROWN_WEAPON, + mon = bhit(u.dx, u.dy, range, + tethered_weapon ? THROWN_TETHERED_WEAPON : THROWN_WEAPON, (int FDECL((*), (MONST_P, OBJ_P))) 0, (int FDECL((*), (OBJ_P, OBJ_P))) 0, &obj); thrownobj = obj; /* obj may be null now */ @@ -1236,8 +1237,14 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ if (Is_airlevel(&u.uz) || Levitation) hurtle(-u.dx, -u.dy, urange, TRUE); - if (!obj) + if (!obj) { + /* bhit display cleanup was left with this caller + for tethered_weapon, but clean it up now since + we're about to return */ + if (tethered_weapon) + tmp_at(DISP_END, 0); return; + } } if (mon) { @@ -1264,8 +1271,11 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ } if (!thrownobj) { - ; /* missile has already been handled */ + /* missile has already been handled */ + if (tethered_weapon) tmp_at(DISP_END, 0); } else if (u.uswallow) { + if (tethered_weapon) + tmp_at(DISP_END, 0); /* ball is not picked up by monster */ if (obj != uball) (void) mpickobj(u.ustuck, obj); @@ -1274,9 +1284,12 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ /* Mjollnir must we wielded to be thrown--caller verifies this; aklys must we wielded as primary to return when thrown */ if ((obj->oartifact == ART_MJOLLNIR && Role_if(PM_VALKYRIE)) - || (obj->otyp == AKLYS && (wep_mask & W_WEP) != 0)) { + || tethered_weapon) { if (rn2(100)) { - sho_obj_return_to_u(obj); /* display its flight */ + if (tethered_weapon) + tmp_at(DISP_END, BACKTRACK); + else + sho_obj_return_to_u(obj); /* display its flight */ if (!impaired && rn2(100)) { pline("%s to your hand!", Tobjnam(obj, "return")); @@ -1320,6 +1333,7 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ thrownobj = (struct obj *) 0; return; } else { + if (tethered_weapon) tmp_at(DISP_END, 0); /* when this location is stepped on, the weapon will be auto-picked up due to 'obj->was_thrown' of 1; addinv() prevents thrown Mjollnir from being placed diff --git a/src/objnam.c b/src/objnam.c index 12bba3c61..b836530b5 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 objnam.c $NHDT-Date: 1521507553 2018/03/20 00:59:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.199 $ */ +/* NetHack 3.6 objnam.c $NHDT-Date: 1525012618 2018/04/29 14:36:58 $ $NHDT-Branch: master $:$NHDT-Revision: 1.202 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1146,7 +1146,8 @@ unsigned doname_flags; if (bimanual(obj)) hand_s = makeplural(hand_s); - Sprintf(eos(bp), " (weapon in %s)", hand_s); + Sprintf(eos(bp), " (%sweapon in %s)", + (obj->otyp == AKLYS) ? "tethered " : "", hand_s); if (warn_obj_cnt && obj == uwep && (EWarn_of_mon & W_WEP) != 0L) { /* presumably can be felt when blind */ diff --git a/src/wield.c b/src/wield.c index 96ec1d40b..c45282a14 100644 --- a/src/wield.c +++ b/src/wield.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 wield.c $NHDT-Date: 1496959480 2017/06/08 22:04:40 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.54 $ */ +/* NetHack 3.6 wield.c $NHDT-Date: 1525012623 2018/04/29 14:37:03 $ $NHDT-Branch: master $:$NHDT-Revision: 1.56 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2009. */ /* NetHack may be freely redistributed. See license for details. */ @@ -187,6 +187,8 @@ struct obj *wep; long dummy = wep->owornmask; wep->owornmask |= W_WEP; + if (wep->otyp == AKLYS && (wep->owornmask & W_WEP) != 0) + You("secure the tether."); prinv((char *) 0, wep, 0L); wep->owornmask = dummy; } diff --git a/src/zap.c b/src/zap.c index 5750b276e..aa902d70c 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 zap.c $NHDT-Date: 1524470244 2018/04/23 07:57:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.275 $ */ +/* NetHack 3.6 zap.c $NHDT-Date: 1525012627 2018/04/29 14:37:07 $ $NHDT-Branch: master $:$NHDT-Revision: 1.277 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -3107,7 +3107,7 @@ int range, *skipstart, *skipend; struct monst * bhit(ddx, ddy, range, weapon, fhitm, fhito, pobj) register int ddx, ddy, range; /* direction and range */ -int weapon; /* see values in hack.h */ +enum bhit_call_types weapon; /* defined in hack.h */ int FDECL((*fhitm), (MONST_P, OBJ_P)), /* fns called when mon/obj hit */ FDECL((*fhito), (OBJ_P, OBJ_P)); struct obj **pobj; /* object tossed/used, set to NULL @@ -3118,6 +3118,7 @@ struct obj **pobj; /* object tossed/used, set to NULL uchar typ; boolean shopdoor = FALSE, point_blank = TRUE; boolean in_skip = FALSE, allow_skip = FALSE; + boolean tethered_weapon = FALSE; int skiprange_start = 0, skiprange_end = 0, skipcount = 0; if (weapon == KICKED_WEAPON) { @@ -3137,6 +3138,10 @@ struct obj **pobj; /* object tossed/used, set to NULL if (weapon == FLASHED_LIGHT) { tmp_at(DISP_BEAM, cmap_to_glyph(S_flashbeam)); + } else if (weapon == THROWN_TETHERED_WEAPON && obj) { + tethered_weapon = TRUE; + weapon = THROWN_WEAPON; /* simplify if's that follow below */ + tmp_at(DISP_TETHER, obj_to_glyph(obj)); } else if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM) tmp_at(DISP_FLASH, obj_to_glyph(obj)); @@ -3262,8 +3267,11 @@ struct obj **pobj; /* object tossed/used, set to NULL if (!mtmp->minvis || perceives(mtmp->data)) return mtmp; } else if (weapon != ZAPPED_WAND) { + /* THROWN_WEAPON, KICKED_WEAPON */ - tmp_at(DISP_END, 0); + if (!tethered_weapon) + tmp_at(DISP_END, 0); + if (cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp)) map_invisible(bhitpos.x, bhitpos.y); return mtmp; @@ -3367,7 +3375,7 @@ struct obj **pobj; /* object tossed/used, set to NULL point_blank = FALSE; /* affects passing through iron bars */ } - if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM) + if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM && !tethered_weapon) tmp_at(DISP_END, 0); if (shopdoor)