Source:NetHack 3.2.0/do.c

Below is the full text to do.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/do.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

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