From 664b4eb643e0e1ed12d0e47859e27541421cd7f1 Mon Sep 17 00:00:00 2001 From: Alex Kompel Date: Sun, 26 Apr 2015 14:47:38 -0700 Subject: [PATCH 1/8] bubble structure contains pointer into static array. Bubble objects are being flat-dumped into save file and this causes segfault in restore() whenever data segment layout changes (e.g. global variables added/removed). bmask should either be stored with the objects. --- include/lev.h | 4 +++- src/mkmaze.c | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/include/lev.h b/include/lev.h index e3e05ec9a..b2a99841a 100644 --- a/include/lev.h +++ b/include/lev.h @@ -13,6 +13,8 @@ #define WRITE_SAVE 0x2 #define FREE_SAVE 0x4 +#define MAX_BMASK 4 + /* operations of the various saveXXXchn & co. routines */ #define perform_bwrite(mode) ((mode) & (COUNT_SAVE|WRITE_SAVE)) #define release_data(mode) ((mode) & FREE_SAVE) @@ -33,7 +35,7 @@ struct container { struct bubble { xchar x, y; /* coordinates of the upper left corner */ schar dx, dy; /* the general direction of the bubble's movement */ - uchar *bm; /* pointer to the bubble bit mask */ + uchar bm[MAX_BMASK+2]; /* bubble bit mask */ struct bubble *prev, *next; /* need to traverse the list up and down */ struct container *cons; }; diff --git a/src/mkmaze.c b/src/mkmaze.c index 42851c0df..5b793b32d 100644 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@ -1267,6 +1267,9 @@ register int x, y, n; impossible("n too large (mk_bubble)"); n = SIZE(bmask) - 1; } + if (bmask[n][1] > MAX_BMASK) { + panic("bmask size is larger than MAX_BMASK"); + } b = (struct bubble *)alloc(sizeof(struct bubble)); if ((x + (int) bmask[n][0] - 1) > bxmax) x = bxmax - bmask[n][0] + 1; if ((y + (int) bmask[n][1] - 1) > bymax) y = bymax - bmask[n][1] + 1; @@ -1274,7 +1277,9 @@ register int x, y, n; b->y = y; b->dx = 1 - rn2(3); b->dy = 1 - rn2(3); - b->bm = bmask[n]; + /* y dimension is the length of bitmap data - see bmask above */ + (void)memcpy((genericptr_t)b->bm, (genericptr_t)bmask[n], + (bmask[n][1]+2)*sizeof(b->bm[0])); b->cons = 0; if (!bbubbles) bbubbles = b; if (ebubbles) { From fdda06f6780e8835127f247b4173ac97a7684782 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Fri, 1 May 2015 11:55:15 +0300 Subject: [PATCH 2/8] Initialize variable --- src/options.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/options.c b/src/options.c index 8a5e65254..cc27a00f7 100644 --- a/src/options.c +++ b/src/options.c @@ -3571,6 +3571,7 @@ boolean setinitial,setfromfile; menu_item *sortl_pick = (menu_item *)0; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin); + any = zeroany; for (i = 0; i < SIZE(sortltype); i++) { sortl_name = sortltype[i]; any.a_char = *sortl_name; From 18a29f0dfe36e1b54a743e83e56c89f8a975c81e Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 1 May 2015 02:32:14 -0700 Subject: [PATCH 3/8] sanity check owornmask Extend the processing done by the wizard mode 'sanity_check' option to look for anomalies with obj->owornmask since there seem to have been a few lately. I haven't actually triggered any so this code isn't very well exercized yet. sanity_check uses pline() rather than impossible() or debugpline() to deliver messages so might not be very useful with keymasking. A sizeable chunk of this diff is just cleaning up indentation so that I could see what I was working with.... --- src/mkobj.c | 249 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 180 insertions(+), 69 deletions(-) diff --git a/src/mkobj.c b/src/mkobj.c index 699c5dbdb..50f2b5b7e 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -1,4 +1,4 @@ -/* NetHack 3.5 mkobj.c $NHDT-Date: 1428715841 2015/04/11 01:30:41 $ $NHDT-Branch: master $:$NHDT-Revision: 1.91 $ */ +/* NetHack 3.5 mkobj.c $NHDT-Date: 1430472720 2015/05/01 09:32:00 $ $NHDT-Branch: master $:$NHDT-Revision: 1.95 $ */ /* NetHack 3.5 mkobj.c $Date: 2012/03/10 02:49:08 $ $Revision: 1.70 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -16,6 +16,7 @@ STATIC_DCL const char *FDECL(where_name, (struct obj *)); STATIC_DCL void FDECL(insane_object, (struct obj *,const char *,const char *,struct monst *)); STATIC_DCL void FDECL(check_contained, (struct obj *,const char *)); +STATIC_DCL void FDECL(sanity_check_worn, (struct obj *)); struct icp { int iprob; /* probability of an item type */ @@ -1968,18 +1969,18 @@ obj_sanity_check() those objects should have already been sanity checked via the floor list so container contents are skipped here */ for (x = 0; x < COLNO; x++) - for (y = 0; y < ROWNO; y++) + for (y = 0; y < ROWNO; y++) for (obj = level.objects[x][y]; obj; obj = obj->nexthere) { - /* should match ; <0,*> should always be empty */ - if (obj->where != OBJ_FLOOR || x == 0 || - obj->ox != x || obj->oy != y) { - char at_fmt[BUFSZ]; + /* should match ; <0,*> should always be empty */ + if (obj->where != OBJ_FLOOR || x == 0 || + obj->ox != x || obj->oy != y) { + char at_fmt[BUFSZ]; - Sprintf(at_fmt, "%%s obj@<%d,%d> %%s %%s: %%s@<%d,%d>", - x, y, obj->ox, obj->oy); - insane_object(obj, at_fmt, "location sanity", - (struct monst *)0); - } + Sprintf(at_fmt, "%%s obj@<%d,%d> %%s %%s: %%s@<%d,%d>", + x, y, obj->ox, obj->oy); + insane_object(obj, at_fmt, "location sanity", + (struct monst *)0); + } } objlist_sanity(invent, OBJ_INVENT, "invent sanity"); @@ -1992,16 +1993,16 @@ obj_sanity_check() /* monsters temporarily in transit; they should have arrived with hero by the time we get called */ if (mydogs) { - pline("mydogs sanity [not empty]"); - mon_obj_sanity(mydogs, "mydogs minvent sanity"); + pline("mydogs sanity [not empty]"); + mon_obj_sanity(mydogs, "mydogs minvent sanity"); } /* objects temporarily freed from invent/floor lists; they should have arrived somewhere by the time we get called */ if (thrownobj) - insane_object(thrownobj, ofmt3, "thrownobj sanity", (struct monst *)0); + insane_object(thrownobj, ofmt3, "thrownobj sanity", (struct monst *)0); if (kickedobj) - insane_object(kickedobj, ofmt3, "kickedobj sanity", (struct monst *)0); + insane_object(kickedobj, ofmt3, "kickedobj sanity", (struct monst *)0); /* [how about current_wand too?] */ } @@ -2015,15 +2016,40 @@ const char *mesg; struct obj *obj; for (obj = objlist; obj; obj = obj->nobj) { - if (obj->where != wheretype) - insane_object(obj, ofmt0, mesg, (struct monst *)0); - if (Has_contents(obj)) { - if (wheretype == OBJ_ONBILL) - /* containers on shop bill should always be empty */ - insane_object(obj, "%s obj contains something! %s %s: %s", - mesg, (struct monst *)0); - check_contained(obj, mesg); - } + if (obj->where != wheretype) + insane_object(obj, ofmt0, mesg, (struct monst *)0); + if (Has_contents(obj)) { + if (wheretype == OBJ_ONBILL) + /* containers on shop bill should always be empty */ + insane_object(obj, "%s obj contains something! %s %s: %s", + mesg, (struct monst *)0); + check_contained(obj, mesg); + } + if (obj->owornmask) { + char maskbuf[40]; + boolean bc_ok = FALSE; + + switch (obj->where) { + case OBJ_INVENT: + case OBJ_MINVENT: + case OBJ_MIGRATING: + sanity_check_worn(obj); + break; + case OBJ_FLOOR: + /* note: ball and chain can also be OBJ_FREE, but not across + turns so this sanity check shouldn't encounter that */ + bc_ok = TRUE; + /*FALLTHRU*/ + default: + if ((obj != uchain && obj != uball) || !bc_ok) { + /* discovered an object not in inventory which + erroneously has worn mask set */ + Sprintf(maskbuf, "worn mask 0x%08lx", obj->owornmask); + insane_object(obj, ofmt0, maskbuf, (struct monst *)0); + } + break; + } + } } } @@ -2037,18 +2063,18 @@ const char *mesg; struct obj *obj; for (mon = monlist; mon; mon = mon->nmon) - for (obj = mon->minvent; obj; obj = obj->nobj) { - if (obj->where != OBJ_MINVENT) - insane_object(obj, mfmt1, mesg, mon); - if (obj->ocarry != mon) - insane_object(obj, mfmt2, mesg, mon); - check_contained(obj, mesg); - } + for (obj = mon->minvent; obj; obj = obj->nobj) { + if (obj->where != OBJ_MINVENT) + insane_object(obj, mfmt1, mesg, mon); + if (obj->ocarry != mon) + insane_object(obj, mfmt2, mesg, mon); + check_contained(obj, mesg); + } } /* This must stay consistent with the defines in obj.h. */ static const char *obj_state_names[NOBJ_STATES] = { - "free", "floor", "contained", "invent", + "free", "floor", "contained", "invent", "minvent", "migrating", "buried", "onbill" }; @@ -2062,8 +2088,8 @@ struct obj *obj; if (!obj) return "nowhere"; where = obj->where; if (where < 0 || where >= NOBJ_STATES || !obj_state_names[where]) { - Sprintf(unknown, "unknown[%d]", where); - return unknown; + Sprintf(unknown, "unknown[%d]", where); + return unknown; } return obj_state_names[where]; } @@ -2079,19 +2105,19 @@ struct monst *mon; objnm = monnm = "null!"; if (obj) { - iflags.override_ID++; - objnm = doname(obj); - iflags.override_ID--; + iflags.override_ID++; + objnm = doname(obj); + iflags.override_ID--; } if (mon || (strstri(mesg, "minvent") && !strstri(mesg, "contained"))) { - Strcat(strcpy(altfmt, fmt), " held by mon %s (%s)"); - if (mon) - monnm = x_monnam(mon, ARTICLE_A, (char *)0, EXACT_NAME, TRUE); - pline(altfmt, mesg, - fmt_ptr((genericptr_t)obj), where_name(obj), objnm, - fmt_ptr((genericptr_t)mon), monnm); + Strcat(strcpy(altfmt, fmt), " held by mon %s (%s)"); + if (mon) + monnm = x_monnam(mon, ARTICLE_A, (char *)0, EXACT_NAME, TRUE); + pline(altfmt, mesg, + fmt_ptr((genericptr_t)obj), where_name(obj), objnm, + fmt_ptr((genericptr_t)mon), monnm); } else { - pline(fmt, mesg, fmt_ptr((genericptr_t)obj), where_name(obj), objnm); + pline(fmt, mesg, fmt_ptr((genericptr_t)obj), where_name(obj), objnm); } } @@ -2109,37 +2135,122 @@ check_contained(container, mesg) /* change "invent sanity" to "contained invent sanity" but leave "nested contained invent sanity" as is */ if (!strstri(mesg, "contained")) - mesg = strcat(strcpy(mesgbuf, "contained "), mesg); + mesg = strcat(strcpy(mesgbuf, "contained "), mesg); for (obj = container->cobj; obj; obj = obj->nobj) { - /* catch direct cycle to avoid unbounded recursion */ - if (obj == container) - panic("failed sanity check: container holds itself"); - if (obj->where != OBJ_CONTAINED) - insane_object(obj, "%s obj %s %s: %s", mesg, (struct monst *)0); - else if (obj->ocontainer != container) - pline("%s obj %s in container %s, not %s", mesg, - fmt_ptr((genericptr_t)obj), - fmt_ptr((genericptr_t)obj->ocontainer), - fmt_ptr((genericptr_t)container)); + /* catch direct cycle to avoid unbounded recursion */ + if (obj == container) + panic("failed sanity check: container holds itself"); + if (obj->where != OBJ_CONTAINED) + insane_object(obj, "%s obj %s %s: %s", mesg, (struct monst *)0); + else if (obj->ocontainer != container) + pline("%s obj %s in container %s, not %s", mesg, + fmt_ptr((genericptr_t)obj), + fmt_ptr((genericptr_t)obj->ocontainer), + fmt_ptr((genericptr_t)container)); - if (Has_contents(obj)) { - /* catch most likely indirect cycle; we won't notice if - parent is present when something comes before it, or - notice more deeply embedded cycles (grandparent, &c) */ - if (obj->cobj == container) - panic("failed sanity check: container holds its parent"); - /* change "contained... sanity" to "nested contained... sanity" - and "nested contained..." to "nested nested contained..." */ - Strcpy(nestedmesg, "nested "); - copynchars(eos(nestedmesg), mesg, - (int)sizeof nestedmesg - (int)strlen(nestedmesg) - 1); - /* recursively check contents */ - check_contained(obj, nestedmesg); - } + if (Has_contents(obj)) { + /* catch most likely indirect cycle; we won't notice if + parent is present when something comes before it, or + notice more deeply embedded cycles (grandparent, &c) */ + if (obj->cobj == container) + panic("failed sanity check: container holds its parent"); + /* change "contained... sanity" to "nested contained... sanity" + and "nested contained..." to "nested nested contained..." */ + Strcpy(nestedmesg, "nested "); + copynchars(eos(nestedmesg), mesg, + (int)sizeof nestedmesg - (int)strlen(nestedmesg) - 1); + /* recursively check contents */ + check_contained(obj, nestedmesg); + } } } +/* check an object in hero's or monster's inventory which has worn mask set */ +STATIC_OVL void +sanity_check_worn(obj) +struct obj *obj; +{ +#if defined(BETA) || defined(DEBUG) + static unsigned long wearbits[] = { + W_ARM, W_ARMC, W_ARMH, W_ARMS, W_ARMG, W_ARMF, W_ARMU, + W_WEP, W_QUIVER, W_SWAPWEP, W_AMUL, W_RINGL, W_RINGR, + W_TOOL, W_SADDLE, W_BALL, W_CHAIN, + 0 + /* [W_ART,W_ARTI are property bits for items which aren't worn] */ + }; + char maskbuf[60]; + unsigned long allmask = 0L; + int i, n = 0; + + for (i = 0; wearbits[i]; ++i) { + allmask |= wearbits[i]; + if ((obj->owornmask & wearbits[i]) != 0L) ++n; + } + if (n > 1) { + /* multiple bits set */ + Sprintf(maskbuf, "worn mask (multiple) 0x%08lx", obj->owornmask); + insane_object(obj, ofmt0, maskbuf, (struct monst *)0); + } + if ((obj->owornmask & ~allmask) != 0L + || (carried(obj) && (obj->owornmask & W_SADDLE) != 0L)) { + /* non-wearable bit(s) set */ + Sprintf(maskbuf, "worn mask (bogus)) 0x%08lx", obj->owornmask); + insane_object(obj, ofmt0, maskbuf, (struct monst *)0); + } + if (n == 1 && (carried(obj) + || (obj->owornmask & (W_BALL|W_CHAIN)) != 0L)) { + const char *what = 0; + + /* verify that obj in hero's invent (or ball/chain elsewhere) + with owornmask of W_foo is the object pointed to by ufoo */ + switch (obj->owornmask) { + case W_ARM: if (obj != uarm) what = "armor"; /* suit */ + break; + case W_ARMC: if (obj != uarmc) what = "cloak"; + break; + case W_ARMH: if (obj != uarmh) what = "helm"; + break; + case W_ARMS: if (obj != uarms) what = "shield"; + break; + case W_ARMG: if (obj != uarmg) what = "gloves"; + break; + case W_ARMF: if (obj != uarmf) what = "boots"; + break; + case W_ARMU: if (obj != uarmu) what = "shirt"; + break; + case W_WEP: if (obj != uwep) what = "primary weapon"; + break; + case W_QUIVER: if (obj != uquiver) what = "quiver"; + break; + case W_SWAPWEP: if (obj != uswapwep) + what = u.twoweap ? "secondary weapon" : "alternate weapon"; + break; + case W_AMUL: if (obj != uamul) what = "amulet"; + break; + case W_RINGL: if (obj != uleft) what = "left ring"; + break; + case W_RINGR: if (obj != uright) what = "right ring"; + break; + case W_TOOL: if (obj != ublindf) what = "blindfold"; + break; + /* case W_SADDLE: */ + case W_BALL: if (obj != uball) what = "ball"; + break; + case W_CHAIN: if (obj != uchain) what = "chain"; + break; + default: break; + } + if (what) { + Sprintf(maskbuf, "worn mask 0x%08lx != %s", obj->owornmask, what); + insane_object(obj, ofmt0, maskbuf, (struct monst *)0); + } + } +#else /* not (BETA || DEBUG) */ + /* dummy use of obj to avoid "arg not used" complaint */ + if (!obj) insane_object(obj, ofmt0, "", (struct monst *)0); +#endif +} /* * wrapper to make "near this object" convenient From 67a53a2aa300bc7fa59bc1d4e43ad59c41867d10 Mon Sep 17 00:00:00 2001 From: nhmall Date: Fri, 1 May 2015 07:39:53 -0400 Subject: [PATCH 4/8] another ball & chain tweak checking if uball is OBJ_FREE was inappropriate, because sometimes it is in inventory. --- src/mon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mon.c b/src/mon.c index 7acc26670..a32032852 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.5 mon.c $NHDT-Date: 1430396792 2015/04/30 12:26:32 $ $NHDT-Branch: master $:$NHDT-Revision: 1.169 $ */ +/* NetHack 3.5 mon.c $NHDT-Date: 1430480373 2015/05/01 11:39:33 $ $NHDT-Branch: master $:$NHDT-Revision: 1.170 $ */ /* NetHack 3.5 mon.c $Date: 2012/05/16 02:15:10 $ $Revision: 1.126 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1850,7 +1850,7 @@ register struct monst *mtmp; u.uy = mtmp->my; u.uswallow = 0; u.uswldtim = 0; - if (Punished && uball->where == OBJ_FREE) placebc(); + if (Punished && uchain->where != OBJ_FLOOR) placebc(); vision_full_recalc = 1; docrt(); } From 40080817cea689d9170b62148590dfd2868a3eb9 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Fri, 1 May 2015 14:52:25 +0300 Subject: [PATCH 5/8] Uninitialized variable --- src/invent.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/invent.c b/src/invent.c index 176d2b8d2..1a2a3b2dd 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1906,6 +1906,7 @@ long* out_cnt; } start_menu(win); + any = zeroany; if (wizard && iflags.override_ID) { char prompt[BUFSZ]; any.a_char = -1; From 8f639796d502e0513652b0ebd7ca8f8d38617407 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Fri, 1 May 2015 22:03:10 +0300 Subject: [PATCH 6/8] Handle boulder-option in config file Setting boulder in config file did not work correctly in post-3.4.3 code, due to the symset changes. --- include/extern.h | 1 + src/drawing.c | 8 ++++++++ src/options.c | 2 ++ 3 files changed, 11 insertions(+) diff --git a/include/extern.h b/include/extern.h index a185be710..741de9138 100644 --- a/include/extern.h +++ b/include/extern.h @@ -515,6 +515,7 @@ E void FDECL(switch_symbols, (int)); E void FDECL(assign_graphics, (int)); E void NDECL(init_r_symbols); E void NDECL(init_symbols); +E void NDECL(update_bouldersym); E void NDECL(init_showsyms); E void NDECL(init_l_symbols); E void FDECL(clear_symsetentry, (int,BOOLEAN_P)); diff --git a/src/drawing.c b/src/drawing.c index d78668e0a..7967831d3 100644 --- a/src/drawing.c +++ b/src/drawing.c @@ -350,6 +350,14 @@ init_symbols() init_r_symbols(); } +void +update_bouldersym() +{ + showsyms[SYM_BOULDER + SYM_OFF_X] = iflags.bouldersym; + l_syms[SYM_BOULDER + SYM_OFF_X] = iflags.bouldersym; + r_syms[SYM_BOULDER + SYM_OFF_X] = iflags.bouldersym; +} + void init_showsyms() { diff --git a/src/options.c b/src/options.c index cc27a00f7..ec14cf766 100644 --- a/src/options.c +++ b/src/options.c @@ -744,6 +744,8 @@ initoptions_finish() /* result in the player's preferred fruit [better than "\033"]. */ obj_descr[SLIME_MOLD].oc_name = "fruit"; + if (iflags.bouldersym) update_bouldersym(); + reglyph_darkroom(); return; From d29ee35ae8e76d9c33fea3b69c359837a6d97c55 Mon Sep 17 00:00:00 2001 From: nhmall Date: Fri, 1 May 2015 18:34:06 -0400 Subject: [PATCH 7/8] fixes entry for previous bubble fix Changes to be committed: modified: doc/fixes35.0 --- doc/fixes35.0 | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 02f3e4e8d..6b853e1f1 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -906,6 +906,7 @@ shopkeepers give honorifics to vampires and elves when commands (D, A, object identify) mix object class filtering with BUCX filtering, take the intersection rather than the union (so ?B picks blessed scrolls rather than all scrolls plus blessed everything) +bmask is stored with the objects on the Plane of Water to prevent segfault Platform- and/or Interface-Specific Fixes From 274904f9be5931c692fc50ec63ee1cccbf511e6b Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 1 May 2015 18:01:12 -0700 Subject: [PATCH 8/8] stabilize loss of gold When gold is stolen by a leprechaun or lost when being "overwhelmed by an urge to take a bath" while dipping in a fountain, if you had 99 gold pieces or less, you'd lose all of it (in the bath case, only if it was at least 10 to start with), but if you had 100 or more, you would lose a random amount which could be as little as 1. And in the bath case, if the random amount was less than 10, you would lose nothing but be told that "you lost some of your money in the fountain". After this change, it is still possible to lose less when starting with more, but not as likely and not as extreme a case as maybe losing only 1 when starting with thousands. The fountain-dip bath case has code to handle mutiple denominations of coins, possibly the only place in the program where that exists. I've left that alone although it should probably be taken out.... --- src/steal.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/steal.c b/src/steal.c index f803ae4da..e3f09f524 100644 --- a/src/steal.c +++ b/src/steal.c @@ -1,4 +1,4 @@ -/* NetHack 3.5 steal.c $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$ */ +/* NetHack 3.5 steal.c $NHDT-Date: 1430528463 2015/05/02 01:01:03 $ $NHDT-Branch: master $:$NHDT-Revision: 1.53 $ */ /* NetHack 3.5 steal.c $Date: 2012/02/05 04:26:48 $ $Revision: 1.41 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -23,15 +23,31 @@ register struct obj *otmp; } long /* actually returns something that fits in an int */ -somegold(umoney) -long umoney; +somegold(lmoney) +long lmoney; { #ifdef LINT /* long conv. ok */ - return(0L); + int igold = 0; #else - return (long)( (umoney < 100) ? umoney : - (umoney > 10000) ? rnd(10000) : rnd((int) umoney) ); + int igold = (lmoney >= (long)LARGEST_INT) ? LARGEST_INT : (int)lmoney; #endif + + if (igold < 50) + ; /* all gold */ + else if (igold < 100) + igold = rn1(igold - 25 + 1, 25); + else if (igold < 500) + igold = rn1(igold - 50 + 1, 50); + else if (igold < 1000) + igold = rn1(igold - 100 + 1, 100); + else if (igold < 5000) + igold = rn1(igold - 500 + 1, 500); + else if (igold < 10000) + igold = rn1(igold - 1000 + 1, 1000); + else + igold = rn1(igold - 5000 + 1, 5000); + + return (long)igold; } /*