diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index 5b11d201e..982a2ed3c 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -675,6 +675,12 @@ compiled with. Adjust inventory letters (most useful when the .op fixinv option is ``on''). +This command allows you to move an item from one particular inventory +slot to another so that it has a letter which is more meaningful for you +or that it will appear in a particular location when inventory listings +are displayed. +``#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 #chat Talk to someone. .lp #conduct diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 96e384422..c411981d4 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -27,7 +27,7 @@ \begin{document} % % input file: guidebook.mn -% $Revision: 1.85 $ $Date: 2004/10/28 01:48:52 $ +% $Revision: 1.86 $ $Date: 2004/10/30 01:44:12 $ % %.ds h0 " %.ds h1 %.ds h2 \% @@ -894,6 +894,12 @@ the game was compiled with. Adjust inventory letters (most useful when the {\it fixinv\/} option is ``on''). +This command allows you to move an item from one particular inventory +slot to another so that it has a letter which is more meaningful for you +or that it will appear in a particular location when inventory listings +are displayed. +``{\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 \item[\tb{\#chat}] Talk to someone. diff --git a/doc/fixes34.4 b/doc/fixes34.4 index 7e779e615..6ce129750 100644 --- a/doc/fixes34.4 +++ b/doc/fixes34.4 @@ -79,6 +79,7 @@ when you're teetering on the edge of a pit you can use '>' to enter the pit when asked for a direction, a response of '?' yields help and then asks again when adding an item to inventory, try to stack it with the quiver slot before trying against other carried objects +#adjust can be used to split an inventory stack Platform- and/or Interface-Specific New Features diff --git a/src/invent.c b/src/invent.c index e808c519b..d8b01f111 100644 --- a/src/invent.c +++ b/src/invent.c @@ -2616,16 +2616,30 @@ reassign() * 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. + * + * 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 + * to the destination, and the only candidate for merging with + * it is the stack already at the 'to' slot, if any. When the + * destination is non-empty but won't merge, whatever is there + * 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. */ int doorganize() /* inventory organizer by Del Lamb */ { - struct obj *obj, *otmp; + struct obj *obj, *otmp, *splitting, *bumped; register int ix, cur; register char let; char alphabet[52+1], buf[52+1]; char qbuf[QBUFSZ]; - char allowall[2]; + char allowall[3]; /* { ALLOW_COUNT, ALL_CLASSES, 0 } */ const char *adj_type; if (!invent) { @@ -2636,16 +2650,26 @@ doorganize() /* inventory organizer by Del Lamb */ if (!flags.invlet_constant) reassign(); /* get object the user wants to organize (the 'from' slot) */ - allowall[0] = ALL_CLASSES; allowall[1] = '\0'; + allowall[0] = ALLOW_COUNT; + allowall[1] = ALL_CLASSES; + allowall[2] = '\0'; if (!(obj = getobj(allowall,"adjust"))) return(0); + /* figure out whether user gave a split count to getobj() */ + splitting = bumped = 0; + 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 */ for (ix = 0, let = 'a'; let <= 'z'; ) alphabet[ix++] = let++; for (let = 'A'; let <= 'Z'; ) alphabet[ix++] = let++; alphabet[ix] = '\0'; /* for floating inv letters, truncate list after the first open slot */ if (!flags.invlet_constant && (ix = inv_cnt()) < 52) - alphabet[ix + 1] = '\0'; + alphabet[ix + (splitting ? 0 : 1)] = '\0'; /* blank out all the letters currently in use in the inventory */ /* except those that will be merged with the selected object */ @@ -2667,7 +2691,12 @@ doorganize() /* inventory organizer by Del Lamb */ Sprintf(qbuf, "Adjust letter to what [%s]?", buf); for (;;) { let = yn_function(qbuf, (char *)0, '\0'); - if (index(quitchars, let)) { + if (index(quitchars, let) || + /* adjusting to same slot is meaningful since all + compatible stacks get collected along the way, + but splitting to same slot is not */ + (splitting && let == obj->invlet)) { + if (splitting) (void) merged(&splitting, &obj); pline(Never_mind); return 0; } @@ -2676,7 +2705,7 @@ doorganize() /* inventory organizer by Del Lamb */ } /* change the inventory and print the resulting item */ - adj_type = "Moving:"; + adj_type = !splitting ? "Moving:" : "Splitting:"; /* * don't use freeinv/addinv to avoid double-touching artifacts, @@ -2684,19 +2713,51 @@ doorganize() /* inventory organizer by Del Lamb */ */ extract_nobj(obj, &invent); - for (otmp = invent; otmp;) - if (merged(&otmp,&obj)) { - adj_type = "Merging:"; - obj = otmp; - otmp = otmp->nobj; - extract_nobj(obj, &invent); - } else { - if (otmp->invlet == let) { - adj_type = "Swapping:"; - otmp->invlet = obj->invlet; - } - otmp = otmp->nobj; + for (otmp = invent; otmp; ) { + if (!splitting) { + if (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) { + 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 = obj->onamelth; + + /* 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)) { + obj->onamelth = 0; + /* restore name iff merging is still not possible */ + if (!mergable(otmp, obj)) obj->onamelth = olth; + } + + if (merged(&otmp, &obj)) { + obj = otmp; + extract_nobj(obj, &invent); + } else if (inv_cnt() >= 52) { + (void) merged(&splitting, &obj); /* undo split */ + /* "knapsack cannot accommodate any more items" */ + Your("pack is too full."); + return 0; + } else { + bumped = otmp; + extract_nobj(bumped, &invent); + } + break; + } /* found 'to' slot */ + } /* splitting */ + otmp = otmp->nobj; + } /* inline addinv; insert loose object at beginning of inventory */ obj->invlet = let; @@ -2704,8 +2765,20 @@ doorganize() /* inventory organizer by Del Lamb */ obj->where = OBJ_INVENT; invent = obj; reorder_invent(); + if (bumped) { + /* splitting the 'from' stack is causing an incompatible + stack in the 'to' slot to be moved into an open one; + we need to do another inline insertion to inventory */ + assigninvlet(bumped); + bumped->nobj = invent; + bumped->where = OBJ_INVENT; + invent = bumped; + reorder_invent(); + } + /* messages deferred until inventory has been fully reestablished */ prinv(adj_type, obj, 0L); + if (bumped) prinv("Moving:", bumped, 0L); update_inventory(); return(0); }