1 /* SCCS Id: @(#)do.c 3.4 2003/12/02 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
4
5 /* Contains code for 'd', 'D' (drop), '>', '<' (up, down) */
6
7 #include "hack.h"
8 #include "lev.h"
9
10 #ifdef SINKS
11 # ifdef OVLB
12 STATIC_DCL void FDECL(trycall, (struct obj *));
13 # endif /* OVLB */
14 STATIC_DCL void FDECL(dosinkring, (struct obj *));
15 #endif /* SINKS */
16
17 STATIC_PTR int FDECL(drop, (struct obj *));
18 STATIC_PTR int NDECL(wipeoff);
19
20 #ifdef OVL0
21 STATIC_DCL int FDECL(menu_drop, (int));
22 #endif
23 #ifdef OVL2
24 STATIC_DCL int NDECL(currentlevel_rewrite);
25 STATIC_DCL void NDECL(final_level);
26 /* static boolean FDECL(badspot, (XCHAR_P,XCHAR_P)); */
27 #endif
28
29 #ifdef OVLB
30
31 static NEARDATA const char drop_types[] =
32 { ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, 0 };
33
34 /* 'd' command: drop one inventory item */
35 int
dodrop()36 dodrop()
37 {
38 #ifndef GOLDOBJ
39 int result, i = (invent || u.ugold) ? 0 : (SIZE(drop_types) - 1);
40 #else
41 int result, i = (invent) ? 0 : (SIZE(drop_types) - 1);
42 #endif
43
44 if (*u.ushops) sellobj_state(SELL_DELIBERATE);
45 result = drop(getobj(&drop_types[i], "drop"));
46 if (*u.ushops) sellobj_state(SELL_NORMAL);
47 reset_occupations();
48
49 return result;
50 }
51
52 #endif /* OVLB */
53 #ifdef OVL0
54
55 /* Called when a boulder is dropped, thrown, or pushed. If it ends up
56 * in a pool, it either fills the pool up or sinks away. In either case,
57 * it's gone for good... If the destination is not a pool, returns FALSE.
58 */
59 boolean
boulder_hits_pool(otmp,rx,ry,pushing)60 boulder_hits_pool(otmp, rx, ry, pushing)
61 struct obj *otmp;
62 register int rx, ry;
63 boolean pushing;
64 {
65 if (!otmp || otmp->otyp != BOULDER)
66 impossible("Not a boulder?");
67 else if (!Is_waterlevel(&u.uz) && (is_pool(rx,ry) || is_lava(rx,ry))) {
68 boolean lava = is_lava(rx,ry), fills_up;
69 const char *what = waterbody_name(rx,ry);
70 schar ltyp = levl[rx][ry].typ;
71 int chance = rn2(10); /* water: 90%; lava: 10% */
72 fills_up = lava ? chance == 0 : chance != 0;
73
74 if (fills_up) {
75 struct trap *ttmp = t_at(rx, ry);
76
77 if (ltyp == DRAWBRIDGE_UP) {
78 levl[rx][ry].drawbridgemask &= ~DB_UNDER; /* clear lava */
79 levl[rx][ry].drawbridgemask |= DB_FLOOR;
80 } else
81 levl[rx][ry].typ = ROOM;
82
83 if (ttmp) (void) delfloortrap(ttmp);
84 bury_objs(rx, ry);
85
86 newsym(rx,ry);
87 if (pushing) {
88 You("push %s into the %s.", the(xname(otmp)), what);
89 if (flags.verbose && !Blind)
90 pline("Now you can cross it!");
91 /* no splashing in this case */
92 }
93 }
94 if (!fills_up || !pushing) { /* splashing occurs */
95 if (!u.uinwater) {
96 if (pushing ? !Blind : cansee(rx,ry)) {
97 There("is a large splash as %s %s the %s.",
98 the(xname(otmp)), fills_up? "fills":"falls into",
99 what);
100 } else if (flags.soundok)
101 You_hear("a%s splash.", lava ? " sizzling" : "");
102 wake_nearto(rx, ry, 40);
103 }
104
105 if (fills_up && u.uinwater && distu(rx,ry) == 0) {
106 u.uinwater = 0;
107 docrt();
108 vision_full_recalc = 1;
109 You("find yourself on dry land again!");
110 } else if (lava && distu(rx,ry) <= 2) {
111 You("are hit by molten lava%c",
112 Fire_resistance ? '.' : '!');
113 burn_away_slime();
114 losehp(d((Fire_resistance ? 1 : 3), 6),
115 "molten lava", KILLED_BY);
116 } else if (!fills_up && flags.verbose &&
117 (pushing ? !Blind : cansee(rx,ry)))
118 pline("It sinks without a trace!");
119 }
120
121 /* boulder is now gone */
122 if (pushing) delobj(otmp);
123 else obfree(otmp, (struct obj *)0);
124 return TRUE;
125 }
126 return FALSE;
127 }
128
129 /* Used for objects which sometimes do special things when dropped; must be
130 * called with the object not in any chain. Returns TRUE if the object goes
131 * away.
132 */
133 boolean
flooreffects(obj,x,y,verb)134 flooreffects(obj,x,y,verb)
135 struct obj *obj;
136 int x,y;
137 const char *verb;
138 {
139 struct trap *t;
140 struct monst *mtmp;
141
142 if (obj->where != OBJ_FREE)
143 panic("flooreffects: obj not free");
144
145 /* make sure things like water_damage() have no pointers to follow */
146 obj->nobj = obj->nexthere = (struct obj *)0;
147
148 if (obj->otyp == BOULDER && boulder_hits_pool(obj, x, y, FALSE))
149 return TRUE;
150 else if (obj->otyp == BOULDER && (t = t_at(x,y)) != 0 &&
151 (t->ttyp==PIT || t->ttyp==SPIKED_PIT
152 || t->ttyp==TRAPDOOR || t->ttyp==HOLE)) {
153 if (((mtmp = m_at(x, y)) && mtmp->mtrapped) ||
154 (u.utrap && u.ux == x && u.uy == y)) {
155 if (*verb)
156 pline_The("boulder %s into the pit%s.",
157 vtense((const char *)0, verb),
158 (mtmp) ? "" : " with you");
159 if (mtmp) {
160 if (!passes_walls(mtmp->data) &&
161 !throws_rocks(mtmp->data)) {
162 if (hmon(mtmp, obj, TRUE) && !is_whirly(mtmp->data))
163 return FALSE; /* still alive */
164 }
165 mtmp->mtrapped = 0;
166 } else {
167 if (!Passes_walls && !throws_rocks(youmonst.data)) {
168 losehp(rnd(15), "squished under a boulder",
169 NO_KILLER_PREFIX);
170 return FALSE; /* player remains trapped */
171 } else u.utrap = 0;
172 }
173 }
174 if (*verb) {
175 if (Blind) {
176 if ((x == u.ux) && (y == u.uy))
177 You_hear("a CRASH! beneath you.");
178 else
179 You_hear("the boulder %s.", verb);
180 } else if (cansee(x, y)) {
181 pline_The("boulder %s%s.",
182 t->tseen ? "" : "triggers and ",
183 t->ttyp == TRAPDOOR ? "plugs a trap door" :
184 t->ttyp == HOLE ? "plugs a hole" :
185 "fills a pit");
186 }
187 }
188 deltrap(t);
189 obfree(obj, (struct obj *)0);
190 bury_objs(x, y);
191 newsym(x,y);
192 return TRUE;
193 } else if (is_lava(x, y)) {
194 return fire_damage(obj, FALSE, FALSE, x, y);
195 } else if (is_pool(x, y)) {
196 /* Reasonably bulky objects (arbitrary) splash when dropped.
197 * If you're floating above the water even small things make noise.
198 * Stuff dropped near fountains always misses */
199 if ((Blind || (Levitation || Flying)) && flags.soundok &&
200 ((x == u.ux) && (y == u.uy))) {
201 if (!Underwater) {
202 if (weight(obj) > 9) {
203 pline("Splash!");
204 } else if (Levitation || Flying) {
205 pline("Plop!");
206 }
207 }
208 map_background(x, y, 0);
209 newsym(x, y);
210 }
211 water_damage(obj, FALSE, FALSE);
212 } else if (u.ux == x && u.uy == y &&
213 (!u.utrap || u.utraptype != TT_PIT) &&
214 (t = t_at(x,y)) != 0 && t->tseen &&
215 (t->ttyp==PIT || t->ttyp==SPIKED_PIT)) {
216 /* you escaped a pit and are standing on the precipice */
217 if (Blind && flags.soundok)
218 You_hear("%s %s downwards.",
219 The(xname(obj)), otense(obj, "tumble"));
220 else
221 pline("%s %s into %s pit.",
222 The(xname(obj)), otense(obj, "tumble"),
223 the_your[t->madeby_u]);
224 }
225 return FALSE;
226 }
227
228 #endif /* OVL0 */
229 #ifdef OVLB
230
231 void
doaltarobj(obj)232 doaltarobj(obj) /* obj is an object dropped on an altar */
233 register struct obj *obj;
234 {
235 if (Blind)
236 return;
237
238 /* KMH, conduct */
239 u.uconduct.gnostic++;
240
241 if ((obj->blessed || obj->cursed) && obj->oclass != COIN_CLASS) {
242 There("is %s flash as %s %s the altar.",
243 an(hcolor(obj->blessed ? NH_AMBER : NH_BLACK)),
244 doname(obj), otense(obj, "hit"));
245 if (!Hallucination) obj->bknown = 1;
246 } else {
247 pline("%s %s on the altar.", Doname2(obj),
248 otense(obj, "land"));
249 obj->bknown = 1;
250 }
251 }
252
253 #ifdef SINKS
254 STATIC_OVL
255 void
trycall(obj)256 trycall(obj)
257 register struct obj *obj;
258 {
259 if(!objects[obj->otyp].oc_name_known &&
260 !objects[obj->otyp].oc_uname)
261 docall(obj);
262 }
263
264 STATIC_OVL
265 void
dosinkring(obj)266 dosinkring(obj) /* obj is a ring being dropped over a kitchen sink */
267 register struct obj *obj;
268 {
269 register struct obj *otmp,*otmp2;
270 register boolean ideed = TRUE;
271
272 You("drop %s down the drain.", doname(obj));
273 obj->in_use = TRUE; /* block free identification via interrupt */
274 switch(obj->otyp) { /* effects that can be noticed without eyes */
275 case RIN_SEARCHING:
276 You("thought your %s got lost in the sink, but there it is!",
277 xname(obj));
278 goto giveback;
279 case RIN_SLOW_DIGESTION:
280 pline_The("ring is regurgitated!");
281 giveback:
282 obj->in_use = FALSE;
283 dropx(obj);
284 trycall(obj);
285 return;
286 case RIN_LEVITATION:
287 pline_The("sink quivers upward for a moment.");
288 break;
289 case RIN_POISON_RESISTANCE:
290 You("smell rotten %s.", makeplural(fruitname(FALSE)));
291 break;
292 case RIN_AGGRAVATE_MONSTER:
293 pline("Several flies buzz angrily around the sink.");
294 break;
295 case RIN_SHOCK_RESISTANCE:
296 pline("Static electricity surrounds the sink.");
297 break;
298 case RIN_CONFLICT:
299 You_hear("loud noises coming from the drain.");
300 break;
301 case RIN_SUSTAIN_ABILITY: /* KMH */
302 pline_The("water flow seems fixed.");
303 break;
304 case RIN_GAIN_STRENGTH:
305 pline_The("water flow seems %ser now.",
306 (obj->spe<0) ? "weak" : "strong");
307 break;
308 case RIN_GAIN_CONSTITUTION:
309 pline_The("water flow seems %ser now.",
310 (obj->spe<0) ? "less" : "great");
311 break;
312 case RIN_INCREASE_ACCURACY: /* KMH */
313 pline_The("water flow %s the drain.",
314 (obj->spe<0) ? "misses" : "hits");
315 break;
316 case RIN_INCREASE_DAMAGE:
317 pline_The("water's force seems %ser now.",
318 (obj->spe<0) ? "small" : "great");
319 break;
320 case RIN_HUNGER:
321 ideed = FALSE;
322 for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp2) {
323 otmp2 = otmp->nexthere;
324 if (otmp != uball && otmp != uchain &&
325 !obj_resists(otmp, 1, 99)) {
326 if (!Blind) {
327 pline("Suddenly, %s %s from the sink!",
328 doname(otmp), otense(otmp, "vanish"));
329 ideed = TRUE;
330 }
331 delobj(otmp);
332 }
333 }
334 break;
335 case MEAT_RING:
336 /* Not the same as aggravate monster; besides, it's obvious. */
337 pline("Several flies buzz around the sink.");
338 break;
339 default:
340 ideed = FALSE;
341 break;
342 }
343 if(!Blind && !ideed && obj->otyp != RIN_HUNGER) {
344 ideed = TRUE;
345 switch(obj->otyp) { /* effects that need eyes */
346 case RIN_ADORNMENT:
347 pline_The("faucets flash brightly for a moment.");
348 break;
349 case RIN_REGENERATION:
350 pline_The("sink looks as good as new.");
351 break;
352 case RIN_INVISIBILITY:
353 You("don't see anything happen to the sink.");
354 break;
355 case RIN_FREE_ACTION:
356 You("see the ring slide right down the drain!");
357 break;
358 case RIN_SEE_INVISIBLE:
359 You("see some air in the sink.");
360 break;
361 case RIN_STEALTH:
362 pline_The("sink seems to blend into the floor for a moment.");
363 break;
364 case RIN_FIRE_RESISTANCE:
365 pline_The("hot water faucet flashes brightly for a moment.");
366 break;
367 case RIN_COLD_RESISTANCE:
368 pline_The("cold water faucet flashes brightly for a moment.");
369 break;
370 case RIN_PROTECTION_FROM_SHAPE_CHAN:
371 pline_The("sink looks nothing like a fountain.");
372 break;
373 case RIN_PROTECTION:
374 pline_The("sink glows %s for a moment.",
375 hcolor((obj->spe<0) ? NH_BLACK : NH_SILVER));
376 break;
377 case RIN_WARNING:
378 pline_The("sink glows %s for a moment.", hcolor(NH_WHITE));
379 break;
380 case RIN_TELEPORTATION:
381 pline_The("sink momentarily vanishes.");
382 break;
383 case RIN_TELEPORT_CONTROL:
384 pline_The("sink looks like it is being beamed aboard somewhere.");
385 break;
386 case RIN_POLYMORPH:
387 pline_The("sink momentarily looks like a fountain.");
388 break;
389 case RIN_POLYMORPH_CONTROL:
390 pline_The("sink momentarily looks like a regularly erupting geyser.");
391 break;
392 }
393 }
394 if(ideed)
395 trycall(obj);
396 else
397 You_hear("the ring bouncing down the drainpipe.");
398 if (!rn2(20)) {
399 pline_The("sink backs up, leaving %s.", doname(obj));
400 obj->in_use = FALSE;
401 dropx(obj);
402 } else
403 useup(obj);
404 }
405 #endif
406
407 #endif /* OVLB */
408 #ifdef OVL0
409
410 /* some common tests when trying to drop or throw items */
411 boolean
canletgo(obj,word)412 canletgo(obj,word)
413 register struct obj *obj;
414 register const char *word;
415 {
416 if(obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)){
417 if (*word)
418 Norep("You cannot %s %s you are wearing.",word,
419 something);
420 return(FALSE);
421 }
422 if (obj->otyp == LOADSTONE && obj->cursed) {
423 /* getobj() kludge sets corpsenm to user's specified count
424 when refusing to split a stack of cursed loadstones */
425 if (*word) {
426 /* getobj() ignores a count for throwing since that is
427 implicitly forced to be 1; replicate its kludge... */
428 if (!strcmp(word, "throw") && obj->quan > 1L)
429 obj->corpsenm = 1;
430 pline("For some reason, you cannot %s%s the stone%s!",
431 word, obj->corpsenm ? " any of" : "",
432 plur(obj->quan));
433 }
434 obj->corpsenm = 0; /* reset */
435 obj->bknown = 1;
436 return(FALSE);
437 }
438 if (obj->otyp == LEASH && obj->leashmon != 0) {
439 if (*word)
440 pline_The("leash is tied around your %s.",
441 body_part(HAND));
442 return(FALSE);
443 }
444 #ifdef STEED
445 if (obj->owornmask & W_SADDLE) {
446 if (*word)
447 You("cannot %s %s you are sitting on.", word,
448 something);
449 return (FALSE);
450 }
451 #endif
452 return(TRUE);
453 }
454
455 STATIC_PTR
456 int
drop(obj)457 drop(obj)
458 register struct obj *obj;
459 {
460 if(!obj) return(0);
461 if(!canletgo(obj,"drop"))
462 return(0);
463 if(obj == uwep) {
464 if(welded(uwep)) {
465 weldmsg(obj);
466 return(0);
467 }
468 setuwep((struct obj *)0);
469 }
470 if(obj == uquiver) {
471 setuqwep((struct obj *)0);
472 }
473 if (obj == uswapwep) {
474 setuswapwep((struct obj *)0);
475 }
476
477 if (u.uswallow) {
478 /* barrier between you and the floor */
479 if(flags.verbose)
480 {
481 char buf[BUFSZ];
482
483 /* doname can call s_suffix, reusing its buffer */
484 Strcpy(buf, s_suffix(mon_nam(u.ustuck)));
485 You("drop %s into %s %s.", doname(obj), buf,
486 mbodypart(u.ustuck, STOMACH));
487 }
488 } else {
489 #ifdef SINKS
490 if((obj->oclass == RING_CLASS || obj->otyp == MEAT_RING) &&
491 IS_SINK(levl[u.ux][u.uy].typ)) {
492 dosinkring(obj);
493 return(1);
494 }
495 #endif
496 if (!can_reach_floor()) {
497 if(flags.verbose) You("drop %s.", doname(obj));
498 #ifndef GOLDOBJ
499 if (obj->oclass != COIN_CLASS || obj == invent) freeinv(obj);
500 #else
501 /* Ensure update when we drop gold objects */
502 if (obj->oclass == COIN_CLASS) flags.botl = 1;
503 freeinv(obj);
504 #endif
505 hitfloor(obj);
506 return(1);
507 }
508 if (!IS_ALTAR(levl[u.ux][u.uy].typ) && flags.verbose)
509 You("drop %s.", doname(obj));
510 }
511 dropx(obj);
512 return(1);
513 }
514
515 /* Called in several places - may produce output */
516 /* eg ship_object() and dropy() -> sellobj() both produce output */
517 void
dropx(obj)518 dropx(obj)
519 register struct obj *obj;
520 {
521 #ifndef GOLDOBJ
522 if (obj->oclass != COIN_CLASS || obj == invent) freeinv(obj);
523 #else
524 /* Ensure update when we drop gold objects */
525 if (obj->oclass == COIN_CLASS) flags.botl = 1;
526 freeinv(obj);
527 #endif
528 if (!u.uswallow) {
529 if (ship_object(obj, u.ux, u.uy, FALSE)) return;
530 if (IS_ALTAR(levl[u.ux][u.uy].typ))
531 doaltarobj(obj); /* set bknown */
532 }
533 dropy(obj);
534 }
535
536 void
dropy(obj)537 dropy(obj)
538 register struct obj *obj;
539 {
540 if (obj == uwep) setuwep((struct obj *)0);
541 if (obj == uquiver) setuqwep((struct obj *)0);
542 if (obj == uswapwep) setuswapwep((struct obj *)0);
543
544 if (!u.uswallow && flooreffects(obj,u.ux,u.uy,"drop")) return;
545 /* uswallow check done by GAN 01/29/87 */
546 if(u.uswallow) {
547 boolean could_petrify = FALSE;
548 boolean could_poly = FALSE;
549 boolean could_slime = FALSE;
550 boolean could_grow = FALSE;
551 boolean could_heal = FALSE;
552
553 if (obj != uball) { /* mon doesn't pick up ball */
554 if (obj->otyp == CORPSE) {
555 could_petrify = touch_petrifies(&mons[obj->corpsenm]);
556 could_poly = polyfodder(obj);
557 could_slime = (obj->corpsenm == PM_GREEN_SLIME);
558 could_grow = (obj->corpsenm == PM_WRAITH);
559 could_heal = (obj->corpsenm == PM_NURSE);
560 }
561 (void) mpickobj(u.ustuck,obj);
562 if (is_animal(u.ustuck->data)) {
563 if (could_poly || could_slime) {
564 (void) newcham(u.ustuck,
565 could_poly ? (struct permonst *)0 :
566 &mons[PM_GREEN_SLIME],
567 FALSE, could_slime);
568 delobj(obj); /* corpse is digested */
569 } else if (could_petrify) {
570 minstapetrify(u.ustuck, TRUE);
571 /* Don't leave a cockatrice corpse in a statue */
572 if (!u.uswallow) delobj(obj);
573 } else if (could_grow) {
574 (void) grow_up(u.ustuck, (struct monst *)0);
575 delobj(obj); /* corpse is digested */
576 } else if (could_heal) {
577 u.ustuck->mhp = u.ustuck->mhpmax;
578 delobj(obj); /* corpse is digested */
579 }
580 }
581 }
582 } else {
583 place_object(obj, u.ux, u.uy);
584 if (obj == uball)
585 drop_ball(u.ux,u.uy);
586 else
587 sellobj(obj, u.ux, u.uy);
588 stackobj(obj);
589 if(Blind && Levitation)
590 map_object(obj, 0);
591 newsym(u.ux,u.uy); /* remap location under self */
592 }
593 }
594
595 /* things that must change when not held; recurse into containers.
596 Called for both player and monsters */
597 void
obj_no_longer_held(obj)598 obj_no_longer_held(obj)
599 struct obj *obj;
600 {
601 if (!obj) {
602 return;
603 } else if ((Is_container(obj) || obj->otyp == STATUE) && obj->cobj) {
604 struct obj *contents;
605 for(contents=obj->cobj; contents; contents=contents->nobj)
606 obj_no_longer_held(contents);
607 }
608 switch(obj->otyp) {
609 case CRYSKNIFE:
610 /* KMH -- Fixed crysknives have only 10% chance of reverting */
611 /* only changes when not held by player or monster */
612 if (!obj->oerodeproof || !rn2(10)) {
613 obj->otyp = WORM_TOOTH;
614 obj->oerodeproof = 0;
615 }
616 break;
617 }
618 }
619
620 /* 'D' command: drop several things */
621 int
doddrop()622 doddrop()
623 {
624 int result = 0;
625
626 add_valid_menu_class(0); /* clear any classes already there */
627 if (*u.ushops) sellobj_state(SELL_DELIBERATE);
628 if (flags.menu_style != MENU_TRADITIONAL ||
629 (result = ggetobj("drop", drop, 0, FALSE, (unsigned *)0)) < -1)
630 result = menu_drop(result);
631 if (*u.ushops) sellobj_state(SELL_NORMAL);
632 reset_occupations();
633
634 return result;
635 }
636
637 /* Drop things from the hero's inventory, using a menu. */
638 STATIC_OVL int
menu_drop(retry)639 menu_drop(retry)
640 int retry;
641 {
642 int n, i, n_dropped = 0;
643 long cnt;
644 struct obj *otmp, *otmp2;
645 #ifndef GOLDOBJ
646 struct obj *u_gold = 0;
647 #endif
648 menu_item *pick_list;
649 boolean all_categories = TRUE;
650 boolean drop_everything = FALSE;
651
652 #ifndef GOLDOBJ
653 if (u.ugold) {
654 /* Hack: gold is not in the inventory, so make a gold object
655 and put it at the head of the inventory list. */
656 u_gold = mkgoldobj(u.ugold); /* removes from u.ugold */
657 u_gold->in_use = TRUE;
658 u.ugold = u_gold->quan; /* put the gold back */
659 assigninvlet(u_gold); /* might end up as NOINVSYM */
660 u_gold->nobj = invent;
661 invent = u_gold;
662 }
663 #endif
664 if (retry) {
665 all_categories = (retry == -2);
666 } else if (flags.menu_style == MENU_FULL) {
667 all_categories = FALSE;
668 n = query_category("Drop what type of items?",
669 invent,
670 UNPAID_TYPES | ALL_TYPES | CHOOSE_ALL |
671 BUC_BLESSED | BUC_CURSED | BUC_UNCURSED | BUC_UNKNOWN,
672 &pick_list, PICK_ANY);
673 if (!n) goto drop_done;
674 for (i = 0; i < n; i++) {
675 if (pick_list[i].item.a_int == ALL_TYPES_SELECTED)
676 all_categories = TRUE;
677 else if (pick_list[i].item.a_int == 'A')
678 drop_everything = TRUE;
679 else
680 add_valid_menu_class(pick_list[i].item.a_int);
681 }
682 free((genericptr_t) pick_list);
683 } else if (flags.menu_style == MENU_COMBINATION) {
684 unsigned ggoresults = 0;
685 all_categories = FALSE;
686 /* Gather valid classes via traditional NetHack method */
687 i = ggetobj("drop", drop, 0, TRUE, &ggoresults);
688 if (i == -2) all_categories = TRUE;
689 if (ggoresults & ALL_FINISHED) {
690 n_dropped = i;
691 goto drop_done;
692 }
693 }
694
695 if (drop_everything) {
696 for(otmp = invent; otmp; otmp = otmp2) {
697 otmp2 = otmp->nobj;
698 n_dropped += drop(otmp);
699 }
700 } else {
701 /* should coordinate with perm invent, maybe not show worn items */
702 n = query_objlist("What would you like to drop?", invent,
703 USE_INVLET|INVORDER_SORT, &pick_list,
704 PICK_ANY, all_categories ? allow_all : allow_category);
705 if (n > 0) {
706 for (i = 0; i < n; i++) {
707 otmp = pick_list[i].item.a_obj;
708 cnt = pick_list[i].count;
709 if (cnt < otmp->quan) {
710 if (welded(otmp)) {
711 ; /* don't split */
712 } else if (otmp->otyp == LOADSTONE && otmp->cursed) {
713 /* same kludge as getobj(), for canletgo()'s use */
714 otmp->corpsenm = (int) cnt; /* don't split */
715 } else {
716 #ifndef GOLDOBJ
717 if (otmp->oclass == COIN_CLASS)
718 (void) splitobj(otmp, otmp->quan - cnt);
719 else
720 #endif
721 otmp = splitobj(otmp, cnt);
722 }
723 }
724 n_dropped += drop(otmp);
725 }
726 free((genericptr_t) pick_list);
727 }
728 }
729
730 drop_done:
731 #ifndef GOLDOBJ
732 if (u_gold && invent && invent->oclass == COIN_CLASS) {
733 /* didn't drop [all of] it */
734 u_gold = invent;
735 invent = u_gold->nobj;
736 u_gold->in_use = FALSE;
737 dealloc_obj(u_gold);
738 update_inventory();
739 }
740 #endif
741 return n_dropped;
742 }
743
744 #endif /* OVL0 */
745 #ifdef OVL2
746
747 /* on a ladder, used in goto_level */
748 static NEARDATA boolean at_ladder = FALSE;
749
750 int
dodown()751 dodown()
752 {
753 struct trap *trap = 0;
754 boolean stairs_down = ((u.ux == xdnstair && u.uy == ydnstair) ||
755 (u.ux == sstairs.sx && u.uy == sstairs.sy && !sstairs.up)),
756 ladder_down = (u.ux == xdnladder && u.uy == ydnladder);
757
758 #ifdef STEED
759 if (u.usteed && !u.usteed->mcanmove) {
760 pline("%s won't move!", Monnam(u.usteed));
761 return(0);
762 } else if (u.usteed && u.usteed->meating) {
763 pline("%s is still eating.", Monnam(u.usteed));
764 return(0);
765 } else
766 #endif
767 if (Levitation) {
768 if ((HLevitation & I_SPECIAL) || (ELevitation & W_ARTI)) {
769 /* end controlled levitation */
770 if (ELevitation & W_ARTI) {
771 struct obj *obj;
772
773 for(obj = invent; obj; obj = obj->nobj) {
774 if (obj->oartifact &&
775 artifact_has_invprop(obj,LEVITATION)) {
776 if (obj->age < monstermoves)
777 obj->age = monstermoves + rnz(100);
778 else
779 obj->age += rnz(100);
780 }
781 }
782 }
783 if (float_down(I_SPECIAL|TIMEOUT, W_ARTI))
784 return (1); /* came down, so moved */
785 }
786 floating_above(stairs_down ? "stairs" : ladder_down ?
787 "ladder" : surface(u.ux, u.uy));
788 return (0); /* didn't move */
789 }
790 if (!stairs_down && !ladder_down) {
791 if (!(trap = t_at(u.ux,u.uy)) ||
792 (trap->ttyp != TRAPDOOR && trap->ttyp != HOLE)
793 || !Can_fall_thru(&u.uz) || !trap->tseen) {
794
795 if (flags.autodig && !flags.nopick &&
796 uwep && is_pick(uwep)) {
797 return use_pick_axe2(uwep);
798 } else {
799 You_cant("go down here.");
800 return(0);
801 }
802 }
803 }
804 if(u.ustuck) {
805 You("are %s, and cannot go down.",
806 !u.uswallow ? "being held" : is_animal(u.ustuck->data) ?
807 "swallowed" : "engulfed");
808 return(1);
809 }
810 if (on_level(&valley_level, &u.uz) && !u.uevent.gehennom_entered) {
811 You("are standing at the gate to Gehennom.");
812 pline("Unspeakable cruelty and harm lurk down there.");
813 if (yn("Are you sure you want to enter?") != 'y')
814 return(0);
815 else pline("So be it.");
816 u.uevent.gehennom_entered = 1; /* don't ask again */
817 }
818
819 if(!next_to_u()) {
820 You("are held back by your pet!");
821 return(0);
822 }
823
824 if (trap)
825 You("%s %s.", locomotion(youmonst.data, "jump"),
826 trap->ttyp == HOLE ? "down the hole" : "through the trap door");
827
828 if (trap && Is_stronghold(&u.uz)) {
829 goto_hell(FALSE, TRUE);
830 } else {
831 at_ladder = (boolean) (levl[u.ux][u.uy].typ == LADDER);
832 next_level(!trap);
833 at_ladder = FALSE;
834 }
835 return(1);
836 }
837
838 int
doup()839 doup()
840 {
841 if( (u.ux != xupstair || u.uy != yupstair)
842 && (!xupladder || u.ux != xupladder || u.uy != yupladder)
843 && (!sstairs.sx || u.ux != sstairs.sx || u.uy != sstairs.sy
844 || !sstairs.up)
845 ) {
846 You_cant("go up here.");
847 return(0);
848 }
849 #ifdef STEED
850 if (u.usteed && !u.usteed->mcanmove) {
851 pline("%s won't move!", Monnam(u.usteed));
852 return(0);
853 } else if (u.usteed && u.usteed->meating) {
854 pline("%s is still eating.", Monnam(u.usteed));
855 return(0);
856 } else
857 #endif
858 if(u.ustuck) {
859 You("are %s, and cannot go up.",
860 !u.uswallow ? "being held" : is_animal(u.ustuck->data) ?
861 "swallowed" : "engulfed");
862 return(1);
863 }
864 if(near_capacity() > SLT_ENCUMBER) {
865 /* No levitation check; inv_weight() already allows for it */
866 Your("load is too heavy to climb the %s.",
867 levl[u.ux][u.uy].typ == STAIRS ? "stairs" : "ladder");
868 return(1);
869 }
870 if(ledger_no(&u.uz) == 1) {
871 if (yn("Beware, there will be no return! Still climb?") != 'y')
872 return(0);
873 }
874 if(!next_to_u()) {
875 You("are held back by your pet!");
876 return(0);
877 }
878 at_ladder = (boolean) (levl[u.ux][u.uy].typ == LADDER);
879 prev_level(TRUE);
880 at_ladder = FALSE;
881 return(1);
882 }
883
884 d_level save_dlevel = {0, 0};
885
886 /* check that we can write out the current level */
887 STATIC_OVL int
currentlevel_rewrite()888 currentlevel_rewrite()
889 {
890 register int fd;
891 char whynot[BUFSZ];
892
893 /* since level change might be a bit slow, flush any buffered screen
894 * output (like "you fall through a trap door") */
895 mark_synch();
896
897 fd = create_levelfile(ledger_no(&u.uz), whynot);
898 if (fd < 0) {
899 /*
900 * This is not quite impossible: e.g., we may have
901 * exceeded our quota. If that is the case then we
902 * cannot leave this level, and cannot save either.
903 * Another possibility is that the directory was not
904 * writable.
905 */
906 pline("%s", whynot);
907 return -1;
908 }
909
910 #ifdef MFLOPPY
911 if (!savelev(fd, ledger_no(&u.uz), COUNT_SAVE)) {
912 (void) close(fd);
913 delete_levelfile(ledger_no(&u.uz));
914 pline("NetHack is out of disk space for making levels!");
915 You("can save, quit, or continue playing.");
916 return -1;
917 }
918 #endif
919 return fd;
920 }
921
922 #ifdef INSURANCE
923 void
save_currentstate()924 save_currentstate()
925 {
926 int fd;
927
928 if (flags.ins_chkpt) {
929 /* write out just-attained level, with pets and everything */
930 fd = currentlevel_rewrite();
931 if(fd < 0) return;
932 bufon(fd);
933 savelev(fd,ledger_no(&u.uz), WRITE_SAVE);
934 bclose(fd);
935 }
936
937 /* write out non-level state */
938 savestateinlock();
939 }
940 #endif
941
942 /*
943 static boolean
944 badspot(x, y)
945 register xchar x, y;
946 {
947 return((levl[x][y].typ != ROOM && levl[x][y].typ != AIR &&
948 levl[x][y].typ != CORR) || MON_AT(x, y));
949 }
950 */
951
952 void
goto_level(newlevel,at_stairs,falling,portal)953 goto_level(newlevel, at_stairs, falling, portal)
954 d_level *newlevel;
955 boolean at_stairs, falling, portal;
956 {
957 int fd, l_idx;
958 xchar new_ledger;
959 boolean cant_go_back,
960 up = (depth(newlevel) < depth(&u.uz)),
961 newdungeon = (u.uz.dnum != newlevel->dnum),
962 was_in_W_tower = In_W_tower(u.ux, u.uy, &u.uz),
963 familiar = FALSE;
964 boolean new = FALSE; /* made a new level? */
965 struct monst *mtmp;
966 char whynot[BUFSZ];
967
968 if (dunlev(newlevel) > dunlevs_in_dungeon(newlevel))
969 newlevel->dlevel = dunlevs_in_dungeon(newlevel);
970 if (newdungeon && In_endgame(newlevel)) { /* 1st Endgame Level !!! */
971 if (u.uhave.amulet)
972 assign_level(newlevel, &earth_level);
973 else return;
974 }
975 new_ledger = ledger_no(newlevel);
976 if (new_ledger <= 0)
977 done(ESCAPED); /* in fact < 0 is impossible */
978
979 /* If you have the amulet and are trying to get out of Gehennom, going
980 * up a set of stairs sometimes does some very strange things!
981 * Biased against law and towards chaos, but not nearly as strongly
982 * as it used to be (prior to 3.2.0).
983 * Odds: old new
984 * "up" L N C "up" L N C
985 * +1 75.0 75.0 75.0 +1 75.0 75.0 75.0
986 * 0 0.0 12.5 25.0 0 6.25 8.33 12.5
987 * -1 8.33 4.17 0.0 -1 6.25 8.33 12.5
988 * -2 8.33 4.17 0.0 -2 6.25 8.33 0.0
989 * -3 8.33 4.17 0.0 -3 6.25 0.0 0.0
990 */
991 if (Inhell && up && u.uhave.amulet && !newdungeon && !portal &&
992 (dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz)-3)) {
993 if (!rn2(4)) {
994 int odds = 3 + (int)u.ualign.type, /* 2..4 */
995 diff = odds <= 1 ? 0 : rn2(odds); /* paranoia */
996
997 if (diff != 0) {
998 assign_rnd_level(newlevel, &u.uz, diff);
999 /* if inside the tower, stay inside */
1000 if (was_in_W_tower &&
1001 !On_W_tower_level(newlevel)) diff = 0;
1002 }
1003 if (diff == 0)
1004 assign_level(newlevel, &u.uz);
1005
1006 new_ledger = ledger_no(newlevel);
1007
1008 pline("A mysterious force momentarily surrounds you...");
1009 if (on_level(newlevel, &u.uz)) {
1010 (void) safe_teleds(FALSE);
1011 (void) next_to_u();
1012 return;
1013 } else
1014 at_stairs = at_ladder = FALSE;
1015 }
1016 }
1017
1018 /* Prevent the player from going past the first quest level unless
1019 * (s)he has been given the go-ahead by the leader.
1020 */
1021 if (on_level(&u.uz, &qstart_level) && !newdungeon && !ok_to_quest()) {
1022 pline("A mysterious force prevents you from descending.");
1023 return;
1024 }
1025
1026 if (on_level(newlevel, &u.uz)) return; /* this can happen */
1027
1028 fd = currentlevel_rewrite();
1029 if (fd < 0) return;
1030
1031 if (falling) /* assuming this is only trap door or hole */
1032 impact_drop((struct obj *)0, u.ux, u.uy, newlevel->dlevel);
1033
1034 check_special_room(TRUE); /* probably was a trap door */
1035 if (Punished) unplacebc();
1036 u.utrap = 0; /* needed in level_tele */
1037 fill_pit(u.ux, u.uy);
1038 u.ustuck = 0; /* idem */
1039 u.uinwater = 0;
1040 u.uundetected = 0; /* not hidden, even if means are available */
1041 keepdogs(FALSE);
1042 if (u.uswallow) /* idem */
1043 u.uswldtim = u.uswallow = 0;
1044 /*
1045 * We no longer see anything on the level. Make sure that this
1046 * follows u.uswallow set to null since uswallow overrides all
1047 * normal vision.
1048 */
1049 vision_recalc(2);
1050
1051 /*
1052 * Save the level we're leaving. If we're entering the endgame,
1053 * we can get rid of all existing levels because they cannot be
1054 * reached any more. We still need to use savelev()'s cleanup
1055 * for the level being left, to recover dynamic memory in use and
1056 * to avoid dangling timers and light sources.
1057 */
1058 cant_go_back = (newdungeon && In_endgame(newlevel));
1059 if (!cant_go_back) {
1060 update_mlstmv(); /* current monsters are becoming inactive */
1061 bufon(fd); /* use buffered output */
1062 }
1063 savelev(fd, ledger_no(&u.uz),
1064 cant_go_back ? FREE_SAVE : (WRITE_SAVE | FREE_SAVE));
1065 bclose(fd);
1066 if (cant_go_back) {
1067 /* discard unreachable levels; keep #0 */
1068 for (l_idx = maxledgerno(); l_idx > 0; --l_idx)
1069 delete_levelfile(l_idx);
1070 }
1071
1072 #ifdef REINCARNATION
1073 if (Is_rogue_level(newlevel) || Is_rogue_level(&u.uz))
1074 assign_rogue_graphics(Is_rogue_level(newlevel));
1075 #endif
1076 #ifdef USE_TILES
1077 substitute_tiles(newlevel);
1078 #endif
1079 assign_level(&u.uz0, &u.uz);
1080 assign_level(&u.uz, newlevel);
1081 assign_level(&u.utolev, newlevel);
1082 u.utotype = 0;
1083 if (dunlev_reached(&u.uz) < dunlev(&u.uz))
1084 dunlev_reached(&u.uz) = dunlev(&u.uz);
1085 reset_rndmonst(NON_PM); /* u.uz change affects monster generation */
1086
1087 /* set default level change destination areas */
1088 /* the special level code may override these */
1089 (void) memset((genericptr_t) &updest, 0, sizeof updest);
1090 (void) memset((genericptr_t) &dndest, 0, sizeof dndest);
1091
1092 if (!(level_info[new_ledger].flags & LFILE_EXISTS)) {
1093 /* entering this level for first time; make it now */
1094 if (level_info[new_ledger].flags & (FORGOTTEN|VISITED)) {
1095 impossible("goto_level: returning to discarded level?");
1096 level_info[new_ledger].flags &= ~(FORGOTTEN|VISITED);
1097 }
1098 mklev();
1099 new = TRUE; /* made the level */
1100 } else {
1101 /* returning to previously visited level; reload it */
1102 fd = open_levelfile(new_ledger, whynot);
1103 if (fd < 0) {
1104 pline("%s", whynot);
1105 pline("Probably someone removed it.");
1106 killer = whynot;
1107 done(TRICKED);
1108 /* we'll reach here if running in wizard mode */
1109 error("Cannot continue this game.");
1110 }
1111 minit(); /* ZEROCOMP */
1112 getlev(fd, hackpid, new_ledger, FALSE);
1113 (void) close(fd);
1114 }
1115 /* do this prior to level-change pline messages */
1116 vision_reset(); /* clear old level's line-of-sight */
1117 vision_full_recalc = 0; /* don't let that reenable vision yet */
1118 flush_screen(-1); /* ensure all map flushes are postponed */
1119
1120 if (portal && !In_endgame(&u.uz)) {
1121 /* find the portal on the new level */
1122 register struct trap *ttrap;
1123
1124 for (ttrap = ftrap; ttrap; ttrap = ttrap->ntrap)
1125 if (ttrap->ttyp == MAGIC_PORTAL) break;
1126
1127 if (!ttrap) panic("goto_level: no corresponding portal!");
1128 seetrap(ttrap);
1129 u_on_newpos(ttrap->tx, ttrap->ty);
1130 } else if (at_stairs && !In_endgame(&u.uz)) {
1131 if (up) {
1132 if (at_ladder) {
1133 u_on_newpos(xdnladder, ydnladder);
1134 } else {
1135 if (newdungeon) {
1136 if (Is_stronghold(&u.uz)) {
1137 register xchar x, y;
1138
1139 do {
1140 x = (COLNO - 2 - rnd(5));
1141 y = rn1(ROWNO - 4, 3);
1142 } while(occupied(x, y) ||
1143 IS_WALL(levl[x][y].typ));
1144 u_on_newpos(x, y);
1145 } else u_on_sstairs();
1146 } else u_on_dnstairs();
1147 }
1148 /* Remove bug which crashes with levitation/punishment KAA */
1149 if (Punished && !Levitation) {
1150 pline("With great effort you climb the %s.",
1151 at_ladder ? "ladder" : "stairs");
1152 } else if (at_ladder)
1153 You("climb up the ladder.");
1154 } else { /* down */
1155 if (at_ladder) {
1156 u_on_newpos(xupladder, yupladder);
1157 } else {
1158 if (newdungeon) u_on_sstairs();
1159 else u_on_upstairs();
1160 }
1161 if (u.dz && Flying)
1162 You("fly down along the %s.",
1163 at_ladder ? "ladder" : "stairs");
1164 else if (u.dz &&
1165 (near_capacity() > UNENCUMBERED || Punished || Fumbling)) {
1166 You("fall down the %s.", at_ladder ? "ladder" : "stairs");
1167 if (Punished) {
1168 drag_down();
1169 if (carried(uball)) {
1170 if (uwep == uball)
1171 setuwep((struct obj *)0);
1172 if (uswapwep == uball)
1173 setuswapwep((struct obj *)0);
1174 if (uquiver == uball)
1175 setuqwep((struct obj *)0);
1176 freeinv(uball);
1177 }
1178 }
1179 #ifdef STEED
1180 /* falling off steed has its own losehp() call */
1181 if (u.usteed)
1182 dismount_steed(DISMOUNT_FELL);
1183 else
1184 #endif
1185 losehp(rnd(3), "falling downstairs", KILLED_BY);
1186 selftouch("Falling, you");
1187 } else if (u.dz && at_ladder)
1188 You("climb down the ladder.");
1189 }
1190 } else { /* trap door or level_tele or In_endgame */
1191 if (was_in_W_tower && On_W_tower_level(&u.uz))
1192 /* Stay inside the Wizard's tower when feasible. */
1193 /* Note: up vs down doesn't really matter in this case. */
1194 place_lregion(dndest.nlx, dndest.nly,
1195 dndest.nhx, dndest.nhy,
1196 0,0, 0,0, LR_DOWNTELE, (d_level *) 0);
1197 else if (up)
1198 place_lregion(updest.lx, updest.ly,
1199 updest.hx, updest.hy,
1200 updest.nlx, updest.nly,
1201 updest.nhx, updest.nhy,
1202 LR_UPTELE, (d_level *) 0);
1203 else
1204 place_lregion(dndest.lx, dndest.ly,
1205 dndest.hx, dndest.hy,
1206 dndest.nlx, dndest.nly,
1207 dndest.nhx, dndest.nhy,
1208 LR_DOWNTELE, (d_level *) 0);
1209 if (falling) {
1210 if (Punished) ballfall();
1211 selftouch("Falling, you");
1212 }
1213 }
1214
1215 if (Punished) placebc();
1216 obj_delivery(); /* before killing geno'd monsters' eggs */
1217 losedogs();
1218 kill_genocided_monsters(); /* for those wiped out while in limbo */
1219 /*
1220 * Expire all timers that have gone off while away. Must be
1221 * after migrating monsters and objects are delivered
1222 * (losedogs and obj_delivery).
1223 */
1224 run_timers();
1225
1226 initrack();
1227
1228 if ((mtmp = m_at(u.ux, u.uy)) != 0
1229 #ifdef STEED
1230 && mtmp != u.usteed
1231 #endif
1232 ) {
1233 /* There's a monster at your target destination; it might be one
1234 which accompanied you--see mon_arrive(dogmove.c)--or perhaps
1235 it was already here. Randomly move you to an adjacent spot
1236 or else the monster to any nearby location. Prior to 3.3.0
1237 the latter was done unconditionally. */
1238 coord cc;
1239
1240 if (!rn2(2) &&
1241 enexto(&cc, u.ux, u.uy, youmonst.data) &&
1242 distu(cc.x, cc.y) <= 2)
1243 u_on_newpos(cc.x, cc.y); /*[maybe give message here?]*/
1244 else
1245 mnexto(mtmp);
1246
1247 if ((mtmp = m_at(u.ux, u.uy)) != 0) {
1248 impossible("mnexto failed (do.c)?");
1249 (void) rloc(mtmp, FALSE);
1250 }
1251 }
1252
1253 /* initial movement of bubbles just before vision_recalc */
1254 if (Is_waterlevel(&u.uz))
1255 movebubbles();
1256
1257 if (level_info[new_ledger].flags & FORGOTTEN) {
1258 forget_map(ALL_MAP); /* forget the map */
1259 forget_traps(); /* forget all traps too */
1260 familiar = TRUE;
1261 level_info[new_ledger].flags &= ~FORGOTTEN;
1262 }
1263
1264 /* Reset the screen. */
1265 vision_reset(); /* reset the blockages */
1266 docrt(); /* does a full vision recalc */
1267 flush_screen(-1);
1268
1269 /*
1270 * Move all plines beyond the screen reset.
1271 */
1272
1273 /* give room entrance message, if any */
1274 check_special_room(FALSE);
1275
1276 /* Check whether we just entered Gehennom. */
1277 if (!In_hell(&u.uz0) && Inhell) {
1278 if (Is_valley(&u.uz)) {
1279 You("arrive at the Valley of the Dead...");
1280 pline_The("odor of burnt flesh and decay pervades the air.");
1281 #ifdef MICRO
1282 display_nhwindow(WIN_MESSAGE, FALSE);
1283 #endif
1284 You_hear("groans and moans everywhere.");
1285 } else pline("It is hot here. You smell smoke...");
1286 }
1287
1288 if (familiar) {
1289 static const char * const fam_msgs[4] = {
1290 "You have a sense of deja vu.",
1291 "You feel like you've been here before.",
1292 "This place %s familiar...",
1293 0 /* no message */
1294 };
1295 static const char * const halu_fam_msgs[4] = {
1296 "Whoa! Everything %s different.",
1297 "You are surrounded by twisty little passages, all alike.",
1298 "Gee, this %s like uncle Conan's place...",
1299 0 /* no message */
1300 };
1301 const char *mesg;
1302 char buf[BUFSZ];
1303 int which = rn2(4);
1304
1305 if (Hallucination)
1306 mesg = halu_fam_msgs[which];
1307 else
1308 mesg = fam_msgs[which];
1309 if (mesg && index(mesg, '%')) {
1310 Sprintf(buf, mesg, !Blind ? "looks" : "seems");
1311 mesg = buf;
1312 }
1313 if (mesg) pline(mesg);
1314 }
1315
1316 #ifdef REINCARNATION
1317 if (new && Is_rogue_level(&u.uz))
1318 You("enter what seems to be an older, more primitive world.");
1319 #endif
1320 /* Final confrontation */
1321 if (In_endgame(&u.uz) && newdungeon && u.uhave.amulet)
1322 resurrect();
1323 if (newdungeon && In_V_tower(&u.uz) && In_hell(&u.uz0))
1324 pline_The("heat and smoke are gone.");
1325
1326 /* the message from your quest leader */
1327 if (!In_quest(&u.uz0) && at_dgn_entrance("The Quest") &&
1328 !(u.uevent.qexpelled || u.uevent.qcompleted || quest_status.leader_is_dead)) {
1329
1330 if (u.uevent.qcalled) {
1331 com_pager(Role_if(PM_ROGUE) ? 4 : 3);
1332 } else {
1333 com_pager(2);
1334 u.uevent.qcalled = TRUE;
1335 }
1336 }
1337
1338 /* once Croesus is dead, his alarm doesn't work any more */
1339 if (Is_knox(&u.uz) && (new || !mvitals[PM_CROESUS].died)) {
1340 You("penetrated a high security area!");
1341 pline("An alarm sounds!");
1342 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
1343 if (!DEADMONSTER(mtmp) && mtmp->msleeping) mtmp->msleeping = 0;
1344 }
1345
1346 if (on_level(&u.uz, &astral_level))
1347 final_level();
1348 else
1349 onquest();
1350 assign_level(&u.uz0, &u.uz); /* reset u.uz0 */
1351
1352 #ifdef INSURANCE
1353 save_currentstate();
1354 #endif
1355
1356 /* assume this will always return TRUE when changing level */
1357 (void) in_out_region(u.ux, u.uy);
1358 (void) pickup(1);
1359 }
1360
1361 STATIC_OVL void
final_level()1362 final_level()
1363 {
1364 struct monst *mtmp;
1365 struct obj *otmp;
1366 coord mm;
1367 int i;
1368
1369 /* reset monster hostility relative to player */
1370 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
1371 if (!DEADMONSTER(mtmp)) reset_hostility(mtmp);
1372
1373 /* create some player-monsters */
1374 create_mplayers(rn1(4, 3), TRUE);
1375
1376 /* create a guardian angel next to player, if worthy */
1377 if (Conflict) {
1378 pline(
1379 "A voice booms: \"Thy desire for conflict shall be fulfilled!\"");
1380 for (i = rnd(4); i > 0; --i) {
1381 mm.x = u.ux;
1382 mm.y = u.uy;
1383 if (enexto(&mm, mm.x, mm.y, &mons[PM_ANGEL]))
1384 (void) mk_roamer(&mons[PM_ANGEL], u.ualign.type,
1385 mm.x, mm.y, FALSE);
1386 }
1387
1388 } else if (u.ualign.record > 8) { /* fervent */
1389 pline("A voice whispers: \"Thou hast been worthy of me!\"");
1390 mm.x = u.ux;
1391 mm.y = u.uy;
1392 if (enexto(&mm, mm.x, mm.y, &mons[PM_ANGEL])) {
1393 if ((mtmp = mk_roamer(&mons[PM_ANGEL], u.ualign.type,
1394 mm.x, mm.y, TRUE)) != 0) {
1395 if (!Blind)
1396 pline("An angel appears near you.");
1397 else
1398 You_feel("the presence of a friendly angel near you.");
1399 /* guardian angel -- the one case mtame doesn't
1400 * imply an edog structure, so we don't want to
1401 * call tamedog().
1402 */
1403 mtmp->mtame = 10;
1404 /* make him strong enough vs. endgame foes */
1405 mtmp->m_lev = rn1(8,15);
1406 mtmp->mhp = mtmp->mhpmax =
1407 d((int)mtmp->m_lev,10) + 30 + rnd(30);
1408 if ((otmp = select_hwep(mtmp)) == 0) {
1409 otmp = mksobj(SILVER_SABER, FALSE, FALSE);
1410 if (mpickobj(mtmp, otmp))
1411 panic("merged weapon?");
1412 }
1413 bless(otmp);
1414 if (otmp->spe < 4) otmp->spe += rnd(4);
1415 if ((otmp = which_armor(mtmp, W_ARMS)) == 0 ||
1416 otmp->otyp != SHIELD_OF_REFLECTION) {
1417 (void) mongets(mtmp, AMULET_OF_REFLECTION);
1418 m_dowear(mtmp, TRUE);
1419 }
1420 }
1421 }
1422 }
1423 }
1424
1425 static char *dfr_pre_msg = 0, /* pline() before level change */
1426 *dfr_post_msg = 0; /* pline() after level change */
1427
1428 /* change levels at the end of this turn, after monsters finish moving */
1429 void
schedule_goto(tolev,at_stairs,falling,portal_flag,pre_msg,post_msg)1430 schedule_goto(tolev, at_stairs, falling, portal_flag, pre_msg, post_msg)
1431 d_level *tolev;
1432 boolean at_stairs, falling;
1433 int portal_flag;
1434 const char *pre_msg, *post_msg;
1435 {
1436 int typmask = 0100; /* non-zero triggers `deferred_goto' */
1437
1438 /* destination flags (`goto_level' args) */
1439 if (at_stairs) typmask |= 1;
1440 if (falling) typmask |= 2;
1441 if (portal_flag) typmask |= 4;
1442 if (portal_flag < 0) typmask |= 0200; /* flag for portal removal */
1443 u.utotype = typmask;
1444 /* destination level */
1445 assign_level(&u.utolev, tolev);
1446
1447 if (pre_msg)
1448 dfr_pre_msg = strcpy((char *)alloc(strlen(pre_msg) + 1), pre_msg);
1449 if (post_msg)
1450 dfr_post_msg = strcpy((char *)alloc(strlen(post_msg)+1), post_msg);
1451 }
1452
1453 /* handle something like portal ejection */
1454 void
deferred_goto()1455 deferred_goto()
1456 {
1457 if (!on_level(&u.uz, &u.utolev)) {
1458 d_level dest;
1459 int typmask = u.utotype; /* save it; goto_level zeroes u.utotype */
1460
1461 assign_level(&dest, &u.utolev);
1462 if (dfr_pre_msg) pline(dfr_pre_msg);
1463 goto_level(&dest, !!(typmask&1), !!(typmask&2), !!(typmask&4));
1464 if (typmask & 0200) { /* remove portal */
1465 struct trap *t = t_at(u.ux, u.uy);
1466
1467 if (t) {
1468 deltrap(t);
1469 newsym(u.ux, u.uy);
1470 }
1471 }
1472 if (dfr_post_msg) pline(dfr_post_msg);
1473 }
1474 u.utotype = 0; /* our caller keys off of this */
1475 if (dfr_pre_msg)
1476 free((genericptr_t)dfr_pre_msg), dfr_pre_msg = 0;
1477 if (dfr_post_msg)
1478 free((genericptr_t)dfr_post_msg), dfr_post_msg = 0;
1479 }
1480
1481 #endif /* OVL2 */
1482 #ifdef OVL3
1483
1484 /*
1485 * Return TRUE if we created a monster for the corpse. If successful, the
1486 * corpse is gone.
1487 */
1488 boolean
revive_corpse(corpse)1489 revive_corpse(corpse)
1490 struct obj *corpse;
1491 {
1492 struct monst *mtmp, *mcarry;
1493 boolean is_uwep, chewed;
1494 xchar where;
1495 char *cname, cname_buf[BUFSZ];
1496 struct obj *container = (struct obj *)0;
1497 int container_where = 0;
1498
1499 where = corpse->where;
1500 is_uwep = corpse == uwep;
1501 cname = eos(strcpy(cname_buf, "bite-covered "));
1502 Strcpy(cname, corpse_xname(corpse, TRUE));
1503 mcarry = (where == OBJ_MINVENT) ? corpse->ocarry : 0;
1504
1505 if (where == OBJ_CONTAINED) {
1506 struct monst *mtmp2 = (struct monst *)0;
1507 container = corpse->ocontainer;
1508 mtmp2 = get_container_location(container, &container_where, (int *)0);
1509 /* container_where is the outermost container's location even if nested */
1510 if (container_where == OBJ_MINVENT && mtmp2) mcarry = mtmp2;
1511 }
1512 mtmp = revive(corpse); /* corpse is gone if successful */
1513
1514 if (mtmp) {
1515 chewed = (mtmp->mhp < mtmp->mhpmax);
1516 if (chewed) cname = cname_buf; /* include "bite-covered" prefix */
1517 switch (where) {
1518 case OBJ_INVENT:
1519 if (is_uwep)
1520 pline_The("%s writhes out of your grasp!", cname);
1521 else
1522 You_feel("squirming in your backpack!");
1523 break;
1524
1525 case OBJ_FLOOR:
1526 if (cansee(mtmp->mx, mtmp->my))
1527 pline("%s rises from the dead!", chewed ?
1528 Adjmonnam(mtmp, "bite-covered") : Monnam(mtmp));
1529 break;
1530
1531 case OBJ_MINVENT: /* probably a nymph's */
1532 if (cansee(mtmp->mx, mtmp->my)) {
1533 if (canseemon(mcarry))
1534 pline("Startled, %s drops %s as it revives!",
1535 mon_nam(mcarry), an(cname));
1536 else
1537 pline("%s suddenly appears!", chewed ?
1538 Adjmonnam(mtmp, "bite-covered") : Monnam(mtmp));
1539 }
1540 break;
1541 case OBJ_CONTAINED:
1542 if (container_where == OBJ_MINVENT && cansee(mtmp->mx, mtmp->my) &&
1543 mcarry && canseemon(mcarry) && container) {
1544 char sackname[BUFSZ];
1545 Sprintf(sackname, "%s %s", s_suffix(mon_nam(mcarry)),
1546 xname(container));
1547 pline("%s writhes out of %s!", Amonnam(mtmp), sackname);
1548 } else if (container_where == OBJ_INVENT && container) {
1549 char sackname[BUFSZ];
1550 Strcpy(sackname, an(xname(container)));
1551 pline("%s %s out of %s in your pack!",
1552 Blind ? Something : Amonnam(mtmp),
1553 locomotion(mtmp->data,"writhes"),
1554 sackname);
1555 } else if (container_where == OBJ_FLOOR && container &&
1556 cansee(mtmp->mx, mtmp->my)) {
1557 char sackname[BUFSZ];
1558 Strcpy(sackname, an(xname(container)));
1559 pline("%s escapes from %s!", Amonnam(mtmp), sackname);
1560 }
1561 break;
1562 default:
1563 /* we should be able to handle the other cases... */
1564 impossible("revive_corpse: lost corpse @ %d", where);
1565 break;
1566 }
1567 return TRUE;
1568 }
1569 return FALSE;
1570 }
1571
1572 /* Revive the corpse via a timeout. */
1573 /*ARGSUSED*/
1574 void
revive_mon(arg,timeout)1575 revive_mon(arg, timeout)
1576 genericptr_t arg;
1577 long timeout;
1578 {
1579 struct obj *body = (struct obj *) arg;
1580
1581 /* if we succeed, the corpse is gone, otherwise, rot it away */
1582 if (!revive_corpse(body)) {
1583 if (is_rider(&mons[body->corpsenm]))
1584 You_feel("less hassled.");
1585 (void) start_timer(250L - (monstermoves-body->age),
1586 TIMER_OBJECT, ROT_CORPSE, arg);
1587 }
1588 }
1589
1590 int
donull()1591 donull()
1592 {
1593 return(1); /* Do nothing, but let other things happen */
1594 }
1595
1596 #endif /* OVL3 */
1597 #ifdef OVLB
1598
1599 STATIC_PTR int
wipeoff()1600 wipeoff()
1601 {
1602 if(u.ucreamed < 4) u.ucreamed = 0;
1603 else u.ucreamed -= 4;
1604 if (Blinded < 4) Blinded = 0;
1605 else Blinded -= 4;
1606 if (!Blinded) {
1607 pline("You've got the glop off.");
1608 u.ucreamed = 0;
1609 Blinded = 1;
1610 make_blinded(0L,TRUE);
1611 return(0);
1612 } else if (!u.ucreamed) {
1613 Your("%s feels clean now.", body_part(FACE));
1614 return(0);
1615 }
1616 return(1); /* still busy */
1617 }
1618
1619 int
dowipe()1620 dowipe()
1621 {
1622 if(u.ucreamed) {
1623 static NEARDATA char buf[39];
1624
1625 Sprintf(buf, "wiping off your %s", body_part(FACE));
1626 set_occupation(wipeoff, buf, 0);
1627 /* Not totally correct; what if they change back after now
1628 * but before they're finished wiping?
1629 */
1630 return(1);
1631 }
1632 Your("%s is already clean.", body_part(FACE));
1633 return(1);
1634 }
1635
1636 void
set_wounded_legs(side,timex)1637 set_wounded_legs(side, timex)
1638 register long side;
1639 register int timex;
1640 {
1641 /* KMH -- STEED
1642 * If you are riding, your steed gets the wounded legs instead.
1643 * You still call this function, but don't lose hp.
1644 * Caller is also responsible for adjusting messages.
1645 */
1646
1647 if(!Wounded_legs) {
1648 ATEMP(A_DEX)--;
1649 flags.botl = 1;
1650 }
1651
1652 if(!Wounded_legs || (HWounded_legs & TIMEOUT))
1653 HWounded_legs = timex;
1654 EWounded_legs = side;
1655 (void)encumber_msg();
1656 }
1657
1658 void
heal_legs()1659 heal_legs()
1660 {
1661 if(Wounded_legs) {
1662 if (ATEMP(A_DEX) < 0) {
1663 ATEMP(A_DEX)++;
1664 flags.botl = 1;
1665 }
1666
1667 #ifdef STEED
1668 if (!u.usteed)
1669 #endif
1670 {
1671 /* KMH, intrinsics patch */
1672 if((EWounded_legs & BOTH_SIDES) == BOTH_SIDES) {
1673 Your("%s feel somewhat better.",
1674 makeplural(body_part(LEG)));
1675 } else {
1676 Your("%s feels somewhat better.",
1677 body_part(LEG));
1678 }
1679 }
1680 HWounded_legs = EWounded_legs = 0;
1681 }
1682 (void)encumber_msg();
1683 }
1684
1685 #endif /* OVLB */
1686
1687 /*do.c*/
1688