From: nethack.allison Date: Sat, 15 Nov 2003 23:15:01 +0000 (+0000) Subject: more autopickup_exception X-Git-Tag: MOVE2GIT~1588 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=94ff3505b4a672cc583eaeb4ce8a1024d111013f;p=nethack more autopickup_exception An optimization. Split the patterns into two chains, one for things you want "always picked up", and one for things you want "never picked up". That way, the entire exception list isn't being checked twice, once for each type of check. The check for things to "always pick up" only checks the chain at the AP_GRAB index, and the check for things to "never pick up" only checks the chain at the AP_LEAVE index. - Also modifies the toggle autopickup '@' message appropriately for the AUTOPICKUP_EXCEPTIONS build. (it just tacks on ", with some exceptions" if there are some) --- diff --git a/include/flag.h b/include/flag.h index 9489214b3..7963d1ba0 100644 --- a/include/flag.h +++ b/include/flag.h @@ -264,8 +264,10 @@ struct instance_flags { boolean clicklook; /* allow right-clicking for look */ boolean obsolete; /* obsolete options can point at this, it isn't used */ #ifdef AUTOPICKUP_EXCEPTIONS - struct autopickup_exception *autopickup_exceptions; -#endif /* AUTOPICKUP_EXCEPTIONS */ + struct autopickup_exception *autopickup_exceptions[2]; +#define AP_LEAVE 0 +#define AP_GRAB 1 +#endif #ifdef WIN32CON #define MAX_ALTKEYHANDLER 25 char altkeyhandler[MAX_ALTKEYHANDLER]; diff --git a/src/options.c b/src/options.c index e5265191a..2df48da52 100644 --- a/src/options.c +++ b/src/options.c @@ -444,7 +444,7 @@ STATIC_OVL boolean FDECL(is_wc2_option, (const char *)); STATIC_OVL boolean FDECL(wc2_supported, (const char *)); #ifdef AUTOPICKUP_EXCEPTIONS STATIC_DCL void FDECL(remove_autopickup_exception, (struct autopickup_exception *)); -STATIC_OVL int NDECL(count_ape_maps); +STATIC_OVL int FDECL(count_ape_maps, (int *, int *)); #endif /* check whether a user-supplied option string is a proper leading @@ -2468,7 +2468,7 @@ doset() #ifdef AUTOPICKUP_EXCEPTIONS any.a_int = -1; Sprintf(buf, "autopickup exceptions (%d currently set)", - count_ape_maps()); + count_ape_maps((int *)0, (int *)0)); add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); #endif /* AUTOPICKUP_EXCEPTIONS */ @@ -2800,27 +2800,24 @@ boolean setinitial,setfromfile; #ifdef AUTOPICKUP_EXCEPTIONS } else if (!strcmp("autopickup_exception", optname)) { boolean retval; - int pick_cnt, pick_idx, opt_idx = 0, numapes = 0, ilet; - struct autopickup_exception *ape = iflags.autopickup_exceptions; + int pick_cnt, pick_idx, opt_idx = 0, pass; + int totalapes = 0, numapes[2] = {0,0}; menu_item *pick_list = (menu_item *)0; anything any; char apebuf[BUFSZ]; + struct autopickup_exception *ape; static const char *action_titles[] = { "a", "add new autopickup exception", "l", "list autopickup exceptions", "r", "remove existing autopickup exception" }; - - while(ape) { - ape = ape->next; - numapes++; - } + totalapes = count_ape_maps(&numapes[AP_LEAVE], &numapes[AP_GRAB]); ape_again: - if (numapes > 0) { + if (totalapes > 0) { tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin); any.a_int = 0; - for (i = 0; i < (numapes ? SIZE(action_titles) : + for (i = 0; i < (totalapes ? SIZE(action_titles) : SIZE(action_titles) - 4); i += 2) { any.a_int++; add_menu(tmpwin, NO_GLYPH, &any, *action_titles[i], @@ -2838,43 +2835,37 @@ ape_again: if (pick_cnt < 1) return FALSE; } /* else just ask for new pickup exception string */ - if (opt_idx == 0) { + if (opt_idx == 0) { /* add new */ getlin("What new autopickup exception pattern?", &apebuf[1]); - if (apebuf[1] == '\033') retval = FALSE; + if (apebuf[1] == '\033') return FALSE; apebuf[0] = '"'; Strcat(apebuf,"\""); add_autopickup_exception(apebuf); - } else if (opt_idx == 1) { - tmpwin = create_nhwindow(NHW_TEXT); - ape = iflags.autopickup_exceptions; - for (i = 0; i < numapes && ape; i++) { - Sprintf(apebuf, "\"%s\" (%s)", - ape->pattern, - ape->grab ? "always pickup" : "never pickup"); - putstr(tmpwin, 0, apebuf); - ape = ape->next; - } - display_nhwindow(tmpwin, FALSE); - destroy_nhwindow(tmpwin); - goto ape_again; - } else { - ape = iflags.autopickup_exceptions; - ilet = 'a'; + } else { /* remove */ tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin); - for (i = 0; i < numapes && ape; i++) { - any.a_void = ape; + for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) { + if (numapes[pass] == 0) continue; + ape = iflags.autopickup_exceptions[pass]; + any.a_void = 0; + add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings, + (pass == 0) ? "Never pickup" : "Always pickup", + MENU_UNSELECTED); + for (i = 0; i < numapes[pass] && ape; i++) { + any.a_void = (opt_idx == 1) ? 0 : ape; Sprintf(apebuf, "\"%s\"", ape->pattern); - add_menu(tmpwin, NO_GLYPH, &any, ilet, 0, - ATR_NONE, apebuf, MENU_UNSELECTED); - if (ilet == 'z') ilet = 'A'; - else if (ilet == 'Z') ilet = 'a'; /* shouldn't happen */ - else ilet++; + add_menu(tmpwin, NO_GLYPH, &any, + 0, 0, ATR_NONE, apebuf, MENU_UNSELECTED); ape = ape->next; + } } - end_menu(tmpwin, "Remove which autopickup exceptions?"); - pick_cnt = select_menu(tmpwin, PICK_ANY, &pick_list); - if (pick_cnt) { + Sprintf(apebuf, "%s autopickup exceptions", + (opt_idx == 1) ? "List of" : "Remove which"); + end_menu(tmpwin, apebuf); + pick_cnt = select_menu(tmpwin, + (opt_idx == 1) ? PICK_NONE : PICK_ANY, + &pick_list); + if (pick_cnt > 0) { for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) remove_autopickup_exception( (struct autopickup_exception *)pick_list[pick_idx].item.a_void); @@ -2882,6 +2873,7 @@ ape_again: free((genericptr_t)pick_list); pick_list = (menu_item *)0; destroy_nhwindow(tmpwin); + if (opt_idx == 1) goto ape_again; } retval = TRUE; #endif /* AUTOPICKUP_EXCEPTIONS */ @@ -3163,7 +3155,14 @@ dotogglepickup() flags.pickup = !flags.pickup; if (flags.pickup) { oc_to_str(flags.pickup_types, ocl); - Sprintf(buf, "ON, for %s objects", ocl[0] ? ocl : "all"); + Sprintf(buf, "ON, for %s objects%s", ocl[0] ? ocl : "all", +#ifdef AUTOPICKUP_EXCEPTIONS + (iflags.autopickup_exceptions[AP_LEAVE] || + iflags.autopickup_exceptions[AP_GRAB]) ? + ((count_ape_maps((int *)0, (int *)0) == 1) ? + ", with one exception" : ", with some exceptions") : +#endif + ""); } else { Strcpy(buf, "OFF"); } @@ -3176,7 +3175,7 @@ int add_autopickup_exception(mapping) const char *mapping; { - struct autopickup_exception *newape, *ape; + struct autopickup_exception *ape, **apehead; char text[256], *text2; static int allocsize = 0; int textsize = 0; @@ -3192,25 +3191,16 @@ const char *mapping; ++text2; } textsize = strlen(text2); - if (!iflags.autopickup_exceptions) { - iflags.autopickup_exceptions = (struct autopickup_exception *) - alloc(sizeof(struct autopickup_exception)); - iflags.autopickup_exceptions->pattern = (char *) - alloc(textsize+1); - Strcpy(iflags.autopickup_exceptions->pattern, text2); - iflags.autopickup_exceptions->grab = grab; - iflags.autopickup_exceptions->next = - (struct autopickup_exception *)0; - } else { - ape = iflags.autopickup_exceptions; - newape = (struct autopickup_exception *)alloc( - sizeof(struct autopickup_exception)); - newape->pattern = (char *)alloc(textsize+1); - Strcpy(newape->pattern, text2); - newape->grab = grab; - newape->next = iflags.autopickup_exceptions; - iflags.autopickup_exceptions = newape; - } + apehead = (grab) ? &iflags.autopickup_exceptions[AP_GRAB] : + &iflags.autopickup_exceptions[AP_LEAVE]; + ape = (struct autopickup_exception *) + alloc(sizeof(struct autopickup_exception)); + ape->pattern = (char *) alloc(textsize+1); + Strcpy(ape->pattern, text2); + ape->grab = grab; + if (!*apehead) ape->next = (struct autopickup_exception *)0; + else ape->next = *apehead; + *apehead = ape; } else { raw_print("syntax error in AUTOPICKUP_EXCEPTION"); return 0; @@ -3223,13 +3213,14 @@ remove_autopickup_exception(whichape) struct autopickup_exception *whichape; { struct autopickup_exception *ape, *prev = 0; + int chain = whichape->grab ? AP_GRAB : AP_LEAVE; - for (ape = iflags.autopickup_exceptions; ape;) { + for (ape = iflags.autopickup_exceptions[chain]; ape;) { if (ape == whichape) { struct autopickup_exception *freeape = ape; ape = ape->next; if (prev) prev->next = ape; - else iflags.autopickup_exceptions = ape; + else iflags.autopickup_exceptions[chain] = ape; free(freeape->pattern); free(freeape); } else { @@ -3240,26 +3231,37 @@ struct autopickup_exception *whichape; } STATIC_OVL int -count_ape_maps() +count_ape_maps(leave, grab) +int *leave, *grab; { - struct autopickup_exception *ape = iflags.autopickup_exceptions; - int cnt = 0; - while(ape) { - ++cnt; - ape = ape->next; + struct autopickup_exception *ape; + int pass, totalapes, numapes[2] = {0,0}; + + for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) { + ape = iflags.autopickup_exceptions[pass]; + while(ape) { + ape = ape->next; + numapes[pass]++; + } } - return cnt; + totalapes = numapes[AP_LEAVE] + numapes[AP_GRAB]; + if (leave) *leave = numapes[AP_LEAVE]; + if (grab) *grab = numapes[AP_GRAB]; + return totalapes; } void free_autopickup_exceptions() { - struct autopickup_exception *ape = iflags.autopickup_exceptions; + struct autopickup_exception *ape; + int pass; - while((ape = iflags.autopickup_exceptions) != 0) { - free(ape->pattern); - iflags.autopickup_exceptions = ape->next; - free(ape); + for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) { + while((ape = iflags.autopickup_exceptions[pass]) != 0) { + free(ape->pattern); + iflags.autopickup_exceptions[pass] = ape->next; + free(ape); + } } } #endif /* AUTOPICKUP_EXCEPTIONS */ diff --git a/src/pickup.c b/src/pickup.c index ce0b21e81..b453f7553 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -606,10 +606,11 @@ boolean grab; /* forced pickup, rather than forced leave behind? */ * Does the text description of this match an exception? */ char *objdesc = makesingular(xname(obj)); - struct autopickup_exception *ape = iflags.autopickup_exceptions; + struct autopickup_exception *ape = (grab) ? + iflags.autopickup_exceptions[AP_GRAB] : + iflags.autopickup_exceptions[AP_LEAVE]; while (ape) { - if (pmatch(ape->pattern, objdesc) && - ((grab && ape->grab) || (!grab && !ape->grab))) return TRUE; + if (pmatch(ape->pattern, objdesc)) return TRUE; ape = ape->next; } return FALSE;