Show your approximate accumulated score on bottom line (default off).
.lp "silent "
Suppress terminal beeps (default on).
+.lp sortloot
+Controls the sorting behavior of the pickup lists for inventory
+and #loot commands and some others.
+The possible values are:
+.PS full
+.PL full
+always sort the lists;
+.PL loot
+only sort the lists that don't use inventory letters, like with
+the #loot and pickup commands;
+.PL none
+show lists the traditional way without sorting.
+.PE
.lp sortpack
Sort the pack contents by type when displaying inventory (default on).
.lp sparkle
\item[\ib{silent}]
Suppress terminal beeps (default on).
%.lp
+\item[\ib{sortloot}]
+Controls the sorting behavior of pickup lists for inventory
+and \#loot commands and some others.
+
+The possible values are:
+%.sd
+%.si
+{\tt full} --- always sort the lists;\\
+{\tt loot} --- only sort the lists that don't use inventory
+ letters, like with the \#loot and pickup commands;\\
+{\tt none} --- show lists the traditional way without sorting.
+%.ei
+%.ed
+%.lp
\item[\ib{sortpack}]
Sort the pack contents by type when displaying inventory (default on).
%.lp
Aardvark Joe's Extended Logfile
Michael Deutschmann's use_darkgray
Clive Crous' dark_room
+Jukka Lahtinen's sortloot
Code Cleanup and Reorganization
/* ### invent.c ### */
+E struct obj **FDECL(objarr_init, (int));
+E void FDECL(objarr_set, (struct obj *, int, struct obj **, BOOLEAN_P));
E void FDECL(assigninvlet, (struct obj *));
E struct obj *FDECL(merge_choice, (struct obj *,struct obj *));
E int FDECL(merged, (struct obj **,struct obj **));
E boolean FDECL(not_fully_identified, (struct obj *));
E char *FDECL(corpse_xname, (struct obj *,const char *,unsigned));
E char *FDECL(cxname, (struct obj *));
+E char *FDECL(cxname_singular, (struct obj *));
E char *FDECL(killer_xname, (struct obj *));
E char *FDECL(short_oname, (struct obj *,char *(*)(OBJ_P),char *(*)(OBJ_P),
unsigned));
boolean showexp; /* show experience points */
boolean showscore; /* show score */
boolean silent; /* whether the bell rings or not */
+ boolean sortloot; /* sort items alphabetically when looting */
boolean sortpack; /* sorted inventory */
boolean sparkle; /* show "resisting" special FX (Scott Bigham) */
boolean standout; /* use standout for --More-- */
boolean identified, all_containers, reportempty;
{
register struct obj *box, *obj;
+ struct obj **oarray;
+ int i,j,n;
+ char *invlet;
char buf[BUFSZ];
boolean cat, deadcat;
continue; /* wrong type of container */
} else if (box->cobj) {
winid tmpwin = create_nhwindow(NHW_MENU);
+
+ /* count the number of items */
+ for (n = 0, obj = box->cobj; obj; obj = obj->nobj) n++;
+ /* Make a temporary array to store the objects sorted */
+ oarray = objarr_init(n);
+
+ /* Add objects to the array */
+ i = 0;
+ invlet = flags.inv_order;
+ nextclass:
+ for (obj = box->cobj; obj; obj = obj->nobj) {
+ if (!flags.sortpack || obj->oclass == *invlet) {
+ objarr_set(obj, i++, oarray, (flags.sortloot == 'f' || flags.sortloot == 'l') );
+ }
+ } /* for loop */
+ if (flags.sortpack) {
+ if (*++invlet) goto nextclass;
+ }
+
Sprintf(buf, "Contents of %s:", the(xname(box)));
putstr(tmpwin, 0, buf);
putstr(tmpwin, 0, "");
- for (obj = box->cobj; obj; obj = obj->nobj) {
+ for (i = 0; i < n; i++) {
+ obj = oarray[i];
if (identified) {
makeknown(obj->otyp);
obj->known = obj->bknown =
}
putstr(tmpwin, 0, doname(obj));
}
+ free(oarray);
if (cat) putstr(tmpwin, 0, "Schroedinger's cat");
else if (deadcat) putstr(tmpwin, 0, "Schroedinger's dead cat");
display_nhwindow(tmpwin, TRUE);
#define NOINVSYM '#'
#define CONTAINED_SYM '>' /* designator for inside a container */
+STATIC_DCL int FDECL(sortloot_cmp, (struct obj *, struct obj *));
STATIC_DCL void NDECL(reorder_invent);
STATIC_DCL boolean FDECL(mergable,(struct obj *,struct obj *));
STATIC_DCL void FDECL(noarmor, (BOOLEAN_P));
*/
static char venom_inv[] = { VENOM_CLASS, 0 }; /* (constant) */
+
+int
+sortloot_cmp(obj1, obj2)
+struct obj *obj1;
+struct obj *obj2;
+{
+ int val1 = 0;
+ int val2 = 0;
+
+ /* Sort object names in lexicographical order, ignoring quantity. */
+ int name_cmp = strcmpi(cxname_singular(obj1), cxname_singular(obj2));
+
+ if (name_cmp != 0) {
+ return name_cmp;
+ }
+
+ /* Sort by BUC. Map blessed to 4, uncursed to 2, cursed to 1, and unknown to 0. */
+ val1 = obj1->bknown ? (obj1->blessed << 2) + ((!obj1->blessed && !obj1->cursed) << 1) + obj1->cursed : 0;
+ val2 = obj2->bknown ? (obj2->blessed << 2) + ((!obj2->blessed && !obj2->cursed) << 1) + obj2->cursed : 0;
+ if (val1 != val2) {
+ return val2 - val1; /* Because bigger is better. */
+ }
+
+ /* Sort by greasing. This will put the objects in degreasing order. */
+ val1 = obj1->greased;
+ val2 = obj2->greased;
+ if (val1 != val2) {
+ return val2 - val1; /* Because bigger is better. */
+ }
+
+ /* Sort by erosion. The effective amount is what matters. */
+ val1 = greatest_erosion(obj1);
+ val2 = greatest_erosion(obj2);
+ if (val1 != val2) {
+ return val1 - val2; /* Because bigger is WORSE. */
+ }
+
+ /* Sort by erodeproofing. Map known-invulnerable to 1, and both
+ * known-vulnerable and unknown-vulnerability to 0, because that's how they're displayed. */
+ val1 = obj1->rknown && obj1->oerodeproof;
+ val2 = obj2->rknown && obj2->oerodeproof;
+ if (val1 != val2) {
+ return val2 - val1; /* Because bigger is better. */
+ }
+
+ /* Sort by enchantment. Map unknown to -1000, which is comfortably below the range of ->spe. */
+ val1 = obj1->known ? obj1->spe : -1000;
+ val2 = obj2->known ? obj2->spe : -1000;
+ if (val1 != val2) {
+ return val2 - val1; /* Because bigger is better. */
+ }
+
+ return 0; /* They're identical, as far as we're concerned. */
+}
+
+struct obj **
+objarr_init(n)
+int n;
+{
+ return (struct obj **)alloc(n * sizeof(struct obj *));
+}
+
+void
+objarr_set(otmp, idx, oarray, dosort)
+struct obj *otmp;
+int idx;
+struct obj **oarray;
+boolean dosort;
+{
+ if (dosort) {
+ int j;
+ for (j = idx; j; j--) {
+ if (sortloot_cmp(otmp, oarray[j-1]) > 0) break;
+ oarray[j] = oarray[j-1];
+ }
+ oarray[j] = otmp;
+ } else {
+ oarray[idx] = otmp;
+ }
+}
+
+
void
assigninvlet(otmp)
register struct obj *otmp;
static winid local_win = WIN_ERR; /* window for partial menus */
anything any;
menu_item *selected;
+ struct obj **oarray;
+ int i, j;
/* overriden by global flag */
if (flags.perm_invent) {
return ret;
}
+ /* count the number of items */
+ for (n = 0, otmp = invent; otmp; otmp = otmp->nobj)
+ if (!lets || !*lets || index(lets, otmp->invlet)) n++;
+
+ oarray = objarr_init(n);
+
+ /* Add objects to the array */
+ i = 0;
+ for (otmp = invent; otmp; otmp = otmp->nobj)
+ if (!lets || !*lets || index(lets, otmp->invlet)) {
+ objarr_set(otmp, i++, oarray, (flags.sortloot == 'f'));
+ }
+
start_menu(win);
if (wizard && iflags.override_ID) {
char prompt[BUFSZ];
nextclass:
classcount = 0;
any = zeroany; /* set all bits to zero */
- for(otmp = invent; otmp; otmp = otmp->nobj) {
- ilet = otmp->invlet;
- if(!lets || !*lets || index(lets, ilet)) {
- any = zeroany; /* zero */
- if (!flags.sortpack || otmp->oclass == *invlet) {
- if (flags.sortpack && !classcount) {
- add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
+ for(i = 0; i < n; i++) {
+ otmp = oarray[i];
+ ilet = otmp->invlet;
+ any = zeroany; /* zero */
+ if (!flags.sortpack || otmp->oclass == *invlet) {
+ if (flags.sortpack && !classcount) {
+ add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
let_to_name(*invlet, FALSE, (want_reply && iflags.menu_head_objsym)), MENU_UNSELECTED);
- classcount++;
- }
- any.a_char = ilet;
- add_menu(win, obj_to_glyph(otmp),
- &any, ilet, 0, ATR_NONE, doname(otmp),
- MENU_UNSELECTED);
- }
+ classcount++;
}
+ any.a_char = ilet;
+ add_menu(win, obj_to_glyph(otmp),
+ &any, ilet, 0, ATR_NONE, doname(otmp),
+ MENU_UNSELECTED);
+ }
}
if (flags.sortpack) {
if (*++invlet) goto nextclass;
goto nextclass;
}
}
+ free(oarray);
end_menu(win, (char *) 0);
n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected);
STATIC_DCL boolean FDECL(singplur_lookup, (char *,char *,BOOLEAN_P,
const char *const *));
STATIC_DCL char *FDECL(singplur_compound, (char *));
+STATIC_DCL char *FDECL(xname_flags, (struct obj *, unsigned));
+
struct Jitem {
int item;
char *
xname(obj)
+struct obj *obj;
+{
+ return xname_flags(obj, CXN_NORMAL);
+}
+
+char *
+xname_flags(obj, cxn_flags)
register struct obj *obj;
+unsigned cxn_flags; /* bitmask of CXN_xxx values */
{
register char *buf;
register int typ = obj->otyp;
const char *actualn = OBJ_NAME(*ocl);
const char *dn = OBJ_DESCR(*ocl);
const char *un = ocl->oc_uname;
- boolean pluralize = (obj->quan != 1L);
+ boolean pluralize = (obj->quan != 1L) && !(cxn_flags & CXN_SINGULAR);
boolean known, dknown, bknown;
buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */
return xname(obj);
}
+/* like cxname, but ignores quantity */
+char *
+cxname_singular(obj)
+struct obj *obj;
+{
+ if (obj->otyp == CORPSE)
+ return corpse_xname(obj, (const char *)0, CXN_SINGULAR);
+ return xname_flags(obj, CXN_SINGULAR);
+}
+
/* treat an object as fully ID'd when it might be used as reason for death */
char *
killer_xname(obj)
{ "scroll_amount", "amount to scroll map when scroll_margin is reached",
20, DISP_IN_GAME }, /*WC*/
{ "scroll_margin", "scroll map when this far from the edge", 20, DISP_IN_GAME }, /*WC*/
+ { "sortloot", "sort object selection lists by description", 4, SET_IN_GAME },
#ifdef MSDOS
{ "soundcard", "type of sound card to use", 20, SET_IN_FILE },
#endif
(genericptr_t)def_inv_order, sizeof flags.inv_order);
flags.pickup_types[0] = '\0';
flags.pickup_burden = MOD_ENCUMBER;
+ flags.sortloot = 'l'; /* sort only loot by default */
for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++)
flags.end_disclose[i] = DISCLOSE_PROMPT_DEFAULT_NO;
return;
}
+ fullname = "sortloot";
+ if (match_optname(opts, fullname, 4, TRUE)) {
+ op = string_for_env_opt(fullname, opts, FALSE);
+ if (op) {
+ switch (tolower(*op)) {
+ case 'n':
+ case 'l':
+ case 'f': flags.sortloot = tolower(*op);
+ break;
+ default: badoption(opts);
+ return;
+ }
+ }
+ return;
+ }
+
fullname = "suppress_alert";
if (match_optname(opts, fullname, 4, TRUE)) {
if (duplicate) complain_about_duplicate(opts,1);
"teleport", "run", "walk", "crawl"
};
+static NEARDATA const char *sortltype[] = {
+ "none", "loot", "full"
+};
+
/*
* Convert the given string of object classes to a string of default object
* symbols.
char buf[BUFSZ];
/* Special handling of menustyle, pickup_burden, pickup_types,
- * disclose, runmode, msg_window, menu_headings, and number_pad options.
+ * disclose, runmode, msg_window, menu_headings, sortloot,
+ * and number_pad options.
* Also takes care of interactive autopickup_exception_handling changes.
*/
if (!strcmp("menustyle", optname)) {
}
destroy_nhwindow(tmpwin);
#endif
+ } else if (!strcmp("sortloot", optname)) {
+ const char *sortl_name;
+ menu_item *sortl_pick = (menu_item *)0;
+ tmpwin = create_nhwindow(NHW_MENU);
+ start_menu(tmpwin);
+ for (i = 0; i < SIZE(sortltype); i++) {
+ sortl_name = sortltype[i];
+ any.a_char = *sortl_name;
+ add_menu(tmpwin, NO_GLYPH, &any, *sortl_name, 0,
+ ATR_NONE, sortl_name, MENU_UNSELECTED);
+ }
+ end_menu(tmpwin, "Select loot sorting type:");
+ if (select_menu(tmpwin, PICK_ONE, &sortl_pick) > 0) {
+ flags.sortloot = sortl_pick->item.a_char;
+ free((genericptr_t)sortl_pick);
+ }
+ destroy_nhwindow(tmpwin);
} else if (!strcmp("align_message", optname) ||
!strcmp("align_status", optname)) {
menu_item *window_pick = (menu_item *)0;
if (iflags.wc_scroll_margin) Sprintf(buf, "%d",iflags.wc_scroll_margin);
else Strcpy(buf, defopt);
}
+ else if (!strcmp(optname, "sortloot")) {
+ char *sortname = (char *)NULL;
+ for (i=0; i < SIZE(sortltype) && sortname==(char *)NULL; i++) {
+ if (flags.sortloot == sortltype[i][0])
+ sortname = (char *)sortltype[i];
+ }
+ if (sortname != (char *)NULL)
+ Sprintf(buf, "%s", sortname);
+ }
else if (!strcmp(optname, "player_selection"))
Sprintf(buf, "%s", iflags.wc_player_selection ? "prompts" : "dialog");
#ifdef MSDOS
int how; /* type of query */
boolean FDECL((*allow), (OBJ_P));/* allow function */
{
- int n;
+ int i, j, n;
winid win;
struct obj *curr, *last, fake_hero_object;
+ struct obj **oarray;
char *pack;
anything any;
boolean printed_type_name,
return 1;
}
+ oarray = objarr_init(n);
+ /* Add objects to the array */
+ i = 0;
+ for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
+ if ((*allow)(curr)) {
+ objarr_set(curr, i++, oarray, (flags.sortloot == 'f' ||
+ (flags.sortloot == 'l' && !(qflags & USE_INVLET))));
+ }
+ }
+
win = create_nhwindow(NHW_MENU);
start_menu(win);
any = zeroany;
pack = flags.inv_order;
do {
printed_type_name = FALSE;
- for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
+ for (i = 0; i < n; i++) {
+ curr = oarray[i];
if ((qflags & FEEL_COCKATRICE) && curr->otyp == CORPSE &&
will_feel_cockatrice(curr, FALSE)) {
destroy_nhwindow(win); /* stop the menu and revert */
}
pack++;
} while (sorted && *pack);
+ free(oarray);
if (engulfer) {
char buf[BUFSZ];