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.
This commit is contained in:
PatR
2017-12-05 03:38:23 -08:00
parent fdf07f932b
commit d7f26afba8
4 changed files with 102 additions and 70 deletions
+14 -6
View File
@@ -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 h0 "NetHack Guidebook
.ds h1 .ds h1
.ds h2 % .ds h2 %
@@ -930,11 +930,19 @@ being moved.
``#adjust'' can also be used to split a stack of objects; when ``#adjust'' can also be used to split a stack of objects; when
choosing the item to adjust, enter a count prior to its letter. choosing the item to adjust, enter a count prior to its letter.
.lp "" .lp ""
When no count is given, other compatible stacks are merged with the source Adjusting without a count used to collect all compatible stacks when
stack as it's moved to the destination. When a split count is given, the moving to the destination. That behavior has been changed; to gather
only stack that might be merged is the one already in the destination. compatible stacks, ``#adjust'' a stack into its own inventory slot.
To move a whole stack without having other compatible ones merge with it, If it has a name assigned, other stacks with the same name or with
specify a ``split'' count which matches the full stack size. 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 .lp #annotate
Allows you to specify one line of text to associate with the current Allows you to specify one line of text to associate with the current
dungeon level. All levels with annotations are displayed by the dungeon level. All levels with annotations are displayed by the
+13 -5
View File
@@ -1110,11 +1110,19 @@ being moved.
``{\tt \#adjust}'' can also be used to split a stack of objects; when ``{\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.\\ choosing the item to adjust, enter a count prior to its letter.\\
%.lp "" %.lp ""
When no count is given, other compatible stacks are merged with the source Adjusting without a count used to collect all compatible stacks when
stack as it's moved to the destination. When a split count is given, the moving to the destination. That behavior has been changed; to gather
only stack that might be merged is the one already in the destination. compatible stacks, ``{\tt \#adjust}'' a stack into its own inventory slot.
To move a whole stack without having other compatible ones merge with it, If it has a name assigned, other stacks with the same name or with
specify a ``split'' count which matches the full stack size. 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 %.lp
\item[\tb{\#annotate}] \item[\tb{\#annotate}]
Allows you to specify one line of text to associate with the current Allows you to specify one line of text to associate with the current
+3 -3
View File
@@ -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 "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 option herecmd_menu to make a mouse click on your character pop up
a context menu, and extended command #herecmdmenu to do the same a context menu, and extended command #herecmdmenu to do the same
for #adjust, specifying a split count which matches an inventory slot's full change #adjust's behavior when collecting compatible stacks; that used to
size will move or swap that stack without combining other compatible occur for any #adjust which lacked a split count, now it only happens
stacks (except for the one in the destination slot, if applicable) when 'adjusting' into a stack's own inventory slot
Platform- and/or Interface-Specific New Features Platform- and/or Interface-Specific New Features
+72 -56
View File
@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1472,9 +1472,6 @@ redo_menu:
else if (otmp->otyp == LOADSTONE && otmp->cursed) else if (otmp->otyp == LOADSTONE && otmp->cursed)
/* kludge for canletgo()'s can't-drop-this message */ /* kludge for canletgo()'s can't-drop-this message */
otmp->corpsenm = (int) cnt; otmp->corpsenm = (int) cnt;
} else if (!strcmp(word, "adjust")) {
/* specifying stack's full count means something to #adjust */
otmp->nomerge = 1;
} }
} }
return otmp; return otmp;
@@ -3539,10 +3536,18 @@ reassign()
* then a 'to' slot for its destination. Open slots and those * then a 'to' slot for its destination. Open slots and those
* filled by compatible stacks are listed as likely candidates * filled by compatible stacks are listed as likely candidates
* but user can pick any inventory letter (including 'from'). * 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, * If the user specifies a count when choosing the 'from' slot,
* and that count is less than the full size of the stack, * and that count is less than the full size of the stack,
* then the stack will be split. The 'count' portion is moved * 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 * will be moved to an open slot; if there isn't any open slot
* available, the adjustment attempt fails. * available, the adjustment attempt fails.
* *
* Splitting has one special case: if 'to' slot is non-empty * To minimize merging for 'from == to', unnamed stacks will
* and is compatible with 'from' in all respects except for * merge with named 'from' but named ones won't merge with
* user-assigned names, the 'count' portion being moved is * unnamed 'from'. Otherwise attempting to collect all unnamed
* effectively renamed so that it will merge with 'to' stack. * 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 int
doorganize() /* inventory organizer by Del Lamb */ 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 lets[1 + 52 + 1 + 1]; /* room for '$a-zA-Z#\0' */
char qbuf[QBUFSZ]; char qbuf[QBUFSZ];
char allowall[4]; /* { ALLOW_COUNT, ALL_CLASSES, 0, 0 } */ char allowall[4]; /* { ALLOW_COUNT, ALL_CLASSES, 0, 0 } */
char *objname, *otmpname;
const char *adj_type; const char *adj_type;
boolean ever_mind = FALSE, dont_collect = FALSE; boolean ever_mind = FALSE, collect;
if (!invent) { if (!invent) {
You("aren't carrying anything to adjust."); 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() */ /* figure out whether user gave a split count to getobj() */
splitting = bumped = 0; splitting = bumped = 0;
if (obj->nomerge) { for (otmp = invent; otmp; otmp = otmp->nobj)
/* player specified full count; no split occurred and we'll if (otmp->nobj == obj) { /* knowledge of splitobj() operation */
avoid collecting compatible stacks when moving this one */ if (otmp->invlet == obj->invlet)
obj->nomerge = 0; splitting = otmp;
dont_collect = TRUE; break;
} else { }
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 */ /* initialize the list with all lower and upper case letters */
lets[GOLD_INDX] = (obj->oclass == COIN_CLASS) ? GOLD_SYM : ' '; 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 /* adjusting to same slot is meaningful since all
compatible stacks get collected along the way, compatible stacks get collected along the way,
but splitting to same slot is not */ but splitting to same slot is not */
|| ((splitting || dont_collect) && let == obj->invlet)) { || (splitting && let == obj->invlet)) {
noadjust: noadjust:
if (splitting) if (splitting)
(void) merged(&splitting, &obj); (void) merged(&splitting, &obj);
@@ -3691,8 +3699,9 @@ doorganize() /* inventory organizer by Del Lamb */
pline("Select an inventory slot letter."); /* else try again */ pline("Select an inventory slot letter."); /* else try again */
} }
collect = (let == obj->invlet);
/* change the inventory and print the resulting item */ /* 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, * don't use freeinv/addinv to avoid double-touching artifacts,
@@ -3701,45 +3710,52 @@ doorganize() /* inventory organizer by Del Lamb */
extract_nobj(obj, &invent); extract_nobj(obj, &invent);
for (otmp = invent; otmp;) { for (otmp = invent; otmp;) {
if (!splitting && !dont_collect) { /* it's tempting to pull this outside the loop, but merged() could
if (merged(&otmp, &obj)) { 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:"; adj_type = "Merging:";
obj = otmp; obj = otmp;
otmp = otmp->nobj; otmp = otmp->nobj;
extract_nobj(obj, &invent); extract_nobj(obj, &invent);
continue; /* otmp has already been updated */ 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:"; adj_type = "Swapping:";
otmp->invlet = obj->invlet; otmp->invlet = obj->invlet;
} } else {
} else { /* strip 'from' name if it has one */
/* splitting: don't merge extra compatible stacks; if (objname && !obj->oartifact)
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);
ONAME(obj) = (char *) 0; ONAME(obj) = (char *) 0;
/* restore name iff merging is still not possible */ if (!mergable(otmp, obj)) {
if (!mergable(otmp, obj)) { /* won't merge; put 'from' name back */
ONAME(obj) = holdname; if (objname)
holdname = (char *) 0; ONAME(obj) = objname;
} else } else {
free((genericptr_t) holdname); /* will merge; discard 'from' name */
if (objname)
free((genericptr_t) objname), objname = 0;
} }
if (merged(&otmp, &obj)) { if (merged(&otmp, &obj)) {
adj_type = "Splitting and merging:";
obj = otmp; obj = otmp;
extract_nobj(obj, &invent); extract_nobj(obj, &invent);
} else if (inv_cnt(FALSE) >= 52 && !dont_collect) { } else if (inv_cnt(FALSE) >= 52) {
(void) merged(&splitting, &obj); /* undo split */ (void) merged(&splitting, &obj); /* undo split */
/* "knapsack cannot accommodate any more items" */ /* "knapsack cannot accommodate any more items" */
Your("pack is too full."); Your("pack is too full.");
@@ -3748,9 +3764,9 @@ doorganize() /* inventory organizer by Del Lamb */
bumped = otmp; bumped = otmp;
extract_nobj(bumped, &invent); extract_nobj(bumped, &invent);
} }
break; } /* moving vs splitting */
} /* found 'to' slot */ break; /* not collecting and found 'to' slot */
} /* splitting */ } /* collect */
otmp = otmp->nobj; otmp = otmp->nobj;
} }