From 2fb9cf7a1c05de5a8db600679fba677ddb92025d Mon Sep 17 00:00:00 2001 From: HMM Date: Tue, 24 Sep 2019 18:20:49 -0400 Subject: [PATCH 1/8] Rework autopickup exceptions to override one another like menucolors --- include/extern.h | 2 +- include/flag.h | 5 ++- src/cmd.c | 3 +- src/options.c | 95 +++++++++++++++++++++--------------------------- src/pickup.c | 31 ++++++---------- 5 files changed, 60 insertions(+), 76 deletions(-) diff --git a/include/extern.h b/include/extern.h index 7c37297b3..d4e255744 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1893,7 +1893,7 @@ E boolean NDECL(u_handsy); E int FDECL(use_container, (struct obj **, int, BOOLEAN_P)); E int FDECL(loot_mon, (struct monst *, int *, boolean *)); E int NDECL(dotip); -E boolean FDECL(is_autopickup_exception, (struct obj *, BOOLEAN_P)); +E struct autopickup_exception *FDECL(check_autopickup_exceptions, (struct obj *)); E boolean FDECL(autopick_testobj, (struct obj *, BOOLEAN_P)); /* ### pline.c ### */ diff --git a/include/flag.h b/include/flag.h index 3ea3ada26..4990fe691 100644 --- a/include/flag.h +++ b/include/flag.h @@ -423,9 +423,12 @@ struct instance_flags { int wc2_statuslines; /* default = 2, curses can handle 3 */ int wc2_windowborders; /* display borders on NetHack windows */ int wc2_petattr; /* text attributes for pet */ - struct autopickup_exception *autopickup_exceptions[2]; + /* VE edit: APE overhaul */ + struct autopickup_exception *autopickup_exceptions; +/* #define AP_LEAVE 0 #define AP_GRAB 1 +*/ #ifdef WIN32 #define MAX_ALTKEYHANDLER 25 char altkeyhandler[MAX_ALTKEYHANDLER]; diff --git a/src/cmd.c b/src/cmd.c index 82a7819c7..a9b17bd86 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -2139,8 +2139,7 @@ int final; *ocl ? "'" : "", *ocl ? ocl : "all types", *ocl ? "'" : ""); if (flags.pickup_thrown && *ocl) /* *ocl: don't show if 'all types' */ Strcat(buf, " plus thrown"); - if (iflags.autopickup_exceptions[AP_GRAB] - || iflags.autopickup_exceptions[AP_LEAVE]) + if (iflags.autopickup_exceptions) Strcat(buf, ", with exceptions"); } else Strcpy(buf, "off"); diff --git a/src/options.c b/src/options.c index 50f92ca86..ecacfb60e 100644 --- a/src/options.c +++ b/src/options.c @@ -573,7 +573,7 @@ STATIC_DCL boolean FDECL(special_handling, (const char *, STATIC_DCL const char *FDECL(get_compopt_value, (const char *, char *)); STATIC_DCL void FDECL(remove_autopickup_exception, (struct autopickup_exception *)); -STATIC_DCL int FDECL(count_ape_maps, (int *, int *)); +STATIC_DCL int NDECL(count_ape_maps); /* VE edit: APE overhaul */ STATIC_DCL boolean FDECL(is_wc_option, (const char *)); STATIC_DCL boolean FDECL(wc_supported, (const char *)); @@ -4411,10 +4411,11 @@ int nset; add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); } +/* VE edit: APE overhaul */ int count_apes(VOID_ARGS) { - return count_ape_maps((int *) 0, (int *) 0); + return count_ape_maps(); } enum opt_other_enums { @@ -5285,13 +5286,13 @@ boolean setinitial, setfromfile; goto menucolors_again; } } else if (!strcmp("autopickup_exception", optname)) { - int opt_idx, pass, totalapes = 0, numapes[2] = { 0, 0 }; - char apebuf[1 + BUFSZ]; /* so &apebuf[1] is BUFSZ long for getlin() */ + int opt_idx, pass, numapes = 0; + char apebuf[2 + BUFSZ]; /* so &apebuf[1] is BUFSZ long for getlin() */ struct autopickup_exception *ape; ape_again: - totalapes = count_ape_maps(&numapes[AP_LEAVE], &numapes[AP_GRAB]); - opt_idx = handle_add_list_remove("autopickup exception", totalapes); + numapes = count_ape_maps(); + opt_idx = handle_add_list_remove("autopickup exception", numapes); if (opt_idx == 3) { /* done */ return TRUE; } else if (opt_idx == 0) { /* add new */ @@ -5307,7 +5308,7 @@ boolean setinitial, setfromfile; /* guarantee room for \" prefix and \"\0 suffix; -2 is good enough for apebuf[] but -3 makes sure the whole thing fits within normal BUFSZ */ - apebuf[sizeof apebuf - 3] = '\0'; + apebuf[sizeof apebuf - 2] = '\0'; Strcat(apebuf, "\""); add_autopickup_exception(apebuf); } @@ -5318,18 +5319,19 @@ boolean setinitial, setfromfile; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin); - for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) { - if (numapes[pass] == 0) - continue; - ape = iflags.autopickup_exceptions[pass]; + if (numapes) { + ape = (struct autopickup_exception *) + iflags.autopickup_exceptions; any = zeroany; add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings, - (pass == 0) ? "Never pickup" : "Always pickup", + "Always pickup '<'; never pickup '>'", MENU_UNSELECTED); - for (i = 0; i < numapes[pass] && ape; i++) { + for (i = 0; i < numapes && ape; i++) { any.a_void = (opt_idx == 1) ? 0 : ape; - /* length of pattern plus quotes is less than BUFSZ */ - Sprintf(apebuf, "\"%s\"", ape->pattern); + /* length of pattern plus quotes (plus '<'/'>') is less than + BUFSZ */ + Sprintf(apebuf, "\"%c%s\"", ape->grab ? '<' : '>', + ape->pattern); add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, apebuf, MENU_UNSELECTED); ape = ape->next; @@ -5889,9 +5891,8 @@ dotogglepickup() if (flags.pickup) { oc_to_str(flags.pickup_types, ocl); Sprintf(buf, "ON, for %s objects%s", ocl[0] ? ocl : "all", - (iflags.autopickup_exceptions[AP_LEAVE] - || iflags.autopickup_exceptions[AP_GRAB]) - ? ((count_ape_maps((int *) 0, (int *) 0) == 1) + (iflags.autopickup_exceptions) + ? ((count_ape_maps() == 1) ? ", with one exception" : ", with some exceptions") : ""); @@ -5902,6 +5903,7 @@ dotogglepickup() return 0; } +/* VE edit: APE overhaul */ int add_autopickup_exception(mapping) const char *mapping; @@ -5910,7 +5912,7 @@ const char *mapping; APE_regex_error[] = "regex error in AUTOPICKUP_EXCEPTION", APE_syntax_error[] = "syntax error in AUTOPICKUP_EXCEPTION"; - struct autopickup_exception *ape, **apehead; + struct autopickup_exception *ape; char text[256], end; int n; boolean grab = FALSE; @@ -5942,31 +5944,29 @@ const char *mapping; free((genericptr_t) ape); return 0; } - apehead = (grab) ? &iflags.autopickup_exceptions[AP_GRAB] - : &iflags.autopickup_exceptions[AP_LEAVE]; ape->pattern = dupstr(text); ape->grab = grab; - ape->next = *apehead; - *apehead = ape; + ape->next = (struct autopickup_exception *) iflags.autopickup_exceptions; + iflags.autopickup_exceptions = (struct autopickup_exception *) ape; return 1; } +/* VE edit: APE overhaul */ STATIC_OVL void remove_autopickup_exception(whichape) struct autopickup_exception *whichape; { struct autopickup_exception *ape, *freeape, *prev = 0; - int chain = whichape->grab ? AP_GRAB : AP_LEAVE; - for (ape = iflags.autopickup_exceptions[chain]; ape;) { + for (ape = iflags.autopickup_exceptions; ape;) { if (ape == whichape) { freeape = ape; ape = ape->next; if (prev) prev->next = ape; else - iflags.autopickup_exceptions[chain] = ape; + iflags.autopickup_exceptions = ape; regex_free(freeape->regex); free((genericptr_t) freeape->pattern); free((genericptr_t) freeape); @@ -5977,42 +5977,31 @@ struct autopickup_exception *whichape; } } +/* VE edit: APE overhaul */ STATIC_OVL int -count_ape_maps(leave, grab) -int *leave, *grab; +count_ape_maps() { - struct autopickup_exception *ape; - int pass, totalapes, numapes[2]; + int numapes = 0; + struct autopickup_exception *ape = iflags.autopickup_exceptions; - numapes[0] = numapes[1] = 0; - for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) { - ape = iflags.autopickup_exceptions[pass]; - while (ape) { - ape = ape->next; - numapes[pass]++; - } + while (ape) { + numapes++; + ape = ape->next; } - totalapes = numapes[AP_LEAVE] + numapes[AP_GRAB]; - if (leave) - *leave = numapes[AP_LEAVE]; - if (grab) - *grab = numapes[AP_GRAB]; - return totalapes; + + return numapes; } +/* VE edit: APE overhaul */ void free_autopickup_exceptions() { - struct autopickup_exception *ape; - int pass; - - for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) { - while ((ape = iflags.autopickup_exceptions[pass]) != 0) { - regex_free(ape->regex); - free((genericptr_t) ape->pattern); - iflags.autopickup_exceptions[pass] = ape->next; - free((genericptr_t) ape); - } + struct autopickup_exception *ape = iflags.autopickup_exceptions; + while ((ape = iflags.autopickup_exceptions) != 0) { + regex_free(ape->regex); + free((genericptr_t) ape->pattern); + iflags.autopickup_exceptions = ape->next; + free((genericptr_t) ape); } } diff --git a/src/pickup.c b/src/pickup.c index e47d989da..647f1daa9 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -711,28 +711,20 @@ int what; /* should be a long */ return (n_tried > 0); } -boolean -is_autopickup_exception(obj, grab) +struct autopickup_exception * +check_autopickup_exceptions(obj) struct obj *obj; -boolean grab; /* forced pickup, rather than forced leave behind? */ { /* * Does the text description of this match an exception? */ struct autopickup_exception - *ape = (grab) ? iflags.autopickup_exceptions[AP_GRAB] - : iflags.autopickup_exceptions[AP_LEAVE]; - + *ape = iflags.autopickup_exceptions; if (ape) { char *objdesc = makesingular(doname(obj)); - - while (ape) { - if (regex_match(objdesc, ape->regex)) - return TRUE; - ape = ape->next; - } + do if (regex_match(objdesc, ape->regex)) return ape; + while (ape = ape->next); } - return FALSE; } boolean @@ -755,12 +747,13 @@ boolean calc_costly; /* check for pickup_types */ pickit = (!*otypes || index(otypes, otmp->oclass)); - /* check for "always pick up */ - if (!pickit) - pickit = is_autopickup_exception(otmp, TRUE); - /* then for "never pick up */ - if (pickit) - pickit = !is_autopickup_exception(otmp, FALSE); + + /* check for autopickup excpetions */ + struct autopickup_exception + *ape = check_autopickup_exceptions(otmp); + if (ape) + pickit = ape->grab; + /* pickup_thrown overrides pickup_types and exceptions */ if (!pickit) pickit = (flags.pickup_thrown && otmp->was_thrown); From 234e5f38f23085c8fca597c9d38f71f24cd175fd Mon Sep 17 00:00:00 2001 From: HMM Date: Tue, 24 Sep 2019 20:05:37 -0400 Subject: [PATCH 2/8] Clean up stray comments --- include/flag.h | 5 ----- src/options.c | 7 +------ 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/include/flag.h b/include/flag.h index 3c9528df9..090f6e1b0 100644 --- a/include/flag.h +++ b/include/flag.h @@ -423,12 +423,7 @@ struct instance_flags { int wc2_statuslines; /* default = 2, curses can handle 3 */ int wc2_windowborders; /* display borders on NetHack windows */ int wc2_petattr; /* text attributes for pet */ - /* VE edit: APE overhaul */ struct autopickup_exception *autopickup_exceptions; -/* -#define AP_LEAVE 0 -#define AP_GRAB 1 -*/ #ifdef WIN32 #define MAX_ALTKEYHANDLER 25 char altkeyhandler[MAX_ALTKEYHANDLER]; diff --git a/src/options.c b/src/options.c index ecacfb60e..7952c1312 100644 --- a/src/options.c +++ b/src/options.c @@ -573,7 +573,7 @@ STATIC_DCL boolean FDECL(special_handling, (const char *, STATIC_DCL const char *FDECL(get_compopt_value, (const char *, char *)); STATIC_DCL void FDECL(remove_autopickup_exception, (struct autopickup_exception *)); -STATIC_DCL int NDECL(count_ape_maps); /* VE edit: APE overhaul */ +STATIC_DCL int NDECL(count_ape_maps); STATIC_DCL boolean FDECL(is_wc_option, (const char *)); STATIC_DCL boolean FDECL(wc_supported, (const char *)); @@ -4411,7 +4411,6 @@ int nset; add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); } -/* VE edit: APE overhaul */ int count_apes(VOID_ARGS) { @@ -5903,7 +5902,6 @@ dotogglepickup() return 0; } -/* VE edit: APE overhaul */ int add_autopickup_exception(mapping) const char *mapping; @@ -5952,7 +5950,6 @@ const char *mapping; return 1; } -/* VE edit: APE overhaul */ STATIC_OVL void remove_autopickup_exception(whichape) struct autopickup_exception *whichape; @@ -5977,7 +5974,6 @@ struct autopickup_exception *whichape; } } -/* VE edit: APE overhaul */ STATIC_OVL int count_ape_maps() { @@ -5992,7 +5988,6 @@ count_ape_maps() return numapes; } -/* VE edit: APE overhaul */ void free_autopickup_exceptions() { From f68561fbe1f3fbb7760aee4db046553a1bfd16e1 Mon Sep 17 00:00:00 2001 From: HMM Date: Fri, 27 Sep 2019 15:17:53 -0400 Subject: [PATCH 3/8] Fix check_autopickup_exceptions to return null pointer if no exception is found --- src/pickup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pickup.c b/src/pickup.c index 647f1daa9..c0ef2b0cf 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -722,9 +722,9 @@ struct obj *obj; *ape = iflags.autopickup_exceptions; if (ape) { char *objdesc = makesingular(doname(obj)); - do if (regex_match(objdesc, ape->regex)) return ape; - while (ape = ape->next); + while (ape && !regex_match(objdesc, ape->regex)) ape = ape->next; } + return ape; } boolean From 1f5e6198871a920fa2453690584a1fde764e8f37 Mon Sep 17 00:00:00 2001 From: HMM Date: Fri, 27 Sep 2019 15:42:50 -0400 Subject: [PATCH 4/8] Delete unusued local variable --- src/options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/options.c b/src/options.c index 7952c1312..f8abf5fb0 100644 --- a/src/options.c +++ b/src/options.c @@ -5285,7 +5285,7 @@ boolean setinitial, setfromfile; goto menucolors_again; } } else if (!strcmp("autopickup_exception", optname)) { - int opt_idx, pass, numapes = 0; + int opt_idx, numapes = 0; char apebuf[2 + BUFSZ]; /* so &apebuf[1] is BUFSZ long for getlin() */ struct autopickup_exception *ape; From ca952469033b7eaa0184fd53cb33ebba7eb2c508 Mon Sep 17 00:00:00 2001 From: HMM Date: Mon, 30 Sep 2019 02:12:06 -0400 Subject: [PATCH 5/8] Remove redundant function "count_ape_maps" --- src/options.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/options.c b/src/options.c index f8abf5fb0..836e86d7a 100644 --- a/src/options.c +++ b/src/options.c @@ -573,7 +573,6 @@ STATIC_DCL boolean FDECL(special_handling, (const char *, STATIC_DCL const char *FDECL(get_compopt_value, (const char *, char *)); STATIC_DCL void FDECL(remove_autopickup_exception, (struct autopickup_exception *)); -STATIC_DCL int NDECL(count_ape_maps); STATIC_DCL boolean FDECL(is_wc_option, (const char *)); STATIC_DCL boolean FDECL(wc_supported, (const char *)); @@ -4414,7 +4413,15 @@ int nset; int count_apes(VOID_ARGS) { - return count_ape_maps(); + int numapes = 0; + struct autopickup_exception *ape = iflags.autopickup_exceptions; + + while (ape) { + numapes++; + ape = ape->next; + } + + return numapes; } enum opt_other_enums { @@ -5290,7 +5297,7 @@ boolean setinitial, setfromfile; struct autopickup_exception *ape; ape_again: - numapes = count_ape_maps(); + numapes = count_apes(); opt_idx = handle_add_list_remove("autopickup exception", numapes); if (opt_idx == 3) { /* done */ return TRUE; @@ -5891,7 +5898,7 @@ dotogglepickup() oc_to_str(flags.pickup_types, ocl); Sprintf(buf, "ON, for %s objects%s", ocl[0] ? ocl : "all", (iflags.autopickup_exceptions) - ? ((count_ape_maps() == 1) + ? ((count_apes() == 1) ? ", with one exception" : ", with some exceptions") : ""); @@ -5974,20 +5981,6 @@ struct autopickup_exception *whichape; } } -STATIC_OVL int -count_ape_maps() -{ - int numapes = 0; - struct autopickup_exception *ape = iflags.autopickup_exceptions; - - while (ape) { - numapes++; - ape = ape->next; - } - - return numapes; -} - void free_autopickup_exceptions() { From 29946b551bfec60a41ca5a7e3b48fee5e09a9602 Mon Sep 17 00:00:00 2001 From: nhmall Date: Mon, 30 Sep 2019 10:54:03 -0400 Subject: [PATCH 6/8] autopickup exception priority in pull request 226 The pull request #226 commentary follows: One major limitation of the autopickup exception system is that you can't define an exception from an exception, despite both menucolors and msgtypes prioritizing rules based on the order they are defined in .nethackrc. This is because the "always pickup" and "never pickup" exceptions are tracked in different lists, and at runtime, when the player steps over an object, the game checks these lists seperately, with "never pickup" taking precedence. This means that if you want to pick up some but not all items matching a given expression, you may need to write a long and kludgy list of regexes to get the behavior you want. I've edited the autopickup exception code to remove this necessity: now the exceptions are stored in one list, and conflicts between them are resolved based on their relative position in that list. Whether an exception was inclusive or exclusive was already tracked individually; I don't know why they were stored separately in the first place. This edit makes the system both more convenient and more consistent with the semantics of menucolors and msgtypes. With these changes, the 33 autopickup exception rules in the wiki article linked above may be replaced with the following 7 much simpler rules for the exact same effect: AUTOPICKUP_EXCEPTION=">.* corpse.*" AUTOPICKUP_EXCEPTION="<.* newt corpse.*" AUTOPICKUP_EXCEPTION="<.* lichen corpse.*" AUTOPICKUP_EXCEPTION="<.* lizard corpse.*" AUTOPICKUP_EXCEPTION="<.* floating eye corpse.*" AUTOPICKUP_EXCEPTION="<.* wraith corpse.* AUTOPICKUP_EXCEPTION=">.*\>.*" closes #226 --- doc/fixes36.3 | 1 + include/decl.h | 1 + include/flag.h | 1 - src/cmd.c | 2 +- src/decl.c | 2 ++ src/options.c | 20 ++++++++++---------- src/pickup.c | 14 ++++++++------ 7 files changed, 23 insertions(+), 18 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index fbac27988..4d853b695 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -314,6 +314,7 @@ NetHack Community Patches (or Variation) Included ------------------------------------------------- add a couple of engraving suggestions in pull request #79 chasonr's faster method to write characters to msdos VGA in pull request #220 +autopickup exception priority change in pull request #226 Code Cleanup and Reorganization diff --git a/include/decl.h b/include/decl.h index e030ce454..974af0f10 100644 --- a/include/decl.h +++ b/include/decl.h @@ -418,6 +418,7 @@ struct autopickup_exception { boolean grab; struct autopickup_exception *next; }; +E struct autopickup_exception *apelist; struct plinemsg_type { xchar msgtype; /* one of MSGTYP_foo */ diff --git a/include/flag.h b/include/flag.h index 090f6e1b0..8fe94339b 100644 --- a/include/flag.h +++ b/include/flag.h @@ -423,7 +423,6 @@ struct instance_flags { int wc2_statuslines; /* default = 2, curses can handle 3 */ int wc2_windowborders; /* display borders on NetHack windows */ int wc2_petattr; /* text attributes for pet */ - struct autopickup_exception *autopickup_exceptions; #ifdef WIN32 #define MAX_ALTKEYHANDLER 25 char altkeyhandler[MAX_ALTKEYHANDLER]; diff --git a/src/cmd.c b/src/cmd.c index a9b17bd86..e6c4049b1 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -2139,7 +2139,7 @@ int final; *ocl ? "'" : "", *ocl ? ocl : "all types", *ocl ? "'" : ""); if (flags.pickup_thrown && *ocl) /* *ocl: don't show if 'all types' */ Strcat(buf, " plus thrown"); - if (iflags.autopickup_exceptions) + if (apelist) Strcat(buf, ", with exceptions"); } else Strcpy(buf, "off"); diff --git a/src/decl.c b/src/decl.c index f81271b52..c6e6c6039 100644 --- a/src/decl.c +++ b/src/decl.c @@ -213,6 +213,8 @@ char preferred_pet; /* '\0', 'c', 'd', 'n' (none) */ NEARDATA struct monst *mydogs = (struct monst *) 0; /* monsters that are moving to another dungeon level */ NEARDATA struct monst *migrating_mons = (struct monst *) 0; +NEARDATA struct autopickup_exception *apelist = + (struct autopickup_exception *)0; NEARDATA struct mvitals mvitals[NUMMONS]; NEARDATA long domove_attempting = 0L; diff --git a/src/options.c b/src/options.c index 836e86d7a..bddc35102 100644 --- a/src/options.c +++ b/src/options.c @@ -4414,7 +4414,7 @@ int count_apes(VOID_ARGS) { int numapes = 0; - struct autopickup_exception *ape = iflags.autopickup_exceptions; + struct autopickup_exception *ape = apelist; while (ape) { numapes++; @@ -5327,7 +5327,7 @@ boolean setinitial, setfromfile; start_menu(tmpwin); if (numapes) { ape = (struct autopickup_exception *) - iflags.autopickup_exceptions; + apelist; any = zeroany; add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings, "Always pickup '<'; never pickup '>'", @@ -5897,7 +5897,7 @@ dotogglepickup() if (flags.pickup) { oc_to_str(flags.pickup_types, ocl); Sprintf(buf, "ON, for %s objects%s", ocl[0] ? ocl : "all", - (iflags.autopickup_exceptions) + (apelist) ? ((count_apes() == 1) ? ", with one exception" : ", with some exceptions") @@ -5952,8 +5952,8 @@ const char *mapping; ape->pattern = dupstr(text); ape->grab = grab; - ape->next = (struct autopickup_exception *) iflags.autopickup_exceptions; - iflags.autopickup_exceptions = (struct autopickup_exception *) ape; + ape->next = (struct autopickup_exception *) apelist; + apelist = (struct autopickup_exception *) ape; return 1; } @@ -5963,14 +5963,14 @@ struct autopickup_exception *whichape; { struct autopickup_exception *ape, *freeape, *prev = 0; - for (ape = iflags.autopickup_exceptions; ape;) { + for (ape = apelist; ape;) { if (ape == whichape) { freeape = ape; ape = ape->next; if (prev) prev->next = ape; else - iflags.autopickup_exceptions = ape; + apelist = ape; regex_free(freeape->regex); free((genericptr_t) freeape->pattern); free((genericptr_t) freeape); @@ -5984,11 +5984,11 @@ struct autopickup_exception *whichape; void free_autopickup_exceptions() { - struct autopickup_exception *ape = iflags.autopickup_exceptions; - while ((ape = iflags.autopickup_exceptions) != 0) { + struct autopickup_exception *ape = apelist; + while ((ape = apelist) != 0) { regex_free(ape->regex); free((genericptr_t) ape->pattern); - iflags.autopickup_exceptions = ape->next; + apelist = ape->next; free((genericptr_t) ape); } } diff --git a/src/pickup.c b/src/pickup.c index c0ef2b0cf..ab8d5f069 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -718,11 +718,13 @@ struct obj *obj; /* * Does the text description of this match an exception? */ - struct autopickup_exception - *ape = iflags.autopickup_exceptions; + struct autopickup_exception *ape = apelist; + if (ape) { char *objdesc = makesingular(doname(obj)); - while (ape && !regex_match(objdesc, ape->regex)) ape = ape->next; + + while (ape && !regex_match(objdesc, ape->regex)) + ape = ape->next; } return ape; } @@ -732,6 +734,7 @@ autopick_testobj(otmp, calc_costly) struct obj *otmp; boolean calc_costly; { + struct autopickup_exception *ape; static boolean costly = FALSE; const char *otypes = flags.pickup_types; boolean pickit; @@ -748,9 +751,8 @@ boolean calc_costly; /* check for pickup_types */ pickit = (!*otypes || index(otypes, otmp->oclass)); - /* check for autopickup excpetions */ - struct autopickup_exception - *ape = check_autopickup_exceptions(otmp); + /* check for autopickup exceptions */ + ape = check_autopickup_exceptions(otmp); if (ape) pickit = ape->grab; From 72252d5dc6bde42be4a7810d44361f6c803c9872 Mon Sep 17 00:00:00 2001 From: nhmall Date: Tue, 1 Oct 2019 17:47:45 -0400 Subject: [PATCH 7/8] follow-on bits --- src/options.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/options.c b/src/options.c index bddc35102..2e494948a 100644 --- a/src/options.c +++ b/src/options.c @@ -5326,8 +5326,7 @@ boolean setinitial, setfromfile; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin); if (numapes) { - ape = (struct autopickup_exception *) - apelist; + ape = apelist; any = zeroany; add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings, "Always pickup '<'; never pickup '>'", @@ -5952,8 +5951,8 @@ const char *mapping; ape->pattern = dupstr(text); ape->grab = grab; - ape->next = (struct autopickup_exception *) apelist; - apelist = (struct autopickup_exception *) ape; + ape->next = apelist; + apelist = ape; return 1; } @@ -5985,6 +5984,7 @@ void free_autopickup_exceptions() { struct autopickup_exception *ape = apelist; + while ((ape = apelist) != 0) { regex_free(ape->regex); free((genericptr_t) ape->pattern); From e520071f5206149764155f796841aeb9f523b2b6 Mon Sep 17 00:00:00 2001 From: nhmall Date: Tue, 1 Oct 2019 19:57:04 -0400 Subject: [PATCH 8/8] update guidebook --- doc/Guidebook.mn | 15 ++++++++++----- doc/Guidebook.tex | 12 +++++++----- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index ce6d40df0..9fb47b12e 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -24,7 +24,7 @@ .ds vr "NetHack 3.6 .ds f0 "\*(vr .ds f1 -.ds f2 "July 9, 2019 +.ds f2 "October 1, 2019 . .\" A note on some special characters: .\" \(lq = left double quote @@ -3852,11 +3852,16 @@ character in the pattern, specifically: .CC > "never pickup an object that matches rest of pattern." .ei .ed -A \(lqnever pickup\(rq rule takes precedence over an \(lqalways pickup\(rq -rule if both match. +The +.op autopickup_exception +rules are processed in the order in which they appear in your config file, +thus allowing a later rule to override an earlier rule. .lp "" -Exceptions can be set with the \(oqO\(cq command, but ones set that way will -not be preserved across saves and restores. +Exceptions can be set with the \(oqO\(cq command, but because they are not +included in your config file, they won't be in effect if you save and then +restore your game. +.op autopickup_exception +rules and not saved with the game. .\" end of ``.lp autopickup_exception'' entry; continue enclosing page... .\" use .lp "text" to make an unindented paragraph ("text" should be short) .lp "Here are some examples:" diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 7cb9bf0b1..9b52fb5cd 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -45,7 +45,7 @@ %.au \author{Original version - Eric S. Raymond\\ (Edited and expanded for 3.6 by Mike Stephenson and others)} -\date{July 9, 2019} +\date{October 1, 2019} \maketitle @@ -4293,12 +4293,14 @@ character in the pattern, specifically: %.ei %.ed -A ``never pickup'' rule takes precedence over an ``always pickup'' rule if -both match. +The {\it autopickup\verb+_+exception\/} rules are processed in the order +in which they appear in your config file, thus allowing a later rule to override +an earlier rule. %.lp "" -Exceptions can be set with the `{\tt O}' command, but ones set that way will -not be preserved across saves and restores. +Exceptions can be set with the `{\tt O}' command, but because they are not included +in your config file, they won't be in effect if you save and then restore your game. +{\it autopickup\verb+_+exception\/} rules are not saved with the game. \elist %.lp "Here are some examples:"