From d7f26afba85801f41547de49e5564fc21ad38ceb Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 5 Dec 2017 03:38:23 -0800 Subject: [PATCH] more #adjust (#H6571) Make the suggested change that only adjusting something into its own slot be the way to collect/merge compatible stacks with it, instead of any #adjust without a split count. This removes the previous special case for a count that matches the stack size. Having to know the exact count was not a burden on the player, but being able to move things around without merging with other stacks makes more sense than the original behavior or the hack to work-around that behavior. --- doc/Guidebook.mn | 20 +++++--- doc/Guidebook.tex | 18 +++++-- doc/fixes36.1 | 6 +-- src/invent.c | 128 ++++++++++++++++++++++++++-------------------- 4 files changed, 102 insertions(+), 70 deletions(-) diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index 16199ef81..3989cec93 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -1,4 +1,4 @@ -.\" $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.240 $ $NHDT-Date: 1512098127 2017/12/01 03:15:27 $ +.\" $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.241 $ $NHDT-Date: 1512473628 2017/12/05 11:33:48 $ .ds h0 "NetHack Guidebook .ds h1 .ds h2 % @@ -930,11 +930,19 @@ being moved. ``#adjust'' can also be used to split a stack of objects; when choosing the item to adjust, enter a count prior to its letter. .lp "" -When no count is given, other compatible stacks are merged with the source -stack as it's moved to the destination. When a split count is given, the -only stack that might be merged is the one already in the destination. -To move a whole stack without having other compatible ones merge with it, -specify a ``split'' count which matches the full stack size. +Adjusting without a count used to collect all compatible stacks when +moving to the destination. That behavior has been changed; to gather +compatible stacks, ``#adjust'' a stack into its own inventory slot. +If it has a name assigned, other stacks with the same name or with +no name will merge provided that all their other attributes match. +If it does not have a name, only other stacks with no name are eligible. +In either case, otherwise compatible stacks with a different name +will not be merged. This contrasts with using ``#adjust'' to move +from one slot to a different slot. In that situation, moving (no +count given) a compatible stack will merge if either stack has a +name when the other doesn't and give that name to the result, while +splitting (count given) will ignore the source stack's name when +deciding whether to merge with the destination stack. .lp #annotate Allows you to specify one line of text to associate with the current dungeon level. All levels with annotations are displayed by the diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index e776b02d0..ea948813b 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -1110,11 +1110,19 @@ being moved. ``{\tt \#adjust}'' can also be used to split a stack of objects; when choosing the item to adjust, enter a count prior to its letter.\\ %.lp "" -When no count is given, other compatible stacks are merged with the source -stack as it's moved to the destination. When a split count is given, the -only stack that might be merged is the one already in the destination. -To move a whole stack without having other compatible ones merge with it, -specify a ``split'' count which matches the full stack size. +Adjusting without a count used to collect all compatible stacks when +moving to the destination. That behavior has been changed; to gather +compatible stacks, ``{\tt \#adjust}'' a stack into its own inventory slot. +If it has a name assigned, other stacks with the same name or with +no name will merge provided that all their other attributes match. +If it does not have a name, only other stacks with no name are eligible. +In either case, otherwise compatible stacks with a different name +will not be merged. This contrasts with using ``{\tt \#adjust}'' to move +from one slot to a different slot. In that situation, moving (no +count given) a compatible stack will merge if either stack has a +name when the other doesn't and give that name to the result, while +splitting (count given) will ignore the source stack's name when +deciding whether to merge with the destination stack. %.lp \item[\tb{\#annotate}] Allows you to specify one line of text to associate with the current diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 4e1d79c76..8b27ef999 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -720,9 +720,9 @@ Master Key of Thievery always finds door and chest traps if used to lock or "Elbereth" now erodes based on attacks by the player, not monsters scared option herecmd_menu to make a mouse click on your character pop up a context menu, and extended command #herecmdmenu to do the same -for #adjust, specifying a split count which matches an inventory slot's full - size will move or swap that stack without combining other compatible - stacks (except for the one in the destination slot, if applicable) +change #adjust's behavior when collecting compatible stacks; that used to + occur for any #adjust which lacked a split count, now it only happens + when 'adjusting' into a stack's own inventory slot Platform- and/or Interface-Specific New Features diff --git a/src/invent.c b/src/invent.c index 4a8a68815..89d823eec 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 invent.c $NHDT-Date: 1512096431 2017/12/01 02:47:11 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.222 $ */ +/* NetHack 3.6 invent.c $NHDT-Date: 1512473628 2017/12/05 11:33:48 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.223 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1472,9 +1472,6 @@ redo_menu: else if (otmp->otyp == LOADSTONE && otmp->cursed) /* kludge for canletgo()'s can't-drop-this message */ otmp->corpsenm = (int) cnt; - } else if (!strcmp(word, "adjust")) { - /* specifying stack's full count means something to #adjust */ - otmp->nomerge = 1; } } return otmp; @@ -3539,10 +3536,18 @@ reassign() * then a 'to' slot for its destination. Open slots and those * filled by compatible stacks are listed as likely candidates * but user can pick any inventory letter (including 'from'). - * All compatible items found are gathered into the 'from' - * stack as it is moved. If the 'to' slot isn't empty and - * doesn't merge, then its stack is swapped to the 'from' slot. * + * to == from, 'from' has a name + * All compatible items (same name or no name) are gathered + * into the 'from' stack. No count is allowed. + * to == from, 'from' does not have a name + * All compatible items without a name are gathered into the + * 'from' stack. No count is allowed. Compatible stacks with + * names are left as-is. + * to != from, no count + * Move 'from' to 'to'. If 'to' is not empty, merge 'from' + * into it if possible, otherwise swap it with the 'from' slot. + * to != from, count given * If the user specifies a count when choosing the 'from' slot, * and that count is less than the full size of the stack, * then the stack will be split. The 'count' portion is moved @@ -3552,10 +3557,19 @@ reassign() * will be moved to an open slot; if there isn't any open slot * available, the adjustment attempt fails. * - * Splitting has one special case: if 'to' slot is non-empty - * and is compatible with 'from' in all respects except for - * user-assigned names, the 'count' portion being moved is - * effectively renamed so that it will merge with 'to' stack. + * To minimize merging for 'from == to', unnamed stacks will + * merge with named 'from' but named ones won't merge with + * unnamed 'from'. Otherwise attempting to collect all unnamed + * stacks would lump the first compatible named stack with them + * and give them its name. + * + * To maximize merging for 'from != to', compatible stacks will + * merge when either lacks a name (or they already have the same + * name). When no count is given and one stack has a name and + * the other doesn't, the merged result will have that name. + * However, when splitting results in a merger, the name of the + * destination overrides that of the source, even if destination + * is unnamed and source is named. */ int doorganize() /* inventory organizer by Del Lamb */ @@ -3569,8 +3583,9 @@ doorganize() /* inventory organizer by Del Lamb */ char lets[1 + 52 + 1 + 1]; /* room for '$a-zA-Z#\0' */ char qbuf[QBUFSZ]; char allowall[4]; /* { ALLOW_COUNT, ALL_CLASSES, 0, 0 } */ + char *objname, *otmpname; const char *adj_type; - boolean ever_mind = FALSE, dont_collect = FALSE; + boolean ever_mind = FALSE, collect; if (!invent) { You("aren't carrying anything to adjust."); @@ -3602,19 +3617,12 @@ doorganize() /* inventory organizer by Del Lamb */ /* figure out whether user gave a split count to getobj() */ splitting = bumped = 0; - if (obj->nomerge) { - /* player specified full count; no split occurred and we'll - avoid collecting compatible stacks when moving this one */ - obj->nomerge = 0; - dont_collect = TRUE; - } else { - for (otmp = invent; otmp; otmp = otmp->nobj) - if (otmp->nobj == obj) { /* knowledge of splitobj() operation */ - if (otmp->invlet == obj->invlet) - splitting = otmp; - break; - } - } + for (otmp = invent; otmp; otmp = otmp->nobj) + if (otmp->nobj == obj) { /* knowledge of splitobj() operation */ + if (otmp->invlet == obj->invlet) + splitting = otmp; + break; + } /* initialize the list with all lower and upper case letters */ lets[GOLD_INDX] = (obj->oclass == COIN_CLASS) ? GOLD_SYM : ' '; @@ -3668,7 +3676,7 @@ doorganize() /* inventory organizer by Del Lamb */ /* adjusting to same slot is meaningful since all compatible stacks get collected along the way, but splitting to same slot is not */ - || ((splitting || dont_collect) && let == obj->invlet)) { + || (splitting && let == obj->invlet)) { noadjust: if (splitting) (void) merged(&splitting, &obj); @@ -3691,8 +3699,9 @@ doorganize() /* inventory organizer by Del Lamb */ pline("Select an inventory slot letter."); /* else try again */ } + collect = (let == obj->invlet); /* change the inventory and print the resulting item */ - adj_type = !splitting ? "Moving:" : "Splitting:"; + adj_type = collect ? "Collecting" : !splitting ? "Moving:" : "Splitting:"; /* * don't use freeinv/addinv to avoid double-touching artifacts, @@ -3701,45 +3710,52 @@ doorganize() /* inventory organizer by Del Lamb */ extract_nobj(obj, &invent); for (otmp = invent; otmp;) { - if (!splitting && !dont_collect) { - if (merged(&otmp, &obj)) { + /* it's tempting to pull this outside the loop, but merged() could + free ONAME(obj) [via obfree()] and replace it with ONAME(otmp) */ + objname = has_oname(obj) ? ONAME(obj) : (char *) 0; + + if (collect) { + /* Collecting: #adjust an inventory stack into its same slot; + keep it there and merge other compatible stacks into it. + Traditional inventory behavior is to merge unnamed stacks + with compatible named ones; we only want that if it is + the 'from' stack (obj) with a name and candidate (otmp) + without one, not unnamed 'from' with named candidate. */ + otmpname = has_oname(otmp) ? ONAME(otmp) : (char *) 0; + if ((!otmpname || (objname && !strcmp(objname, otmpname))) + && merged(&otmp, &obj)) { adj_type = "Merging:"; obj = otmp; otmp = otmp->nobj; extract_nobj(obj, &invent); continue; /* otmp has already been updated */ - } else if (otmp->invlet == let) { + } + } else if (otmp->invlet == let) { + /* Moving or splitting: don't merge extra compatible stacks. + Found 'otmp' in destination slot; merge if compatible, + otherwise bump whatever is there to an open slot. */ + if (!splitting) { adj_type = "Swapping:"; otmp->invlet = obj->invlet; - } - } else { - /* splitting: don't merge extra compatible stacks; - if destination is compatible, do merge with it, - otherwise bump whatever is there to an open slot */ - if (otmp->invlet == let) { - int olth = 0; - - if (has_oname(obj)) - olth = strlen(ONAME(obj)); - /* ugly hack: if these objects aren't going to merge - solely because they have conflicting user-assigned - names, strip off the name of the one being moved */ - if (olth && !obj->oartifact && !mergable(otmp, obj)) { - char *holdname = ONAME(obj); - + } else { + /* strip 'from' name if it has one */ + if (objname && !obj->oartifact) ONAME(obj) = (char *) 0; - /* restore name iff merging is still not possible */ - if (!mergable(otmp, obj)) { - ONAME(obj) = holdname; - holdname = (char *) 0; - } else - free((genericptr_t) holdname); + if (!mergable(otmp, obj)) { + /* won't merge; put 'from' name back */ + if (objname) + ONAME(obj) = objname; + } else { + /* will merge; discard 'from' name */ + if (objname) + free((genericptr_t) objname), objname = 0; } if (merged(&otmp, &obj)) { + adj_type = "Splitting and merging:"; obj = otmp; extract_nobj(obj, &invent); - } else if (inv_cnt(FALSE) >= 52 && !dont_collect) { + } else if (inv_cnt(FALSE) >= 52) { (void) merged(&splitting, &obj); /* undo split */ /* "knapsack cannot accommodate any more items" */ Your("pack is too full."); @@ -3748,9 +3764,9 @@ doorganize() /* inventory organizer by Del Lamb */ bumped = otmp; extract_nobj(bumped, &invent); } - break; - } /* found 'to' slot */ - } /* splitting */ + } /* moving vs splitting */ + break; /* not collecting and found 'to' slot */ + } /* collect */ otmp = otmp->nobj; } -- 2.50.1