1 /* SCCS Id: @(#)pickup.c 3.4 2003/07/27 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
6 * Contains code for picking objects up, and container use.
11 STATIC_DCL
void simple_look(struct obj
*,BOOLEAN_P
);
13 STATIC_DCL boolean
query_classes(char *,boolean
*,boolean
*,
14 const char *,struct obj
*,BOOLEAN_P
,BOOLEAN_P
,int *);
16 STATIC_DCL boolean
query_classes(char *,boolean
*,boolean
*,
17 const char *,struct obj
*,BOOLEAN_P
,int *);
19 STATIC_DCL
void check_here(BOOLEAN_P
);
20 STATIC_DCL boolean
n_or_more(struct obj
*);
21 STATIC_DCL boolean
all_but_uchain(struct obj
*);
23 STATIC_DCL boolean
allow_cat_no_uchain(struct obj
*);
25 STATIC_DCL
int autopick(struct obj
*, int, menu_item
**);
26 STATIC_DCL
int count_categories(struct obj
*,int);
27 STATIC_DCL
long carry_count(struct obj
*,struct obj
*,long,BOOLEAN_P
,int *,int *);
28 STATIC_DCL
int lift_object(struct obj
*,struct obj
*,long *,BOOLEAN_P
,BOOLEAN_P
);
29 STATIC_PTR
int in_container_(struct obj
*,BOOLEAN_P
);
30 STATIC_PTR
int in_container(struct obj
*);
31 STATIC_PTR
int ck_bag(struct obj
*);
32 STATIC_PTR
int out_container(struct obj
*);
33 STATIC_DCL
void observe_quantum_cat(struct obj
*);
34 STATIC_DCL
int menu_loot(int, struct obj
*, BOOLEAN_P
);
35 STATIC_DCL
int in_or_out_menu(const char *,struct obj
*, BOOLEAN_P
, BOOLEAN_P
);
36 STATIC_DCL
int container_at(int, int, BOOLEAN_P
);
37 STATIC_DCL boolean
able_to_loot(int, int);
38 STATIC_DCL boolean
mon_beside(int, int);
40 /* define for query_objlist() and autopickup() */
41 #define FOLLOW(curr, flags) \
42 (((flags) & BY_NEXTHERE) ? (curr)->nexthere : (curr)->nobj)
44 #define CEILDIV(x,y) (((x)+(y)-1)/(y)) /* ceil(x/y) */
46 * How much the weight of the given container will change when the given
47 * object is removed from it. This calculation must match the one used
48 * by weight() in mkobj.c.
50 #define DELTA_CWT(cont,obj) \
51 ((cont)->cursed ? (obj)->owt * ((cont)->oartifact ? 4 : 2) : \
52 CEILDIV((obj)->owt, ((cont)->oartifact ? 3 : 2) * ((cont)->blessed ? 2 : 1)))
54 #define HANDYBAG_CWT(cont,obj) \
55 (flags.female ? ((obj)->owt * 4 / 5) : (obj)->owt )
57 #define GOLD_WT(n) (((n) + 50L) / 100L)
58 /* if you can figure this out, give yourself a hearty pat on the back... */
59 #define GOLD_CAPACITY(w,n) (((w) * -100L) - ((n) + 50L) - 1L)
61 /* A variable set in use_container(), to be used by the callback routines */
62 /* in_container() and out_container() from askchain() and use_container(). */
63 /* Also used by memu_loot() and container_gone(). */
64 static NEARDATA
struct obj
*current_container
;
65 #define Icebox (current_container->otyp == ICE_BOX || current_container->otyp == DISPERSION_BOX || current_container->otyp == ICE_BOX_OF_HOLDING || current_container->otyp == ICE_BOX_OF_WATERPROOFING || current_container->otyp == ICE_BOX_OF_DIGESTION)
67 static const char moderateloadmsg
[] = "You have a little trouble lifting";
68 static const char nearloadmsg
[] = "You have much trouble lifting";
69 static const char overloadmsg
[] = "You have extreme difficulty lifting";
71 /* BUG: this lets you look at cockatrice corpses while blind without
73 /* much simpler version of the look-here code; used by query_classes() */
75 simple_look(otmp
, here
)
76 struct obj
*otmp
; /* list of objects */
77 boolean here
; /* flag for type of obj list linkage */
79 /* Neither of the first two cases is expected to happen, since
80 * we're only called after multiple classes of objects have been
81 * detected, hence multiple objects must be present.
84 if (InventoryDoesNotGo
&& !program_state
.gameover
) {
85 pline("Not enough memory to create inventory window");
86 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
91 impossible("simple_look(null)");
92 } else if (!(here
? otmp
->nexthere
: otmp
->nobj
)) {
93 pline("%s", doname(otmp
));
95 winid tmpwin
= create_nhwindow(NHW_MENU
);
96 putstr(tmpwin
, 0, "");
98 putstr(tmpwin
, 0, doname(otmp
));
99 otmp
= here
? otmp
->nexthere
: otmp
->nobj
;
101 display_nhwindow(tmpwin
, TRUE
);
102 destroy_nhwindow(tmpwin
);
108 collect_obj_classes(ilets
, otmp
, here
, incl_gold
, filter
, itemcount
)
110 register struct obj
*otmp
;
111 boolean here
, incl_gold
;
112 boolean (*filter
)(OBJ_P
);
116 collect_obj_classes(ilets
, otmp
, here
, filter
, itemcount
)
118 register struct obj
*otmp
;
120 boolean (*filter
)(OBJ_P
);
124 register int iletct
= 0;
130 ilets
[iletct
++] = def_oc_syms
[COIN_CLASS
];
132 ilets
[iletct
] = '\0'; /* terminate ilets so that index() will work */
134 c
= def_oc_syms
[(int)otmp
->oclass
];
135 if (!index(ilets
, c
) && (!filter
|| (*filter
)(otmp
)))
136 ilets
[iletct
++] = c
, ilets
[iletct
] = '\0';
138 otmp
= here
? otmp
->nexthere
: otmp
->nobj
;
145 * Suppose some '?' and '!' objects are present, but '/' objects aren't:
146 * "a" picks all items without further prompting;
147 * "A" steps through all items, asking one by one;
148 * "?" steps through '?' items, asking, and ignores '!' ones;
149 * "/" becomes 'A', since no '/' present;
150 * "?a" or "a?" picks all '?' without further prompting;
151 * "/a" or "a/" becomes 'A' since there aren't any '/'
152 * (bug fix: 3.1.0 thru 3.1.3 treated it as "a");
153 * "?/a" or "a?/" or "/a?",&c picks all '?' even though no '/'
154 * (ie, treated as if it had just been "?a").
158 query_classes(oclasses
, one_at_a_time
, everything
, action
, objs
,
159 here
, incl_gold
, menu_on_demand
)
161 boolean
*one_at_a_time
, *everything
;
164 boolean here
, incl_gold
;
168 query_classes(oclasses
, one_at_a_time
, everything
, action
, objs
,
169 here
, menu_on_demand
)
171 boolean
*one_at_a_time
, *everything
;
178 char ilets
[20], inbuf
[BUFSZ
];
179 int iletct
, oclassct
;
180 boolean not_everything
;
185 oclasses
[oclassct
= 0] = '\0';
186 *one_at_a_time
= *everything
= m_seen
= FALSE
;
187 iletct
= collect_obj_classes(ilets
, objs
, here
,
191 (boolean (*)(OBJ_P
)) 0, &itemcount
);
194 } else if (iletct
== 1) {
195 oclasses
[0] = def_char_to_objclass(ilets
[0]);
197 if (itemcount
&& menu_on_demand
) {
198 ilets
[iletct
++] = 'm';
200 ilets
[iletct
] = '\0';
202 } else { /* more than one choice available */
203 const char *where
= 0;
204 register char sym
, oc_of_sym
, *p
;
205 /* additional choices */
206 ilets
[iletct
++] = ' ';
207 ilets
[iletct
++] = 'a';
208 ilets
[iletct
++] = 'A';
209 ilets
[iletct
++] = (objs
== invent
? 'i' : ':');
210 if (menu_on_demand
) {
211 ilets
[iletct
++] = 'm';
214 ilets
[iletct
] = '\0';
216 oclasses
[oclassct
= 0] = '\0';
217 *one_at_a_time
= *everything
= FALSE
;
218 not_everything
= FALSE
;
219 sprintf(qbuf
,"What kinds of thing do you want to %s? [%s]",
222 if (*inbuf
== '\033') return FALSE
;
224 for (p
= inbuf
; (sym
= *p
++); ) {
225 /* new A function (selective all) added by GAN 01/09/87 */
226 if (sym
== ' ') continue;
227 else if (sym
== 'A') *one_at_a_time
= TRUE
;
228 else if (sym
== 'a') {
229 if (yn("You decided to autoselect everything, please confirm with y if that's what you really wanted") == 'y') *everything
= TRUE
;
230 } else if (sym
== ':') {
231 simple_look(objs
, here
); /* dumb if objs==invent */
233 } else if (sym
== 'i') {
234 (void) display_inventory((char *)0, TRUE
);
236 } else if (sym
== 'm') {
239 oc_of_sym
= def_char_to_objclass(sym
);
240 if (index(ilets
,sym
)) {
241 add_valid_menu_class(oc_of_sym
);
242 oclasses
[oclassct
++] = oc_of_sym
;
243 oclasses
[oclassct
] = '\0';
246 where
= !strcmp(action
,"pick up") ? "here" :
247 !strcmp(action
,"take out") ?
250 There("are no %c's %s.", sym
, where
);
252 You("have no %c's.", sym
);
253 not_everything
= TRUE
;
257 if (m_seen
&& menu_on_demand
) {
258 *menu_on_demand
= (*everything
|| !oclassct
) ? -2 : -3;
261 if (!oclassct
&& (!*everything
|| not_everything
)) {
262 /* didn't pick anything,
263 or tried to pick something that's not present */
264 *one_at_a_time
= TRUE
; /* force 'A' */
265 *everything
= FALSE
; /* inhibit 'a' */
271 /* look at the objects at our location, unless there are too many of them */
273 check_here(picked_some
)
276 register struct obj
*obj
;
279 /* count the objects here */
280 for (obj
= level
.objects
[u
.ux
][u
.uy
]; obj
; obj
= obj
->nexthere
) {
281 if ((obj
!= uchain
) && !obj
->dynamitekaboom
)
285 /* If there are objects here, take a look. */
287 if (flags
.run
) nomul(0, 0, FALSE
);
289 (void) look_here(ct
, picked_some
);
291 sense_engr_at(u
.ux
, u
.uy
, FALSE
);
295 /* Value set by query_objlist() for n_or_more(). */
296 static long val_for_n_or_more
;
298 /* query_objlist callback: return TRUE if obj's count is >= reference value */
303 if (obj
== uchain
) return FALSE
;
304 if (obj
->dynamitekaboom
) return FALSE
;
305 return (obj
->quan
>= val_for_n_or_more
);
308 /* List of valid menu classes for query_objlist() and allow_category callback */
309 static char valid_menu_classes
[MAXOCLASSES
+ 2];
312 add_valid_menu_class(c
)
315 static int vmc_count
= 0;
317 if (c
== 0) /* reset */
320 valid_menu_classes
[vmc_count
++] = (char)c
;
321 valid_menu_classes
[vmc_count
] = '\0';
324 /* query_objlist callback: return TRUE if not uchain */
329 return ((obj
!= uchain
) && !obj
->dynamitekaboom
);
332 /* query_objlist callback: return TRUE */
345 if (Role_if(PM_PRIEST
)) obj
->bknown
= TRUE
;
346 if (((index(valid_menu_classes
,'u') != (char *)0) && obj
->unpaid
&& !Hallucination
) ||
347 (index(valid_menu_classes
, obj
->oclass
) != (char *)0))
349 else if (((index(valid_menu_classes
,'I') != (char *)0) && not_fully_identified(obj
) && !Hallucination
) ||
350 (index(valid_menu_classes
, obj
->oclass
) != (char *)0))
352 else if (((index(valid_menu_classes
,'U') != (char *)0) &&
353 (obj
->oclass
!= COIN_CLASS
&& obj
->bknown
&& !obj
->blessed
&& !obj
->cursed
&& !Hallucination
)))
355 else if (((index(valid_menu_classes
,'B') != (char *)0) &&
356 (obj
->oclass
!= COIN_CLASS
&& obj
->bknown
&& obj
->blessed
&& !Hallucination
)))
358 else if (((index(valid_menu_classes
,'C') != (char *)0) &&
359 (obj
->oclass
!= COIN_CLASS
&& obj
->bknown
&& obj
->cursed
&& !Hallucination
)))
361 else if (((index(valid_menu_classes
,'X') != (char *)0) &&
362 (obj
->oclass
!= COIN_CLASS
&& !obj
->bknown
&& !Hallucination
)))
369 /* query_objlist callback: return TRUE if valid category (class), no uchain */
371 allow_cat_no_uchain(obj
)
374 if ((obj
!= uchain
) &&
375 (((index(valid_menu_classes
,'u') != (char *)0) && obj
->unpaid
) ||
376 (index(valid_menu_classes
, obj
->oclass
) != (char *)0)))
383 /* query_objlist callback: return TRUE if valid class and worn */
385 is_worn_by_type(otmp
)
386 register struct obj
*otmp
;
388 return((boolean
)(!!(otmp
->owornmask
&
389 (W_ARMOR
| W_RING
| W_AMUL
| W_IMPLANT
| W_TOOL
| W_WEP
| W_SWAPWEP
| W_QUIVER
)))
390 && (index(valid_menu_classes
, otmp
->oclass
) != (char *)0));
394 * Have the hero pick things from the ground
395 * or a monster's inventory if swallowed.
400 * <0 pickup count of something
402 * Returns 1 if tried to pick something up, whether
403 * or not it succeeded.
407 int what
; /* should be a long */
409 int i
, n
, res
, count
, n_tried
= 0, n_picked
= 0;
410 menu_item
*pick_list
= (menu_item
*) 0;
411 boolean autopickup
= what
> 0;
412 struct obj
*objchain
;
415 if (what
< 0) /* pick N of something */
417 else /* pick anything */
421 struct trap
*ttmp
= t_at(u
.ux
, u
.uy
);
422 /* no auto-pick if no-pick move, nothing there, or in a pool */
423 if (autopickup
&& (flags
.nopick
|| !OBJ_AT(u
.ux
, u
.uy
) ||
424 (is_waterypool(u
.ux
, u
.uy
) && !is_crystalwater(u
.ux
, u
.uy
) && !Underwater
) || (is_watertunnel(u
.ux
, u
.uy
) && !Underwater
) || is_lava(u
.ux
, u
.uy
))) {
425 sense_engr_at(u
.ux
, u
.uy
, FALSE
);
429 /* no pickup if levitating & not on air or water level */
430 if (!can_reach_floor()) {
431 if ((multi
&& !flags
.run
) || (autopickup
&& !flags
.pickup
))
432 sense_engr_at(u
.ux
, u
.uy
, FALSE
);
435 if (ttmp
&& ttmp
->tseen
) {
436 /* Allow pickup from holes and trap doors that you escaped
437 * from because that stuff is teetering on the edge just
438 * like you, but not pits, because there is an elevation
439 * discrepancy with stuff in pits.
441 if ((ttmp
->ttyp
== PIT
|| ttmp
->ttyp
== SPIKED_PIT
|| ttmp
->ttyp
== GIANT_CHASM
|| ttmp
->ttyp
== SHIT_PIT
|| ttmp
->ttyp
== MANA_PIT
|| ttmp
->ttyp
== ANOXIC_PIT
|| ttmp
->ttyp
== HYPOXIC_PIT
|| ttmp
->ttyp
== ACID_PIT
) &&
442 (!u
.utrap
|| (u
.utrap
&& u
.utraptype
!= TT_PIT
)) && !Passes_walls
&& !Flying
) {
443 sense_engr_at(u
.ux
, u
.uy
, FALSE
);
447 /* multi && !flags.run means they are in the middle of some other
448 * action, or possibly paralyzed, sleeping, etc.... and they just
449 * teleported onto the object. They shouldn't pick it up.
451 if ((multi
&& !flags
.run
) || (autopickup
&& !flags
.pickup
)) {
455 if (notake(youmonst
.data
) && !(uarmg
&& itemhasappearance(uarmg
, APP_HOOKED_GLOVES
)) && !Race_if(PM_TRANSFORMER
) ) {
457 You("are physically incapable of picking anything up.");
458 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
460 if (yn("But maybe you can reach the items anyway. Try it?") == 'y') {
461 if (rn2(3) && !polyskillchance()) {
462 make_hallucinated(HHallucination
+ rnd(50),FALSE
,0L);
463 pline("Oh wow! Is that your own shiny reflection you just saw?");
464 if (!rn2(20)) badeffect();
465 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
478 /* if there's anything here, stop running */
479 if (OBJ_AT(u
.ux
,u
.uy
) && flags
.run
&& flags
.run
!= 8 && !flags
.nopick
) nomul(0, 0, FALSE
);
482 add_valid_menu_class(0); /* reset */
484 objchain
= level
.objects
[u
.ux
][u
.uy
];
485 traverse_how
= BY_NEXTHERE
;
486 } else {pline(FunnyHallu
? "There's something embedded here, but you can't dislodge it..." : "You can't take items out of a monster's interior!");
487 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
488 return (0); /* otherwise the player could snatch worn amulets of life saving or similar stuff! --Amy */
491 objchain = u.ustuck->minvent;
492 traverse_how = 0;*/ /* nobj */
495 * Start the actual pickup process. This is split into two main
496 * sections, the newer menu and the older "traditional" methods.
497 * Automatic pickup has been split into its own menu-style routine
498 * to make things less confusing.
501 n
= autopick(objchain
, traverse_how
, &pick_list
);
505 if ((flags
.menu_style
!= MENU_TRADITIONAL
&& !InventoryDoesNotGo
) || iflags
.menu_requested
) {
507 /* use menus exclusively */
508 if (count
) { /* looking for N of something */
510 sprintf(buf
, "Pick %d of what?", count
);
511 val_for_n_or_more
= count
; /* set up callback selector */
512 n
= query_objlist(buf
, objchain
,
513 traverse_how
|AUTOSELECT_SINGLE
|INVORDER_SORT
,
514 &pick_list
, PICK_ONE
, n_or_more
);
515 /* correct counts, if any given */
516 for (i
= 0; i
< n
; i
++)
517 pick_list
[i
].count
= count
;
519 n
= query_objlist("Pick up what?", objchain
,
520 traverse_how
|AUTOSELECT_SINGLE
|INVORDER_SORT
|FEEL_COCKATRICE
,
521 &pick_list
, PICK_ANY
, all_but_uchain
);
525 for (n_picked
= i
= 0 ; i
< n
; i
++) {
526 res
= pickup_object(pick_list
[i
].item
.a_obj
,pick_list
[i
].count
,
528 if (res
< 0) break; /* can't continue */
531 if (pick_list
) free((void *)pick_list
);
534 /* old style interface */
537 boolean all_of_a_type
, selective
;
538 char oclasses
[MAXOCLASSES
];
539 struct obj
*obj
, *obj2
;
541 oclasses
[0] = '\0'; /* types to consider (empty for all) */
542 all_of_a_type
= TRUE
; /* take all of considered types */
543 selective
= FALSE
; /* ask for each item */
545 /* check for more than one object */
547 obj
; obj
= (traverse_how
== BY_NEXTHERE
) ? obj
->nexthere
: obj
->nobj
)
550 if (ct
== 1 && count
) {
551 /* if only one thing, then pick it */
553 lcount
= min(obj
->quan
, (long)count
);
555 if (pickup_object(obj
, lcount
, FALSE
, FALSE
) > 0)
556 n_picked
++; /* picked something */
559 } else if (ct
>= 2) {
562 There("are %s objects here.",
563 (ct
<= 10) ? "several" : "many");
564 if (!query_classes(oclasses
, &selective
, &all_of_a_type
,
566 traverse_how
== BY_NEXTHERE
,
571 if (!via_menu
) return (0);
572 n
= query_objlist("Pick up what?",
574 traverse_how
|(selective
? 0 : INVORDER_SORT
),
575 &pick_list
, PICK_ANY
,
576 via_menu
== -2 ? allow_all
: allow_category
);
581 for (obj
= objchain
; obj
; obj
= obj2
) {
582 if (traverse_how
== BY_NEXTHERE
)
583 obj2
= obj
->nexthere
; /* perhaps obj will be picked up */
588 if (!selective
&& oclasses
[0] && !index(oclasses
,obj
->oclass
))
591 if (!all_of_a_type
) {
593 sprintf(qbuf
, "Pick up %s?",
594 safe_qbuf("", sizeof("Pick up ?"), doname(obj
),
595 an(simple_typename(obj
->otyp
)), "something"));
596 switch ((obj
->quan
< 2L) ? ynaq(qbuf
) : ynNaq(qbuf
)) {
597 case 'q': goto end_query
; /* out 2 levels */
600 all_of_a_type
= TRUE
;
603 oclasses
[0] = obj
->oclass
;
607 case '#': /* count was entered */
608 if (!yn_number
) continue; /* 0 count => No */
609 lcount
= (long) yn_number
;
610 if (lcount
> obj
->quan
) lcount
= obj
->quan
;
616 if (lcount
== -1L) lcount
= obj
->quan
;
619 if ((res
= pickup_object(obj
, lcount
, FALSE
, FALSE
)) < 0) break;
623 ; /* semicolon needed by brain-damaged compilers */
627 if (!OBJ_AT(u
.ux
,u
.uy
)) u
.uundetected
= 0;
629 /* position may need updating (invisible hero) */
630 if (n_picked
) newsym(u
.ux
,u
.uy
);
632 /* see whether there's anything else here, after auto-pickup is done */
633 if (autopickup
) check_here(n_picked
> 0);
636 /* Picking up stuff no longer consumes turns. --Amy */
637 /* See comment in do.c about soviet mode */
638 /* message is only given if you actually tried to pick something up */
641 if (!rn2(10) && n_tried
) pline("Eto zanimayet ochered' potomu, chto sovetskiy khochet, chtoby igra byla der'mo.");
642 return (n_tried
> 0);
643 /* I considered making it "return 1" just to spite the player, but decided to be lenient. */
645 return /*(n_tried > */0/*)*/;
648 #ifdef AUTOPICKUP_EXCEPTIONS
650 is_autopickup_exception(obj
, grab
)
652 boolean grab
; /* forced pickup, rather than forced leave behind? */
655 * Does the text description of this match an exception?
657 char *objdesc
= makesingular(doname(obj
));
658 struct autopickup_exception
*ape
= (grab
) ?
659 iflags
.autopickup_exceptions
[AP_GRAB
] :
660 iflags
.autopickup_exceptions
[AP_LEAVE
];
662 if (pmatch(ape
->pattern
, objdesc
)) return TRUE
;
667 #endif /* AUTOPICKUP_EXCEPTIONS */
670 * Pick from the given list using flags.pickup_types. Return the number
671 * of items picked (not counts). Create an array that returns pointers
672 * and counts of the items to be picked up. If the number of items
673 * picked is zero, the pickup list is left alone. The caller of this
674 * function must free the pickup list.
677 autopick(olist
, follow
, pick_list
)
678 struct obj
*olist
; /* the object list */
679 int follow
; /* how to follow the object list */
680 menu_item
**pick_list
; /* list of objects and counts to pick up */
682 menu_item
*pi
; /* pick item */
685 const char *otypes
= flags
.pickup_types
;
687 /* first count the number of eligible items */
688 for (n
= 0, curr
= olist
; curr
; curr
= FOLLOW(curr
, follow
)) {
690 if (AlwaysAutopickup
|| u
.uprops
[AUTOPICKUP_ALWAYS
].extrinsic
|| have_autopickupstone()) n
++;
693 #ifndef AUTOPICKUP_EXCEPTIONS
694 if (/*!*otypes || */index(otypes
, curr
->oclass
) ||
695 (flags
.pickup_thrown
&& curr
->was_thrown
&& !(curr
->cursed
&& curr
->bknown
&& !flags
.pickup_cursed
&& !Hallucination
&& !(PlayerUninformation
) ) ) )
697 if ((/*!*otypes || */index(otypes
, curr
->oclass
) ||
698 (flags
.pickup_thrown
&& curr
->was_thrown
&& !(curr
->cursed
&& curr
->bknown
&& !flags
.pickup_cursed
&& !Hallucination
&& !(PlayerUninformation
) ) ) ||
699 is_autopickup_exception(curr
, TRUE
)) &&
700 !is_autopickup_exception(curr
, FALSE
))
707 *pick_list
= pi
= (menu_item
*) alloc(sizeof(menu_item
) * n
);
708 for (n
= 0, curr
= olist
; curr
; curr
= FOLLOW(curr
, follow
)) {
710 if (AlwaysAutopickup
|| u
.uprops
[AUTOPICKUP_ALWAYS
].extrinsic
|| have_autopickupstone()) {
711 pi
[n
].item
.a_obj
= curr
;
712 pi
[n
].count
= curr
->quan
;
717 #ifndef AUTOPICKUP_EXCEPTIONS
718 if (/*!*otypes || */index(otypes
, curr
->oclass
) ||
719 (flags
.pickup_thrown
&& curr
->was_thrown
&& !(curr
->cursed
&& curr
->bknown
&& !flags
.pickup_cursed
&& !Hallucination
&& !(PlayerUninformation
) ) ) ) {
721 if ((/*!*otypes || */index(otypes
, curr
->oclass
) ||
722 (flags
.pickup_thrown
&& curr
->was_thrown
&& !(curr
->cursed
&& curr
->bknown
&& !flags
.pickup_cursed
&& !Hallucination
&& !(PlayerUninformation
) ) ) ||
723 is_autopickup_exception(curr
, TRUE
)) && !is_autopickup_exception(curr
, FALSE
)) {
725 pi
[n
].item
.a_obj
= curr
;
726 pi
[n
].count
= curr
->quan
;
739 * Put up a menu using the given object list. Only those objects on the
740 * list that meet the approval of the allow function are displayed. Return
741 * a count of the number of items selected, as well as an allocated array of
742 * menu_items, containing pointers to the objects selected and counts. The
743 * returned counts are guaranteed to be in bounds and non-zero.
746 * BY_NEXTHERE - Follow object list via nexthere instead of nobj.
747 * AUTOSELECT_SINGLE - Don't ask if only 1 object qualifies - just
749 * USE_INVLET - Use object's invlet.
750 * INVORDER_SORT - Use hero's pack order.
751 * SIGNAL_NOMENU - Return -1 rather than 0 if nothing passes "allow".
752 * SIGNAL_CANCEL - Return -2 rather than 0 if player cancels.
755 query_objlist(qstr
, olist
, qflags
, pick_list
, how
, allow
)
756 const char *qstr
; /* query string */
757 struct obj
*olist
; /* the list to pick from */
758 int qflags
; /* options to control the query */
759 menu_item
**pick_list
; /* return list of items picked */
760 int how
; /* type of query */
761 boolean (*allow
)(OBJ_P
);/* allow function */
766 struct obj
*curr
, *last
;
770 boolean printed_type_name
;
772 if (InventoryDoesNotGo
&& !program_state
.gameover
) {pline("Not enough memory to create inventory window");
773 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
777 *pick_list
= (menu_item
*) 0;
778 if (!olist
) return 0;
780 /* count the number of items allowed */
781 for (n
= 0, last
= 0, curr
= olist
; curr
; curr
= FOLLOW(curr
, qflags
)) {
783 if ((*allow
)(curr
)) {
789 if (n
== 0) /* nothing to pick here */
790 return (qflags
& SIGNAL_NOMENU
) ? -1 : 0;
792 if (n
== 1 && (qflags
& AUTOSELECT_SINGLE
)) {
793 *pick_list
= (menu_item
*) alloc(sizeof(menu_item
));
794 (*pick_list
)->item
.a_obj
= last
;
795 (*pick_list
)->count
= last
->quan
;
799 /* Make a temporary array to store the objects sorted */
800 oarray
= (struct obj
**)alloc(n
*sizeof(struct obj
*));
802 /* Add objects to the array */
804 for (curr
= olist
; curr
; curr
= FOLLOW(curr
, qflags
)) {
805 if ((*allow
)(curr
)) {
806 if ((iflags
.sortloot
== 'f' ||
807 (iflags
.sortloot
== 'l' && !(qflags
& USE_INVLET
))) && !(Hallucination
|| PlayerUninformation
))
809 /* Insert object at correct index */
812 if (strcmpi(cxname3(curr
), cxname3(oarray
[j
-1]))>0) break;
813 oarray
[j
] = oarray
[j
-1];
818 /* Just add it to the array */
824 win
= create_nhwindow(NHW_MENU
);
826 any
.a_obj
= (struct obj
*) 0;
829 * Run through the list and add the objects to the menu. If
830 * INVORDER_SORT is set, we'll run through the list once for
831 * each type so we can group them. The allow function will only
832 * be called once per object in the list.
834 pack
= flags
.inv_order
;
836 printed_type_name
= FALSE
;
837 /*for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {*/
838 for (i
= 0; i
< n
; i
++) {
841 if ((qflags
& FEEL_COCKATRICE
) && (curr
->otyp
== CORPSE
|| curr
->otyp
== EGG
) &&
842 will_feel_cockatrice(curr
, FALSE
)) {
843 destroy_nhwindow(win
); /* stop the menu and revert */
844 (void) look_here(0, FALSE
);
847 if ((!(qflags
& INVORDER_SORT
) || curr
->oclass
== *pack
)
850 /* if sorting, print type name (once only) */
851 if (qflags
& INVORDER_SORT
&& !printed_type_name
) {
852 any
.a_obj
= (struct obj
*) 0;
853 add_menu(win
, NO_GLYPH
, &any
, 0, 0, iflags
.menu_headings
,
854 let_to_name(*pack
, FALSE
, iflags
.showsym
), MENU_UNSELECTED
);
855 printed_type_name
= TRUE
;
859 add_menu(win
, obj_to_glyph(curr
), &any
,
860 qflags
& USE_INVLET
? curr
->invlet
: 0,
861 def_oc_syms
[(int)objects
[curr
->otyp
].oc_class
],
862 ATR_NONE
, doname(curr
), MENU_UNSELECTED
);
866 } while (qflags
& INVORDER_SORT
&& *pack
);
870 n
= select_menu(win
, how
, pick_list
);
871 destroy_nhwindow(win
);
877 /* fix up counts: -1 means no count used => pick all */
878 for (i
= 0, mi
= *pick_list
; i
< n
; i
++, mi
++)
879 if (mi
->count
== -1L || mi
->count
> mi
->item
.a_obj
->quan
)
880 mi
->count
= mi
->item
.a_obj
->quan
;
882 /* caller's don't expect -1 */
883 n
= (qflags
& SIGNAL_CANCEL
) ? -2 : 0;
889 * allow menu-based category (class) selection (for Drop,take off etc.)
893 query_category(qstr
, olist
, qflags
, pick_list
, how
)
894 const char *qstr
; /* query string */
895 struct obj
*olist
; /* the list to pick from */
896 int qflags
; /* behaviour modification flags */
897 menu_item
**pick_list
; /* return list of items picked */
898 int how
; /* type of query */
905 boolean collected_type_name
;
908 boolean do_unpaid
= FALSE
;
909 boolean do_unided
= FALSE
;
910 boolean do_blessed
= FALSE
, do_cursed
= FALSE
, do_uncursed
= FALSE
,
911 do_buc_unknown
= FALSE
;
912 int num_buc_types
= 0;
914 *pick_list
= (menu_item
*) 0;
915 if (!olist
) return 0;
916 if ((qflags
& UNPAID_TYPES
) && count_unpaid(olist
) && !Hallucination
) do_unpaid
= TRUE
;
917 if ((qflags
& NOTFULLYIDED
) && count_notfullyided(olist
) && !Hallucination
) do_unided
= TRUE
;
918 if ((qflags
& BUC_BLESSED
) && count_buc(olist
, BUC_BLESSED
) && !Hallucination
&& !(PlayerUninformation
) ) {
922 if ((qflags
& BUC_CURSED
) && count_buc(olist
, BUC_CURSED
) && !Hallucination
&& !(PlayerUninformation
) ) {
926 if ((qflags
& BUC_UNCURSED
) && count_buc(olist
, BUC_UNCURSED
) && !Hallucination
&& !(PlayerUninformation
) ) {
930 if ((qflags
& BUC_UNKNOWN
) && count_buc(olist
, BUC_UNKNOWN
) && !Hallucination
&& !(PlayerUninformation
) ) {
931 do_buc_unknown
= TRUE
;
935 ccount
= count_categories(olist
, qflags
);
936 /* no point in actually showing a menu for a single category */
937 if (ccount
== 1 && !do_unpaid
&& num_buc_types
<= 1 && !(qflags
& BILLED_TYPES
)) {
938 for (curr
= olist
; curr
; curr
= FOLLOW(curr
, qflags
)) {
939 if ((qflags
& WORN_TYPES
) &&
940 !(curr
->owornmask
& (W_ARMOR
|W_RING
|W_AMUL
|W_IMPLANT
|W_TOOL
|W_WEP
|W_SWAPWEP
|W_QUIVER
)))
945 *pick_list
= (menu_item
*) alloc(sizeof(menu_item
));
946 (*pick_list
)->item
.a_int
= curr
->oclass
;
950 impossible("query_category: no single object match");
956 win
= create_nhwindow(NHW_MENU
);
958 pack
= flags
.inv_order
;
959 if ((qflags
& ALL_TYPES
) && (ccount
> 1)) {
962 any
.a_int
= ALL_TYPES_SELECTED
;
963 add_menu(win
, NO_GLYPH
, &any
, invlet
, 0, ATR_NONE
,
964 (qflags
& WORN_TYPES
) ? "All worn types" : "All types",
970 collected_type_name
= FALSE
;
971 for (curr
= olist
; curr
; curr
= FOLLOW(curr
, qflags
)) {
972 if (curr
->oclass
== *pack
) {
973 if ((qflags
& WORN_TYPES
) &&
974 !(curr
->owornmask
& (W_ARMOR
| W_RING
| W_AMUL
| W_IMPLANT
| W_TOOL
|
975 W_WEP
| W_SWAPWEP
| W_QUIVER
)))
977 if (!collected_type_name
) {
979 any
.a_int
= curr
->oclass
;
980 add_menu(win
, NO_GLYPH
, &any
, invlet
++,
981 def_oc_syms
[(int)objects
[curr
->otyp
].oc_class
],
982 ATR_NONE
, let_to_name(*pack
, FALSE
, iflags
.showsym
),
984 collected_type_name
= TRUE
;
990 impossible("query_category: too many categories");
995 /* unidentified items */
1000 add_menu(win
, NO_GLYPH
, &any
, invlet
, 0, ATR_NONE
,
1001 "Unidentified items", MENU_UNSELECTED
);
1003 /* unpaid items if there are any */
1008 add_menu(win
, NO_GLYPH
, &any
, invlet
, 0, ATR_NONE
,
1009 "Unpaid items", MENU_UNSELECTED
);
1011 /* billed items: checked by caller, so always include if BILLED_TYPES */
1012 if (qflags
& BILLED_TYPES
) {
1016 add_menu(win
, NO_GLYPH
, &any
, invlet
, 0, ATR_NONE
,
1017 "Unpaid items already used up", MENU_UNSELECTED
);
1019 if (qflags
& CHOOSE_ALL
) {
1023 add_menu(win
, NO_GLYPH
, &any
, invlet
, 0, ATR_NONE
,
1024 (qflags
& WORN_TYPES
) ?
1025 "Auto-select every item being worn" :
1026 "Auto-select every item", MENU_UNSELECTED
);
1028 /* items with b/u/c/unknown if there are any */
1033 add_menu(win
, NO_GLYPH
, &any
, invlet
, 0, ATR_NONE
,
1034 "Items known to be Blessed", MENU_UNSELECTED
);
1040 add_menu(win
, NO_GLYPH
, &any
, invlet
, 0, ATR_NONE
,
1041 "Items known to be Cursed", MENU_UNSELECTED
);
1047 add_menu(win
, NO_GLYPH
, &any
, invlet
, 0, ATR_NONE
,
1048 "Items known to be Uncursed", MENU_UNSELECTED
);
1050 if (do_buc_unknown
) {
1054 add_menu(win
, NO_GLYPH
, &any
, invlet
, 0, ATR_NONE
,
1055 "Items of unknown B/C/U status",
1058 end_menu(win
, qstr
);
1059 n
= select_menu(win
, how
, pick_list
);
1060 destroy_nhwindow(win
);
1062 n
= 0; /* caller's don't expect -1 */
1067 count_categories(olist
, qflags
)
1072 boolean counted_category
;
1076 pack
= flags
.inv_order
;
1078 counted_category
= FALSE
;
1079 for (curr
= olist
; curr
; curr
= FOLLOW(curr
, qflags
)) {
1080 if (curr
->oclass
== *pack
) {
1081 if ((qflags
& WORN_TYPES
) &&
1082 !(curr
->owornmask
& (W_ARMOR
| W_RING
| W_AMUL
| W_IMPLANT
| W_TOOL
|
1083 W_WEP
| W_SWAPWEP
| W_QUIVER
)))
1085 if (!counted_category
) {
1087 counted_category
= TRUE
;
1096 /* could we carry `obj'? if not, could we carry some of it/them? */
1098 carry_count(obj
, container
, count
, telekinesis
, wt_before
, wt_after
)
1099 struct obj
*obj
, *container
; /* object to pick up, bag it's coming out of */
1101 boolean telekinesis
;
1102 int *wt_before
, *wt_after
;
1104 boolean adjust_wt
= container
&& carried(container
),
1105 is_gold
= obj
->oclass
== COIN_CLASS
;
1106 int wt
, iw
, ow
, oow
;
1109 long umoney
= money_cnt(invent
);
1112 const char *verb
, *prefx1
, *prefx2
, *suffx
;
1113 char obj_nambuf
[BUFSZ
], where
[BUFSZ
];
1115 savequan
= obj
->quan
;
1118 iw
= max_capacity();
1120 if (count
!= savequan
) {
1122 obj
->owt
= (unsigned)weight(obj
);
1124 wt
= iw
+ (int)obj
->owt
;
1126 wt
-= (container
->otyp
== BAG_OF_HOLDING
|| container
->otyp
== ICE_BOX_OF_HOLDING
|| container
->otyp
== CHEST_OF_HOLDING
|| container
->oartifact
== ART_SACK_OF_HOLDING
) ?
1127 (int)DELTA_CWT(container
, obj
) : (container
->otyp
== HANDYBAG
) ? (int)HANDYBAG_CWT(container
, obj
) : (int)obj
->owt
;
1129 if (is_gold
) /* merged gold might affect cumulative weight */
1130 wt
-= (GOLD_WT(u
.ugold
) + GOLD_WT(count
) - GOLD_WT(u
.ugold
+ count
));
1132 /* This will go with silver+copper & new gold weight */
1133 if (is_gold
) /* merged gold might affect cumulative weight */
1134 wt
-= (GOLD_WT(umoney
) + GOLD_WT(count
) - GOLD_WT(umoney
+ count
));
1136 if (count
!= savequan
) {
1137 obj
->quan
= savequan
;
1146 /* see how many we can lift */
1149 iw
-= (int)GOLD_WT(u
.ugold
);
1151 qq
= GOLD_CAPACITY((long)iw
, u
.ugold
);
1154 qq
= 50L - (u
.ugold
% 100L) - 1L;
1156 iw
-= (int)GOLD_WT(umoney
);
1158 qq
= GOLD_CAPACITY((long)iw
, umoney
);
1161 qq
= 50L - (umoney
% 100L) - 1L;
1163 if (qq
< 0L) qq
+= 100L;
1164 for ( ; qq
<= count
; qq
+= 100L) {
1166 obj
->owt
= (unsigned)GOLD_WT(qq
);
1168 ow
= (int)GOLD_WT(u
.ugold
+ qq
);
1170 ow
= (int)GOLD_WT(umoney
+ qq
);
1172 ow
-= (container
->otyp
== BAG_OF_HOLDING
|| container
->otyp
== ICE_BOX_OF_HOLDING
|| container
->otyp
== CHEST_OF_HOLDING
|| container
->oartifact
== ART_SACK_OF_HOLDING
) ?
1173 (int)DELTA_CWT(container
, obj
) : (container
->otyp
== HANDYBAG
) ? (int)HANDYBAG_CWT(container
, obj
) : (int)obj
->owt
;
1174 if (iw
+ ow
>= 0) break;
1180 if (qq
< 0L) qq
= 0L;
1181 else if (qq
> count
) qq
= count
;
1183 wt
= iw
+ (int)GOLD_WT(u
.ugold
+ qq
);
1185 wt
= iw
+ (int)GOLD_WT(umoney
+ qq
);
1187 } else if (count
> 1 || count
< obj
->quan
) {
1189 * Ugh. Calc num to lift by changing the quan of of the
1190 * object and calling weight.
1192 * This works for containers only because containers
1193 * don't merge. -dean
1195 for (qq
= 1L; qq
<= count
; qq
++) {
1197 obj
->owt
= (unsigned)(ow
= weight(obj
));
1199 ow
-= (container
->otyp
== BAG_OF_HOLDING
|| container
->otyp
== ICE_BOX_OF_HOLDING
|| container
->otyp
== CHEST_OF_HOLDING
|| container
->oartifact
== ART_SACK_OF_HOLDING
) ?
1200 (int)DELTA_CWT(container
, obj
) : (container
->otyp
== HANDYBAG
) ? (int)HANDYBAG_CWT(container
, obj
) : (int)obj
->owt
;
1207 /* there's only one, and we can't lift it */
1210 obj
->quan
= savequan
;
1214 /* some message will be given */
1215 strcpy(obj_nambuf
, doname(obj
));
1217 sprintf(where
, "in %s", the(xname(container
)));
1220 strcpy(where
, "lying here");
1221 verb
= telekinesis
? "acquire" : "lift";
1224 /* lint supppression */
1225 *obj_nambuf
= *where
= '\0';
1228 /* we can carry qq of them */
1231 You("can only %s %s of the %s %s.",
1232 verb
, (qq
== 1L) ? "one" : "some", obj_nambuf
, where
);
1237 if (!container
) strcpy(where
, "here"); /* slightly shorter form */
1239 if (invent
|| u
.ugold
) {
1241 if (invent
|| umoney
) {
1243 prefx1
= "you cannot ";
1245 suffx
= " any more";
1247 prefx1
= (obj
->quan
== 1L) ? "it " : "even one ";
1248 prefx2
= "is too heavy for you to ";
1251 There("%s %s %s, but %s%s%s%s.",
1252 otense(obj
, "are"), obj_nambuf
, where
,
1253 prefx1
, prefx2
, verb
, suffx
);
1255 /* *wt_after = iw; */
1259 /* determine whether character is able and player is willing to carry `obj' */
1262 lift_object(obj
, container
, cnt_p
, telekinesis
, alwaysflag
)
1263 struct obj
*obj
, *container
; /* object to pick up, bag it's coming out of */
1265 boolean telekinesis
;
1268 int result
, old_wt
, new_wt
, prev_encumbr
, next_encumbr
;
1270 if (obj
->otyp
== BOULDER
&& In_sokoban(&u
.uz
)) {
1271 You("cannot get your %s around this %s.",
1272 body_part(HAND
), xname(obj
));
1275 if (obj
->otyp
== LOADSTONE
|| obj
->otyp
== LOADBOULDER
|| obj
->otyp
== STARLIGHTSTONE
|| alwaysflag
||
1276 (obj
->otyp
== BOULDER
&& (throws_rocks(youmonst
.data
) || (uarmg
&& uarmg
->oartifact
== ART_MOUNTAIN_FISTS
)) ) ||
1277 (obj
->oartifact
&& arti_is_evil(obj
)) )
1278 return 1; /* lift regardless of current situation */
1280 *cnt_p
= carry_count(obj
, container
, *cnt_p
, telekinesis
, &old_wt
, &new_wt
);
1282 result
= -1; /* nothing lifted */
1284 /* Trying to allow the player to pick up as much as they want. --Amy
1285 * If you REALLY want the limit to come back for some weird reason, enable the knapsacklimit option */
1288 } else if ((flags
.knapsacklimit
|| InventorySizeLimited
) && obj
->otyp
!= LOADSTONE
&& obj
->otyp
!= HEALTHSTONE
&& obj
->otyp
!= LUCKSTONE
&& obj
->otyp
!= MANASTONE
&& obj
->otyp
!= SLEEPSTONE
&& obj
->otyp
!= LOADBOULDER
&& obj
->otyp
!= STARLIGHTSTONE
&& obj
->otyp
!= STONE_OF_MAGIC_RESISTANCE
&& !is_nastygraystone(obj
) && !is_feminismstone(obj
) && obj
->oclass
!= COIN_CLASS
&& inv_cnt() >= (InventorySizeXtra
? 26 : 52) &&
1289 !merge_choice(invent
, obj
)) {
1291 } else if ((flags
.knapsacklimit
|| InventorySizeLimited
) && obj
->otyp
!= LOADSTONE
&& obj
->otyp
!= HEALTHSTONE
&& obj
->otyp
!= LUCKSTONE
&& obj
->otyp
!= MANASTONE
&& obj
->otyp
!= SLEEPSTONE
&& obj
->otyp
!= LOADBOULDER
&& obj
->otyp
!= STARLIGHTSTONE
&& obj
->otyp
!= STONE_OF_MAGIC_RESISTANCE
&& !is_nastygraystone(obj
) && !is_feminismstone(obj
) && inv_cnt() >= (InventorySizeXtra
? 26 : 52) && !merge_choice(invent
, obj
)) {
1293 Your("knapsack cannot accommodate any more items.");
1294 result
= -1; /* nothing lifted */
1297 prev_encumbr
= near_capacity();
1298 if (prev_encumbr
< flags
.pickup_burden
)
1299 prev_encumbr
= flags
.pickup_burden
;
1300 next_encumbr
= calc_capacity(new_wt
- old_wt
);
1301 if (next_encumbr
> prev_encumbr
&& !(AlwaysAutopickup
|| u
.uprops
[AUTOPICKUP_ALWAYS
].extrinsic
|| have_autopickupstone()) ) {
1302 /* if (telekinesis) {
1303 result = 0; */ /* don't lift */ /* Amy edit: nonsense! let the player pick up the goddamn item! */
1306 long savequan
= obj
->quan
;
1310 (next_encumbr
> HVY_ENCUMBER
) ? overloadmsg
:
1311 (next_encumbr
> MOD_ENCUMBER
) ? nearloadmsg
:
1313 sprintf(eos(qbuf
), " %s. Continue?",
1314 safe_qbuf(qbuf
, sizeof(" . Continue?"),
1315 doname(obj
), an(simple_typename(obj
->otyp
)), "something"));
1316 obj
->quan
= savequan
;
1317 switch (ynq(qbuf
)) {
1318 case 'q': result
= -1; break;
1319 case 'n': result
= 0; break;
1320 default: break; /* 'y' => result == 1 */
1322 clear_nhwindow(WIN_MESSAGE
);
1327 if (obj
->otyp
== SCR_SCARE_MONSTER
&& !stack_too_big(obj
) && result
<= 0 && !container
)
1332 /* To prevent qbuf overflow in prompts use planA only
1333 * if it fits, or planB if PlanA doesn't fit,
1334 * finally using the fallback as a last resort.
1335 * last_restort is expected to be very short.
1338 safe_qbuf(qbuf
, padlength
, planA
, planB
, last_resort
)
1339 const char *qbuf
, *planA
, *planB
, *last_resort
;
1342 /* convert size_t (or int for ancient systems) to ordinary unsigned */
1343 unsigned len_qbuf
= (unsigned)strlen(qbuf
),
1344 len_planA
= (unsigned)strlen(planA
),
1345 len_planB
= (unsigned)strlen(planB
),
1346 len_lastR
= (unsigned)strlen(last_resort
);
1347 unsigned textleft
= QBUFSZ
- (len_qbuf
+ padlength
);
1349 if (len_lastR
>= textleft
) {
1350 impossible("safe_qbuf: last_resort too large at %u characters.",
1354 return (len_planA
< textleft
) ? planA
:
1355 (len_planB
< textleft
) ? planB
: last_resort
;
1359 * Pick up <count> of obj from the ground and add it to the hero's inventory.
1360 * Returns -1 if caller should break out of its loop, 0 if nothing picked
1361 * up, 1 if otherwise.
1364 pickup_object(obj
, count
, telekinesis
, alwaysflag
)
1367 boolean telekinesis
; /* not picking it up directly by hand */
1368 boolean alwaysflag
; /* force the item to be picked up even if it burdens you --Amy */
1372 const char *where
= (obj
->ox
== u
.ux
&& obj
->oy
== u
.uy
) ?
1376 if (obj
->quan
< count
) {
1377 impossible("pickup_object: count %ld > quan %ld?",
1382 /* In case of auto-pickup, where we haven't had a chance
1383 to look at it yet; affects docall(SCR_SCARE_MONSTER). */
1385 if ((!obj
->oinvis
|| See_invisible
) && !obj
->oinvisreal
)
1388 if (obj
== uchain
) { /* do not pick up attached chain */
1390 } else if (obj
->dynamitekaboom
) {
1392 } else if ( (obj
== uball
) && obj
->otyp
== GOLD_PIECE
) {
1394 } else if (obj
->oartifact
&& !touch_artifact(obj
,&youmonst
)) {
1397 } else if (obj
->oclass
== COIN_CLASS
) {
1398 /* Special consideration for gold pieces... */
1399 long iw
= (long)max_capacity() - GOLD_WT(u
.ugold
);
1400 long gold_capacity
= GOLD_CAPACITY(iw
, u
.ugold
);
1402 if (gold_capacity
<= 0L) {
1404 "There %s %ld gold piece%s %s, but you cannot carry any more.",
1406 obj
->quan
, plur(obj
->quan
), where
);
1408 } else if (gold_capacity
< count
) {
1409 You("can only %s %s of the %ld gold pieces lying %s.",
1410 telekinesis
? "acquire" : "carry",
1411 gold_capacity
== 1L ? "one" : "some", obj
->quan
, where
);
1412 pline("%s %ld gold piece%s.",
1413 nearloadmsg
, gold_capacity
, plur(gold_capacity
));
1414 u
.ugold
+= gold_capacity
;
1415 obj
->quan
-= gold_capacity
;
1416 costly_gold(obj
->ox
, obj
->oy
, gold_capacity
);
1418 /* The SC343-20 bugfix causes phantom crash bugs BECAUSE OBJ IS BEING DELETED. --Amy */
1420 if ((nearload
= near_capacity()) != 0)
1421 pline("%s %ld gold piece%s.",
1422 nearload
< MOD_ENCUMBER
?
1423 moderateloadmsg
: nearloadmsg
,
1424 count
, plur(count
));
1426 prinv((char *) 0, obj
, count
);
1427 costly_gold(obj
->ox
, obj
->oy
, count
);
1428 if (count
== obj
->quan
)
1434 if (flags
.run
) nomul(0, 0, FALSE
);
1437 } else if (obj
->otyp
== PETRIFYIUM_BAR
) {
1438 if ( (!uarmg
|| FingerlessGloves
) && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) ) && !telekinesis
) {
1439 if (poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
))
1440 display_nhwindow(WIN_MESSAGE
, FALSE
);
1442 static char kbuf
[BUFSZ
];
1444 strcpy(kbuf
, "touching a petrifyium bar");
1445 pline("Touching a petrifyium bar is a fatal mistake.");
1452 } else if (obj
->otyp
== PETRIFYIUM_BRA
) {
1453 if ( (!uarmg
|| FingerlessGloves
) && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) ) && !telekinesis
) {
1454 if (poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
))
1455 display_nhwindow(WIN_MESSAGE
, FALSE
);
1457 static char kbuf
[BUFSZ
];
1459 strcpy(kbuf
, "touching a petrifyium bra");
1460 pline("Touching a petrifyium bra is a fatal mistake.");
1467 } else if (obj
->otyp
== CORPSE
) {
1468 if ( (touch_petrifies(&mons
[obj
->corpsenm
])) && (!uarmg
|| FingerlessGloves
)
1469 && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) ) && !telekinesis
) {
1470 if (poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
))
1471 display_nhwindow(WIN_MESSAGE
, FALSE
);
1473 static char kbuf
[BUFSZ
];
1475 pline("Touching this type of corpse is a fatal mistake.");
1476 strcpy(kbuf
, "touching a petrifying corpse");
1480 } else if (is_rider(&mons
[obj
->corpsenm
]) || is_deadlysin(&mons
[obj
->corpsenm
])) {
1481 pline("At your %s, the corpse suddenly moves...",
1482 telekinesis
? "attempted acquisition" : "touch");
1483 (void) revive_corpse(obj
, FALSE
);
1484 exercise(A_WIS
, FALSE
);
1487 } else if (obj
->otyp
== EGG
) {
1488 if ( (touch_petrifies(&mons
[obj
->corpsenm
])) && obj
->corpsenm
!= PM_PLAYERMON
&& (!uarmg
|| FingerlessGloves
)
1489 && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) ) && !telekinesis
) {
1490 if (poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
))
1491 display_nhwindow(WIN_MESSAGE
, FALSE
);
1493 static char kbuf
[BUFSZ
];
1494 strcpy(kbuf
, "coming into contact with a petrifying object");
1496 pline("Touching a petrifying egg is a fatal mistake.");
1501 } else if (obj
->otyp
== SCR_SCARE_MONSTER
&& !stack_too_big(obj
)) {
1502 if (obj
->blessed
) obj
->blessed
= 0;
1503 else if (!obj
->spe
&& !obj
->cursed
) obj
->spe
= 1;
1505 pline_The("scroll%s %s to dust as you %s %s up.",
1506 plur(obj
->quan
), otense(obj
, "turn"),
1507 telekinesis
? "raise" : "pick",
1508 (obj
->quan
== 1L) ? "it" : "them");
1509 if (!(objects
[SCR_SCARE_MONSTER
].oc_name_known
) &&
1510 !(objects
[SCR_SCARE_MONSTER
].oc_uname
))
1512 useupf(obj
, obj
->quan
);
1513 return 1; /* tried to pick something up and failed, but
1514 don't want to terminate pickup loop yet */
1516 } else if (obj
->otyp
== SCR_INSTANT_AMNESIA
) {
1518 useupf(obj
, obj
->quan
);
1519 forget(ALL_SPELLS
|ALL_MAP
, FALSE
);
1520 pline("If ever I should forget, May God make me more wretched Than ever I have been yet!");
1521 return 1; /* tried to pick something up and failed, but
1522 don't want to terminate pickup loop yet */
1523 } else if (obj
&& obj
->oclass
== SCROLL_CLASS
&& !rn2(2) && (DustbinBug
|| u
.uprops
[DUSTBIN_BUG
].extrinsic
|| have_dustbinstone())) {
1524 useupf(obj
, obj
->quan
);
1525 pline("Your clumsy %s accidentally rip the paper to pieces.", makeplural(body_part(HAND
)));
1526 return 1; /* tried to pick something up and failed, but
1527 don't want to terminate pickup loop yet */
1531 if (Role_if(PM_YAUTJA
) && obj
&& obj
->otyp
== CHEMISTRY_SET
) obj
->known
= TRUE
;
1532 if (Role_if(PM_CRACKER
) && obj
&& obj
->oclass
== SCROLL_CLASS
) obj
->bknown
= TRUE
;
1534 if (obj
&& obj
->oclass
== WAND_CLASS
&& (ManaBatteryBug
|| u
.uprops
[MANA_BATTERY_BUG
].extrinsic
|| have_batterystone()) && obj
->spe
>= 0) {
1536 if (obj
->spe
== 0) obj
->spe
= -1;
1538 obj
->spe
-= rnd(obj
->spe
);
1539 if (!rn2(3)) obj
->spe
= 0;
1543 if (obj
&& obj
->oclass
== POTION_CLASS
&& !rn2(3) && (Monsterfingers
|| u
.uprops
[MONSTERFINGERS_EFFECT
].extrinsic
|| have_butterfingerstone()) ) {
1544 pline("Whoops, the bottle breaks unexpectedly!");
1546 useupf(obj
, obj
->quan
);
1547 return 1; /* tried to pick something up and failed, but
1548 don't want to terminate pickup loop yet */
1551 if (obj
&& obj
->oartifact
== ART_HAAAAAAAAAAAAA_LELUJA
) {
1553 obj
->cursed
= obj
->hvycurse
= obj
->prmcurse
= obj
->evilcurse
= obj
->morgcurse
= obj
->bbrcurse
= obj
->stckcurse
= 0;
1557 if ((res
= lift_object(obj
, (struct obj
*)0, &count
, telekinesis
, alwaysflag
)) <= 0)
1561 /* Whats left of the special case for gold :-) */
1562 if (obj
->oclass
== COIN_CLASS
) flags
.botl
= 1;
1564 if (obj
->quan
!= count
&& obj
->otyp
!= LOADSTONE
&& obj
->otyp
!= LUCKSTONE
&& obj
->otyp
!= HEALTHSTONE
&& obj
->otyp
!= MANASTONE
&& obj
->otyp
!= SLEEPSTONE
&& obj
->otyp
!= LOADBOULDER
&& obj
->otyp
!= STARLIGHTSTONE
&& obj
->otyp
!= STONE_OF_MAGIC_RESISTANCE
&& !is_nastygraystone(obj
) && !is_feminismstone(obj
) )
1565 obj
= splitobj(obj
, count
);
1567 if (TooHeavyEffect
|| u
.uprops
[TOO_HEAVY_EFFECT
].extrinsic
|| have_tooheavystone() || (uamul
&& uamul
->oartifact
== ART_THAT_OLD_BUG
) || (uarmg
&& uarmg
->oartifact
== ART_SUPERHEAVYKLONK
) ) {
1568 if (IncreasedGravity
< 10000000) IncreasedGravity
+= 50;
1571 obj
= pick_obj(obj
);
1573 /* evil patch addition: Nasty gray stones aren't usually generated cursed, but they autocurse if you pick them up. BUC testing won't save you! --Amy */
1574 if (is_nastygraystone(obj
)) curse(obj
);
1575 if (is_feminismstone(obj
)) {
1577 pline("Oh no, apparently there is some sort of curse on this gem. It won't leave your inventory as long as it's still cursed.");
1580 /* artifact versions of such stones should be harder to get rid of --Amy */
1581 if ( (is_nastygraystone(obj
) || is_feminismstone(obj
)) ) {
1582 if (obj
->oartifact
) {
1583 if (!rn2(3)) obj
->cursed
= obj
->hvycurse
= TRUE
;
1584 if (!rn2(3)) obj
->cursed
= obj
->stckcurse
= TRUE
;
1588 if (uwep
&& uwep
== obj
) mrg_to_wielded
= TRUE
;
1589 nearload
= near_capacity();
1590 prinv(nearload
== SLT_ENCUMBER
? moderateloadmsg
: (char *) 0,
1592 mrg_to_wielded
= FALSE
;
1597 * Do the actual work of picking otmp from the floor or monster's interior
1598 * and putting it in the hero's inventory. Take care of billing. Return a
1599 * pointer to the object where otmp ends up. This may be different
1600 * from otmp because of merging.
1602 * Gold never reaches this routine unless GOLDOBJ is defined.
1608 obj_extract_self(otmp
);
1609 if (!u
.uswallow
&& otmp
!= uball
&& costly_spot(otmp
->ox
, otmp
->oy
)) {
1610 char saveushops
[5], fakeshop
[2];
1612 /* addtobill cares about your location rather than the object's;
1613 usually they'll be the same, but not when using telekinesis
1614 (if ever implemented) or a grappling hook */
1615 strcpy(saveushops
, u
.ushops
);
1616 fakeshop
[0] = *in_rooms(otmp
->ox
, otmp
->oy
, SHOPBASE
);
1618 strcpy(u
.ushops
, fakeshop
);
1619 /* sets obj->unpaid if necessary */
1620 addtobill(otmp
, TRUE
, FALSE
, FALSE
);
1621 strcpy(u
.ushops
, saveushops
);
1622 /* if you're outside the shop, make shk notice */
1623 if (!index(u
.ushops
, *fakeshop
))
1624 remote_burglary(otmp
->ox
, otmp
->oy
);
1626 if (otmp
->no_charge
) /* only applies to objects outside invent */
1627 otmp
->no_charge
= 0;
1628 if (otmp
->was_thrown
) /* likewise */
1629 otmp
->was_thrown
= 0;
1630 newsym(otmp
->ox
, otmp
->oy
);
1631 return addinv(otmp
); /* might merge it with other objects */
1635 * prints a message if encumbrance changed since the last check and
1636 * returns the new encumbrance value (from near_capacity()).
1641 static int oldcap
= UNENCUMBERED
;
1642 int newcap
= near_capacity();
1644 if(oldcap
< newcap
) {
1646 case 1: Your("movements are slowed slightly because of your load.");
1648 case 2: You("rebalance your load. Movement is difficult.");
1650 case 3: You("%s under your heavy load. Movement is very hard.",
1651 stagger(youmonst
.data
, "stagger"));
1653 default: You("%s move a handspan with this load!",
1654 newcap
== 4 ? "can barely" : "can't even");
1658 } else if(oldcap
> newcap
) {
1660 case 0: Your("movements are now unencumbered.");
1662 case 1: Your("movements are only slowed slightly by your load.");
1664 case 2: You("rebalance your load. Movement is still difficult.");
1666 case 3: You("%s under your load. Movement is still very hard.",
1667 stagger(youmonst
.data
, "stagger"));
1677 /* Is there a container at x,y. Optional: return count of containers at x,y */
1679 container_at(x
, y
, countem
)
1683 struct obj
*cobj
, *nobj
;
1684 int container_count
= 0;
1686 for(cobj
= level
.objects
[x
][y
]; cobj
; cobj
= nobj
) {
1687 nobj
= cobj
->nexthere
;
1688 if(Is_container(cobj
)) {
1690 if (!countem
) break;
1693 return container_count
;
1700 if (!can_reach_floor()) {
1701 if (u
.usteed
&& !(uwep
&& uwep
->oartifact
== ART_SORTIE_A_GAUCHE
) && !(powerfulimplants() && uimplant
&& uimplant
->oartifact
== ART_READY_FOR_A_RIDE
) && !FemtrapActiveKerstin
&& !(bmwride(ART_DEEPER_LAID_BMW
)) && (PlayerCannotUseSkills
|| P_SKILL(P_RIDING
) < P_BASIC
) )
1702 rider_cant_reach(); /* not skilled enough to reach */
1704 You("cannot reach the %s.", surface(x
, y
));
1706 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1708 } else if ((is_waterypool(x
, y
) || is_watertunnel(x
,y
) || is_lava(x
, y
)) && !is_crystalwater(x
, y
)) {
1709 /* at present, can't loot in water even when Underwater */
1710 You("cannot loot things that are deep in the %s.",
1711 is_lava(x
, y
) ? "lava" : "water");
1712 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1714 } else if (nolimbs(youmonst
.data
) && !Race_if(PM_TRANSFORMER
) ) {
1715 pline("Without limbs, you cannot loot anything.");
1716 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1718 } else if (!freehandX() && !(Role_if(PM_CELLAR_CHILD
) && uwep
&& (weapon_type(uwep
) == P_QUARTERSTAFF
)) ) {
1719 pline("Without a free %s, you cannot loot anything.",
1721 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1732 for(i
= -1; i
<= 1; i
++)
1733 for(j
= -1; j
<= 1; j
++) {
1736 if(isok(nx
, ny
) && MON_AT(nx
, ny
))
1743 doloot() /* loot a container on the floor or loot saddle from mon. */
1747 pline("The loot command is currently unavailable!");
1748 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1752 struct obj
*cobj
, *nobj
;
1753 register int c
= -1;
1756 boolean underfoot
= TRUE
;
1757 const char *dont_find_anything
= "don't find anything";
1760 int prev_inquiry
= 0;
1761 boolean prev_loot
= FALSE
;
1764 if (trap
= t_at(u
.ux
, u
.uy
)) {
1765 if (trap
->ttyp
== VIVISECTION_TRAP
) {
1766 You("are in vivisection, and therefore unable to loot anything!");
1767 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1772 if (check_capacity((char *)0)) {
1773 /* "Can't do that while carrying so much stuff." */
1777 /* It used to check for hands here, but I removed that because actually looting a container already checks if your
1778 * form has hands. It was really annoying that you could have twice the failure chance when looting off the ground
1779 * as opposed to applying a container in your inventory, so I changed that. --Amy */
1781 cc
.x
= u
.ux
; cc
.y
= u
.uy
;
1785 if (container_at(cc
.x
, cc
.y
, FALSE
)) {
1786 boolean any
= FALSE
;
1788 if (!able_to_loot(cc
.x
, cc
.y
)) return 0;
1789 for (cobj
= level
.objects
[cc
.x
][cc
.y
]; cobj
; cobj
= nobj
) {
1790 nobj
= cobj
->nexthere
;
1792 if (Is_container(cobj
)) {
1793 sprintf(qbuf
, "There is %s here, loot it?",
1794 safe_qbuf("", sizeof("There is here, loot it?"),
1795 doname(cobj
), an(simple_typename(cobj
->otyp
)),
1798 if (c
== 'q') return (timepassed
);
1799 if (c
== 'n') continue;
1802 if (cobj
->olocked
) {
1803 if (uwep
&& uwep
->oartifact
== ART_FINAL_DOOR_SOLUTION
) {
1804 cobj
->olocked
= FALSE
;
1807 pline("Hmmm, it seems to be locked.");
1811 if (cobj
->otyp
== BAG_OF_TRICKS
) {
1813 You("carefully open the bag...");
1814 pline("It develops a huge set of teeth and bites you!");
1816 if (Half_physical_damage
&& (rn2(2) || (uwep
&& uwep
->oartifact
== ART_SOOTHE_
)) ) tmp
= (tmp
+1) / 2;
1817 if (StrongHalf_physical_damage
&& (rn2(2) || (uwep
&& uwep
->oartifact
== ART_SOOTHE_
)) ) tmp
= (tmp
+1) / 2;
1818 losehp(tmp
, "carnivorous bag", KILLED_BY_AN
);
1819 makeknown(BAG_OF_TRICKS
);
1824 You("carefully open %s...", the(xname(cobj
)));
1825 if ((cobj
->otyp
== BAG_OF_DIGESTION
|| cobj
->otyp
== LARGE_BOX_OF_DIGESTION
|| cobj
->otyp
== ICE_BOX_OF_DIGESTION
) && !timepassed
) timepassed
= 1;
1826 if ((cobj
->otyp
== BAG_OF_HOLDING
|| cobj
->otyp
== CHEST_OF_HOLDING
|| cobj
->oartifact
== ART_SACK_OF_HOLDING
|| cobj
->otyp
== ICE_BOX_OF_HOLDING
) && cobj
->cursed
&& !timepassed
) timepassed
= 1;
1827 timepassed
|= use_container(&cobj
, 0); /* ATTENTION: cobj might be gone now (boh explosion) --Amy */
1829 /* might have triggered chest trap or magic bag explosion */
1830 if (multi
< 0 || !cobj
) return 1;
1834 } else if (Confusion
) {
1837 long contribution
= rnd((int)min(LARGEST_INT
,u
.ugold
));
1838 struct obj
*goldob
= mkgoldobj(contribution
);
1841 /* Find a money object to mess with */
1842 for (goldob
= invent
; goldob
; goldob
= goldob
->nobj
) {
1843 if (goldob
->oclass
== COIN_CLASS
) break;
1846 long contribution
= rnd((int)min(LARGEST_INT
, goldob
->quan
));
1847 if (contribution
< goldob
->quan
)
1848 goldob
= splitobj(goldob
, contribution
);
1851 if (IS_THRONE(levl
[u
.ux
][u
.uy
].typ
)){
1852 struct obj
*coffers
;
1854 /* find the original coffers chest, or any chest */
1855 for (pass
= 2; pass
> -1; pass
-= 2)
1856 for (coffers
= fobj
; coffers
; coffers
= coffers
->nobj
)
1857 if (coffers
->otyp
== CHEST
&& coffers
->spe
== pass
)
1858 goto gotit
; /* two level break */
1861 verbalize("Thank you for your contribution to reduce the debt.");
1862 (void) add_to_container(coffers
, goldob
, TRUE
);
1863 coffers
->owt
= weight(coffers
);
1865 struct monst
*mon
= makemon(courtmon(),
1866 u
.ux
, u
.uy
, NO_MM_FLAGS
);
1869 mon
->mgold
+= goldob
->quan
;
1871 pline("The exchequer accepts your contribution.");
1876 if (!rn2(5) && IS_THRONE(levl
[u
.ux
][u
.uy
].typ
)) { /* reduce player's farming ability */
1877 /* may have teleported */
1878 levl
[u
.ux
][u
.uy
].typ
= ROOM
;
1879 pline_The("throne vanishes in a puff of logic.");
1882 return 1; /* this is supposed to take time! --Amy */
1888 add_to_minv(mon
, goldob
);
1889 pline("The exchequer accepts your contribution.");
1897 pline("Ok, now there is loot here.");
1900 } else if (IS_GRAVE(levl
[cc
.x
][cc
.y
].typ
)) {
1901 You("need to dig up the grave to effectively loot it...");
1904 * 3.3.1 introduced directional looting for some things.
1906 if (c
!= 'y' && mon_beside(u
.ux
, u
.uy
)) {
1907 if (!get_adjacent_loc("Loot in what direction?", "Invalid loot location",
1908 u
.ux
, u
.uy
, &cc
)) return 0;
1909 if (cc
.x
== u
.ux
&& cc
.y
== u
.uy
) {
1911 if (container_at(cc
.x
, cc
.y
, FALSE
))
1916 You("%s to loot on the %s.", dont_find_anything
,
1917 ceiling(cc
.x
, cc
.y
));
1921 mtmp
= m_at(cc
.x
, cc
.y
);
1922 if (mtmp
) timepassed
= loot_mon(mtmp
, &prev_inquiry
, &prev_loot
);
1924 /* Preserve pre-3.3.1 behaviour for containers.
1925 * Adjust this if-block to allow container looting
1926 * from one square away to change that in the future.
1929 if (container_at(cc
.x
, cc
.y
, FALSE
)) {
1931 You_cant("loot anything %sthere with %s in the way.",
1932 prev_inquiry
? "else " : "", mon_nam(mtmp
));
1935 You("have to be at a container to loot it.");
1938 You("%s %sthere to loot.", dont_find_anything
,
1939 (prev_inquiry
|| prev_loot
) ? "else " : "");
1943 } else if (c
!= 'y' && c
!= 'n') {
1944 You("%s %s to loot.", dont_find_anything
,
1945 underfoot
? "here" : "there");
1947 return (timepassed
);
1950 /* loot_mon() returns amount of time passed.
1953 loot_mon(mtmp
, passed_info
, prev_loot
)
1963 /* 3.3.1 introduced the ability to remove saddle from a steed */
1964 /* *passed_info is set to TRUE if a loot query was given. */
1965 /* *prev_loot is set to TRUE if something was actually acquired in here. */
1966 if (mtmp
&& mtmp
!= u
.usteed
&& (otmp
= which_armor(mtmp
, W_SADDLE
))) {
1968 if (passed_info
) *passed_info
= 1;
1969 sprintf(qbuf
, "Do you want to remove the saddle from %s?",
1970 x_monnam(mtmp
, ARTICLE_THE
, (char *)0, SUPPRESS_SADDLE
, FALSE
));
1971 if ((c
= yn_function(qbuf
, ynqchars
, 'n')) == 'y') {
1972 if (nolimbs(youmonst
.data
) && !Race_if(PM_TRANSFORMER
) ) {
1973 You_cant("do that without limbs."); /* not body_part(HAND) */
1977 You("can't. The saddle seems to be stuck to %s.",
1978 x_monnam(mtmp
, ARTICLE_THE
, (char *)0,
1979 SUPPRESS_SADDLE
, FALSE
));
1981 /* the attempt costs you time */
1984 /* wtf, why was it guaranteed to work even for a hostile horse trying to kill you??? --Amy */
1985 if (!mtmp
->mtame
&& !mtmp
->mpeaceful
) {
1986 pline("%s doesn't just let you remove the saddle!", Monnam(mtmp
));
1989 obj_extract_self(otmp
);
1990 if ((unwornmask
= otmp
->owornmask
) != 0L) {
1991 mtmp
->misc_worn_check
&= ~unwornmask
;
1992 otmp
->owornmask
= 0L;
1993 update_mon_intrinsics(mtmp
, otmp
, FALSE
, FALSE
);
1995 otmp
= hold_another_object(otmp
, "You drop %s!", doname(otmp
),
1997 timepassed
= rnd(3);
1998 if (prev_loot
) *prev_loot
= TRUE
;
1999 } else if (c
== 'q') {
2003 /* 3.4.0 introduced the ability to pick things up from within swallower's stomach */
2005 int count
= passed_info
? *passed_info
: 0;
2006 timepassed
= pickup(count
);
2012 * Decide whether an object being placed into a magic bag will cause
2013 * it to explode. If the object is a bag itself, check recursively.
2016 mbag_explodes(obj
, depthin
)
2020 /* these won't cause an explosion when they're empty */
2021 if ((obj
->otyp
== WAN_CANCELLATION
|| obj
->otyp
== BAG_OF_TRICKS
) &&
2025 /* odds: 1/1, 2/2, 3/4, 4/8, 5/16, 6/32, 7/64, 8/128, 9/128, 10/128,... */
2026 if ((Is_mbag(obj
) || obj
->otyp
== WAN_CANCELLATION
) &&
2027 (rn2(1 << (depthin
> 7 ? 7 : depthin
)) <= depthin
))
2029 else if (Has_contents(obj
)) {
2032 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
)
2033 if (mbag_explodes(otmp
, depthin
+1)) return TRUE
;
2039 destroy_mbag(bomb
, silent
)
2045 struct monst
*mtmp
= (struct monst
*)0;
2047 if (get_obj_location(bomb
, &x
, &y
, BURIED_TOO
| CONTAINED_TOO
)) {
2048 switch(bomb
->where
) {
2050 mtmp
= bomb
->ocarry
;
2051 if (bomb
== MON_WEP(mtmp
)) {
2052 bomb
->owornmask
&= ~W_WEP
;
2055 if (!silent
&& canseemon(mtmp
))
2056 You("see %s engulfed in an explosion!", mon_nam(mtmp
));
2057 mtmp
->mhp
-= d(6,6);
2058 if (mtmp
->mhp
< 1) {
2060 monkilled(mtmp
, silent
? "" : "explosion", AD_PHYS
);
2061 else xkilled(mtmp
, !silent
);
2065 /* This shouldn't be silent! */
2066 pline("Something explodes inside your knapsack!");
2070 } else if (bomb
== uswapwep
) {
2073 } else if (bomb
== uquiver
) {
2077 losehp(d(6,6), "carrying live explosives", KILLED_BY
);
2080 underwater
= (is_waterypool(x
, y
) || is_watertunnel(x
,y
));
2082 if (x
== u
.ux
&& y
== u
.uy
) {
2083 if (underwater
&& (Flying
|| Levitation
))
2084 pline_The("water boils beneath you.");
2085 else if (underwater
&& (Wwalking
|| Race_if(PM_KORONST
)))
2086 pline_The("water erupts around you.");
2087 else pline("A bag explodes under your %s!",
2088 makeplural(body_part(FOOT
)));
2089 } else if (cansee(x
, y
))
2091 "see a plume of water shoot up." :
2092 "see a bag explode.");
2094 if (underwater
&& (Flying
|| Levitation
|| Wwalking
|| Race_if(PM_KORONST
))) {
2095 if ((Wwalking
|| Race_if(PM_KORONST
)) && x
== u
.ux
&& y
== u
.uy
) {
2102 trap
.ttyp
= RUST_TRAP
;
2107 trap
.dst
.dlevel
= -1;
2113 default: /* Buried, contained, etc. */
2115 You_hear("a muffled explosion.");
2122 if (Has_contents(bomb
))
2123 delete_contents(bomb
);
2125 obj_extract_self(bomb
);
2126 obfree(bomb
, (struct obj
*)0);
2130 int put_into_container(struct obj
*container
, struct obj
*obj
)
2134 t
= current_container
;
2135 current_container
= container
;
2136 in_container_(obj
,FALSE
);
2137 current_container
= t
;
2139 /* control reaches end of non-void function, but is this one even used anywhere?! --Amy */
2140 return 1; /* eh, let's return 1 for now, can still change it if necessary */
2144 /* Returns: -1 to stop, 1 item was inserted, 0 item was not inserted. */
2146 in_container_(obj
,invobj
)
2147 register struct obj
*obj
;
2150 boolean floor_container
= !carried(current_container
);
2151 boolean was_unpaid
= FALSE
;
2154 if (!current_container
) {
2155 impossible("<in> no current_container?");
2157 } else if (obj
== uball
|| obj
== uchain
) {
2158 You("must be kidding.");
2160 } else if (obj
== current_container
) {
2161 pline(FunnyHallu
? "You try folding it with some ikebana technique but to no avail." : "That would be an interesting topological exercise.");
2163 } else if (obj
->owornmask
& (W_ARMOR
| W_RING
| W_AMUL
| W_IMPLANT
| W_TOOL
)) {
2164 Norep("You cannot %s %s you are wearing.",
2165 Icebox
? "refrigerate" : "stash", something
);
2167 } else if ((obj
->otyp
== LOADSTONE
|| obj
->otyp
== LUCKSTONE
|| obj
->otyp
== HEALTHSTONE
|| obj
->otyp
== MANASTONE
|| obj
->otyp
== SLEEPSTONE
|| obj
->otyp
== LOADBOULDER
|| obj
->otyp
== STARLIGHTSTONE
|| obj
->otyp
== STONE_OF_MAGIC_RESISTANCE
|| is_nastygraystone(obj
) ) && obj
->cursed
) {
2169 pline_The("stone%s won't leave your person.", plur(obj
->quan
));
2171 } else if (obj
->otyp
== LUCKSTONE
&& isevilvariant
&& !obj
->cursed
&& !obj
->blessed
&& Luck
< 0) {
2172 pline("Har har har, an evil presence prevents you from getting rid of that!");
2174 } else if (is_feminismstone(obj
) && obj
->cursed
) {
2176 pline_The("gem%s will not leave your inventory as long as they're cursed.", plur(obj
->quan
));
2178 } else if ( (obj
->otyp
== AMULET_OF_YENDOR
&& !u
.freeplaymode
) || (obj
->otyp
== FAKE_AMULET_OF_YENDOR
&& !u
.freeplaymode
) ||
2179 (obj
->otyp
== CANDELABRUM_OF_INVOCATION
&& !u
.uevent
.invoked
) ||
2180 (obj
->otyp
== BELL_OF_OPENING
&& !u
.uevent
.invoked
) ||
2181 (obj
->oartifact
== ART_KEY_OF_LAW
&& !u
.uevent
.invoked
) ||
2182 (obj
->oartifact
== ART_GAUNTLET_KEY
&& !u
.uevent
.invoked
) ||
2183 (obj
->oartifact
== ART_KEY_OF_NEUTRALITY
&& !u
.uevent
.invoked
) ||
2184 (obj
->oartifact
== ART_KEY_OF_CHAOS
&& !u
.uevent
.invoked
) ||
2185 (obj
->otyp
== SPE_BOOK_OF_THE_DEAD
&& !u
.uevent
.invoked
) ) {
2186 /* Prohibit Amulets in containers; if you allow it, monsters can't
2187 * steal them. It also becomes a pain to check to see if someone
2188 * has the Amulet. Ditto for the Candelabrum, the Bell and the Book.
2190 pline("%s cannot be confined in such trappings.", The(xname(obj
)));
2192 } else if (obj
->otyp
== LEATHER_LEASH
&& obj
->leashmon
!= 0) {
2193 pline("%s attached to your pet.", Tobjnam(obj
, "are"));
2195 } else if (obj
->otyp
== INKA_LEASH
&& obj
->leashmon
!= 0) {
2196 pline("%s attached to your pet.", Tobjnam(obj
, "are"));
2198 } else if (obj
->otyp
== ADAMANT_LEASH
&& obj
->leashmon
!= 0) {
2199 pline("%s attached to your pet.", Tobjnam(obj
, "are"));
2201 } else if (obj
== uwep
) {
2206 setuwep((struct obj
*) 0, FALSE
, TRUE
);
2207 if (uwep
) return 0; /* unwielded, died, rewielded */
2208 } else if (obj
== uswapwep
) {
2209 setuswapwep((struct obj
*) 0, FALSE
);
2210 if (uswapwep
) return 0; /* unwielded, died, rewielded */
2211 } else if (obj
== uquiver
) {
2212 setuqwep((struct obj
*) 0);
2213 if (uquiver
) return 0; /* unwielded, died, rewielded */
2216 if (obj
->otyp
== CORPSE
) {
2217 if ( (touch_petrifies(&mons
[obj
->corpsenm
])) && (!uarmg
|| FingerlessGloves
)
2218 && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) )) {
2219 if (poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
))
2220 display_nhwindow(WIN_MESSAGE
, FALSE
);
2222 static char kbuf
[BUFSZ
];
2224 pline("Touching this type of corpse is a fatal mistake.");
2225 strcpy(kbuf
, "touching a petrifying corpse");
2232 if (obj
->otyp
== PETRIFYIUM_BAR
) {
2233 if ((!uarmg
|| FingerlessGloves
) && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) )) {
2234 if (poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
))
2235 display_nhwindow(WIN_MESSAGE
, FALSE
);
2237 static char kbuf
[BUFSZ
];
2239 strcpy(kbuf
, "touching a petrifyium bar");
2240 pline("Touching a petrifyium bar is a fatal mistake.");
2247 if (obj
->otyp
== PETRIFYIUM_BRA
) {
2248 if ((!uarmg
|| FingerlessGloves
) && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) )) {
2249 if (poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
))
2250 display_nhwindow(WIN_MESSAGE
, FALSE
);
2252 static char kbuf
[BUFSZ
];
2254 strcpy(kbuf
, "touching a petrifyium bra");
2255 pline("Touching a petrifyium bra is a fatal mistake.");
2262 if (obj
->otyp
== EGG
) {
2263 if ( (touch_petrifies(&mons
[obj
->corpsenm
])) && obj
->corpsenm
!= PM_PLAYERMON
&& (!uarmg
|| FingerlessGloves
)
2264 && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) )) {
2265 if (poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
))
2266 display_nhwindow(WIN_MESSAGE
, FALSE
);
2268 static char kbuf
[BUFSZ
];
2270 pline("Touching a petrifying egg is a fatal mistake.");
2271 strcpy(kbuf
, "touching a petrifying egg");
2278 /* boxes, boulders, and big statues can't fit into any container */
2279 if (obj
->otyp
== ICE_BOX
|| obj
->otyp
== DISPERSION_BOX
|| obj
->otyp
== ICE_BOX_OF_HOLDING
|| obj
->otyp
== ICE_BOX_OF_WATERPROOFING
|| obj
->otyp
== ICE_BOX_OF_DIGESTION
|| Is_box(obj
) || obj
->otyp
== BOULDER
||
2280 (obj
->otyp
== STATUE
&& bigmonst(&mons
[obj
->corpsenm
]))) {
2282 * xname() uses a static result array. Save obj's name
2283 * before current_container's name is computed. Don't
2284 * use the result of strcpy() within You() --- the order
2285 * of evaluation of the parameters is undefined.
2287 strcpy(buf
, the(xname(obj
)));
2288 You("cannot fit %s into %s.", buf
,
2289 the(xname(current_container
)));
2293 if (invobj
) freeinv(obj
);
2295 if (obj_is_burning(obj
)) /* this used to be part of freeinv() */
2296 (void) snuff_lit(obj
);
2298 if (floor_container
&& costly_spot(u
.ux
, u
.uy
)) {
2299 if (current_container
->no_charge
&& !obj
->unpaid
) {
2300 /* don't sell when putting the item into your own container */
2302 } else if (obj
->oclass
!= COIN_CLASS
) {
2303 /* sellobj() will take an unpaid item off the shop bill
2304 * note: coins are handled later */
2305 was_unpaid
= obj
->unpaid
? TRUE
: FALSE
;
2306 sellobj_state(SELL_DELIBERATE
);
2307 sellobj(obj
, u
.ux
, u
.uy
);
2308 sellobj_state(SELL_NORMAL
);
2311 if (Icebox
&& !age_is_relative(obj
) && !is_lightsaber(obj
)) {
2312 obj
->icedobject
= TRUE
;
2313 obj
->age
= monstermoves
- obj
->age
; /* actual age */
2314 /* stop any corpse timeouts when frozen */
2315 if (obj
->otyp
== CORPSE
&& obj
->timed
) {
2316 long rot_alarm
= stop_timer(ROT_CORPSE
, (void *)obj
);
2317 (void) stop_timer(MOLDY_CORPSE
, (void *)obj
);
2318 (void) stop_timer(REVIVE_MON
, (void *)obj
);
2319 /* mark a non-reviving corpse as such */
2320 if (rot_alarm
) obj
->norevive
= 1;
2324 /* There are ice boxes of holding --Amy */
2325 if (Is_mbag(current_container
) && mbag_explodes(obj
, 0)) {
2326 /* explicitly mention what item is triggering the explosion */
2328 "As you put %s inside, you are blasted by a magical explosion!",
2330 if (PlayerHearsSoundEffects
) pline(issoviet
? "VD GA GA GA vy takoy nemnogo nub, kto ne znayet, kak igrat' na vsekh! Ya ne byl by nastol'ko glup, no vy poteryali sumku provedeniya v nastoyashcheye vremya i, veroyatno, slomal vse zel'ya, kotoryye byli v nem. TY POLNYY OTSTOY!" : "Caeauwaesh! Well and?");
2331 if (Has_contents(obj
)) {
2333 while((otmp
= container_extract_indestructable(obj
)))
2334 if (!flooreffects(otmp
, u
.ux
, u
.uy
, "fall"))
2335 place_object(otmp
, u
.ux
, u
.uy
);
2338 /* did not actually insert obj yet */
2339 if (was_unpaid
) addtobill(obj
, FALSE
, FALSE
, TRUE
);
2341 /* if (Has_contents(obj))
2342 delete_contents(obj);
2343 obfree(obj, (struct obj *)0);
2344 delete_contents(current_container);
2345 if (!floor_container)
2346 useup(current_container);
2347 else if (obj_here(current_container, u.ux, u.uy))
2348 useupf(current_container, current_container->quan);
2350 panic("in_container: bag not found."); */
2352 /* dump it out onto the floor so the scatterage can take effect */
2353 if (dump_container(current_container
, TRUE
, u
.ux
, u
.uy
)) {
2354 pline("The contents fly everywhere!");
2356 scatter(u
.ux
,u
.uy
,10,VIS_EFFECTS
|MAY_HIT
|MAY_DESTROY
|MAY_FRACTURE
,0);
2358 losehp(d(6,6),"magical explosion", KILLED_BY_AN
);
2359 current_container
= 0; /* baggone = TRUE; */
2362 if (current_container
) {
2363 strcpy(buf
, the(xname(current_container
)));
2364 if (invobj
) You("put %s into %s.", doname(obj
), buf
);
2366 /* gold in container always needs to be added to credit */
2367 if (floor_container
&& obj
->oclass
== COIN_CLASS
)
2368 sellobj(obj
, current_container
->ox
, current_container
->oy
);
2369 (void) add_to_container(current_container
, obj
, TRUE
);
2370 current_container
->owt
= weight(current_container
);
2372 /* gold needs this, and freeinv() many lines above may cause
2373 * the encumbrance to disappear from the status, so just always
2374 * update status immediately.
2378 return(current_container
? 1 : -1);
2383 register struct obj
*obj
;
2385 return in_container_(obj
,TRUE
);
2393 return current_container
&& obj
!= current_container
;
2397 /* Returns: -1 to stop, 1 item was removed, 0 item was not removed. */
2400 register struct obj
*obj
;
2402 register struct obj
*otmp
;
2403 boolean is_gold
= (obj
->oclass
== COIN_CLASS
);
2407 if (!current_container
) {
2408 impossible("<out> no current_container?");
2410 } else if (is_gold
) {
2411 obj
->owt
= weight(obj
);
2414 if(obj
->oartifact
&& !touch_artifact(obj
,&youmonst
)) return 0;
2416 if (obj
->otyp
== CORPSE
) {
2417 if ( (touch_petrifies(&mons
[obj
->corpsenm
])) && (!uarmg
|| FingerlessGloves
)
2418 && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) )) {
2419 if (poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
))
2420 display_nhwindow(WIN_MESSAGE
, FALSE
);
2422 static char kbuf
[BUFSZ
];
2424 pline("Touching this type of corpse is a fatal mistake.");
2425 strcpy(kbuf
, "touching a petrifying corpse");
2432 if (obj
->otyp
== PETRIFYIUM_BAR
) {
2433 if ( (!uarmg
|| FingerlessGloves
) && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) )) {
2434 if (poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
))
2435 display_nhwindow(WIN_MESSAGE
, FALSE
);
2437 static char kbuf
[BUFSZ
];
2439 strcpy(kbuf
, "touching a petrifyium bar");
2440 pline("Touching a petrifyium bar is a fatal mistake.");
2447 if (obj
->otyp
== PETRIFYIUM_BRA
) {
2448 if ( (!uarmg
|| FingerlessGloves
) && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) )) {
2449 if (poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
))
2450 display_nhwindow(WIN_MESSAGE
, FALSE
);
2452 static char kbuf
[BUFSZ
];
2454 strcpy(kbuf
, "touching a petrifyium bra");
2455 pline("Touching a petrifyium bra is a fatal mistake.");
2462 if (obj
->otyp
== EGG
) {
2463 if ( (touch_petrifies(&mons
[obj
->corpsenm
])) && obj
->corpsenm
!= PM_PLAYERMON
&& (!uarmg
|| FingerlessGloves
)
2464 && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) )) {
2465 if (poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
))
2466 display_nhwindow(WIN_MESSAGE
, FALSE
);
2468 static char kbuf
[BUFSZ
];
2470 pline("Touching a petrifying egg is a fatal mistake.");
2471 strcpy(kbuf
, "touching a petrifying egg");
2479 if ((res
= lift_object(obj
, current_container
, &count
, FALSE
, FALSE
)) <= 0)
2482 if (obj
->quan
!= count
&& obj
->otyp
!= LOADSTONE
&& obj
->otyp
!= LUCKSTONE
&& obj
->otyp
!= HEALTHSTONE
&& obj
->otyp
!= MANASTONE
&& obj
->otyp
!= SLEEPSTONE
&& obj
->otyp
!= LOADBOULDER
&& obj
->otyp
!= STARLIGHTSTONE
&& obj
->otyp
!= STONE_OF_MAGIC_RESISTANCE
&& !is_nastygraystone(obj
) && !is_feminismstone(obj
) )
2483 obj
= splitobj(obj
, count
);
2485 /* Remove the object from the list. */
2486 obj_extract_self(obj
);
2487 current_container
->owt
= weight(current_container
);
2489 if (Icebox
&& !age_is_relative(obj
) && !is_lightsaber(obj
)) {
2490 obj
->icedobject
= TRUE
;
2491 obj
->age
= monstermoves
- obj
->age
; /* actual age */
2492 if (obj
->otyp
== CORPSE
)
2493 start_corpse_timeout(obj
);
2495 /* simulated point of time */
2497 if(!obj
->unpaid
&& !carried(current_container
) &&
2498 costly_spot(current_container
->ox
, current_container
->oy
)) {
2499 obj
->ox
= current_container
->ox
;
2500 obj
->oy
= current_container
->oy
;
2501 addtobill(obj
, FALSE
, FALSE
, FALSE
);
2503 if (is_pick(obj
) && !obj
->unpaid
&& *u
.ushops
&& shop_keeper(*u
.ushops
))
2504 verbalize("You sneaky cad! Get out of here with that pick!");
2507 loadlev
= near_capacity();
2509 (loadlev
< MOD_ENCUMBER
?
2510 "You have a little trouble removing" :
2511 "You have much trouble removing") : (char *)0,
2518 bot(); /* update character's gold piece count immediately */
2523 /* an object inside a cursed bag of holding is being destroyed */
2525 mbag_item_gone(held
, item
, yourfault
)
2533 /* In the Evil Variant, you aren't told which items have been destroyed. --Amy */
2536 Norep("Stuff has vanished!");
2537 else if (item
->dknown
)
2538 pline("%s %s vanished!", Doname2(item
), otense(item
, "have"));
2540 You("%s %s disappear!", Blind
? "notice" : "see", doname(item
));
2542 if (*u
.ushops
&& (shkp
= shop_keeper(*u
.ushops
)) != 0) {
2543 if (held
? (boolean
) item
->unpaid
: costly_spot(u
.ux
, u
.uy
))
2544 loss
= stolen_value(item
, u
.ux
, u
.uy
,
2545 (boolean
)shkp
->mpeaceful
, TRUE
, TRUE
);
2549 /* [ALI] In Slash'EM we must delete the contents of containers before
2550 * we call obj_extract_self() so that any indestructable items can
2551 * migrate into the bag of holding. We are also constrained by the
2552 * need to wait until after we have calculated any loss.
2554 if (Has_contents(item
)) delete_contents(item
);
2555 obj_extract_self(item
);
2556 obfree(item
, (struct obj
*) 0);
2561 observe_quantum_cat(box
)
2564 static NEARDATA
const char sc
[] = "Schroedinger's Cat";
2565 struct obj
*deadcat
;
2566 struct monst
*livecat
;
2569 box
->spe
= 0; /* box->owt will be updated below */
2570 if (get_obj_location(box
, &ox
, &oy
, 0))
2571 box
->ox
= ox
, box
->oy
= oy
; /* in case it's being carried */
2573 /* this isn't really right, since any form of observation
2574 (telepathic or monster/object/food detection) ought to
2575 force the determination of alive vs dead state; but basing
2576 it just on opening the box is much simpler to cope with */
2577 livecat
= rn2(2) ? makemon(&mons
[PM_HOUSECAT
],
2578 box
->ox
, box
->oy
, NO_MINVENT
) : 0;
2580 livecat
->mpeaceful
= 1;
2581 set_malign(livecat
);
2582 if (!canspotmon(livecat
))
2583 You("think %s brushed your %s.", something
, body_part(FOOT
));
2585 pline("%s inside the box is still alive!", Monnam(livecat
));
2586 (void) christen_monst(livecat
, sc
);
2588 deadcat
= mk_named_object(CORPSE
, &mons
[PM_HOUSECAT
],
2589 box
->ox
, box
->oy
, sc
);
2591 obj_extract_self(deadcat
);
2592 (void) add_to_container(box
, deadcat
, TRUE
);
2594 pline_The("%s inside the box is dead!",
2595 Hallucination
? rndmonnam() : "housecat");
2597 box
->owt
= weight(box
);
2612 pline("You're hit by a massive explosion!");
2614 losehp( (d(6,6) + rnd((monster_difficulty()) + 1) ), "massive explosion", KILLED_BY_AN
);
2615 exercise(A_STR
, FALSE
);
2621 pline("A cloud of noxious gas billows out at you.");
2622 poisoned("gas cloud", A_STR
, "cloud of poison gas",15);
2623 exercise(A_CON
, FALSE
);
2629 You_feel("a needle prick your %s.",body_part(ARM
));
2630 poisoned("needle", A_CON
, "poisoned needle",10);
2631 exercise(A_CON
, FALSE
);
2637 dofiretrap((struct obj
*)0);
2644 You("are jolted by a surge of electricity!");
2645 if((Shock_resistance
&& (StrongShock_resistance
|| rn2(10))) || ShockImmunity
) {
2646 shieldeff(u
.ux
, u
.uy
);
2647 You("don't seem to be affected.");
2650 losehp(d(4, 4) + rnd((monster_difficulty() / 2) + 1), "electric shock", KILLED_BY_AN
);
2651 if (isevilvariant
|| !rn2(issoviet
? 6 : 33)) /* new calculations --Amy */ destroy_item(RING_CLASS
, AD_ELEC
);
2652 if (isevilvariant
|| !rn2(issoviet
? 6 : 33)) /* new calculations --Amy */ destroy_item(WAND_CLASS
, AD_ELEC
);
2653 if (isevilvariant
|| !rn2(issoviet
? 30 : 165)) /* new calculations --Amy */ destroy_item(AMULET_CLASS
, AD_ELEC
);
2659 if (!Free_action
|| !rn2(StrongFree_action
? 100 : 20)) {
2660 pline("Suddenly you are frozen in place!");
2661 if (PlayerHearsSoundEffects
) pline(issoviet
? "Teper' vy ne mozhete dvigat'sya. Nadeyus', chto-to ubivayet vas, prezhde chem vash paralich zakonchitsya." : "Klltsch-tsch-tsch-tsch-tsch!");
2662 if (isstunfish
) nomul(-rnz(11), "frozen by a container kaboom", TRUE
);
2663 else nomul(-rn1(5, 6), "frozen by a container kaboom", TRUE
);
2664 exercise(A_DEX
, FALSE
);
2665 nomovemsg
= You_can_move_again
;
2666 } else You("momentarily stiffen.");
2671 pline("A cloud of %s gas billows out at you.", Blind
? "booming" : rndcolor() );
2674 You("%s and get dizzy...",
2675 stagger(youmonst
.data
, "stagger"));
2677 You("%s and your vision blurs...",
2678 stagger(youmonst
.data
, "stagger"));
2679 if (PlayerHearsSoundEffects
) pline(issoviet
? "Imet' delo s effektami statusa ili sdat'sya!" : "Wrueue-ue-e-ue-e-ue-e...");
2681 make_stunned(HStun
+ rn1(7, 16) + rnd((monster_difficulty() / 2) + 1),FALSE
);
2682 (void) make_hallucinated(HHallucination
+ rn1(5, 16) + rnd((monster_difficulty() / 2) + 1),FALSE
,0L);
2684 default: impossible("bad kaboom trap");
2689 /* used by askchain() to check for magic bag explosion */
2694 /* result is only meaningful while use_container() is executing */
2695 return ((fn
== in_container
|| fn
== out_container
) && !current_container
);
2699 use_container(objp
, held
)
2703 struct obj
*curr
, *otmp
, *obj
= *objp
;
2705 struct obj
*u_gold
= (struct obj
*)0;
2708 boolean one_by_one
, allflag
, quantum_cat
= FALSE
,
2709 loot_out
= FALSE
, loot_in
= FALSE
, loot_reverse
= FALSE
;
2710 char select
[MAXOCLASSES
+1];
2711 char qbuf
[BUFSZ
], emptymsg
[BUFSZ
], pbuf
[QBUFSZ
];
2713 int cnt
= 0, used
= 0, lcnt
= 0,
2715 int monsterator
= 0;
2717 if (obj
&& obj
->oartifact
== ART_SNAP_TOO
&& !rn2(100)) {
2718 obj
->olocked
= TRUE
;
2719 obj
->obroken
= FALSE
;
2721 if (obj
&& obj
->oartifact
== ART_CANNOTRAP
) obj
->otrapped
= FALSE
;
2724 if (nohands(youmonst
.data
) && !Race_if(PM_TRANSFORMER
) && !(obj
&& obj
->otyp
== HANDYBAG
) ) {
2725 You("have no hands!"); /* not `body_part(HAND)' */
2726 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
2728 if (yn("Try to open the container with another part of your body instead?") == 'y') {
2729 if (rn2(3) && !polyskillchance()) {
2730 You_feel("a wrenching sensation.");
2731 if (!rn2(20)) badeffect();
2732 if (PlayerHearsSoundEffects
) pline(issoviet
? "Tam net nikakoy zashchity. Tam net nikakoy nadezhdy. Yedinstvennoye, chto yest'? Uverennost' v tom, chto vy, igrok, budet umeret' uzhasnoy i muchitel'noy smert'yu." : "SCHRING!");
2733 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
2735 if (isstunfish
) nomul(-rnz(10), "wrenched in a container", TRUE
);
2736 else nomul(-rnd(10), "wrenched in a container", TRUE
);
2737 nomovemsg
= "You are conscious again.";
2738 afternmv
= Hear_again
;
2744 } else if (!freehandX() && !(obj
->oartifact
== ART_MINNIE_S_HANDBAG
) && !(Role_if(PM_CELLAR_CHILD
) && uwep
&& (weapon_type(uwep
) == P_QUARTERSTAFF
)) ) {
2745 You("have no free %s.", body_part(HAND
));
2746 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
2751 if (uwep
&& uwep
->oartifact
== ART_FINAL_DOOR_SOLUTION
) {
2752 obj
->olocked
= FALSE
;
2755 pline("%s to be locked.", Tobjnam(obj
, "seem"));
2756 if (held
) You("must put it down to unlock.");
2760 if (obj
->otrapped
) {
2761 if (held
) You("open %s...", the(xname(obj
)));
2762 if (Role_if(PM_CYBERNINJA
) && rn2(5)) {
2763 You("discover a trap on %s and disarm it.", the(xname(obj
)));
2764 obj
->otrapped
= FALSE
;
2767 (void) chest_trap(obj
, HAND
, FALSE
);
2768 /* even if the trap fails, you've used up this turn */
2769 if (multi
>= 0) { /* in case we didn't become paralyzed */
2770 nomul(-1, "opening a trapped container", TRUE
);
2776 current_container
= obj
; /* for use by in/out_container */
2777 /* from here on out, all early returns go through containerdone */
2779 if (obj
->oartifact
== ART_ELECTRONIC_LOCK
) {
2780 if (ContainerKaboom
< 10000) ContainerKaboom
= 10000;
2783 if (obj
->oartifact
== ART_DEMONSEAL
) {
2784 if (obj
->invoketimer
<= monstermoves
) {
2787 pm
= rn2(2) ? dprince(rn2((int)A_LAWFUL
+2) - 1) : dlord(rn2((int)A_LAWFUL
+2) - 1);
2788 if (pm
>= PM_ORCUS
&& pm
<= PM_DEMOGORGON
) u
.conclusiocount
++;
2789 if (pm
&& (pm
!= NON_PM
)) {
2790 (void) makemon(&mons
[pm
], u
.ux
, u
.uy
, MM_ADJACENTOK
|MM_ANGRY
|MM_FRENZIED
);
2791 You("triggered an ancient trap on this container...");
2794 int artitimeout
= rnz(2000);
2795 if (!rn2(5)) artitimeout
= rnz(20000); /* squeaking does not help here, as it's not an actual invoke --Amy */
2796 obj
->invoketimer
= (monstermoves
+ artitimeout
);
2800 if (obj
->spe
== 1) {
2801 observe_quantum_cat(obj
);
2803 quantum_cat
= TRUE
; /* for adjusting "it's empty" message */
2805 /* [ALI] If a container vanishes which contains indestructible
2806 * objects then these will be added to the magic bag. This makes
2807 * it very hard to combine the count and vanish loops so we do
2810 /* Sometimes toss objects if a cursed magic bag or a bag of digestion */
2811 if (Is_mbag(obj
) && obj
->cursed
) {
2812 for (curr
= obj
->cobj
; curr
; curr
= otmp
) {
2814 if (!rn2(13) && !evades_destruction(curr
) && !stack_too_big(curr
)) {
2815 if (obj
&& obj
->oartifact
== ART_RECYCLER_BIN
) {
2817 if (curr
->oartifact
) {
2820 pline("Wow, that must have been expensive!");
2823 if (obj
&& obj
->oartifact
== ART_MONSTERATOR
) {
2826 loss
+= mbag_item_gone(held
, curr
, TRUE
);
2831 if ( (obj
->otyp
== BAG_OF_DIGESTION
|| obj
->otyp
== ICE_BOX_OF_DIGESTION
|| obj
->otyp
== LARGE_BOX_OF_DIGESTION
) && !rn2(obj
->blessed
? 20 : (obj
->cursed
? 2 : 10))) {
2832 for (curr
= obj
->cobj
; curr
; curr
= otmp
) {
2834 if (!evades_destruction(curr
) && !stack_too_big(curr
)) {
2835 if (obj
&& obj
->oartifact
== ART_RECYCLER_BIN
) {
2837 if (curr
->oartifact
) {
2840 pline("Wow, that must have been expensive!");
2843 if (obj
&& obj
->oartifact
== ART_MONSTERATOR
) {
2846 loss
+= mbag_item_gone(held
, curr
, TRUE
);
2851 /* Count the number of contained objects. */
2852 for (curr
= obj
->cobj
; curr
; curr
= curr
->nobj
)
2855 if (loss
) /* magic bag lost some shop goods */
2856 You("owe %ld %s for lost merchandise.", loss
, currency(loss
));
2857 obj
->owt
= weight(obj
); /* in case any items were lost */
2859 if (monsterator
> 10) {
2861 if (Aggravate_monster
) {
2863 reset_rndmonst(NON_PM
);
2866 if (monsterator
> 200) monsterator
= 200;
2868 u
.lamefarmer
= TRUE
;
2870 while (monsterator
> 0) {
2872 (void) makemon((struct permonst
*)0, u
.ux
, u
.uy
, NO_MM_FLAGS
);
2875 if (monsterator
< 0) monsterator
= 0; /* fail safe */
2879 u
.lamefarmer
= FALSE
;
2883 if (ContainerKaboom
|| u
.uprops
[CONTAINER_KABOOM
].extrinsic
|| have_containerkaboomstone()) {
2888 sprintf(emptymsg
, "%s is %sempty.", Yname2(obj
),
2889 quantum_cat
? "now " : "");
2890 if (current_container
->otyp
== MEDICAL_KIT
) {
2892 pline("%s", emptymsg
);
2894 (void) display_cinventory(current_container
);
2897 if (cnt
|| (flags
.menu_style
== MENU_FULL
&& !InventoryDoesNotGo
)) {
2898 strcpy(qbuf
, "Do you want to take something out of ");
2899 sprintf(eos(qbuf
), "%s?",
2900 safe_qbuf(qbuf
, 1, yname(obj
), ysimple_name(obj
), "it"));
2901 if (flags
.menu_style
!= MENU_TRADITIONAL
&& !InventoryDoesNotGo
) {
2902 if (flags
.menu_style
== MENU_FULL
) {
2904 char menuprompt
[BUFSZ
];
2905 boolean outokay
= (cnt
!= 0),
2906 inokay
= (invent
!= 0);
2909 if (u
.ugold
) inokay
= TRUE
;
2911 if (!outokay
&& !inokay
) {
2912 pline("%s", emptymsg
);
2913 You("don't have anything to put in.");
2916 menuprompt
[0] = '\0';
2917 if (!cnt
) sprintf(menuprompt
, "%s ", emptymsg
);
2918 strcat(menuprompt
, "Do what?");
2919 t
= in_or_out_menu(menuprompt
, current_container
,
2925 loot_out
= (t
& 0x01) != 0;
2926 loot_in
= (t
& 0x02) != 0;
2929 loot_out
= loot_in
= loot_reverse
= 1;
2931 } else { /* MENU_COMBINATION or MENU_PARTIAL */
2932 loot_out
= (yn_function(qbuf
, "ynq", 'n') == 'y');
2934 if (loot_out
&& !loot_reverse
) {
2935 add_valid_menu_class(0); /* reset */
2936 used
|= menu_loot(0, current_container
, FALSE
) > 0;
2939 /* traditional code */
2941 menu_on_request
= 0;
2942 add_valid_menu_class(0); /* reset */
2943 strcpy(pbuf
, ":ynq");
2944 if (cnt
) strcat(pbuf
, "m");
2945 switch (yn_function(qbuf
, pbuf
, 'n')) {
2947 if (InventoryDoesNotGo
) {
2948 pline("Not enough memory to create inventory window");
2951 container_contents(current_container
, FALSE
, FALSE
);
2954 if (query_classes(select
, &one_by_one
, &allflag
,
2955 "take out", current_container
->cobj
,
2960 &menu_on_request
)) {
2961 if (askchain((struct obj
**)¤t_container
->cobj
,
2962 (one_by_one
? (char *)0 : select
),
2963 allflag
, out_container
,
2966 if (current_container
->oartifact
!= ART_GITTA_S_HANDBAG
&& !(uarmc
&& uarmc
->otyp
== UTILITY_CLOAK
&& rn2(2)) && current_container
->oartifact
!= ART_GIDDEM_FAST_
) {
2970 } else if (menu_on_request
< 0) {
2971 used
|= menu_loot(menu_on_request
,
2972 current_container
, FALSE
) > 0;
2978 menu_on_request
= -2; /* triggers ALL_CLASSES */
2979 used
|= menu_loot(menu_on_request
, current_container
, FALSE
) > 0;
2987 pline("%s", emptymsg
); /* <whatever> is empty. */
2991 if (!invent
&& u
.ugold
== 0) {
2995 /* nothing to put in, but some feedback is necessary */
2996 You("don't have anything to put in.");
2999 if (flags
.menu_style
!= MENU_FULL
|| InventoryDoesNotGo
) {
3000 sprintf(qbuf
, "Do you wish to put %s in?", something
);
3001 strcpy(pbuf
, ynqchars
);
3002 if ((flags
.menu_style
== MENU_TRADITIONAL
|| InventoryDoesNotGo
) && invent
&& inv_cnt() > 0)
3004 switch (yn_function(qbuf
, pbuf
, 'n')) {
3011 add_valid_menu_class(0); /* reset */
3012 menu_on_request
= -2; /* triggers ALL_CLASSES */
3013 used
|= menu_loot(menu_on_request
, current_container
, TRUE
) > 0;
3021 * Gone: being nice about only selecting food if we know we are
3022 * putting things in an ice chest.
3028 * Hack: gold is not in the inventory, so make a gold object
3029 * and put it at the head of the inventory list.
3031 u_gold
= mkgoldobj(u
.ugold
); /* removes from u.ugold */
3032 u_gold
->in_use
= TRUE
;
3033 u
.ugold
= u_gold
->quan
; /* put the gold back */
3034 assigninvlet(u_gold
); /* might end up as NOINVSYM */
3035 u_gold
->nobj
= invent
;
3039 add_valid_menu_class(0); /* reset */
3040 if (flags
.menu_style
!= MENU_TRADITIONAL
&& !InventoryDoesNotGo
) {
3041 used
|= menu_loot(0, current_container
, TRUE
) > 0;
3043 /* traditional code */
3044 menu_on_request
= 0;
3045 if (query_classes(select
, &one_by_one
, &allflag
, "put in",
3050 &menu_on_request
)) {
3051 (void) askchain((struct obj
**)&invent
,
3052 (one_by_one
? (char *)0 : select
), allflag
,
3053 in_container
, ck_bag
, 0, "nodot");
3054 if (current_container
->oartifact
!= ART_KLARABELLA_S_HANDBAG
&& !(uarmc
&& uarmc
->otyp
== UTILITY_CLOAK
&& rn2(2)) && current_container
->oartifact
!= ART_STASHIT
) {
3057 } else if (menu_on_request
< 0) {
3058 used
|= menu_loot(menu_on_request
,
3059 current_container
, TRUE
) > 0;
3065 if (u_gold
&& invent
&& invent
->oclass
== COIN_CLASS
) {
3066 /* didn't stash [all of] it */
3068 invent
= u_gold
->nobj
;
3069 u_gold
->in_use
= FALSE
;
3070 dealloc_obj(u_gold
);
3074 if (loot_out
&& loot_reverse
) {
3075 add_valid_menu_class(0); /* reset */
3076 used
|= menu_loot(0, current_container
, FALSE
) > 0;
3080 if (u_gold
&& invent
&& invent
->oclass
== COIN_CLASS
) {
3081 /* didn't stash [all of] it */
3083 invent
= u_gold
->nobj
;
3084 u_gold
->in_use
= FALSE
;
3085 dealloc_obj(u_gold
);
3090 *objp
= current_container
; /* might have become null */
3091 current_container
= 0; /* avoid hanging on to stale pointer */
3095 /* Loot a container (take things out, put things in), using a menu. */
3097 menu_loot(retry
, container
, put_in
)
3099 struct obj
*container
;
3102 int n
, i
, n_looted
= 0;
3103 boolean all_categories
= TRUE
, loot_everything
= FALSE
;
3105 const char *takeout
= "Take out", *putin
= "Put in";
3106 struct obj
*otmp
, *otmp2
;
3107 menu_item
*pick_list
;
3112 all_categories
= (retry
== -2);
3113 } else if (flags
.menu_style
== MENU_FULL
&& !InventoryDoesNotGo
) {
3114 all_categories
= FALSE
;
3115 sprintf(buf
,"%s what type of objects?", put_in
? putin
: takeout
);
3116 mflags
= put_in
? ALL_TYPES
| NOTFULLYIDED
| BUC_ALLBKNOWN
| BUC_UNKNOWN
:
3117 ALL_TYPES
| NOTFULLYIDED
| CHOOSE_ALL
| BUC_ALLBKNOWN
| BUC_UNKNOWN
;
3118 n
= query_category(buf
, put_in
? invent
: container
->cobj
,
3119 mflags
, &pick_list
, PICK_ANY
);
3121 for (i
= 0; i
< n
; i
++) {
3122 if (pick_list
[i
].item
.a_int
== 'A') {
3123 if (yn("You decided to autoselect everything, please confirm with y if that's what you really wanted") == 'y') loot_everything
= TRUE
;
3124 } else if (pick_list
[i
].item
.a_int
== ALL_TYPES_SELECTED
)
3125 all_categories
= TRUE
;
3127 add_valid_menu_class(pick_list
[i
].item
.a_int
);
3129 free((void *) pick_list
);
3132 if (loot_everything
) {
3133 for (otmp
= container
->cobj
; otmp
; otmp
= otmp2
) {
3135 res
= out_container(otmp
);
3139 mflags
= INVORDER_SORT
;
3140 if (put_in
&& flags
.invlet_constant
) mflags
|= USE_INVLET
;
3141 sprintf(buf
,"%s what?", put_in
? putin
: takeout
);
3142 n
= query_objlist(buf
, put_in
? invent
: container
->cobj
,
3143 mflags
, &pick_list
, PICK_ANY
,
3144 all_categories
? allow_all
: allow_category
);
3147 for (i
= 0; i
< n
; i
++) {
3148 otmp
= pick_list
[i
].item
.a_obj
;
3149 count
= pick_list
[i
].count
;
3150 if (count
> 0 && count
< otmp
->quan
) {
3151 otmp
= splitobj(otmp
, count
);
3152 /* special split case also handled by askchain() */
3154 res
= put_in
? in_container(otmp
) : out_container(otmp
);
3156 if (!current_container
) {
3157 /* otmp caused current_container to explode;
3158 both are now gone */
3159 otmp
= 0; /* and break loop */
3160 } else if (otmp
&& otmp
!= pick_list
[i
].item
.a_obj
) {
3161 /* split occurred, merge again */
3162 (void) merged(&pick_list
[i
].item
.a_obj
, &otmp
);
3167 free((void *)pick_list
);
3171 if (uarmc
&& uarmc
->otyp
== UTILITY_CLOAK
&& rn2(2)) return 0;
3173 if (container
&& container
->oartifact
== ART_GITTA_S_HANDBAG
&& !put_in
) return 0;
3174 if (container
&& container
->oartifact
== ART_GIDDEM_FAST_
&& !put_in
) return 0;
3175 if (container
&& container
->oartifact
== ART_KLARABELLA_S_HANDBAG
&& put_in
) return 0;
3176 if (container
&& container
->oartifact
== ART_STASHIT
&& put_in
) return 0;
3181 in_or_out_menu(prompt
, obj
, outokay
, inokay
)
3184 boolean outokay
, inokay
;
3188 menu_item
*pick_list
;
3191 const char *menuselector
= iflags
.lootabc
? "abcd" : "oibr";
3194 win
= create_nhwindow(NHW_MENU
);
3198 sprintf(buf
,"Take %s out of %s", something
, the(xname(obj
)));
3199 add_menu(win
, NO_GLYPH
, &any
, *menuselector
, 0, ATR_NONE
,
3200 buf
, MENU_UNSELECTED
);
3205 sprintf(buf
,"Put %s into %s", something
, the(xname(obj
)));
3206 add_menu(win
, NO_GLYPH
, &any
, *menuselector
, 0, ATR_NONE
, buf
, MENU_UNSELECTED
);
3209 if (outokay
&& inokay
) {
3211 add_menu(win
, NO_GLYPH
, &any
, *menuselector
, 0, ATR_NONE
,
3212 "Both of the above, out first", MENU_UNSELECTED
);
3215 if (outokay
&& inokay
) {
3217 add_menu(win
, NO_GLYPH
, &any
, *menuselector
, 0, ATR_NONE
,
3218 "Both of the above, in first", MENU_UNSELECTED
);
3220 end_menu(win
, prompt
);
3221 n
= select_menu(win
, PICK_ONE
, &pick_list
);
3222 destroy_nhwindow(win
);
3224 n
= pick_list
[0].item
.a_int
;
3225 free((void *) pick_list
);
3230 /* Dumps out a container, possibly as the prelude/result of an explosion.
3231 * destroy_after trashes the container afterwards; try not to use it :P
3233 * Player is assumed to not be handling the contents directly.
3235 * Returns 1 if at least one object was present, 0 if empty.
3238 dump_container(container
, destroy_after
, coordx
, coordy
)
3239 struct obj
* container
;
3240 BOOLEAN_P destroy_after
;
3243 if (!isok(coordx
, coordy
)) {
3244 impossible("dump_container coordinates %d, %d?", coordx
, coordy
);
3246 coordy
= u
.uy
; /* fail safe */
3249 struct obj
* otmp
,*otmp2
;
3253 if (!container
) { return 0; }
3255 for (otmp
= container
->cobj
; otmp
; otmp
= otmp2
)
3259 obj_extract_self(otmp
);
3260 container
->owt
= weight(container
);
3262 /* we do need to start the timer on these */
3263 if ( (container
->otyp
== ICE_BOX
|| container
->otyp
== DISPERSION_BOX
|| container
->otyp
== ICE_BOX_OF_HOLDING
|| container
->otyp
== ICE_BOX_OF_WATERPROOFING
|| container
->otyp
== ICE_BOX_OF_DIGESTION
) && !age_is_relative(otmp
) && !is_lightsaber(otmp
)) {
3264 otmp
->age
= monstermoves
- otmp
->age
;
3265 otmp
->icedobject
= TRUE
;
3266 if (otmp
->otyp
== CORPSE
) {
3267 start_corpse_timeout(otmp
);
3270 place_object(otmp
,coordx
,coordy
);
3272 if (otmp
->otyp
== GOLD_PIECE
) {
3274 /*dealloc_obj(otmp);*/ /* causes panic, and besides, is it really needed??? --Amy */
3276 bot(); /* update character's gold piece count immediately */
3280 if (destroy_after
) {
3281 if (container
->where
== OBJ_INVENT
) {
3283 } else if (obj_here(container
, u
.ux
, u
.uy
)) {
3284 useupf(container
, container
->quan
);
3292 dump_container_tele(container
, destroy_after
, coordx
, coordy
)
3293 struct obj
* container
;
3294 BOOLEAN_P destroy_after
;
3297 if (!isok(coordx
, coordy
)) {
3298 impossible("dump_container coordinates %d, %d?", coordx
, coordy
);
3300 coordy
= u
.uy
; /* fail safe */
3303 struct obj
* otmp
,*otmp2
;
3307 if (!container
) { return 0; }
3309 for (otmp
= container
->cobj
; otmp
; otmp
= otmp2
)
3313 obj_extract_self(otmp
);
3314 container
->owt
= weight(container
);
3316 /* we do need to start the timer on these */
3317 if ( (container
->otyp
== ICE_BOX
|| container
->otyp
== DISPERSION_BOX
|| container
->otyp
== ICE_BOX_OF_HOLDING
|| container
->otyp
== ICE_BOX_OF_WATERPROOFING
|| container
->otyp
== ICE_BOX_OF_DIGESTION
) && !age_is_relative(otmp
) && !is_lightsaber(otmp
)) {
3318 otmp
->age
= monstermoves
- otmp
->age
;
3319 otmp
->icedobject
= TRUE
;
3320 if (otmp
->otyp
== CORPSE
) {
3321 start_corpse_timeout(otmp
);
3324 place_object(otmp
,coordx
,coordy
);
3327 if (otmp
&& otmp
->otyp
== GOLD_PIECE
) {
3329 /*dealloc_obj(otmp);*/ /* causes panic, and besides, is it really needed??? --Amy */
3331 bot(); /* update character's gold piece count immediately */
3335 if (destroy_after
) {
3336 if (container
->where
== OBJ_INVENT
) {
3338 } else if (obj_here(container
, u
.ux
, u
.uy
)) {
3339 useupf(container
, container
->quan
);
3347 dump_container_huro(container
, destroy_after
, coordx
, coordy
)
3348 struct obj
* container
;
3349 BOOLEAN_P destroy_after
;
3352 if (!isok(coordx
, coordy
)) {
3353 impossible("dump_container coordinates %d, %d?", coordx
, coordy
);
3355 coordy
= u
.uy
; /* fail safe */
3358 struct obj
* otmp
,*otmp2
;
3359 register struct monst
*offmon
;
3363 if (!container
) { return 0; }
3365 for (otmp
= container
->cobj
; otmp
; otmp
= otmp2
)
3369 obj_extract_self(otmp
);
3370 container
->owt
= weight(container
);
3372 /* we do need to start the timer on these */
3373 if ( (container
->otyp
== ICE_BOX
|| container
->otyp
== DISPERSION_BOX
|| container
->otyp
== ICE_BOX_OF_HOLDING
|| container
->otyp
== ICE_BOX_OF_WATERPROOFING
|| container
->otyp
== ICE_BOX_OF_DIGESTION
) && !age_is_relative(otmp
) && !is_lightsaber(otmp
)) {
3374 otmp
->age
= monstermoves
- otmp
->age
;
3375 otmp
->icedobject
= TRUE
;
3376 if (otmp
->otyp
== CORPSE
) {
3377 start_corpse_timeout(otmp
);
3380 if ((offmon
= makemon((struct permonst
*)0, 0, 0, NO_MM_FLAGS
)) != 0) {
3381 (void) mpickobj(offmon
,otmp
,FALSE
);
3382 mdrop_special_objs(offmon
); /* don't levelport ones that have the amulet! */
3383 u_teleport_monB(offmon
, FALSE
);
3385 place_object(otmp
,coordx
,coordy
);
3388 if (otmp
&& otmp
->otyp
== GOLD_PIECE
) {
3390 /*dealloc_obj(otmp);*/ /* causes panic, and besides, is it really needed??? --Amy */
3392 bot(); /* update character's gold piece count immediately */
3396 if (destroy_after
) {
3397 if (container
->where
== OBJ_INVENT
) {
3399 } else if (obj_here(container
, u
.ux
, u
.uy
)) {
3400 useupf(container
, container
->quan
);
3408 dump_container_superhuro(container
, destroy_after
, coordx
, coordy
)
3409 struct obj
* container
;
3410 BOOLEAN_P destroy_after
;
3413 if (!isok(coordx
, coordy
)) {
3414 impossible("dump_container coordinates %d, %d?", coordx
, coordy
);
3416 coordy
= u
.uy
; /* fail safe */
3419 struct obj
* otmp
,*otmp2
;
3420 register struct monst
*offmon
;
3424 if (!container
) { return 0; }
3426 for (otmp
= container
->cobj
; otmp
; otmp
= otmp2
)
3430 obj_extract_self(otmp
);
3431 container
->owt
= weight(container
);
3433 /* we do need to start the timer on these */
3434 if ( (container
->otyp
== ICE_BOX
|| container
->otyp
== DISPERSION_BOX
|| container
->otyp
== ICE_BOX_OF_HOLDING
|| container
->otyp
== ICE_BOX_OF_WATERPROOFING
|| container
->otyp
== ICE_BOX_OF_DIGESTION
) && !age_is_relative(otmp
) && !is_lightsaber(otmp
)) {
3435 otmp
->age
= monstermoves
- otmp
->age
;
3436 otmp
->icedobject
= TRUE
;
3437 if (otmp
->otyp
== CORPSE
) {
3438 start_corpse_timeout(otmp
);
3441 if ((offmon
= makemon((struct permonst
*)0, 0, 0, NO_MM_FLAGS
)) != 0) {
3442 (void) mpickobj(offmon
,otmp
,FALSE
);
3443 mdrop_special_objs(offmon
); /* don't levelport ones that have the amulet! */
3444 u_teleport_monC(offmon
, FALSE
);
3446 place_object(otmp
,coordx
,coordy
);
3449 if (otmp
&& otmp
->otyp
== GOLD_PIECE
) {
3451 /*dealloc_obj(otmp);*/ /* causes panic, and besides, is it really needed??? --Amy */
3453 bot(); /* update character's gold piece count immediately */
3457 if (destroy_after
) {
3458 if (container
->where
== OBJ_INVENT
) {
3460 } else if (obj_here(container
, u
.ux
, u
.uy
)) {
3461 useupf(container
, container
->quan
);