Merge branch 'NetHack-3.6.2'
This commit is contained in:
14
src/.gitattributes
vendored
Normal file
14
src/.gitattributes
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
* NH_filestag=(file%s_for_all_versions)
|
||||
..files NH_filegenerated=Makefile,Makefile.bcc,Makefile.gcc,qt_kde0.moc,qt_win.moc,qttableview.moc,tile.c,monstr.c,vis_tab.c
|
||||
Makefile.bcc NH_filesgentag=(file%s_for_win32_that_are_moved_into_src_at_compile_time)
|
||||
Makefile.gcc NH_filesgentag=>Makefile.bcc
|
||||
Makefile NH_filesgentag=>Makefile.bcc
|
||||
|
||||
qt_kde0.moc NH_filesgentag=(file%s_generated_by_'moc'_for_Qt_interface_at_compile_time)
|
||||
qt_win.moc NH_filesgentag=>qt_kde0.moc
|
||||
qttableview.moc NH_filesgentag=>qt_kde0.moc
|
||||
|
||||
tile.c NH_filesgentag=(file%s_optionally_generated_by_tilemap_at_compile_time)
|
||||
|
||||
monstr.c NH_filesgentag=(file%s_generated_by_makedefs_at_compile_time)
|
||||
vis_tab.c NH_filesgentag=>monstr.c
|
||||
25
src/end.c
25
src/end.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 end.c $NHDT-Date: 1512803167 2017/12/09 07:06:07 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.137 $ */
|
||||
/* NetHack 3.6 end.c $NHDT-Date: 1528332335 2018/06/07 00:45:35 $ $NHDT-Branch: NetHack-3.6.2 $:$NHDT-Revision: 1.141 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Robert Patrick Rankin, 2012. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -985,7 +985,7 @@ winid endwin;
|
||||
if (counting) {
|
||||
nowrap_add(u.urexp, points);
|
||||
} else {
|
||||
makeknown(otmp->otyp);
|
||||
discover_object(otmp->otyp, TRUE, FALSE);
|
||||
otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
|
||||
/* assumes artifacts don't have quan > 1 */
|
||||
Sprintf(pbuf, "%s%s (worth %ld %s and %ld points)",
|
||||
@@ -1178,7 +1178,7 @@ int how;
|
||||
* it in both of those places.
|
||||
*/
|
||||
for (obj = invent; obj; obj = obj->nobj) {
|
||||
makeknown(obj->otyp);
|
||||
discover_object(obj->otyp, TRUE, FALSE);
|
||||
obj->known = obj->bknown = obj->dknown = obj->rknown = 1;
|
||||
if (Is_container(obj) || obj->otyp == STATUE)
|
||||
obj->cknown = obj->lknown = 1;
|
||||
@@ -1400,7 +1400,7 @@ int how;
|
||||
continue;
|
||||
if (objects[typ].oc_class != GEM_CLASS || typ <= LAST_GEM) {
|
||||
otmp = mksobj(typ, FALSE, FALSE);
|
||||
makeknown(otmp->otyp);
|
||||
discover_object(otmp->otyp, TRUE, FALSE);
|
||||
otmp->known = 1; /* for fake amulets */
|
||||
otmp->dknown = 1; /* seen it (blindness fix) */
|
||||
if (has_oname(otmp))
|
||||
@@ -1498,18 +1498,20 @@ boolean identified, all_containers, reportempty;
|
||||
continue; /* wrong type of container */
|
||||
} else if (box->cobj) {
|
||||
winid tmpwin = create_nhwindow(NHW_MENU);
|
||||
Loot *sortedcobj, *srtc;
|
||||
unsigned sortflags;
|
||||
|
||||
sortloot(&box->cobj,
|
||||
(((flags.sortloot == 'l' || flags.sortloot == 'f')
|
||||
? SORTLOOT_LOOT : 0)
|
||||
| (flags.sortpack ? SORTLOOT_PACK : 0)),
|
||||
FALSE);
|
||||
Sprintf(buf, "Contents of %s:", the(xname(box)));
|
||||
putstr(tmpwin, 0, buf);
|
||||
putstr(tmpwin, 0, "");
|
||||
for (obj = box->cobj; obj; obj = obj->nobj) {
|
||||
sortflags = (((flags.sortloot == 'l' || flags.sortloot == 'f')
|
||||
? SORTLOOT_LOOT : 0)
|
||||
| (flags.sortpack ? SORTLOOT_PACK : 0));
|
||||
sortedcobj = sortloot(&box->cobj, sortflags, FALSE,
|
||||
(boolean FDECL((*), (OBJ_P))) 0);
|
||||
for (srtc = sortedcobj; ((obj = srtc->obj) != 0); ++srtc) {
|
||||
if (identified) {
|
||||
makeknown(obj->otyp);
|
||||
discover_object(obj->otyp, TRUE, FALSE);
|
||||
obj->known = obj->bknown = obj->dknown
|
||||
= obj->rknown = 1;
|
||||
if (Is_container(obj) || obj->otyp == STATUE)
|
||||
@@ -1517,6 +1519,7 @@ boolean identified, all_containers, reportempty;
|
||||
}
|
||||
putstr(tmpwin, 0, doname(obj));
|
||||
}
|
||||
unsortloot(&sortedcobj);
|
||||
if (cat)
|
||||
putstr(tmpwin, 0, "Schroedinger's cat");
|
||||
else if (deadcat)
|
||||
|
||||
141
src/invent.c
141
src/invent.c
@@ -46,10 +46,6 @@ static int lastinvnr = 51; /* 0 ... 51 (never saved&restored) */
|
||||
*/
|
||||
static char venom_inv[] = { VENOM_CLASS, 0 }; /* (constant) */
|
||||
|
||||
struct sortloot_item {
|
||||
struct obj *obj;
|
||||
int indx;
|
||||
};
|
||||
unsigned sortlootmode = 0;
|
||||
|
||||
/* qsort comparison routine for sortloot() */
|
||||
@@ -211,6 +207,100 @@ tiebreak:
|
||||
return (sli1->indx - sli2->indx);
|
||||
}
|
||||
|
||||
/*
|
||||
* sortloot() - the story so far...
|
||||
*
|
||||
* The original implementation constructed and returned an array
|
||||
* of pointers to objects in the requested order. Callers had to
|
||||
* count the number of objects, allocate the array, pass one
|
||||
* object at a time to the routine which populates it, traverse
|
||||
* the objects via stepping through the array, then free the
|
||||
* array. The ordering process used a basic insertion sort which
|
||||
* is fine for short lists but inefficient for long ones.
|
||||
*
|
||||
* 3.6.0 (and continuing with 3.6.1) changed all that so that
|
||||
* sortloot was self-contained as far as callers were concerned.
|
||||
* It reordered the linked list into the requested order and then
|
||||
* normal list traversal was used to process it. It also switched
|
||||
* to qsort() on the assumption that the C library implementation
|
||||
* put some effort into sorting efficiently. It also checked
|
||||
* whether the list was already sorted as it got ready to do the
|
||||
* sorting, so re-examining inventory or a pile of objects without
|
||||
* having changed anything would gobble up less CPU than a full
|
||||
* sort. But it had as least two problems (aside from the ordinary
|
||||
* complement of bugs):
|
||||
* 1) some players wanted to get the original order back when they
|
||||
* changed the 'sortloot' option back to 'none', but the list
|
||||
* reordering made that infeasible;
|
||||
* 2) object identification giving the 'ID whole pack' result
|
||||
* would call makeknown() on each newly ID'd object, that would
|
||||
* call update_inventory() to update the persistent inventory
|
||||
* window if one existed, the interface would call the inventory
|
||||
* display routine which would call sortloot() which might change
|
||||
* the order of the list being traversed by the identify code,
|
||||
* possibly skipping the ID of some objects. That could have been
|
||||
* avoided by suppressing 'perm_invent' during identification
|
||||
* (fragile) or by avoiding sortloot() during inventory display
|
||||
* (more robust).
|
||||
*
|
||||
* 3.6.2 reverts to the temporary array of ordered obj pointers
|
||||
* but has sortloot() do the counting and allocation. Callers
|
||||
* need to use array traversal instead of linked list traversal
|
||||
* and need to free the temporary array when done. And the
|
||||
* array contains 'struct sortloot_item' (aka 'Loot') entries
|
||||
* instead of simple 'struct obj *' entries.
|
||||
*/
|
||||
Loot *
|
||||
sortloot(olist, mode, by_nexthere, filterfunc)
|
||||
struct obj **olist; /* previous version might have changed *olist, we don't */
|
||||
unsigned mode; /* flags for sortloot_cmp() */
|
||||
boolean by_nexthere; /* T: traverse via obj->nexthere, F: via obj->nobj */
|
||||
boolean FDECL((*filterfunc), (OBJ_P));
|
||||
{
|
||||
Loot *sliarray;
|
||||
struct obj *o;
|
||||
unsigned n, i;
|
||||
boolean augment_filter;
|
||||
|
||||
for (n = 0, o = *olist; o; o = by_nexthere ? o->nexthere : o->nobj)
|
||||
++n;
|
||||
/* note: if there is a filter function, this might overallocate */
|
||||
sliarray = (Loot *) alloc((n + 1) * sizeof *sliarray);
|
||||
|
||||
augment_filter = (mode & SORTLOOT_PETRIFY) ? TRUE : FALSE;
|
||||
/* populate aliarray[0..n-1] */
|
||||
for (i = 0, o = *olist; o; ++i, o = by_nexthere ? o->nexthere : o->nobj) {
|
||||
if (filterfunc && !(*filterfunc)(o)
|
||||
&& (!augment_filter || o->otyp != CORPSE
|
||||
|| !touch_petrifies(&mons[o->corpsenm])))
|
||||
continue;
|
||||
sliarray[i].obj = o, sliarray[i].indx = (int) i;
|
||||
}
|
||||
n = i;
|
||||
/* add a terminator so that we don't have to pass 'n' back to caller */
|
||||
sliarray[n].obj = (struct obj *) 0, sliarray[n].indx = -1;
|
||||
mode &= ~SORTLOOT_PETRIFY;
|
||||
|
||||
/* do the sort; if no sorting is requested, we'll just return
|
||||
a sortloot_item array reflecting the current ordering */
|
||||
if (mode) {
|
||||
sortlootmode = mode; /* extra input for sortloot_cmp() */
|
||||
qsort((genericptr_t) sliarray, n, sizeof *sliarray, sortloot_cmp);
|
||||
sortlootmode = 0; /* reset static mode flags */
|
||||
}
|
||||
return sliarray;
|
||||
}
|
||||
|
||||
/* sortloot() callers should use this to free up memory it allocates */
|
||||
void
|
||||
unsortloot(loot_array_p)
|
||||
Loot **loot_array_p;
|
||||
{
|
||||
if (*loot_array_p)
|
||||
free((genericptr_t) *loot_array_p), *loot_array_p = (Loot *) 0;
|
||||
}
|
||||
|
||||
#if 0 /* 3.6.0 'revamp' */
|
||||
void
|
||||
sortloot(olist, mode, by_nexthere)
|
||||
struct obj **olist;
|
||||
@@ -248,6 +338,7 @@ boolean by_nexthere; /* T: traverse via obj->nexthere, F: via obj->nobj */
|
||||
}
|
||||
sortlootmode = 0;
|
||||
}
|
||||
#endif /*0*/
|
||||
|
||||
void
|
||||
assigninvlet(otmp)
|
||||
@@ -1097,6 +1188,7 @@ register const char *let, *word;
|
||||
boolean msggiven = FALSE;
|
||||
boolean oneloop = FALSE;
|
||||
long dummymask;
|
||||
Loot *sortedinvent, *srtinv;
|
||||
|
||||
if (*let == ALLOW_COUNT)
|
||||
let++, allowcnt = 1;
|
||||
@@ -1133,15 +1225,13 @@ register const char *let, *word;
|
||||
|
||||
if (!flags.invlet_constant)
|
||||
reassign();
|
||||
else
|
||||
/* in case invent is in packorder, force it to be in invlet
|
||||
order before collecing candidate inventory letters;
|
||||
if player responds with '?' or '*' it will be changed
|
||||
back by display_pickinv(), but by then we'll have 'lets'
|
||||
and so won't have to re-sort in the for(;;) loop below */
|
||||
sortloot(&invent, SORTLOOT_INVLET, FALSE);
|
||||
|
||||
for (otmp = invent; otmp; otmp = otmp->nobj) {
|
||||
/* force invent to be in invlet order before collecting candidate
|
||||
inventory letters */
|
||||
sortedinvent = sortloot(&invent, SORTLOOT_INVLET, FALSE,
|
||||
(boolean FDECL((*), (OBJ_P))) 0);
|
||||
|
||||
for (srtinv = sortedinvent; (otmp = srtinv->obj) != 0; ++srtinv) {
|
||||
if (&bp[foo] == &buf[sizeof buf - 1]
|
||||
|| ap == &altlets[sizeof altlets - 1]) {
|
||||
/* we must have a huge number of NOINVSYM items somehow */
|
||||
@@ -1285,6 +1375,7 @@ register const char *let, *word;
|
||||
allowall = usegold = TRUE;
|
||||
}
|
||||
}
|
||||
unsortloot(&sortedinvent);
|
||||
|
||||
bp[foo] = 0;
|
||||
if (foo == 0 && bp > buf && bp[-1] == ' ')
|
||||
@@ -1763,16 +1854,17 @@ unsigned *resultflags;
|
||||
*/
|
||||
int
|
||||
askchain(objchn, olets, allflag, fn, ckfn, mx, word)
|
||||
struct obj **objchn;
|
||||
struct obj **objchn; /* *objchn might change */
|
||||
int allflag, mx;
|
||||
const char *olets, *word; /* olets is an Obj Class char array */
|
||||
int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
|
||||
{
|
||||
struct obj *otmp, *otmpo;
|
||||
register char sym, ilet;
|
||||
register int cnt = 0, dud = 0, tmp;
|
||||
int cnt = 0, dud = 0, tmp;
|
||||
boolean takeoff, nodot, ident, take_out, put_in, first, ininv, bycat;
|
||||
char qbuf[QBUFSZ], qpfx[QBUFSZ];
|
||||
Loot *sortedchn = 0;
|
||||
|
||||
takeoff = taking_off(word);
|
||||
ident = !strcmp(word, "identify");
|
||||
@@ -1787,7 +1879,8 @@ int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
|
||||
|
||||
/* someday maybe we'll sort by 'olets' too (temporarily replace
|
||||
flags.packorder and pass SORTLOOT_PACK), but not yet... */
|
||||
sortloot(objchn, SORTLOOT_INVLET, FALSE);
|
||||
sortedchn = sortloot(objchn, SORTLOOT_INVLET, FALSE,
|
||||
(boolean FDECL((*), (OBJ_P))) 0);
|
||||
|
||||
first = TRUE;
|
||||
/*
|
||||
@@ -1812,7 +1905,7 @@ nextclass:
|
||||
* track of which list elements have already been processed.
|
||||
*/
|
||||
bypass_objlist(*objchn, FALSE); /* clear chain's bypass bits */
|
||||
while ((otmp = nxt_unbypassed_obj(*objchn)) != 0) {
|
||||
while ((otmp = nxt_unbypassed_loot(sortedchn, *objchn)) != 0) {
|
||||
if (ilet == 'z')
|
||||
ilet = 'A';
|
||||
else if (ilet == 'Z')
|
||||
@@ -1900,11 +1993,13 @@ nextclass:
|
||||
}
|
||||
if (olets && *olets && *++olets)
|
||||
goto nextclass;
|
||||
|
||||
if (!takeoff && (dud || cnt))
|
||||
pline("That was all.");
|
||||
else if (!dud && !cnt)
|
||||
pline("No applicable objects.");
|
||||
ret:
|
||||
unsortloot(&sortedchn);
|
||||
bypass_objlist(*objchn, FALSE);
|
||||
return cnt;
|
||||
}
|
||||
@@ -2195,6 +2290,8 @@ long *out_cnt;
|
||||
winid win; /* windows being used */
|
||||
anything any;
|
||||
menu_item *selected;
|
||||
unsigned sortflags;
|
||||
Loot *sortedinvent, *srtinv;
|
||||
|
||||
if (lets && !*lets)
|
||||
lets = 0; /* simplify tests: (lets) instead of (lets && *lets) */
|
||||
@@ -2268,10 +2365,11 @@ long *out_cnt;
|
||||
return ret;
|
||||
}
|
||||
|
||||
sortloot(&invent,
|
||||
(((flags.sortloot == 'f') ? SORTLOOT_LOOT : SORTLOOT_INVLET)
|
||||
| (flags.sortpack ? SORTLOOT_PACK : 0)),
|
||||
FALSE);
|
||||
sortflags = (flags.sortloot == 'f') ? SORTLOOT_LOOT : SORTLOOT_INVLET;
|
||||
if (flags.sortpack)
|
||||
sortflags |= SORTLOOT_PACK;
|
||||
sortedinvent = sortloot(&invent, sortflags, FALSE,
|
||||
(boolean FDECL((*), (OBJ_P))) 0);
|
||||
|
||||
start_menu(win);
|
||||
any = zeroany;
|
||||
@@ -2296,7 +2394,7 @@ long *out_cnt;
|
||||
}
|
||||
nextclass:
|
||||
classcount = 0;
|
||||
for (otmp = invent; otmp; otmp = otmp->nobj) {
|
||||
for (srtinv = sortedinvent; (otmp = srtinv->obj) != 0; ++srtinv) {
|
||||
if (lets && !index(lets, otmp->invlet))
|
||||
continue;
|
||||
if (!flags.sortpack || otmp->oclass == *invlet) {
|
||||
@@ -2330,6 +2428,7 @@ nextclass:
|
||||
add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE,
|
||||
"(list everything)", MENU_UNSELECTED);
|
||||
}
|
||||
unsortloot(&sortedinvent);
|
||||
/* for permanent inventory where we intend to show everything but
|
||||
nothing has been listed (because there isn't anyhing to list;
|
||||
recognized via any.a_char still being zero; the n==0 case above
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 o_init.c $NHDT-Date: 1450318588 2015/12/17 02:16:28 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.22 $ */
|
||||
/* NetHack 3.6 o_init.c $NHDT-Date: 1528332336 2018/06/07 00:45:36 $ $NHDT-Branch: NetHack-3.6.2 $:$NHDT-Revision: 1.24 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Robert Patrick Rankin, 2011. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -361,7 +361,8 @@ boolean credit_hero;
|
||||
if (credit_hero)
|
||||
exercise(A_WIS, TRUE);
|
||||
}
|
||||
if (moves > 1L)
|
||||
/* moves==1L => initial inventory, gameover => final disclosure */
|
||||
if (moves > 1L && !program_state.gameover)
|
||||
update_inventory();
|
||||
}
|
||||
}
|
||||
|
||||
30
src/pickup.c
30
src/pickup.c
@@ -577,7 +577,8 @@ int what; /* should be a long */
|
||||
|
||||
if (flags.menu_style != MENU_TRADITIONAL || iflags.menu_requested) {
|
||||
/* use menus exclusively */
|
||||
traverse_how |= AUTOSELECT_SINGLE | INVORDER_SORT;
|
||||
traverse_how |= AUTOSELECT_SINGLE
|
||||
| (flags.sortpack ? INVORDER_SORT : 0);
|
||||
if (count) { /* looking for N of something */
|
||||
char qbuf[QBUFSZ];
|
||||
|
||||
@@ -849,6 +850,8 @@ boolean FDECL((*allow), (OBJ_P)); /* allow function */
|
||||
boolean printed_type_name, first,
|
||||
sorted = (qflags & INVORDER_SORT) != 0,
|
||||
engulfer = (qflags & INCLUDE_HERO) != 0;
|
||||
unsigned sortflags;
|
||||
Loot *sortedolist, *srtoli;
|
||||
|
||||
*pick_list = (menu_item *) 0;
|
||||
if (!olist && !engulfer)
|
||||
@@ -876,16 +879,14 @@ boolean FDECL((*allow), (OBJ_P)); /* allow function */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sorted || flags.sortloot != 'n') {
|
||||
sortloot(&olist,
|
||||
(((flags.sortloot == 'f'
|
||||
|| (flags.sortloot == 'l' && !(qflags & USE_INVLET)))
|
||||
? SORTLOOT_LOOT
|
||||
: (qflags & USE_INVLET) ? SORTLOOT_INVLET : 0)
|
||||
| (flags.sortpack ? SORTLOOT_PACK : 0)),
|
||||
(qflags & BY_NEXTHERE) ? TRUE : FALSE);
|
||||
*olist_p = olist;
|
||||
}
|
||||
sortflags = (((flags.sortloot == 'f'
|
||||
|| (flags.sortloot == 'l' && !(qflags & USE_INVLET)))
|
||||
? SORTLOOT_LOOT
|
||||
: ((qflags & USE_INVLET) ? SORTLOOT_INVLET : 0))
|
||||
| (flags.sortpack ? SORTLOOT_PACK : 0)
|
||||
| ((qflags & FEEL_COCKATRICE) ? SORTLOOT_PETRIFY : 0));
|
||||
sortedolist = sortloot(&olist, sortflags,
|
||||
(qflags & BY_NEXTHERE) ? TRUE : FALSE, allow);
|
||||
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
start_menu(win);
|
||||
@@ -893,14 +894,14 @@ boolean FDECL((*allow), (OBJ_P)); /* allow function */
|
||||
/*
|
||||
* Run through the list and add the objects to the menu. If
|
||||
* INVORDER_SORT is set, we'll run through the list once for
|
||||
* each type so we can group them. The allow function will only
|
||||
* be called once per object in the list.
|
||||
* each type so we can group them. The allow function was
|
||||
* called by sortloot() and will be called once per item here.
|
||||
*/
|
||||
pack = flags.inv_order;
|
||||
first = TRUE;
|
||||
do {
|
||||
printed_type_name = FALSE;
|
||||
for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
|
||||
for (srtoli = sortedolist; ((curr = srtoli->obj) != 0); ++srtoli) {
|
||||
if (sorted && curr->oclass != *pack)
|
||||
continue;
|
||||
if ((qflags & FEEL_COCKATRICE) && curr->otyp == CORPSE
|
||||
@@ -932,6 +933,7 @@ boolean FDECL((*allow), (OBJ_P)); /* allow function */
|
||||
}
|
||||
pack++;
|
||||
} while (sorted && *pack);
|
||||
unsortloot(&sortedolist);
|
||||
|
||||
if (engulfer) {
|
||||
char buf[BUFSZ];
|
||||
|
||||
24
src/worn.c
24
src/worn.c
@@ -777,6 +777,30 @@ struct obj *objchain;
|
||||
return objchain;
|
||||
}
|
||||
|
||||
/* like nxt_unbypassed_obj() but operates on sortloot_item array rather
|
||||
than an object linked list; the array contains obj==Null terminator;
|
||||
there's an added complication that the array may have stale pointers
|
||||
for deleted objects (see Multiple-Drop case in askchain(invent.c)) */
|
||||
struct obj *
|
||||
nxt_unbypassed_loot(lootarray, listhead)
|
||||
Loot *lootarray;
|
||||
struct obj *listhead;
|
||||
{
|
||||
struct obj *o, *obj;
|
||||
|
||||
while ((obj = lootarray->obj) != 0) {
|
||||
for (o = listhead; o; o = o->nobj)
|
||||
if (o == obj)
|
||||
break;
|
||||
if (o && !obj->bypass) {
|
||||
bypass_obj(obj);
|
||||
break;
|
||||
}
|
||||
++lootarray;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
void
|
||||
mon_break_armor(mon, polyspot)
|
||||
struct monst *mon;
|
||||
|
||||
Reference in New Issue
Block a user