Merge branch 'NetHack-3.6'

This commit is contained in:
nhmall
2019-05-30 18:10:41 -04:00
6 changed files with 107 additions and 85 deletions

View File

@@ -1,4 +1,4 @@
$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.26 $ $NHDT-Date: 1559088523 2019/05/29 00:08:43 $
$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.27 $ $NHDT-Date: 1559130050 2019/05/29 11:40:50 $
This fixes36.3 file is here to capture information about updates in the 3.6.x
lineage following the release of 3.6.2 in May 2019. Please note, however,
@@ -32,6 +32,7 @@ if hero dies while a thrown or kicked object is in transit, put that object
on the map in case bones data gets saved
fix a memory leak that occurred if player used wizard mode to leave and return
to the Plane of Air or Plane of Water (not possible in normal play)
free sortloot data if object handling is short-circuited by cockatrice corpse
Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 hack.h $NHDT-Date: 1549327459 2019/02/05 00:44:19 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.102 $ */
/* NetHack 3.6 hack.h $NHDT-Date: 1559227823 2019/05/30 14:50:23 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.105 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Pasi Kallinen, 2017. */
/* NetHack may be freely redistributed. See license for details. */
@@ -17,10 +17,7 @@
#define OFF 0
#define BOLT_LIM 8 /* from this distance ranged attacks will be made */
#define MAX_CARR_CAP 1000 /* so that boulders can be heavier */
#define DUMMY \
{ \
0 \
}
#define DUMMY { 0 } /* array initializer, letting [1..N-1] default */
/* The UNDEFINED macros are used to initialize variables whose
initialized value is not relied upon.
@@ -278,24 +275,25 @@ typedef struct sortloot_item Loot;
#include "extern.h"
#endif /* USE_TRAMPOLI */
/* flags to control makemon() */
/* flags to control makemon(); goodpos() uses some plus has some of its own */
#define NO_MM_FLAGS 0x00000 /* use this rather than plain 0 */
#define NO_MINVENT 0x00001 /* suppress minvent when creating mon */
#define MM_NOWAIT 0x00002 /* don't set STRAT_WAITMASK flags */
#define MM_NOCOUNTBIRTH \
0x00004 /* don't increment born counter (for revival) */
#define MM_IGNOREWATER 0x00008 /* ignore water when positioning */
#define MM_ADJACENTOK \
0x00010 /* it is acceptable to use adjacent coordinates */
#define MM_ANGRY 0x00020 /* monster is created angry */
#define MM_NONAME 0x00040 /* monster is not christened */
#define MM_EGD 0x00100 /* add egd structure */
#define MM_EPRI 0x00200 /* add epri structure */
#define MM_ESHK 0x00400 /* add eshk structure */
#define MM_EMIN 0x00800 /* add emin structure */
#define MM_EDOG 0x01000 /* add edog structure */
#define MM_ASLEEP 0x02000 /* monsters should be generated asleep */
#define MM_NOGRP 0x04000 /* suppress creation of monster groups */
#define NO_MINVENT 0x00001 /* suppress minvent when creating mon */
#define MM_NOWAIT 0x00002 /* don't set STRAT_WAITMASK flags */
#define MM_NOCOUNTBIRTH 0x00004 /* don't increment born count (for revival) */
#define MM_IGNOREWATER 0x00008 /* ignore water when positioning */
#define MM_ADJACENTOK 0x00010 /* acceptable to use adjacent coordinates */
#define MM_ANGRY 0x00020 /* monster is created angry */
#define MM_NONAME 0x00040 /* monster is not christened */
#define MM_EGD 0x00100 /* add egd structure */
#define MM_EPRI 0x00200 /* add epri structure */
#define MM_ESHK 0x00400 /* add eshk structure */
#define MM_EMIN 0x00800 /* add emin structure */
#define MM_EDOG 0x01000 /* add edog structure */
#define MM_ASLEEP 0x02000 /* monsters should be generated asleep */
#define MM_NOGRP 0x04000 /* suppress creation of monster groups */
/* if more MM_ flag masks are added, skip or renumber the GP_ one(s) */
#define GP_ALLOW_XY 0x08000 /* [actually used by enexto() to decide whether
* to make an extra call to goodpos()] */
/* flags for make_corpse() and mkcorpstat() */
#define CORPSTAT_NONE 0x00
@@ -327,27 +325,27 @@ typedef struct sortloot_item Loot;
#define ALL_FINISHED 0x01 /* called routine already finished the job */
/* flags to control query_objlist() */
#define BY_NEXTHERE 0x1 /* follow objlist by nexthere field */
#define AUTOSELECT_SINGLE 0x2 /* if only 1 object, don't ask */
#define USE_INVLET 0x4 /* use object's invlet */
#define INVORDER_SORT 0x8 /* sort objects by packorder */
#define SIGNAL_NOMENU 0x10 /* return -1 rather than 0 if none allowed */
#define SIGNAL_ESCAPE 0x20 /* return -2 rather than 0 for ESC */
#define FEEL_COCKATRICE 0x40 /* engage cockatrice checks and react */
#define INCLUDE_HERO 0x80 /* show hero among engulfer's inventory */
#define BY_NEXTHERE 0x01 /* follow objlist by nexthere field */
#define AUTOSELECT_SINGLE 0x02 /* if only 1 object, don't ask */
#define USE_INVLET 0x04 /* use object's invlet */
#define INVORDER_SORT 0x08 /* sort objects by packorder */
#define SIGNAL_NOMENU 0x10 /* return -1 rather than 0 if none allowed */
#define SIGNAL_ESCAPE 0x20 /* return -2 rather than 0 for ESC */
#define FEEL_COCKATRICE 0x40 /* engage cockatrice checks and react */
#define INCLUDE_HERO 0x80 /* show hero among engulfer's inventory */
/* Flags to control query_category() */
/* BY_NEXTHERE used by query_category() too, so skip 0x01 */
#define UNPAID_TYPES 0x02
#define GOLD_TYPES 0x04
#define WORN_TYPES 0x08
#define ALL_TYPES 0x10
#define BILLED_TYPES 0x20
#define CHOOSE_ALL 0x40
#define BUC_BLESSED 0x80
#define BUC_CURSED 0x100
#define UNPAID_TYPES 0x002
#define GOLD_TYPES 0x004
#define WORN_TYPES 0x008
#define ALL_TYPES 0x010
#define BILLED_TYPES 0x020
#define CHOOSE_ALL 0x040
#define BUC_BLESSED 0x080
#define BUC_CURSED 0x100
#define BUC_UNCURSED 0x200
#define BUC_UNKNOWN 0x400
#define BUC_UNKNOWN 0x400
#define BUC_ALLBKNOWN (BUC_BLESSED | BUC_CURSED | BUC_UNCURSED)
#define BUCX_TYPES (BUC_ALLBKNOWN | BUC_UNKNOWN)
#define ALL_TYPES_SELECTED -2

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 mkmaze.c $NHDT-Date: 1559088524 2019/05/29 00:08:44 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.71 $ */
/* NetHack 3.6 mkmaze.c $NHDT-Date: 1559227829 2019/05/30 14:50:29 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.72 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Pasi Kallinen, 2018. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1848,6 +1848,7 @@ boolean ini;
for (olist = (struct obj *) cons->list; olist; olist = otmp) {
otmp = olist->nexthere;
place_object(olist, cons->x, cons->y);
stackobj(olist);
}
break;
}
@@ -1855,7 +1856,12 @@ boolean ini;
case CONS_MON: {
struct monst *mon = (struct monst *) cons->list;
(void) mnearto(mon, cons->x, cons->y, TRUE);
/* mnearto() might fail, and putting the monster into limbo
to try next time hero comes to this level makes no sense
because we can't leave and return (outside wizard mode) */
if (!mnearto(mon, cons->x, cons->y, TRUE)) {
; /* ? */
}
break;
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 mon.c $NHDT-Date: 1556139724 2019/04/24 21:02:04 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.284 $ */
/* NetHack 3.6 mon.c $NHDT-Date: 1559227828 2019/05/30 14:50:28 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.286 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
@@ -2593,12 +2593,11 @@ struct monst *mtmp;
return;
}
if (!enexto(&mm, u.ux, u.uy, mtmp->data)) {
if (!enexto(&mm, u.ux, u.uy, mtmp->data) || !isok(mm.x, mm.y)) {
debugpline1("mnexto: sending %s into limbo", m_monnam(mtmp));
m_into_limbo(mtmp);
return;
}
if (!isok(mm.x, mm.y))
return;
rloc_to(mtmp, mm.x, mm.y);
if (!g.in_mklev && (mtmp->mstrategy & STRAT_APPEARMSG)) {
mtmp->mstrategy &= ~STRAT_APPEARMSG; /* one chance only */
@@ -2672,9 +2671,7 @@ boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
* Migrating_mons that need to be placed will cause
* no end of trouble.
*/
if (!enexto(&mm, newx, newy, mtmp->data))
return 0;
if (!isok(mm.x, mm.y))
if (!enexto(&mm, newx, newy, mtmp->data) || !isok(mm.x, mm.y))
return 0;
newx = mm.x;
newy = mm.y;
@@ -2683,8 +2680,10 @@ boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
if (move_other && othermon) {
res = 2; /* moving another monster out of the way */
if (!mnearto(othermon, x, y, FALSE)) /* no 'move_other' this time */
if (!mnearto(othermon, x, y, FALSE)) { /* no 'move_other' this time */
debugpline1("mnearto: sending %s into limbo", m_monnam(othermon));
m_into_limbo(othermon);
}
}
return res;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 pickup.c $NHDT-Date: 1545785547 2018/12/26 00:52:27 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.222 $ */
/* NetHack 3.6 pickup.c $NHDT-Date: 1559130050 2019/05/29 11:40:50 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.226 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -182,7 +182,7 @@ int *menu_on_demand;
const char *where = 0;
char sym, oc_of_sym, *p;
ask_again:
ask_again:
oclasses[oclassct = 0] = '\0';
*one_at_a_time = *everything = FALSE;
not_everything = filtered = FALSE;
@@ -574,7 +574,7 @@ int what; /* should be a long */
&pick_list, PICK_ANY, all_but_uchain);
}
menu_pickup:
menu_pickup:
n_tried = n;
for (n_picked = i = 0; i < n; i++) {
res = pickup_object(pick_list[i].item.a_obj, pick_list[i].count,
@@ -678,7 +678,7 @@ int what; /* should be a long */
break;
n_picked += res;
}
end_query:
end_query:
; /* statement required after label */
}
@@ -887,6 +887,7 @@ boolean FDECL((*allow), (OBJ_P)); /* allow function */
&& will_feel_cockatrice(curr, FALSE)) {
destroy_nhwindow(win); /* stop the menu and revert */
(void) look_here(0, FALSE);
unsortloot(&sortedolist);
return 0;
}
if ((*allow)(curr)) {
@@ -1925,8 +1926,7 @@ reverse_loot()
if (g_at(x, y))
pline("Ok, now there is loot here.");
} else {
/* find original coffers chest if present, otherwise use nearest one
*/
/* find original coffers chest if present, otherwise use nearest one */
otmp = 0;
for (coffers = fobj; coffers; coffers = coffers->nobj)
if (coffers->otyp == CHEST) {
@@ -2556,7 +2556,7 @@ boolean more_containers; /* True iff #loot multiple and this isn't last one */
* or
* <The/Your/Shk's container> is empty. Do what with it? [:irs nq or ?]
*/
for (;;) { /* repeats iff '?' or ":' gets chosen */
for (;;) { /* repeats iff '?' or ':' gets chosen */
outmaybe = (outokay || !g.current_container->cknown);
if (!outmaybe)
(void) safe_qbuf(qbuf, (char *) 0, " is empty. Do what with it?",
@@ -2684,7 +2684,7 @@ boolean more_containers; /* True iff #loot multiple and this isn't last one */
}
}
containerdone:
containerdone:
if (used) {
/* Not completely correct; if we put something in without knowing
whatever was already inside, now we suddenly do. That can't

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 teleport.c $NHDT-Date: 1553885439 2019/03/29 18:50:39 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.86 $ */
/* NetHack 3.6 teleport.c $NHDT-Date: 1559227830 2019/05/30 14:50:30 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.87 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
@@ -36,7 +36,8 @@ unsigned gpflags;
* which could be co-located and thus get restricted a bit too much.
* oh well.
*/
if (mtmp != &g.youmonst && x == u.ux && y == u.uy
if (x == u.ux && y == u.uy
&& mtmp != &g.youmonst && (mtmp != u.ustuck || !u.uswallow)
&& (!u.usteed || mtmp != u.usteed))
return FALSE;
@@ -105,22 +106,24 @@ coord *cc;
register xchar xx, yy;
struct permonst *mdat;
{
return enexto_core(cc, xx, yy, mdat, 0);
return enexto_core(cc, xx, yy, mdat, NO_MM_FLAGS);
}
boolean
enexto_core(cc, xx, yy, mdat, entflags)
coord *cc;
register xchar xx, yy;
xchar xx, yy;
struct permonst *mdat;
unsigned entflags;
{
#define MAX_GOOD 15
coord good[MAX_GOOD], *good_ptr;
int x, y, range, i;
int xmin, xmax, ymin, ymax;
int xmin, xmax, ymin, ymax, rangemax;
struct monst fakemon; /* dummy monster */
boolean allow_xx_yy = (boolean) ((entflags & GP_ALLOW_XY) != 0);
entflags &= ~GP_ALLOW_XY;
if (!mdat) {
debugpline0("enexto() called with null mdat");
/* default to player's original monster type */
@@ -129,6 +132,13 @@ unsigned entflags;
fakemon = cg.zeromonst;
set_mon_data(&fakemon, mdat); /* set up for goodpos */
/* used to use 'if (range > ROWNO && range > COLNO) return FALSE' below,
so effectively 'max(ROWNO, COLNO)' which performs useless iterations
(possibly many iterations if <xx,yy> is in the center of the map) */
xmax = max(xx - 1, (COLNO - 1) - xx);
ymax = max(yy - 0, (ROWNO - 1) - yy);
rangemax = max(xmax, ymax);
/* setup: no suitable spots yet, first iteration checks adjacent spots */
good_ptr = good;
range = 1;
/*
@@ -141,7 +151,7 @@ unsigned entflags;
ymin = max(0, yy - range);
ymax = min(ROWNO - 1, yy + range);
for (x = xmin; x <= xmax; x++)
for (x = xmin; x <= xmax; x++) {
if (goodpos(x, ymin, &fakemon, entflags)) {
good_ptr->x = x;
good_ptr->y = ymin;
@@ -149,38 +159,46 @@ unsigned entflags;
if (good_ptr++ == &good[MAX_GOOD - 1])
goto full;
}
for (x = xmin; x <= xmax; x++)
if (goodpos(x, ymax, &fakemon, entflags)) {
good_ptr->x = x;
good_ptr->y = ymax;
/* beware of accessing beyond segment boundaries.. */
if (good_ptr++ == &good[MAX_GOOD - 1])
goto full;
}
for (y = ymin + 1; y < ymax; y++)
}
/* 3.6.3: this used to use 'ymin+1' which left top row unchecked */
for (y = ymin; y < ymax; y++) {
if (goodpos(xmin, y, &fakemon, entflags)) {
good_ptr->x = xmin;
good_ptr->y = y;
/* beware of accessing beyond segment boundaries.. */
if (good_ptr++ == &good[MAX_GOOD - 1])
goto full;
}
for (y = ymin + 1; y < ymax; y++)
if (goodpos(xmax, y, &fakemon, entflags)) {
good_ptr->x = xmax;
good_ptr->y = y;
/* beware of accessing beyond segment boundaries.. */
if (good_ptr++ == &good[MAX_GOOD - 1])
goto full;
}
range++;
}
} while (++range <= rangemax && good_ptr == good);
/* return if we've grown too big (nothing is valid) */
if (range > ROWNO && range > COLNO)
/* return False if we exhausted 'range' without finding anything */
if (good_ptr == good) {
/* 3.6.3: earlier versions didn't have the option to try <xx,yy>,
and left 'cc' uninitialized when returning False */
cc->x = xx, cc->y = yy;
/* if every spot other than <xx,yy> has failed, try <xx,yy> itself */
if (allow_xx_yy && goodpos(xx, yy, &fakemon, entflags)) {
return TRUE; /* 'cc' is set */
} else {
debugpline3("enexto(\"%s\",%d,%d) failed", mdat->mname, xx, yy);
return FALSE;
} while (good_ptr == good);
}
}
full:
full:
/* we've got between 1 and SIZE(good) candidates; choose one */
i = rn2((int) (good_ptr - good));
cc->x = good[i].x;
cc->y = good[i].y;
@@ -423,7 +441,7 @@ boolean force_it;
return FALSE;
} else {
Your("leash goes slack.");
release_it:
release_it:
m_unleash(mtmp, FALSE);
return TRUE;
}
@@ -792,7 +810,7 @@ level_tele()
schar destlev;
xchar destdnum;
levTport_menu:
levTport_menu:
destlev = 0;
destdnum = 0;
newlev = (int) print_dungeon(TRUE, &destlev, &destdnum);
@@ -860,7 +878,7 @@ level_tele()
if (In_quest(&u.uz) && newlev > 0)
newlev = newlev + g.dungeons[u.uz.dnum].depth_start - 1;
} else { /* involuntary level tele */
random_levtport:
random_levtport:
newlev = random_teleport_level();
if (newlev == depth(&u.uz)) {
You1(shudder_for_moment);
@@ -1143,7 +1161,7 @@ register int x, y;
register int oldx = mtmp->mx, oldy = mtmp->my;
boolean resident_shk = mtmp->isshk && inhishop(mtmp);
if (x == mtmp->mx && y == mtmp->my && m_at(x,y) == mtmp)
if (x == mtmp->mx && y == mtmp->my && m_at(x, y) == mtmp)
return; /* that was easy */
if (oldx) { /* "pick up" monster */
@@ -1164,11 +1182,11 @@ register int x, y;
if (u.ustuck == mtmp) {
if (u.uswallow) {
u.ux = x;
u.uy = y;
u_on_newpos(mtmp->mx, mtmp->my);
docrt();
} else
u.ustuck = 0;
} else if (distu(mtmp->mx, mtmp->my) > 2) {
unstuck(mtmp);
}
}
newsym(x, y); /* update new location */
@@ -1229,7 +1247,7 @@ boolean suppress_impossible;
impossible("rloc(): couldn't relocate monster");
return FALSE;
found_xy:
found_xy:
rloc_to(mtmp, x, y);
return TRUE;
}
@@ -1238,7 +1256,7 @@ STATIC_OVL void
mvault_tele(mtmp)
struct monst *mtmp;
{
register struct mkroom *croom = search_special(VAULT);
struct mkroom *croom = search_special(VAULT);
coord c;
if (croom && somexy(croom, &c) && goodpos(c.x, c.y, mtmp, 0)) {