* Walk through the chain starting at objchn and ask for all objects * with olet in olets (if nonNULL) and satisfying ckfn (if nonnull) * whether the action in question (i.e., fn) has to be performed. */
| 2374 | * whether the action in question (i.e., fn) has to be performed. |
| 2375 | */ |
| 2376 | int |
| 2377 | askchain( |
| 2378 | struct obj **objchn, /* *objchn might change */ |
| 2379 | const char *olets, /* olets is an Obj Class char array */ |
| 2380 | int allflag, /* bypass prompting about individual items */ |
| 2381 | int (*fn)(OBJ_P), /* action to perform on selected items */ |
| 2382 | int (*ckfn)(OBJ_P), /* callback to decided if an item is selectable */ |
| 2383 | int mx, /* if non-0, maximum number of objects to process */ |
| 2384 | const char *word) /* name of the action */ |
| 2385 | { |
| 2386 | struct obj *otmp, *otmpo; |
| 2387 | char sym, ilet; |
| 2388 | int cnt = 0, dud = 0, tmp; |
| 2389 | boolean takeoff, nodot, ident, take_out, put_in, first, ininv, bycat; |
| 2390 | char qbuf[QBUFSZ], qpfx[QBUFSZ]; |
| 2391 | Loot *sortedchn = 0; |
| 2392 | |
| 2393 | takeoff = taking_off(word); |
| 2394 | ident = !strcmp(word, "identify"); |
| 2395 | take_out = !strcmp(word, "take out"); |
| 2396 | put_in = !strcmp(word, "put in"); |
| 2397 | nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || ident |
| 2398 | || takeoff || take_out || put_in); |
| 2399 | ininv = (*objchn == gi.invent); |
| 2400 | bycat = (menu_class_present('u') |
| 2401 | || menu_class_present('B') || menu_class_present('U') |
| 2402 | || menu_class_present('C') || menu_class_present('X') |
| 2403 | || menu_class_present('P')); |
| 2404 | |
| 2405 | /* someday maybe we'll sort by 'olets' too (temporarily replace |
| 2406 | flags.packorder and pass SORTLOOT_PACK), but not yet... */ |
| 2407 | sortedchn = sortloot(objchn, SORTLOOT_INVLET, FALSE, |
| 2408 | (boolean (*)(OBJ_P)) 0); |
| 2409 | |
| 2410 | first = TRUE; |
| 2411 | /* |
| 2412 | * Interrogate in the object class order specified. |
| 2413 | * For example, if a person specifies =/ then first all rings |
| 2414 | * will be asked about followed by all wands. -dgk |
| 2415 | */ |
| 2416 | nextclass: |
| 2417 | ilet = 'a' - 1; |
| 2418 | if (*objchn && (*objchn)->oclass == COIN_CLASS) |
| 2419 | ilet--; /* extra iteration */ |
| 2420 | /* |
| 2421 | * Multiple Drop can change the gi.invent chain while it operates |
| 2422 | * (dropping a burning potion of oil while levitating creates |
| 2423 | * an explosion which can destroy inventory items), so simple |
| 2424 | * list traversal |
| 2425 | * for (otmp = *objchn; otmp; otmp = otmp2) { |
| 2426 | * otmp2 = otmp->nobj; |
| 2427 | * ... |
| 2428 | * } |
| 2429 | * is inadequate here. Use each object's bypass bit to keep |
| 2430 | * track of which list elements have already been processed. |
| 2431 | */ |
| 2432 | bypass_objlist(*objchn, FALSE); /* clear chain's bypass bits */ |
| 2433 | while ((otmp = nxt_unbypassed_loot(sortedchn, *objchn)) != 0) { |
no test coverage detected