fix #H7205, #H7120, #H5216 - sortloot

H7205 - full-pack identify might skip items if perm_invent is on
        because updating the inventory window might reorder 'invent'
        while the identify code is in the midst of traversing it;
H7120 - pickup that doesn't pick anything up can change the glyph
        shown on the map because the pile might be reordered such
        that a different item is on top;
H5216 - performing a sortloot operation on a pile and then switching
        back to sortloot:none doesn't restore pile's original order.

The 'revamp' that changed the contributed sortloot feature to switch
to simpler usage (object list itself was sorted rather than having a
parallel array that needed to be constructed, sorted, traversed, and
discarded) turns out to have too many problems.  This reverts to a
hybrid solution that constructs an array for traversal, leaving the
linked list in its original order, but hides most of the details of
that from sortloot() callers.  The 'revamp' benefit of being able to
use normal list traversal is lost, as is the potential to skip
sorting when the list turns out to already be in the desired order.

This could stand to have a lot more testing than it's had so far.
This commit is contained in:
PatR
2018-06-09 18:03:37 -07:00
parent fc2d38ed50
commit c7f357e783
7 changed files with 176 additions and 41 deletions

View File

@@ -190,6 +190,14 @@ enum hmon_atkmode_types {
HMON_DRAGGED /* attached iron ball, pulled into mon */
};
/* sortloot() return type; needed before extern.h */
struct sortloot_item {
struct obj *obj;
int indx; /* signed int, because sortloot()'s qsort comparison routine
assumes (a->indx - b->indx) might yield a negative result */
};
typedef struct sortloot_item Loot;
#define MATCH_WARN_OF_MON(mon) \
(Warn_of_mon && ((context.warntype.obj \
&& (context.warntype.obj & (mon)->data->mflags2)) \
@@ -215,8 +223,7 @@ enum hmon_atkmode_types {
#define SYM_OFF_X (SYM_OFF_W + WARNCOUNT)
#define SYM_MAX (SYM_OFF_X + MAXOTHER)
#ifdef USE_TRAMPOLI /* This doesn't belong here, but we have little choice \
*/
#ifdef USE_TRAMPOLI /* this doesn't belong here, but we have little choice */
#undef NDECL
#define NDECL(f) f()
#endif