diff --git a/DEVEL/hooksdir/nhsub b/DEVEL/hooksdir/nhsub index c169609be..a1686bd24 100644 --- a/DEVEL/hooksdir/nhsub +++ b/DEVEL/hooksdir/nhsub @@ -5,7 +5,7 @@ # Note: was originally called nhdate; the rename is not reflected in the code. use strict; -my %opt; #cmd v n f F (other single char, but we don't care) +our %opt; #cmd v n f F m (other single char, but we don't care) my $mode; # a c d f (add, commit, date, date -f) if(length $ENV{GIT_PREFIX}){ @@ -249,7 +249,6 @@ my $count = s/\$$PREFIX-(([A-Za-z][A-Za-z0-9_]*)(: ([^\x24]+))?)\$/&handlevar($2 my $ofile = $file . ".nht"; open(TOUT, ">", $ofile) or die "Can't open $ofile"; -#XXX MUST add a loop here # die "write failed: $!" unless defined syswrite(TOUT, $_); my $offset = 0; my $sent; @@ -267,7 +266,7 @@ my $count = s/\$$PREFIX-(([A-Za-z][A-Za-z0-9_]*)(: ([^\x24]+))?)\$/&handlevar($2 rename $ofile, $file or die "Can't rename $ofile to $file"; } -# XXX docs for --fixup and --squash are wrong in synopsis. --file missing +# XXX docs for --fixup and --squash are wrong in git's synopsis. --file missing # --message --template -t sub cmdparse { my(@in) = @_; @@ -305,11 +304,15 @@ sub cmdparse { shift @in; next; } +# XXX this is messy - time for a rewrite? if(m/^-(.*)/){ foreach my $single ( split(//,$1) ){ # don't do -v here from add/commit if($single ne 'v'){ - $opt{$single}++; + # don't use -m from add/commit + if($opt{cmd} eq 'date' || $single ne 'm'){ + $opt{$single}++; + } } elsif($opt{cmd} eq 'date'){ $opt{$single}++; } @@ -408,8 +411,14 @@ use POSIX qw(strftime); # On pull, keep the current value so we can see the last change date. sub Date { my($val) = @_; - # we add this to make merge easier for now XXX - my $now = time; # not %s below - may not be portable + my $now; + if($opt{m}){ + my $hash = `git log -1 '--format=format:%H' $::current_file`; + #author keni 1429884677 -0400 + chomp($now = `git cat-file -p $hash | awk '/author/{print \$4}'`); + } else { + $now = time; + } # YYYY/MM/DD HH:MM:SS $val = "$now " . strftime("%Y/%m/%d %H:%M:%S", gmtime($now)); return $val; @@ -448,7 +457,7 @@ C - NetHack git command for substitution variables =head1 SYNOPSIS -C +C =head1 DESCRIPTION @@ -498,4 +507,11 @@ even if the NHSUBST attribute is not set for the file, and only if the file is not ignored by git. Not available when invoked as part of C or C. +=item C<-m> + +Use metadata (C and C) to find the last change date to +substitute. Often used with C<-f>. This is useful for cleaning up dates in files that were not +updated when last changed. (Do not use C/C after C +or the changes will be overwritten with the current date.) + =back 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; diff --git a/src/mkobj.c b/src/mkobj.c index 65ced725a..29de61ea6 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 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -15,6 +15,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 */ @@ -1967,18 +1968,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"); @@ -1991,16 +1992,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?] */ } @@ -2014,15 +2015,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; + } + } } } @@ -2036,18 +2062,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" }; @@ -2061,8 +2087,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]; } @@ -2078,19 +2104,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); } } @@ -2108,37 +2134,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 diff --git a/src/mon.c b/src/mon.c index f3af79b6f..b025baebf 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.5 mon.c $NHDT-Date: 1430433254 2015/04/30 22:34:14 $ $NHDT-Branch: win32-x64-working $:$NHDT-Revision: 1.171 $ */ +/* NetHack 3.5 mon.c $NHDT-Date: 1430480373 2015/05/01 11:39:33 $ $NHDT-Branch: master $:$NHDT-Revision: 1.170 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1866,7 +1866,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(); } diff --git a/src/options.c b/src/options.c index b4c814fee..48c12a0a1 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* NetHack 3.5 options.c $NHDT-Date: 1430192504 2015/04/28 03:41:44 $ $NHDT-Branch: master $:$NHDT-Revision: 1.189 $ */ +/* NetHack 3.5 options.c $NHDT-Date: 1430441885 2015/05/01 00:58:05 $ $NHDT-Branch: master $:$NHDT-Revision: 1.191 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -500,7 +500,7 @@ STATIC_OVL int FDECL(count_ape_maps, (int *, int *)); STATIC_DCL const char *FDECL(clr2colorname, (int)); STATIC_DCL const char *FDECL(attr2attrname, (int)); STATIC_DCL int NDECL(query_color); -STATIC_DCL int FDECL(query_attr, (char *)); +STATIC_DCL int FDECL(query_attr, (const char *)); STATIC_DCL boolean FDECL(add_menu_coloring_parsed, (char *, int, int)); STATIC_DCL void FDECL(free_one_menu_coloring, (int)); STATIC_DCL int NDECL(count_menucolors); @@ -1220,7 +1220,7 @@ query_color() int query_attr(prompt) -char *prompt; +const char *prompt; { winid tmpwin; anything any; @@ -1232,7 +1232,8 @@ char *prompt; any = zeroany; for (i = 0; i < SIZE(attrnames); i++) { any.a_int = i + 1; - add_menu(tmpwin, NO_GLYPH, &any, 0, 0, attrnames[i].attr, attrnames[i].name, MENU_UNSELECTED); + add_menu(tmpwin, NO_GLYPH, &any, 0, 0, + attrnames[i].attr, attrnames[i].name, MENU_UNSELECTED); } end_menu(tmpwin, prompt ? prompt : "Pick an attribute"); pick_cnt = select_menu(tmpwin, PICK_ONE, &picks); @@ -3569,6 +3570,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;