re-implement pull req #334 - sorting discoveries
The pull request changed \ and ` output to unconditionally show
discoveries in alphabetical order. That's nearly useless except
when looking at prediscovered weapons and armor that fighter
types start out knowing.
This allows the player to choose sorting order via the new
'sortdiscoveries' option. In addition to setting it via
config file or 'O', it can be set via 'm' prefix for \ and `.
Choices are:
o - sort by class, by order of discovery in class (default);
s - sort by 'sortloot' classification which groups sub-class
items (so all helmets before any other armor, then all
gloves, then boots, and so on); within each sub-class, or
whole class for classes which don't subdivide so usefully,
partly-discovered types (where a name has been assigned)
come before fully ID'd types;
c - sort by class, alphabetically within class;
a - sort alphabetically across all classes.
Turned out to be a large amount of work for fairly little gain,
although I suspect that 'sortdiscoveries:s' will eventually be
more popular than the default.
Invalidates existing save files so that current sort setting can
persist across save/restore cycles.
Closes #334
This commit is contained in:
@@ -205,6 +205,15 @@ scores the parts of the score list you wish [!own/3 top/2 around]
|
||||
to see when the game ends. You choose a combination of
|
||||
top scores, scores around the top scores, and all of your
|
||||
own scores.
|
||||
sortdiscoveries preferred order when viewing list of discovered objects [o]
|
||||
o -- in order of discovery within each class
|
||||
s -- sortloot's "loot" order
|
||||
c -- alphabetized within each class
|
||||
a -- alphabetized across all classes
|
||||
sortloot preferred order when examining a set of objects [n]
|
||||
none -- no sorting
|
||||
loot -- sort piles of objects on floor and in containers
|
||||
full -- 'loot' plus objects in inventory
|
||||
statushilites whether to display status highlights (when non-zero) and [0]
|
||||
also how many turns to display temporary highlights (for
|
||||
'up', 'down', and 'changed' hilite_status rules)
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
.ds vr "NetHack 3.7
|
||||
.ds f0 "\*(vr
|
||||
.ds f1
|
||||
.ds f2 "December 16, 2020
|
||||
.ds f2 "December 19, 2020
|
||||
.
|
||||
.\" A note on some special characters:
|
||||
.\" \(lq = left double quote
|
||||
@@ -1055,8 +1055,12 @@ be added to the end of the list rather than be inserted into the sorted
|
||||
ordering.)
|
||||
.lp \\\\
|
||||
Show what types of objects have been discovered.
|
||||
.lp ""
|
||||
May be preceded by \(oq\f(CRm\fP\(cq to select preferred display order.
|
||||
.lp \`
|
||||
Show discovered types for one class of objects.
|
||||
.lp ""
|
||||
May be preceded by \(oq\f(CRm\fP\(cq to select preferred display order.
|
||||
.lp !
|
||||
Escape to a shell.
|
||||
See \(lq#shell\(rq below for more details.
|
||||
@@ -1258,10 +1262,16 @@ Default key is \(oq\(haD\(cq, and \(oqk\(cq if
|
||||
is on.
|
||||
.lp "#known "
|
||||
Show what object types have been discovered.
|
||||
Default key is \(oq\\\(cq.
|
||||
Default key is \(oq\f(CR\\\fP\(cq.
|
||||
.lp ""
|
||||
The \(oq\f(CRm\fP\(cq prefix allows assigning a new value to the
|
||||
.op sortdiscoveries
|
||||
option to control the order in which the discoveries are displayed.
|
||||
.lp #knownclass
|
||||
Show discovered types for one class of objects.
|
||||
Default key is \(oq\`\(cq.
|
||||
Default key is \(oq\f(CR\`\fP\(cq.
|
||||
.lp ""
|
||||
The \(oq\f(CRm\fP\(cq prefix operates the same as for \(lq#known\(rq.
|
||||
.lp #levelchange
|
||||
Change your experience level.
|
||||
Autocompletes.
|
||||
@@ -4109,19 +4119,47 @@ Persistent.
|
||||
Show your approximate accumulated score on bottom line (default off).
|
||||
Persistent.
|
||||
.lp "silent "
|
||||
Suppress terminal beeps (default on). Persistent.
|
||||
Suppress terminal beeps (default on).
|
||||
Persistent.
|
||||
.lp sortdiscoveries
|
||||
Controls the sorting behavior for the output of the \(oq\f(CR\\\fP\(cq
|
||||
and \(oq\f(CR\`\fP\(cq commands.
|
||||
Persistent.
|
||||
.lp ""
|
||||
The possible values are:
|
||||
.PS o
|
||||
.PL o
|
||||
list object types by class, in discovery order within each class;
|
||||
default;
|
||||
.PL s
|
||||
list object types by
|
||||
.op sortloot
|
||||
classification: by class, by sub-class within class for classes which
|
||||
have substantial groupings (like helmets, boots, gloves, and so forth
|
||||
for armor), with object types partly-discovered via assigned name coming
|
||||
before fully identified types;
|
||||
.PL c
|
||||
list by class, alphabetically within each class;
|
||||
.PL a
|
||||
list alphabetically across all classes.
|
||||
.PE
|
||||
Can be interactively set via the \(oq\f(CRO\fP\(cq command or via using
|
||||
the \(oq\f(CRm\fP\(cq prefix before the \(oq\f(CR\\\fP\(cq
|
||||
or \(oq\f(CR\`\fP\(cq command.
|
||||
.lp sortloot
|
||||
Controls the sorting behavior of the pickup lists for inventory
|
||||
and #loot commands and some others. Persistent.
|
||||
.lp ""
|
||||
The possible values are:
|
||||
.PS full
|
||||
.PS none \" note: with proportional font, "none" is wider than "full" or "loot"
|
||||
.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.
|
||||
show lists the traditional way without sorting;
|
||||
default.
|
||||
.PE
|
||||
.lp sortpack
|
||||
Sort the pack contents by type when displaying inventory (default on).
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
%.au
|
||||
\author{Original version - Eric S. Raymond\\
|
||||
(Edited and expanded for 3.7 by Mike Stephenson and others)}
|
||||
\date{December 16, 2020}
|
||||
\date{December 19, 2020}
|
||||
|
||||
\maketitle
|
||||
|
||||
@@ -1154,9 +1154,15 @@ ordering.)
|
||||
%.lp
|
||||
\item[\tb{$\backslash$}]
|
||||
Show what types of objects have been discovered.
|
||||
\\
|
||||
%.lp ""
|
||||
May be preceded by `{\tt m}' to select preferred display order.
|
||||
%.lp
|
||||
\item[\tb{\`}]
|
||||
Show discovered types for one class of objects.
|
||||
\\
|
||||
.lp ""
|
||||
May be preceded by `{\tt m}' to select preferred display order.
|
||||
%.lp
|
||||
\item[\tb{!}]
|
||||
Escape to a shell.
|
||||
@@ -1340,10 +1346,18 @@ and also `{\tt k}' if {\it number\verb+_+pad\/} is on.
|
||||
\item[\tb{\#known}]
|
||||
Show what object types have been discovered.
|
||||
Default key is `{\tt $\backslash$}'.
|
||||
\\
|
||||
%.lp ""
|
||||
The `{\tt m}' prefix allows assigning a new value to the
|
||||
{\it sortdiscoveries\/}
|
||||
option to control the order in which the discoveries are displayed.
|
||||
%.lp
|
||||
\item[\tb{\#knownclass}]
|
||||
Show discovered types for one class of objects.
|
||||
Default key is `{\tt `}'.
|
||||
\\
|
||||
%.lp ""
|
||||
The `{\tt m}' prefix operates the same as for \(lq#known\(rq.
|
||||
%.lp
|
||||
\item[\tb{\#levelchange}]
|
||||
Change your experience level.
|
||||
@@ -4450,17 +4464,44 @@ Persistent.
|
||||
\item[\ib{silent}]
|
||||
Suppress terminal beeps (default on). Persistent.
|
||||
%.lp
|
||||
\item[\ib{sortdiscoveries}]
|
||||
Controls the sorting behavior for the output of the `{\tt $\backslash$}'
|
||||
and `{\tt \`}' commands.
|
||||
Persistent.
|
||||
\\
|
||||
%.lp ""
|
||||
The possible values are:
|
||||
%.PS o
|
||||
%.PL o
|
||||
(\tt o} --- list object types by class, in discovery order within each class;
|
||||
default;
|
||||
%.PL s
|
||||
{\tt s} --- list object types by {\it sortloot\/}
|
||||
classification: by class, by sub-class within class for classes which
|
||||
have substantial groupings (like helmets, boots, gloves, and so forth
|
||||
for armor), with object types partly-discovered via assigned name coming
|
||||
before fully identified types;
|
||||
\\
|
||||
%.PL c
|
||||
{\tt c} --- list by class, alphabetically within each class;\\
|
||||
%.PL a
|
||||
{\tt a} --- list alphabetically across all classes.\\
|
||||
%.PE
|
||||
Can be interactively set via the `{\tt O}' command or via using
|
||||
the `{\tt m}' prefix before the `{\tt $\backslash$}'
|
||||
or `{\tt \`}' command.
|
||||
%.lp
|
||||
\item[\ib{sortloot}]
|
||||
Controls the sorting behavior of pickup lists for inventory
|
||||
and \#loot commands and some others. Persistent.
|
||||
|
||||
\\
|
||||
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.
|
||||
{\tt none} --- show lists the traditional way without sorting; default.
|
||||
%.ei
|
||||
%.ed
|
||||
%.lp
|
||||
|
||||
@@ -681,6 +681,7 @@ when "?i" (show key bindings) displays commands and their keys, also show
|
||||
assign default key binding for <del> or <delete> to execute #terrain
|
||||
assign M-X to #exploremode
|
||||
make #herecmdmenu and #therecmdmenu autocomplete
|
||||
add 'sortdiscoveries' option to control output of '\' and '`' commands
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific New Features
|
||||
|
||||
@@ -972,6 +972,7 @@ E void NDECL(ustatusline);
|
||||
|
||||
/* ### invent.c ### */
|
||||
|
||||
E void FDECL(loot_classify, (Loot *, struct obj *));
|
||||
E Loot *FDECL(sortloot, (struct obj **, unsigned, BOOLEAN_P,
|
||||
boolean (*)(OBJ_P)));
|
||||
E void FDECL(unsortloot, (Loot **));
|
||||
@@ -1743,6 +1744,7 @@ E void FDECL(savenames, (NHFILE *));
|
||||
E void FDECL(restnames, (NHFILE *));
|
||||
E void FDECL(discover_object, (int, BOOLEAN_P, BOOLEAN_P));
|
||||
E void FDECL(undiscover_object, (int));
|
||||
E int FDECL(choose_disco_sort, (int));
|
||||
E int NDECL(dodiscovered);
|
||||
E int NDECL(doclassdisco);
|
||||
E void NDECL(rename_disco);
|
||||
|
||||
@@ -80,6 +80,7 @@ struct flag {
|
||||
#define PARANOID_EATING 0x0200
|
||||
int pickup_burden; /* maximum burden before prompt */
|
||||
int pile_limit; /* controls feedback when walking over objects */
|
||||
char discosort; /* order of dodiscovery/doclassdisco output: o,s,c,a */
|
||||
char sortloot; /* 'n'=none, 'l'=loot (pickup), 'f'=full ('l'+invent) */
|
||||
char inv_order[MAXOCLASSES];
|
||||
char pickup_types[MAXOCLASSES];
|
||||
@@ -93,8 +94,7 @@ struct flag {
|
||||
char end_disclose[NUM_DISCLOSURE_OPTIONS + 1]; /* disclose various
|
||||
info upon exit */
|
||||
char menu_style; /* User interface style setting */
|
||||
boolean made_fruit; /* don't easily let the user overflow the number of
|
||||
fruits */
|
||||
boolean made_fruit; /* don't easily let user overflow fruit limit */
|
||||
|
||||
/* KMH, role patch -- Variables used during startup.
|
||||
*
|
||||
|
||||
@@ -406,6 +406,8 @@ pfx_##a,
|
||||
&flags.silent)
|
||||
NHOPTB(softkeyboard, 0, opt_in, set_in_config, Off, Yes, No, No, NoAlias,
|
||||
&iflags.wc2_softkeyboard)
|
||||
NHOPTC(sortdiscoveries, 0, opt_in, set_in_game, Yes, Yes, No, Yes,
|
||||
NoAlias, "preferred order when displaying discovered objects")
|
||||
NHOPTC(sortloot, 4, opt_in, set_in_game, No, Yes, No, Yes, NoAlias,
|
||||
"sort object selection lists by description")
|
||||
NHOPTB(sortpack, 0, opt_out, set_in_game, On, Yes, No, No, NoAlias,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Incrementing EDITLEVEL can be used to force invalidation of old bones
|
||||
* and save files.
|
||||
*/
|
||||
#define EDITLEVEL 28
|
||||
#define EDITLEVEL 29
|
||||
|
||||
/*
|
||||
* Development status possibilities.
|
||||
|
||||
@@ -3236,6 +3236,8 @@ int NDECL((*cmd_func));
|
||||
/* 'm' for removing saddle from adjacent monster without checking
|
||||
for containers at <u.ux,u.uy> */
|
||||
|| cmd_func == doloot
|
||||
/* offer menu to choose discoveries sort order */
|
||||
|| cmd_func == dodiscovered || cmd_func == doclassdisco
|
||||
/* travel: pop up a menu of interesting targets in view */
|
||||
|| cmd_func == dotravel
|
||||
/* wait and search: allow even if next to a hostile monster */
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#define CONTAINED_SYM '>' /* designator for inside a container */
|
||||
#define HANDS_SYM '-'
|
||||
|
||||
static void FDECL(loot_classify, (Loot *, struct obj *));
|
||||
static char *FDECL(loot_xname, (struct obj *));
|
||||
static int FDECL(invletter_value, (CHAR_P));
|
||||
static int FDECL(CFDECLSPEC sortloot_cmp, (const genericptr,
|
||||
@@ -54,7 +53,7 @@ static char FDECL(obj_to_let, (struct obj *));
|
||||
static const char venom_inv[] = { VENOM_CLASS, 0 }; /* (constant) */
|
||||
|
||||
/* sortloot() classification; called at most once [per sort] for each object */
|
||||
static void
|
||||
void
|
||||
loot_classify(sort_item, obj)
|
||||
Loot *sort_item;
|
||||
struct obj *obj;
|
||||
|
||||
263
src/o_init.c
263
src/o_init.c
@@ -9,6 +9,8 @@ static void FDECL(setgemprobs, (d_level *));
|
||||
static void FDECL(shuffle, (int, int, BOOLEAN_P));
|
||||
static void NDECL(shuffle_all);
|
||||
static boolean FDECL(interesting_to_discover, (int));
|
||||
static int FDECL(CFDECLSPEC discovered_cmp, (const genericptr,
|
||||
const genericptr));
|
||||
static char *FDECL(oclass_to_name, (CHAR_P, char *));
|
||||
|
||||
#ifdef USE_TILES
|
||||
@@ -465,37 +467,167 @@ static const short uniq_objs[] = {
|
||||
BELL_OF_OPENING,
|
||||
};
|
||||
|
||||
/* discoveries qsort comparison function */
|
||||
static int CFDECLSPEC
|
||||
discovered_cmp(v1, v2)
|
||||
const genericptr v1;
|
||||
const genericptr v2;
|
||||
{
|
||||
const char *s1 = *(const char **) v1;
|
||||
const char *s2 = *(const char **) v2;
|
||||
/* each element starts with "* " or " " but we don't sort by those */
|
||||
int res = strcmpi(s1 + 2, s2 + 2);
|
||||
|
||||
if (res == 0) {
|
||||
; /* no tie-breaker needed */
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static char *
|
||||
sortloot_descr(otyp, outbuf)
|
||||
int otyp;
|
||||
char *outbuf;
|
||||
{
|
||||
Loot sl_cookie;
|
||||
struct obj o;
|
||||
|
||||
o = cg.zeroobj;
|
||||
o.otyp = otyp;
|
||||
o.oclass = objects[otyp].oc_class;
|
||||
o.dknown = 1;
|
||||
o.known = (objects[otyp].oc_name_known || !objects[otyp].oc_uses_known)
|
||||
? 1 : 0;
|
||||
o.corpsenm = NON_PM; /* suppress statue and figurine details */
|
||||
/* but suppressing fruit details leads to "bad fruit #0" */
|
||||
if (otyp == SLIME_MOLD)
|
||||
o.spe = g.context.current_fruit;
|
||||
|
||||
(void) memset((genericptr_t) &sl_cookie, 0, sizeof sl_cookie);
|
||||
sl_cookie.obj = (struct obj *) 0;
|
||||
sl_cookie.str = (char *) 0;
|
||||
|
||||
loot_classify(&sl_cookie, &o);
|
||||
Sprintf(outbuf, "%02d%02d%1d ",
|
||||
sl_cookie.orderclass, sl_cookie.subclass, sl_cookie.disco);
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
#define DISCO_BYCLASS 0 /* by discovery order within each class */
|
||||
#define DISCO_SORTLOOT 1 /* by discovery order within each subclass */
|
||||
#define DISCO_ALPHABYCLASS 2 /* alphabetized within each class */
|
||||
#define DISCO_ALPHABETIZED 3 /* alphabetized across all classes */
|
||||
/* also used in options.c (optfn_sortdiscoveries) */
|
||||
const char disco_order_let[] = "osca";
|
||||
const char *const disco_orders_descr[] = {
|
||||
"by order of discovery within each class",
|
||||
"sortloot order (by class with some sub-class groupings)",
|
||||
"alphabetical within each class",
|
||||
"alphabetical across all classes",
|
||||
(char *) 0
|
||||
};
|
||||
|
||||
int
|
||||
choose_disco_sort(mode)
|
||||
int mode; /* 0 => 'O' cmd, 1 => full discoveries; 2 => class discoveries */
|
||||
{
|
||||
winid tmpwin;
|
||||
menu_item *selected;
|
||||
anything any;
|
||||
int i, n, choice;
|
||||
|
||||
tmpwin = create_nhwindow(NHW_MENU);
|
||||
start_menu(tmpwin, MENU_BEHAVE_STANDARD);
|
||||
any = cg.zeroany; /* zero out all bits */
|
||||
for (i = 0; disco_orders_descr[i]; ++i) {
|
||||
any.a_int = disco_order_let[i];
|
||||
add_menu(tmpwin, NO_GLYPH, &any, (char) any.a_int, 0, ATR_NONE,
|
||||
disco_orders_descr[i],
|
||||
(disco_order_let[i] == flags.discosort)
|
||||
? MENU_ITEMFLAGS_SELECTED
|
||||
: MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
if (mode == 2) {
|
||||
/* called via 'm `' where full alphabetize doesn't make sense
|
||||
(only showing one class so can't span all classes) but the
|
||||
chosen sort will stick and also apply to '\' usage */
|
||||
any = cg.zeroany;
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
|
||||
"", MENU_ITEMFLAGS_NONE);
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
|
||||
"Note: full alphabetical and alphabetical within class",
|
||||
MENU_ITEMFLAGS_NONE);
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
|
||||
" are equivalent for single class discovery, but",
|
||||
MENU_ITEMFLAGS_NONE);
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
|
||||
" will matter for future use of total discoveries.",
|
||||
MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
end_menu(tmpwin, "Ordering of discoveries");
|
||||
|
||||
n = select_menu(tmpwin, PICK_ONE, &selected);
|
||||
destroy_nhwindow(tmpwin);
|
||||
if (n > 0) {
|
||||
choice = selected[0].item.a_int;
|
||||
/* skip preselected entry if we have more than one item chosen */
|
||||
if (n > 1 && choice == (int) flags.discosort)
|
||||
choice = selected[1].item.a_int;
|
||||
free((genericptr_t) selected);
|
||||
flags.discosort = choice;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* the '\' command - show discovered object types */
|
||||
int
|
||||
dodiscovered() /* free after Robert Viduya */
|
||||
{
|
||||
register int i, dis;
|
||||
int ct = 0;
|
||||
char *s, oclass, prev_class, classes[MAXOCLASSES], buf[BUFSZ];
|
||||
winid tmpwin;
|
||||
char *s, *p, oclass, prev_class,
|
||||
classes[MAXOCLASSES], buf[BUFSZ],
|
||||
*sorted_lines[NUM_OBJECTS]; /* overkill */
|
||||
int i, j, sortindx, dis, ct, uniq_ct, arti_ct, sorted_ct;
|
||||
boolean alphabetized, alphabyclass, lootsort;
|
||||
|
||||
if (!flags.discosort || !(p = index(disco_order_let, flags.discosort)))
|
||||
flags.discosort = 'o';
|
||||
|
||||
if (iflags.menu_requested) {
|
||||
if (choose_disco_sort(1) < 0)
|
||||
return 0;
|
||||
}
|
||||
alphabyclass = (flags.discosort == 'c');
|
||||
alphabetized = (flags.discosort == 'a' || alphabyclass);
|
||||
lootsort = (flags.discosort == 's');
|
||||
sortindx = index(disco_order_let, flags.discosort) - disco_order_let;
|
||||
|
||||
tmpwin = create_nhwindow(NHW_MENU);
|
||||
putstr(tmpwin, 0, "Discoveries");
|
||||
Sprintf(buf, "Discoveries, %s", disco_orders_descr[sortindx]);
|
||||
putstr(tmpwin, 0, buf);
|
||||
putstr(tmpwin, 0, "");
|
||||
|
||||
/* gather "unique objects" into a pseudo-class; note that they'll
|
||||
also be displayed individually within their regular class */
|
||||
uniq_ct = 0;
|
||||
for (i = dis = 0; i < SIZE(uniq_objs); i++)
|
||||
if (objects[uniq_objs[i]].oc_name_known) {
|
||||
if (!dis++)
|
||||
putstr(tmpwin, iflags.menu_headings, "Unique items");
|
||||
++uniq_ct;
|
||||
Sprintf(buf, " %s", OBJ_NAME(objects[uniq_objs[i]]));
|
||||
putstr(tmpwin, 0, buf);
|
||||
++ct;
|
||||
}
|
||||
/* display any known artifacts as another pseudo-class */
|
||||
ct += disp_artifact_discoveries(tmpwin);
|
||||
arti_ct = disp_artifact_discoveries(tmpwin);
|
||||
|
||||
/* several classes are omitted from packorder; one is of interest here */
|
||||
Strcpy(classes, flags.inv_order);
|
||||
if (!index(classes, VENOM_CLASS))
|
||||
(void) strkitten(classes, VENOM_CLASS); /* append char to string */
|
||||
|
||||
ct = uniq_ct + arti_ct;
|
||||
sorted_ct = 0;
|
||||
for (s = classes; *s; s++) {
|
||||
oclass = *s;
|
||||
prev_class = oclass + 1; /* forced different from oclass */
|
||||
@@ -504,21 +636,63 @@ dodiscovered() /* free after Robert Viduya */
|
||||
if ((dis = g.disco[i]) != 0 && interesting_to_discover(dis)) {
|
||||
ct++;
|
||||
if (oclass != prev_class) {
|
||||
putstr(tmpwin, iflags.menu_headings,
|
||||
let_to_name(oclass, FALSE, FALSE));
|
||||
prev_class = oclass;
|
||||
if ((alphabyclass || lootsort) && sorted_ct) {
|
||||
/* output previous class */
|
||||
qsort(sorted_lines, sorted_ct, sizeof (char *),
|
||||
discovered_cmp);
|
||||
for (j = 0; j < sorted_ct; ++j) {
|
||||
p = sorted_lines[j];
|
||||
if (lootsort) {
|
||||
p[6] = p[0]; /* '*' or ' ' */
|
||||
p += 6;
|
||||
}
|
||||
putstr(tmpwin, 0, p);
|
||||
free(sorted_lines[j]), sorted_lines[j] = 0;
|
||||
}
|
||||
sorted_ct = 0;
|
||||
}
|
||||
if (!alphabetized || alphabyclass) {
|
||||
/* header for new class */
|
||||
putstr(tmpwin, iflags.menu_headings,
|
||||
let_to_name(oclass, FALSE, FALSE));
|
||||
prev_class = oclass;
|
||||
}
|
||||
}
|
||||
Sprintf(buf, "%s %s",
|
||||
(objects[dis].oc_pre_discovered ? "*" : " "),
|
||||
obj_typename(dis));
|
||||
putstr(tmpwin, 0, buf);
|
||||
Strcpy(buf, objects[dis].oc_pre_discovered ? "* " : " ");
|
||||
if (lootsort)
|
||||
(void) sortloot_descr(dis, &buf[2]);
|
||||
Strcat(buf, obj_typename(dis));
|
||||
|
||||
if (!alphabetized && !lootsort)
|
||||
putstr(tmpwin, 0, buf);
|
||||
else
|
||||
sorted_lines[sorted_ct++] = dupstr(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ct == 0) {
|
||||
You("haven't discovered anything yet...");
|
||||
} else
|
||||
} else {
|
||||
if (sorted_ct) {
|
||||
/* if we're alphabetizing by class, we've already shown the
|
||||
relevant header above; if we're alphabetizing across all
|
||||
classes, we normally don't need a header; but it we showed
|
||||
any unique items or any artifacts then we do need one */
|
||||
if ((uniq_ct || arti_ct) && !alphabyclass)
|
||||
putstr(tmpwin, iflags.menu_headings, "Discovered items");
|
||||
qsort(sorted_lines, sorted_ct, sizeof (char *), discovered_cmp);
|
||||
for (j = 0; j < sorted_ct; ++j) {
|
||||
p = sorted_lines[j];
|
||||
if (lootsort) {
|
||||
p[6] = p[0]; /* '*' or ' ' */
|
||||
p += 6;
|
||||
}
|
||||
putstr(tmpwin, 0, p);
|
||||
free(sorted_lines[j]), sorted_lines[j] = 0;
|
||||
}
|
||||
}
|
||||
display_nhwindow(tmpwin, TRUE);
|
||||
}
|
||||
destroy_nhwindow(tmpwin);
|
||||
|
||||
return 0;
|
||||
@@ -547,13 +721,24 @@ doclassdisco()
|
||||
havent_discovered_any[] = "haven't discovered any %s yet.",
|
||||
unique_items[] = "unique items",
|
||||
artifact_items[] = "artifacts";
|
||||
char *s, c, oclass, menulet, allclasses[MAXOCLASSES],
|
||||
discosyms[2 + MAXOCLASSES + 1], buf[BUFSZ];
|
||||
int i, ct, dis, xtras;
|
||||
boolean traditional;
|
||||
winid tmpwin = WIN_ERR;
|
||||
anything any;
|
||||
menu_item *pick_list = 0;
|
||||
anything any;
|
||||
char *p, *s, c, oclass, menulet, allclasses[MAXOCLASSES],
|
||||
discosyms[2 + MAXOCLASSES + 1], buf[BUFSZ],
|
||||
*sorted_lines[NUM_OBJECTS]; /* overkill */
|
||||
int i, ct, dis, xtras, sorted_ct;
|
||||
boolean traditional, alphabetized, lootsort;
|
||||
|
||||
if (!flags.discosort || !(p = index(disco_order_let, flags.discosort)))
|
||||
flags.discosort = 'o';
|
||||
|
||||
if (iflags.menu_requested) {
|
||||
if (choose_disco_sort(2) < 0)
|
||||
return 0;
|
||||
}
|
||||
alphabetized = (flags.discosort == 'a' || flags.discosort == 'c');
|
||||
lootsort = (flags.discosort == 's');
|
||||
|
||||
discosyms[0] = '\0';
|
||||
traditional = (flags.menu_style == MENU_TRADITIONAL
|
||||
@@ -670,9 +855,9 @@ doclassdisco()
|
||||
upstart(strcpy(buf, unique_items)));
|
||||
for (i = 0; i < SIZE(uniq_objs); i++)
|
||||
if (objects[uniq_objs[i]].oc_name_known) {
|
||||
++ct;
|
||||
Sprintf(buf, " %s", OBJ_NAME(objects[uniq_objs[i]]));
|
||||
putstr(tmpwin, 0, buf);
|
||||
++ct;
|
||||
}
|
||||
if (!ct)
|
||||
You(havent_discovered_any, unique_items);
|
||||
@@ -685,20 +870,40 @@ doclassdisco()
|
||||
break;
|
||||
default:
|
||||
oclass = def_char_to_objclass(c);
|
||||
Sprintf(buf, "Discovered %s", let_to_name(oclass, FALSE, FALSE));
|
||||
putstr(tmpwin, iflags.menu_headings, buf);
|
||||
for (i = g.bases[(int) oclass];
|
||||
i < NUM_OBJECTS && objects[i].oc_class == oclass; ++i) {
|
||||
Sprintf(buf, "Discovered %s in %s", let_to_name(oclass, FALSE, FALSE),
|
||||
(flags.discosort == 'o') ? "order of discovery"
|
||||
: (flags.discosort == 's') ? "'sortloot' order"
|
||||
: "alphabetical order");
|
||||
putstr(tmpwin, 0, buf); /* skip iflags.menu_headings */
|
||||
sorted_ct = 0;
|
||||
for (i = g.bases[(int) oclass]; i < g.bases[oclass + 1] - 1; ++i) {
|
||||
if ((dis = g.disco[i]) != 0 && interesting_to_discover(dis)) {
|
||||
Sprintf(buf, "%s %s",
|
||||
objects[dis].oc_pre_discovered ? "*" : " ",
|
||||
obj_typename(dis));
|
||||
putstr(tmpwin, 0, buf);
|
||||
++ct;
|
||||
Strcpy(buf, objects[dis].oc_pre_discovered ? "* " : " ");
|
||||
if (lootsort)
|
||||
(void) sortloot_descr(dis, &buf[2]);
|
||||
Strcat(buf, obj_typename(dis));
|
||||
|
||||
if (!alphabetized && !lootsort)
|
||||
putstr(tmpwin, 0, buf);
|
||||
else
|
||||
sorted_lines[sorted_ct++] = dupstr(buf);
|
||||
}
|
||||
}
|
||||
if (!ct)
|
||||
if (!ct) {
|
||||
You(havent_discovered_any, oclass_to_name(oclass, buf));
|
||||
} else if (sorted_ct) {
|
||||
qsort(sorted_lines, sorted_ct, sizeof (char *), discovered_cmp);
|
||||
for (i = 0; i < sorted_ct; ++i) {
|
||||
p = sorted_lines[i];
|
||||
if (lootsort) {
|
||||
p[6] = p[0]; /* '*' or ' ' */
|
||||
p += 6;
|
||||
}
|
||||
putstr(tmpwin, 0, p);
|
||||
free(sorted_lines[i]), sorted_lines[i] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (ct)
|
||||
|
||||
@@ -3256,6 +3256,66 @@ char *op;
|
||||
return optn_ok;
|
||||
}
|
||||
|
||||
int
|
||||
optfn_sortdiscoveries(optidx, req, negated, opts, op)
|
||||
int optidx;
|
||||
int req;
|
||||
boolean negated;
|
||||
char *opts;
|
||||
char *op;
|
||||
{
|
||||
if (req == do_init) {
|
||||
flags.discosort = 'o';
|
||||
return optn_ok;
|
||||
}
|
||||
if (req == do_set) {
|
||||
op = string_for_env_opt(allopt[optidx].name, opts, FALSE);
|
||||
if (negated) {
|
||||
flags.discosort = 'o';
|
||||
} else if (op != empty_optstr) {
|
||||
switch (lowc(*op)) {
|
||||
case '0':
|
||||
case 'o': /* order of discovery */
|
||||
flags.discosort = 'o';
|
||||
break;
|
||||
case '1':
|
||||
case 's': /* sortloot order (subclasses for some classes) */
|
||||
flags.discosort = 's';
|
||||
break;
|
||||
case '2':
|
||||
case 'c': /* alphabetical within each class */
|
||||
flags.discosort = 'c';
|
||||
break;
|
||||
case '3':
|
||||
case 'a': /* alphabetical across all classes */
|
||||
flags.discosort = 'a';
|
||||
break;
|
||||
default:
|
||||
config_error_add("Unknown %s parameter '%s'",
|
||||
allopt[optidx].name, op);
|
||||
return optn_silenterr;
|
||||
}
|
||||
} else
|
||||
return optn_err;
|
||||
return optn_ok;
|
||||
}
|
||||
if (req == get_val) {
|
||||
extern const char *const disco_orders_descr[]; /* o_init.c */
|
||||
extern const char disco_order_let[];
|
||||
const char *p = index(disco_order_let, flags.discosort);
|
||||
|
||||
if (!p)
|
||||
flags.discosort = 'o', p = disco_order_let;
|
||||
Strcpy(opts, disco_orders_descr[p - disco_order_let]);
|
||||
return optn_ok;
|
||||
}
|
||||
if (req == do_handler) {
|
||||
/* return handler_sortdiscoveries(); */
|
||||
(void) choose_disco_sort(0); /* o_init.c */
|
||||
}
|
||||
return optn_ok;
|
||||
}
|
||||
|
||||
int
|
||||
optfn_sortloot(optidx, req, negated, opts, op)
|
||||
int optidx;
|
||||
|
||||
Reference in New Issue
Block a user