]> granicus.if.org Git - nethack/commitdiff
more autopickup_exception
authornethack.allison <nethack.allison>
Sat, 15 Nov 2003 23:15:01 +0000 (23:15 +0000)
committernethack.allison <nethack.allison>
Sat, 15 Nov 2003 23:15:01 +0000 (23:15 +0000)
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)

include/flag.h
src/options.c
src/pickup.c

index 9489214b391fffe8466d46160559e06e80b6d2e1..7963d1ba0760708487ca943d5a35e79bc2035600 100644 (file)
@@ -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];
index e5265191af4b88be9311e67debe1d295d32ae1ba..2df48da52eaae3c3c2784e2214c2d0415bf38d18 100644 (file)
@@ -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 */
index ce0b21e81f687d52a3b31b324054122bb8de0245..b453f755341f61c684dc2243b70a1f9bd35d3fa1 100644 (file)
@@ -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;