[net.games.hack] Sorted Inventories for HACK 1.0.3

barry@adelie.UUCP (Barry A. Burke) (01/20/86)

Well, I don't know where the line-eater lives, but he sure must have
been HUNGRY to eat over 100 lines!  Maybe there's something wacky in the
posting- if anybody sees anything, please let me know.

Anyway- here, in it's entirety (I hope), is my original posting...

> Relay-Version: version B 2.10.2 Adelie 8/14/85; site adelie.UUCP
> Posting-Version: version B 2.10.2 Adelie 8/14/85; site adelie.UUCP
> Path: adelie!barry
> From: barry@adelie.UUCP (Barry A. Burke)
> Newsgroups: net.games.hack
> Subject: Sorted Inventory List for 1.0.3 (UN*X Version)
> Message-ID: <570@adelie.UUCP>
> Date: 14 Jan 86 03:24:17 GMT
> Date-Received: 14 Jan 86 03:24:17 GMT
> Reply-To: barry@adelie.UUCP (Barry A. Burke)
> Distribution: net
> Organization: Adelie Corporation, Newtonville MA
> Lines: 390
> Summary:  User defined sort order via HACKOPTIONS
> Keywords:
>
>
> I recently aquired the sources to hack 1.0.3 and several patches to go
> with them.  One was a patch that caused inventory lists to be
> constructed in a pre-defined sort order, but it apparently was for the
> PC version of Hack, not the UNIX version.  So, I undertook to
> "correctly" implement sorted object lists.  At the same time I cleaned
> up the help file and the "O"ptions references within the code (kept
> saying that options were set with "o" instead of "O").
>
> Here's the info file I posted locally to tell the players about the
> change, followed by the diff -c for the modified files: patch(L) should
> be able to handle this fine:
>
> ------------------------info file----cut here----------------
>       The inventory list is now presented sorted by object class
>       (weapon, ring, scroll, etc.).  The sort order can be specified
>       with the new HACKOPTIONS string variable `sortobj:<string>',
>       where <string> is the list of object class letters in the
>       preferred order, as in:
>
>                         sortobj:%%=/!?)[(*`
>
>       which is the default sort order.  The letters stand for:
>
>               %       Food & corpses (doubled just to avoid `printf' probs)
>               =       Rings
>               /       Wands
>               !       Potions
>               ?       Scrolls
>               )       Weapons
>               [       Armor
>               (       Tools
>               *       Gems
>               `       Rocks
>
>
>       The sortobj string needn't contain all the valid letters,
>       unspecified items will be placed at the end of your inventory
>       list.  Thus, sorting can be totally overridden by specifying a
>       null or invalid sort string:
>
>                              sortobj:$
>
>       If you display the current sortobj string, you may notice a
>       leading dollar sign ($).  This is prepended to any string in
>       order to make my somewhat obscure use of "index" work- I gues I
>       could have printf'd (pline'd) sortlist[1], but I didn't bother.
>       Since gold ($) is no longer listed in the inventory, this
>       shouldn't cause any problems.
>
>       The sorted object list is especially nice if used in conjunction
>       with the "nofixinv" option.  If you put this switch in your
>       HACKOPTIONS, the inventory list is "compressed" each time you
>       use up (or drop) an item, and then the letter identifiers are
>       re-assigned, starting at "a".  The default sortobj + nofixinv
>       results in item "a" almost always being FOOD! (kinda neat)
>
>       [Author's Note: sorting without the nofixinv option results in a
>       pretty confusing inventory list- you'll probably want to enable
>       fixinv or disable sorting].
>
> -----------------------patch stuff---------cut here-----------------------
> *** config.h.old      Sun Jan  5 12:02:22 1986
> --- config.h  Wed Jan  8 14:20:31 1986
> ***************
> *** 37,42
>   #define     FMASK   0660    /* file creation mask */
>   #define     HLOCK   "perm"  /* an empty file used for locking purposes */
>   #define LLOCK       "safelock"      /* link to previous */
>
>   #ifdef UNIX
>   /*
>
> --- 37,49 -----
>   #define     FMASK   0660    /* file creation mask */
>   #define     HLOCK   "perm"  /* an empty file used for locking purposes */
>   #define LLOCK       "safelock"      /* link to previous */
> + /*
> +  * Change SORTOBJ to a null string if you don't want items sorted by default.
> +  * User can override this with "sortobj" string in HACKOPTIONS
> +  * 1-8-86 Barry A. Burke  (barry@adelie.UUCP)
> +  */
> + #define SORTOBJ "%%=/!?)[(*`" /* sort order for invent, set=null for no sort */
> + #define SOBJLEN 20                /* maximum length of string (be generous) */
>
>   #ifdef UNIX
>   /*
> *** hack.Decl.c.orig  Mon Dec 23 11:38:23 1985
> --- hack.Decl.c       Sun Jan  5 15:51:23 1986
> ***************
> *** 5,10
>   char nul[40];                       /* contains zeros */
>   char plname[PL_NSIZ];               /* player name */
>   char lock[PL_NSIZ+4] = "1lock";     /* long enough for login name .99 */
>
>   boolean in_mklev, restoring;
>
>
> --- 5,11 -----
>   char nul[40];                       /* contains zeros */
>   char plname[PL_NSIZ];               /* player name */
>   char lock[PL_NSIZ+4] = "1lock";     /* long enough for login name .99 */
> + char sortlist[SOBJLEN+1];           /* sort order for inventory list */
>
>   boolean in_mklev, restoring;
>
> *** hack.invent.c.old Tue Dec 31 15:48:32 1985
> --- hack.invent.c     Mon Jan  6 22:54:27 1986
> ***************
> *** 43,48
>                       (i < 26) ? ('a'+i) : ('A'+i-26));
>       lastinvnr = i;
>   }
>
>   struct obj *
>   addinv(obj)
>
> --- 43,50 -----
>                       (i < 26) ? ('a'+i) : ('A'+i-26));
>       lastinvnr = i;
>   }
> + /* Barry A. Burke <barry@adelie.UUCP> modified addinv() Jan  6, 1985 to
> +    sort the inventory list by type. */
>
>   struct obj *
>   addinv(obj)
> ***************
> *** 49,54
>   register struct obj *obj;
>   {
>       register struct obj *otmp;
>
>       /* merge or attach to end of chain */
>       if(!invent) {
>
> --- 51,58 -----
>   register struct obj *obj;
>   {
>       register struct obj *otmp;
> +     int i;
> +     extern char sortlist[];
>
>       /* merge or attach to end of chain */
>       if(!invent) {
> ***************
> *** 65,91
>       }
>       obj->nobj = 0;
>
> !     if(flags.invlet_constant) {
> !             assigninvlet(obj);
> !             /*
> !              * The ordering of the chain is nowhere significant
> !              * so in case you prefer some other order than the
> !              * historical one, change the code below.
> !              */
> !             if(otmp) {      /* find proper place in chain */
> !                     otmp->nobj = 0;
> !                     if((invent->invlet ^ 040) > (obj->invlet ^ 040)) {
> !                             obj->nobj = invent;
> !                             invent = obj;
> !                     } else
> !                     for(otmp = invent; ; otmp = otmp->nobj) {
> !                         if(!otmp->nobj ||
> !                             (otmp->nobj->invlet ^ 040) > (obj->invlet ^ 040)){
> !                             obj->nobj = otmp->nobj;
> !                             otmp->nobj = obj;
> !                             break;
> !                         }
> !                     }
>               }
>       }
>
>
> --- 69,95 -----
>       }
>       obj->nobj = 0;
>
> !     if(flags.invlet_constant)
> !             assigninvlet(obj);     /* gotta have a letter assigned! */
> !
> !     /* Now, let's sort the new object into the list by object type. */
> !             i = (int) (index(sortlist, obj->olet) - sortlist);
> !     if ( i <= 0 )
> !             i = 100;
> !
> !     if(otmp) {      /* find proper place in chain */
> !             otmp->nobj = 0;
> !             if ( i < (int) (index(sortlist, invent->olet) - sortlist)) {
> !                     obj->nobj = invent;
> !                     invent = obj;
> !             } else
> !             for(otmp = invent; ; otmp = otmp->nobj) {
> !                 if(!otmp->nobj ||
> !                     (i<(int)(index(sortlist,otmp->nobj->olet)-sortlist))) {
> !                     obj->nobj = otmp->nobj;
> !                     otmp->nobj = obj;
> !                     break;
> !                 }
>               }
>       }
>
> *** hack.options.c.orig       Mon Dec 23 11:40:24 1985
> --- hack.options.c    Wed Jan  8 14:23:38 1986
> ***************
> *** 5,10
>   #include "hack.h"
>   extern char *eos();
>
>   initoptions()
>   {
>       register char *opts;
>
> --- 5,12 -----
>   #include "hack.h"
>   extern char *eos();
>
> + extern char sortlist[];
> +
>   initoptions()
>   {
>       register char *opts;
> ***************
> *** 17,22
>       flags.end_top = 5;
>       flags.end_around = 4;
>       flags.female = FALSE;                   /* players are usually male */
>
>       if(opts = getenv("HACKOPTIONS"))
>               parseoptions(opts,TRUE);
>
> --- 19,26 -----
>       flags.end_top = 5;
>       flags.end_around = 4;
>       flags.female = FALSE;                   /* players are usually male */
> +     (void) strcpy( sortlist, "$" );         /* gotta seed it for `index' */
> +     (void) strncat( sortlist, SORTOBJ, strlen(SORTOBJ) );
>
>       if(opts = getenv("HACKOPTIONS"))
>               parseoptions(opts,TRUE);
> ***************
> *** 107,112
>               return;
>       }
>
>       /* endgame:5t[op] 5a[round] o[wn] */
>       if(!strncmp(opts,"endgame",3)) {
>               op = index(opts,':');
>
> --- 111,129 -----
>               return;
>       }
>
> +     /* sortobj:string */
> +     if(!strncmp(opts,"sortobj",4)) {
> +             if(!from_env) {
> +               pline("The inventory sort list can be set only from HACKOPTIONS.");
> +               return;
> +             }
> +             op = index(opts,':');
> +             if(!op) goto bad;
> +             (void) strcpy(sortlist, "$");      /* Need an offset of 1 */
> +             (void) strncat(sortlist, op+1, SOBJLEN-1);
> +             return;
> +      }
> +
>       /* endgame:5t[op] 5a[round] o[wn] */
>       if(!strncmp(opts,"endgame",3)) {
>               op = index(opts,':');
> ***************
> *** 145,151
>               if(!strncmp(opts, "help", 4)) {
>                       pline("%s%s%s",
>   "To set options use `HACKOPTIONS=\"<options>\"' in your environment, or ",
> ! "give the command 'o' followed by the line `<options>' while playing. ",
>   "Here <options> is a list of <option>s separated by commas." );
>                       pline("%s%s%s",
>   "Simple (boolean) options are rest_on_space, news, time, ",
>
> --- 162,168 -----
>               if(!strncmp(opts, "help", 4)) {
>                       pline("%s%s%s",
>   "To set options use `HACKOPTIONS=\"<options>\"' in your environment, or ",
> ! "give the command 'O' followed by the line `<options>' while playing. ",
>   "Here <options> is a list of <option>s separated by commas." );
>                       pline("%s%s%s",
>   "Simple (boolean) options are rest_on_space, news, time, ",
> ***************
> *** 149,155
>   "Here <options> is a list of <option>s separated by commas." );
>                       pline("%s%s%s",
>   "Simple (boolean) options are rest_on_space, news, time, ",
> ! "null, tombstone, (fe)male. ",
>   "These can be negated by prefixing them with '!' or \"no\"." );
>                       pline("%s",
>   "A string option is name, as in HACKOPTIONS=\"name:Merlin-W\"." );
>
> --- 166,172 -----
>   "Here <options> is a list of <option>s separated by commas." );
>                       pline("%s%s%s",
>   "Simple (boolean) options are rest_on_space, news, time, ",
> ! "null, tombstone, (fe)male, fixinvlet. ",
>   "These can be negated by prefixing them with '!' or \"no\"." );
>                       pline("%s",
>   "A string option is name, as in HACKOPTIONS=\"name:Merlin-W\"." );
> ***************
> *** 153,158
>   "These can be negated by prefixing them with '!' or \"no\"." );
>                       pline("%s",
>   "A string option is name, as in HACKOPTIONS=\"name:Merlin-W\"." );
>                       pline("%s%s%s",
>   "A compound option is endgame; it is followed by a description of what ",
>   "parts of the scorelist you want to see. You might for example say: ",
>
> --- 170,181 -----
>   "These can be negated by prefixing them with '!' or \"no\"." );
>                       pline("%s",
>   "A string option is name, as in HACKOPTIONS=\"name:Merlin-W\"." );
> +                             pline("%s%s%s%s%s",
> + "A string option is sortobj; it is followed by a list of the 11 object ",
> + "class letters in the order you want inventories sorted.  If all 11 ",
> + "letters are not provided, unspecified items are tacked onto the end; ",
> + "a null string means do no sorting.  The default sort order is \"",
> + SORTOBJ, "\"." );
>                       pline("%s%s%s",
>   "A compound option is endgame; it is followed by a description of what ",
>   "parts of the scorelist you want to see. You might for example say: ",
> ***************
> *** 160,166
>                       return;
>               }
>               pline("Bad option: %s.", opts);
> !             pline("Type `o help<cr>' for help.");
>               return;
>       }
>       puts("Bad syntax in HACKOPTIONS.");
>
> --- 183,189 -----
>                       return;
>               }
>               pline("Bad option: %s.", opts);
> !             pline("Type `O help<cr>' for help.");
>               return;
>       }
>       puts("Bad syntax in HACKOPTIONS.");
> ***************
> *** 187,192
>           if(flags.notombstone) (void) strcat(buf,"notombstone,");
>           if(flags.no_rest_on_space)
>               (void) strcat(buf,"!rest_on_space,");
>           if(flags.end_top != 5 || flags.end_around != 4 || flags.end_own){
>               (void) sprintf(eos(buf), "endgame: %u topscores/%u around me",
>                       flags.end_top, flags.end_around);
>
> --- 210,217 -----
>           if(flags.notombstone) (void) strcat(buf,"notombstone,");
>           if(flags.no_rest_on_space)
>               (void) strcat(buf,"!rest_on_space,");
> +         (void) strcat(buf,"sortobj:");
> +         (void) strcat(buf,sortlist);
>           if(flags.end_top != 5 || flags.end_around != 4 || flags.end_own){
>               (void) sprintf(eos(buf), "endgame: %u topscores/%u around me",
>                       flags.end_top, flags.end_around);
> *** help.orig Mon Dec 23 11:42:07 1985
> --- help      Tue Jan  7 13:21:00 1986
> ***************
> *** 109,114
>               They can be negated by prefixing them with '!' or "no".
>               A string option is name; it supplies the answer to the question
>               "Who are you?"; it may have a suffix.
>               A compound option is endgame; it is followed by a description
>               of what parts of the list of topscorers should be printed
>               when the game is finished.
>
> --- 109,117 -----
>               They can be negated by prefixing them with '!' or "no".
>               A string option is name; it supplies the answer to the question
>               "Who are you?"; it may have a suffix.
> +             A string option is sortobj; this is a list of the object
> +             type letters in the order you would like them shown in
> +             inventories.
>               A compound option is endgame; it is followed by a description
>               of what parts of the list of topscorers should be printed
>               when the game is finished.
>
> --
> LIVE: Barry A. Burke, (617) 965-8480 x26
> USPS: Adelie Corporation, 288 Walnut St., Newtonville, MA  02160
> UUCP: ..!{harvard | decvax!linus!axiom}!adelie!barry
> ARPA: adelie!barry@harvard.HARVARD.EDU, barry%adelie.UUCP@harvard.HARVARD.EDU

--
LIVE:   Barry A. Burke, (617) 965-8480 x26
USPS:   Adelie Corporation, 288 Walnut St., Newtonville, MA  02160
UUCP:   ..!{harvard | decvax!linus!axiom}!adelie!barry
ARPA:   adelie!barry@harvard.HARVARD.EDU, barry%adelie.UUCP@harvard.HARVARD.EDU