Source:NetHack 3.2.0/detect.c

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

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

1.   /*	SCCS Id: @(#)detect.c	3.2	96/02/28	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    /*  6.     * Detection routines, including crystal ball, magic mapping, and search 7.    * command. 8.    */  9.     10.   #include "hack.h"  11. #include "artifact.h" 12. 13.  extern boolean known;	/* from read.c */ 14.   15.   static void FDECL(do_dknown_of, (struct obj *)); 16.  static boolean FDECL(check_map_spot, (int,int,CHAR_P)); 17.  static boolean FDECL(clear_stale_map, (CHAR_P)); 18.  static void FDECL(sense_trap, (struct trap *,XCHAR_P,XCHAR_P,int)); 19.  static void FDECL(show_map_spot, (int,int)); 20.  STATIC_PTR void FDECL(findone,(int,int,genericptr_t)); 21.  STATIC_PTR void FDECL(openone,(int,int,genericptr_t)); 22.   23.   /* Recursively search obj for an object in class oclass and return 1st found */ 24.  struct obj * 25.  o_in(obj, oclass) 26.  struct obj* obj; 27.  char oclass; 28.  {  29.       register struct obj* otmp; 30.      struct obj *temp; 31.   32.       if (obj->oclass == oclass) return obj; 33.   34.       if (Has_contents(obj)) { 35.  	for (otmp = obj->cobj; otmp; otmp = otmp->nobj) 36.  	    if (otmp->oclass == oclass) return otmp; 37.  	    else if (Has_contents(otmp) && (temp = o_in(otmp, oclass))) 38.  		return temp; 39.      }  40.       return (struct obj *) 0; 41.  }  42.    43.   static void 44.  do_dknown_of(obj) 45.  struct obj *obj; 46.  {  47.       struct obj *otmp; 48.   49.       obj->dknown = 1; 50.      if (Has_contents(obj)) { 51.  	for(otmp = obj->cobj; otmp; otmp = otmp->nobj) 52.  	    do_dknown_of(otmp); 53.      }  54.   }  55.    56.   /* Check whether the location has an outdated object displayed on it. */ 57.   static boolean 58.  check_map_spot(x, y, oclass) 59.  int x, y;  60. register char oclass; 61.  {  62.   	register int glyph; 63.  	register struct obj *otmp; 64.  	register struct monst *mtmp; 65.   66.   	glyph = glyph_at(x,y); 67.  	if (glyph_is_object(glyph)) { 68.  	    /* there's some object shown here */ 69.  	    if (oclass == ALL_CLASSES) { 70.  		return((boolean)( !(level.objects[x][y] ||     /* stale if nothing here */  71.   			    ((mtmp = m_at(x,y)) != 0 && 72.  				(mtmp->mgold || mtmp->minvent))))); 73.  	    } else if (objects[glyph_to_obj(glyph)].oc_class == oclass) { 74.  		/* the object shown here is of interest */ 75.  		for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) 76.  		    if (o_in(otmp, oclass)) return FALSE; 77.  		/* didn't find it; perhaps a monster is carrying it */ 78.  		if ((mtmp = m_at(x,y)) != 0) { 79.  		    if (oclass == GOLD_CLASS && mtmp->mgold) 80.  			return FALSE; 81.  		    else for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) 82.  			    if (o_in(otmp, oclass)) return FALSE; 83.  		}  84.   		/* detection indicates removal of this object from the map */ 85.  		return TRUE; 86.  	    }  87.   	}  88.   	return FALSE; 89.  }  90.    91.   /*  92.      When doing detection, remove stale data from the map display (corpses  93.      rotted away, objects carried away by monsters, etc) so that it won't  94. reappear after the detection has completed. Return true if noticeable 95.     change occurs. 96.   */  97.   static boolean 98.  clear_stale_map(oclass) 99.  register char oclass; 100. {  101.  	register int zx, zy; 102. 	register boolean change_made = FALSE; 103.  104.  	for (zx = 1; zx < COLNO; zx++) 105. 	    for (zy = 0; zy < ROWNO; zy++) 106. 		if (check_map_spot(zx, zy, oclass)) { 107. 		    unmap_object(zx, zy); 108. 		    change_made = TRUE; 109. 		}  110.   111.  	return change_made; 112. }  113.   114.  /* look for gold, on the floor or in monsters' possession */ 115. int 116. gold_detect(sobj) 117. register struct obj *sobj; 118. {  119.      register struct obj *obj; 120.     register struct monst *mtmp; 121.     int uw = u.uinwater; 122.     struct obj *temp; 123.     boolean stale; 124.  125.      known = stale = clear_stale_map(GOLD_CLASS); 126.  127.      /* look for gold carried by monsters (might be in a container) */ 128.     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) 129. 	if (mtmp->mgold) { 130. 	    known = TRUE; 131. 	    goto outgoldmap;	/* skip further searching */ 132. 	} else for (obj = mtmp->minvent; obj; obj = obj->nobj) 133. 	    if (o_in(obj, GOLD_CLASS)) { 134. 		known = TRUE; 135. 		goto outgoldmap;	/* skip further searching */ 136. 	    }  137.   138.      /* look for gold objects */ 139.     for (obj = fobj; obj; obj = obj->nobj) 140. 	if (o_in(obj, GOLD_CLASS)) { 141. 	    known = TRUE; 142. 	    if (obj->ox != u.ux || obj->oy != u.uy) goto outgoldmap; 143. 	}  144.   145.      if (!known) { 146. 	/* no gold found */ 147. 	if (sobj) strange_feeling(sobj, "You feel materially poor."); 148. 	return(1); 149.     }  150.      /* only under me - no separate display required */ 151.     if (stale) docrt; 152.     You("notice some gold between your %s.", makeplural(body_part(FOOT))); 153.     return(0); 154.  155.  outgoldmap: 156.     cls; 157.  158.      u.uinwater = 0; 159.     /* Discover gold locations. */ 160.      for (obj = fobj; obj; obj = obj->nobj) 161. 	if ((temp = o_in(obj, GOLD_CLASS))) { 162. 	    if (temp != obj) { 163. 		temp->ox = obj->ox; 164. 		temp->oy = obj->oy; 165. 	    }  166.  	    map_object(temp,1); 167. 	}  168.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) 169. 	if (mtmp->mgold) { 170. 	    struct obj gold; 171.  172.  	    gold.otyp = GOLD_PIECE; 173. 	    gold.ox = mtmp->mx; 174. 	    gold.oy = mtmp->my; 175. 	    map_object(&gold,1); 176. 	} else for (obj = mtmp->minvent; obj; obj = obj->nobj) 177. 	    if ((temp = o_in(obj, GOLD_CLASS))) { 178. 		temp->ox = mtmp->mx; 179. 		temp->oy = mtmp->my; 180. 		map_object(temp,1); 181. 		break; 182. 	    }  183.   184.      newsym(u.ux,u.uy); 185.     You_feel("very greedy, and sense gold!"); 186.     exercise(A_WIS, TRUE); 187.     display_nhwindow(WIN_MAP, TRUE); 188.     docrt; 189.     u.uinwater = uw; 190.     if (Underwater) under_water(2); 191.     if (u.uburied) under_ground(2); 192.     return(0); 193. }  194.   195.  /* returns 1 if nothing was detected		*/ 196. /* returns 0 if something was detected		*/ 197. int 198. food_detect(sobj) 199. register struct obj	*sobj; 200. {  201.      register struct obj *obj; 202.     register struct monst *mtmp; 203.     register int ct = 0, ctu = 0; 204.     boolean confused = (Confusion || (sobj && sobj->cursed)), stale; 205.     char oclass = confused ? POTION_CLASS : FOOD_CLASS; 206.     const char *what = confused ? something : "food"; 207.     int uw = u.uinwater; 208.  209.      stale = clear_stale_map(oclass); 210.  211.      for (obj = fobj; obj; obj = obj->nobj) 212. 	if (o_in(obj, oclass)) { 213. 	    if (obj->ox == u.ux && obj->oy == u.uy) ctu++; 214. 	    else ct++; 215. 	}  216.      for (mtmp = fmon; mtmp && !ct; mtmp = mtmp->nmon) 217. 	for (obj = mtmp->minvent; obj; obj = obj->nobj) 218. 	    if (o_in(obj, oclass)) { 219. 		ct++; 220. 		break; 221. 	    }  222.   223.      if (!ct && !ctu) { 224. 	known = stale && !confused; 225. 	if (stale) { 226. 	    docrt; 227. 	    You("sense a lack of %s nearby.", what); 228. 	} else if (sobj) 229. 	    strange_feeling(sobj, "Your nose twitches."); 230. 	return !stale; 231.     } else if (!ct) { 232. 	known = TRUE; 233. 	You("%s %s nearby.", sobj ? "smell" : "sense", what); 234.     } else { 235. 	struct obj *temp; 236. 	known = TRUE; 237. 	cls; 238. 	u.uinwater = 0; 239. 	for (obj = fobj; obj; obj = obj->nobj) 240. 	    if ((temp = o_in(obj, oclass)) != 0) { 241. 		if (temp != obj) { 242. 		    temp->ox = obj->ox; 243. 		    temp->oy = obj->oy; 244. 		}  245.  		map_object(temp,1); 246. 	    }  247.  	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) 248. 	    for (obj = mtmp->minvent; obj; obj = obj->nobj) 249. 		if ((temp = o_in(obj, oclass)) != 0) { 250. 		    temp->ox = mtmp->mx; 251. 		    temp->oy = mtmp->my; 252. 		    map_object(temp,1); 253. 		    break;	/* skip rest of this monster's inventory */ 254. 		}  255.  	newsym(u.ux,u.uy); 256. 	if (sobj) Your("nose tingles and you smell %s.", what); 257. 	else You("sense %s.", what); 258. 	display_nhwindow(WIN_MAP, TRUE); 259. 	exercise(A_WIS, TRUE); 260. 	docrt; 261. 	u.uinwater = uw; 262. 	if (Underwater) under_water(2); 263. 	if (u.uburied) under_ground(2); 264.     }  265.      return(0); 266. }  267.   268.  /*  269.   * Used for scrolls, potions, and crystal balls. Returns: 270.  *  271.   *	1 - nothing was detected 272.  *	0 - something was detected 273.  */  274.  int 275. object_detect(detector, class) 276. struct obj	*detector;	/* object doing the detecting */ 277. int		class;		/* an object class, 0 for all */ 278. {  279.      register int x, y;  280. int is_cursed = (detector && detector->cursed); 281.     int do_dknown = 282. 	(detector && detector->oclass == POTION_CLASS && detector->blessed); 283.     int ct = 0, ctu = 0; 284.     register struct obj *obj, *otmp = (struct obj *)0; 285.     register struct monst *mtmp; 286.     int uw = u.uinwater; 287.     const char *stuff; 288.  289.      if (class < 0 || class >= MAXOCLASSES) { 290. 	impossible("object_detect:  illegal class %d", class); 291. 	class = 0; 292.     }  293.   294.      if (Hallucination || (Confusion && class == SCROLL_CLASS)) 295. 	stuff = something; 296.     else 297. 	stuff = class ? oclass_names[class] : "objects"; 298.  299.      if (do_dknown) for(obj = invent; obj; obj = obj->nobj) do_dknown_of(obj); 300.  301.      for (obj = fobj; obj; obj = obj->nobj) { 302. 	if (!class || o_in(obj, class)) { 303. 	    if (obj->ox == u.ux && obj->oy == u.uy) ctu++; 304. 	    else ct++; 305. 	}  306.  	if (do_dknown) do_dknown_of(obj); 307.     }  308.   309.      for (obj = level.buriedobjlist; obj; obj = obj->nobj) { 310. 	if (!class || o_in(obj, class)) { 311. 	    if (obj->ox == u.ux && obj->oy == u.uy) ctu++; 312. 	    else ct++; 313. 	}  314.  	if (do_dknown) do_dknown_of(obj); 315.     }  316.   317.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { 318. 	for (obj = mtmp->minvent; obj; obj = obj->nobj) { 319. 	    if (!class || o_in(obj, class)) ct++; 320. 	    if (do_dknown) do_dknown_of(obj); 321. 	}  322.   323.  	if ((is_cursed && mtmp->m_ap_type == M_AP_OBJECT && 324. 	    (!class || class == objects[mtmp->mappearance].oc_class)) ||  325.  	    (mtmp->mgold && (!class || class == GOLD_CLASS))) { 326. 	    ct++; 327. 	    break; 328. 	}  329.      }  330.   331.      if (!clear_stale_map(!class ? ALL_CLASSES : class) && !ct) { 332. 	if (!ctu) { 333. 	    if (detector) 334. 		strange_feeling(detector, "You feel a lack of something."); 335. 	    return 1; 336. 	}  337.   338.  	You("sense %s nearby.", stuff); 339. 	return 0; 340.     }  341.   342.      cls; 343.  344.      u.uinwater = 0; 345. /*  346.   *	Map all buried objects first. 347.  */  348.      for (obj = level.buriedobjlist; obj; obj = obj->nobj) 349. 	if (!class || (otmp = o_in(obj, class))) { 350. 	    if (class) { 351. 		if (otmp != obj) { 352. 		    otmp->ox = obj->ox; 353. 		    otmp->oy = obj->oy; 354. 		}  355.  		map_object(otmp, 1); 356. 	    } else 357. 		map_object(obj, 1); 358. 	}  359.      /*  360.       * If we are mapping all objects, map only the top object of a pile or  361. * the first object in a monster's inventory. Otherwise, go looking 362.      * for a matching object class and display the first one encountered 363.      * at each location. 364.      *  365.       * Objects on the floor override buried objects. 366.      */  367.      for (x = 1; x < COLNO; x++) 368. 	for (y = 0; y < ROWNO; y++) 369. 	    for (obj = level.objects[x][y]; obj; obj = obj->nexthere) 370. 		if (!class || (otmp = o_in(obj, class))) { 371. 		    if (class) { 372. 			if (otmp != obj) { 373. 			    otmp->ox = obj->ox; 374. 			    otmp->oy = obj->oy; 375. 			}  376.  			map_object(otmp, 1); 377. 		    } else 378. 			map_object(obj, 1); 379. 		    break; 380. 		}  381.   382.      /* Objects in the monster's inventory override floor objects. */ 383.      for (mtmp = fmon ; mtmp ; mtmp = mtmp->nmon) { 384. 	for (obj = mtmp->minvent; obj; obj = obj->nobj) 385. 	    if (!class || (otmp = o_in(obj, class))) { 386. 		if (!class) otmp = obj; 387. 		otmp->ox = mtmp->mx;		/* at monster location */ 388. 		otmp->oy = mtmp->my; 389. 		map_object(otmp, 1); 390. 		break; 391. 	    }  392.   393.   394.  	/* Allow a mimic to override the detected objects it is carrying. */ 395.  	if (is_cursed && mtmp->m_ap_type == M_AP_OBJECT &&  396.  		(!class || class == objects[mtmp->mappearance].oc_class)) { 397. 	    struct obj temp; 398.  399.  	    temp.otyp = mtmp->mappearance;	/* needed for obj_to_glyph */ 400. 	    temp.ox = mtmp->mx; 401. 	    temp.oy = mtmp->my; 402. 	    temp.corpsenm = PM_TENGU;		/* if mimicing a corpse */ 403. 	    map_object(&temp, 1); 404. 	} else if (mtmp->mgold && (!class || class == GOLD_CLASS)) { 405. 	    struct obj gold; 406.  407.  	    gold.otyp = GOLD_PIECE; 408. 	    gold.ox = mtmp->mx; 409. 	    gold.oy = mtmp->my; 410. 	    map_object(&gold, 1); 411. 	}  412.      }  413.   414.      newsym(u.ux,u.uy); 415.     You("detect the %s of %s.", ct ? "presence" : "absence", stuff); 416.     display_nhwindow(WIN_MAP, TRUE); 417.     /*  418.       * What are we going to do when the hero does an object detect while blind 419.      * and the detected object covers a known pool? 420.      */  421.      docrt;	/* this will correctly reset vision */ 422.  423.      u.uinwater = uw; 424.     if (Underwater) under_water(2); 425.     if (u.uburied) under_ground(2); 426.     return 0; 427. }  428.   429.  /*  430.   * Used by: crystal balls, potions, fountains 431.  *  432.   * Returns 1 if nothing was detected. 433.  * Returns 0 if something was detected. 434.  */  435.  int 436. monster_detect(otmp, mclass) 437. register struct obj *otmp;	/* detecting object (if any) */ 438. int mclass;			/* monster class, 0 for all */ 439. {  440.      register struct monst *mtmp; 441.  442.      if (!fmon) { 443. 	if (otmp) 444. 	    strange_feeling(otmp, Hallucination ?  445.  			    "You get the heebie jeebies." :  446.  			    "You feel threatened."); 447. 	return 1; 448.     } else { 449. 	boolean woken = FALSE; 450.  451.  	cls; 452. 	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { 453. 	    if (!mclass || mtmp->data->mlet == mclass) 454. 	    if (mtmp->mx > 0) 455. 		show_glyph(mtmp->mx,mtmp->my,mon_to_glyph(mtmp)); 456. 	    if (otmp && otmp->cursed &&  457.  		(mtmp->msleep || !mtmp->mcanmove)) { 458. 		mtmp->msleep = mtmp->mfrozen = 0; 459. 		mtmp->mcanmove = 1; 460. 		woken = TRUE; 461. 	    }  462.  	}  463.  	display_self; 464. 	You("sense the presence of monsters."); 465. 	if (woken) 466. 	    pline("Monsters sense the presence of you."); 467. 	display_nhwindow(WIN_MAP, TRUE); 468. 	docrt; 469. 	if (Underwater) under_water(2); 470. 	if (u.uburied) under_ground(2); 471.     }  472.      return 0; 473. }  474.   475.  static void 476. sense_trap(trap, x, y, src_cursed) 477. struct trap *trap; 478. xchar x, y;  479. int src_cursed; 480. {  481.      if (Hallucination || src_cursed) { 482. 	struct obj obj;			/* fake object */ 483. 	if (trap) { 484. 	    obj.ox = trap->tx; 485. 	    obj.oy = trap->ty; 486. 	} else { 487. 	    obj.ox = x;  488. obj.oy = y; 489. } 490.  	obj.otyp = (src_cursed) ? GOLD_PIECE : random_object; 491. 	obj.corpsenm = random_monster;	/* if otyp == CORPSE */ 492. 	map_object(&obj,1); 493.     } else if (trap) { 494. 	map_trap(trap,1); 495. 	trap->tseen = 1; 496.     } else { 497. 	struct trap temp_trap;		/* fake trap */ 498. 	temp_trap.tx = x;  499. temp_trap.ty = y; 500. temp_trap.ttyp = BEAR_TRAP;	/* some kind of trap */ 501. 	map_trap(&temp_trap,1); 502.     }  503.   504.  }  505.   506.  /* the detections are pulled out so they can	*/ 507. /* also be used in the crystal ball routine	*/ 508. /* returns 1 if nothing was detected		*/ 509. /* returns 0 if something was detected		*/ 510. int 511. trap_detect(sobj) 512. register struct obj *sobj; 513. /* sobj is null if crystal ball, *scroll if gold detection scroll */ 514. {  515.      register struct trap *ttmp; 516.     register struct obj *obj; 517.     register int door; 518.     int uw = u.uinwater; 519.     boolean found = FALSE; 520.     coord cc; 521.  522.      for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) { 523. 	if (ttmp->tx != u.ux || ttmp->ty != u.uy) 524. 	    goto outtrapmap; 525. 	else found = TRUE; 526.     }  527.      for (obj = fobj; obj; obj = obj->nobj) { 528. 	if ((obj->otyp==LARGE_BOX || obj->otyp==CHEST) && obj->otrapped) 529. 	    if (obj->ox != u.ux || obj->oy != u.uy) 530. 		goto outtrapmap; 531. 	    else found = TRUE; 532.     }  533.      for (door = 0; door <= doorindex; door++) { 534. 	cc = doors[door]; 535. 	if (levl[cc.x][cc.y].doormask & D_TRAPPED) 536. 	    if (cc.x != u.ux || cc.x != u.uy) 537. 		goto outtrapmap; 538. 	    else found = TRUE; 539.     }  540.      if (!found) { 541. 	char buf[42]; 542. 	Sprintf(buf, "Your %s stop itching.", makeplural(body_part(TOE))); 543. 	strange_feeling(sobj,buf); 544. 	return(1); 545.     }  546.      /* traps exist, but only under me - no separate display required */ 547.     Your("%s itch.", makeplural(body_part(TOE))); 548.     return(0); 549. outtrapmap: 550.     cls; 551.  552.      u.uinwater = 0; 553.     for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) 554. 	sense_trap(ttmp, 0, 0, sobj && sobj->cursed); 555.  556.      for (obj = fobj; obj; obj = obj->nobj) 557. 	if ((obj->otyp==LARGE_BOX || obj->otyp==CHEST) && obj->otrapped) 558. 	sense_trap((struct trap *)0, obj->ox, obj->oy, sobj && sobj->cursed); 559.  560.      for (door = 0; door <= doorindex; door++) { 561. 	cc = doors[door]; 562. 	if (levl[cc.x][cc.y].doormask & D_TRAPPED) 563. 	sense_trap((struct trap *)0, cc.x, cc.y, sobj && sobj->cursed); 564.     }  565.   566.      newsym(u.ux,u.uy); 567.     You_feel("%s.", sobj && sobj->cursed ? "very greedy" : "entrapped"); 568.     display_nhwindow(WIN_MAP, TRUE); 569.     docrt; 570.     u.uinwater = uw; 571.     if (Underwater) under_water(2); 572.     if (u.uburied) under_ground(2); 573.     return(0); 574. }  575.   576.  const char * 577. level_distance(where) 578. d_level *where; 579. {  580.      register schar ll = depth(&u.uz) - depth(where); 581.     register boolean indun = (u.uz.dnum == where->dnum); 582.  583.      if (ll < 0) { 584. 	if (ll < (-8 - rn2(3))) 585. 	    if (!indun)	return "far away"; 586. 	    else	return "far below"; 587. 	else if (ll < -1) 588. 	    if (!indun)	return "away below you"; 589. 	    else	return "below you"; 590. 	else 591. 	    if (!indun)	return "in the distance"; 592. 	    else	return "just below"; 593.     } else if (ll > 0) { 594. 	if (ll > (8 + rn2(3))) 595. 	    if (!indun)	return "far away"; 596. 	    else	return "far above"; 597. 	else if (ll > 1) 598. 	    if (!indun)	return "away above you"; 599. 	    else	return "above you"; 600. 	else 601. 	    if (!indun)	return "in the distance"; 602. 	    else	return "just above"; 603.     } else 604. 	    if (!indun)	return "in the distance"; 605. 	    else	return "near you"; 606. }  607.   608.  static struct { 609.     const char *what; 610.     d_level *where; 611. } level_detects[] = { 612.   { "Delphi", &oracle_level }, 613.   { "Medusa's lair", &medusa_level }, 614.   { "a castle", &stronghold_level }, 615.   { "the Wizard of Yendor's tower", &wiz1_level }, 616. };  617.   618.  void 619. use_crystal_ball(obj) 620. struct obj *obj; 621. {  622.      char ch; 623.     int oops; 624.     const char *bname = xname(obj); 625.  626.      if (Blind) { 627. 	pline("Too bad you can't see %s", the(bname)); 628. 	return; 629.     }  630.      oops = (rnd(20) > ACURR(A_INT) || obj->cursed); 631.     if (oops && (obj->spe > 0)) { 632. 	switch (rnd(obj->oartifact ? 4 : 5)) { 633.  	case 1 : pline("%s is too much to comprehend!", The(bname)); 634. 	    break; 635. 	case 2 : pline("%s confuses you!", The(bname)); 636. 	    make_confused(HConfusion + rnd(100),FALSE); 637. 	    break; 638. 	case 3 : pline("%s damages your vision!", The(bname)); 639. 	    make_blinded(Blinded + rnd(100),FALSE); 640. 	    break; 641. 	case 4 : pline("%s zaps your mind!", The(bname)); 642. 	    make_hallucinated(HHallucination + rnd(100),FALSE,0L); 643. 	    break; 644. 	case 5 : pline("%s explodes!", The(bname)); 645. 	    useup(obj); 646. 	    losehp(rnd(30), "exploding crystal ball", KILLED_BY_AN); 647. 	    break; 648. 	}  649.  	check_unpaid(obj); 650. 	obj->spe--; 651. 	return; 652.     }  653.   654.      if (Hallucination) { 655. 	if (!obj->spe) { 656. 	    pline("All you see is funky %s haze.", hcolor((char *)0)); 657. 	} else { 658. 	    switch(rnd(6)) { 659. 	    case 1 : You("grok some groovy globs of incandescent lava."); 660. 		break; 661. 	    case 2 : pline("Whoa!  Psychedelic colors, %s!",  662.  			   poly_gender == 1 ? "babe" : "dude"); 663. 		break; 664. 	    case 3 : pline_The("crystal pulses with sinister %s light!",  665.  				hcolor((char *)0)); 666. 		break; 667. 	    case 4 : You("see goldfish swimming above fluorescent rocks."); 668. 		break; 669. 	    case 5 : You("see tiny snowflakes spinning around a miniature farmhouse."); 670. 		break; 671. 	    default: pline("Oh wow... like a kaleidoscope!"); 672. 		break; 673. 	    }  674.  	    check_unpaid(obj); 675. 	    obj->spe--; 676. 	}  677.  	return; 678.     }  679.   680.      /* read a single character */ 681.     if (flags.verbose) You("may look for an object or monster symbol."); 682.     ch = yn_function("What do you look for?", (char *)0, '\0'); 683.     if (index(quitchars,ch)) { 684. 	if (flags.verbose) pline("Never mind."); 685. 	return; 686.     }  687.      You("peer into %s...", the(bname)); 688.     nomul(-rnd(10)); 689.     nomovemsg = ""; 690.     if (obj->spe <= 0) 691. 	pline_The("vision is unclear."); 692.     else { 693. 	int class; 694. 	int ret = 0; 695.  696.  	makeknown(CRYSTAL_BALL); 697. 	check_unpaid(obj); 698. 	obj->spe--; 699.  700.  	if ((class = def_char_to_objclass(ch)) != MAXOCLASSES) 701. 		ret = object_detect((struct obj *)0, class); 702. 	else if ((class = def_char_to_monclass(ch)) != MAXMCLASSES) 703. 		ret = monster_detect((struct obj *)0, class); 704. 	else switch(ch) { 705. 		case '^': 706. 		    ret = trap_detect((struct obj *)0); 707. 		    break; 708. 		default: 709. 		    {  710.  		    int i = rn2(SIZE(level_detects)); 711. 		    You("see %s, %s.",  712.  			level_detects[i].what,  713.  			level_distance(level_detects[i].where)); 714. 		    }  715.  		    ret = 0; 716. 		    break; 717. 	}  718.   719.  	if (ret) { 720. 	    if (!rn2(100))  /* make them nervous */ 721. 		You("see the Wizard of Yendor gazing out at you."); 722. 	    else pline_The("vision is unclear."); 723. 	}  724.      }  725.      return; 726. }  727.   728.  static void 729. show_map_spot(x, y)  730. register int x, y; 731. { 732.      register struct rm *lev; 733.  734.      if (Confusion && rn2(7)) return; 735.     lev = &levl[x][y]; 736.  737.      if (IS_WALL(lev->typ) || lev->typ == SDOOR) 738. 	lev->seenv = SVALL;		/* we know they are walls */ 739.  740.      /* Secret corridors are found, but not secret doors. */ 741.      if (lev->typ == SCORR) { 742. 	lev->typ = CORR; 743. 	unblock_point(x,y); 744.     }  745.   746.      /* if we don't remember an object or trap there, map it */ 747.     if (lev->typ == ROOM ?  748.  	    (glyph_is_cmap(lev->glyph) && !glyph_is_trap(lev->glyph) && 749. 		glyph_to_cmap(lev->glyph) != ROOM) :  750.  	    (!glyph_is_object(lev->glyph) && !glyph_is_trap(lev->glyph))) { 751. 	if (level.flags.hero_memory) { 752. 	    map_background(x,y,0); 753. 	    newsym(x,y);		/* show it, if not blocked */ 754. 	} else { 755. 	    map_background(x,y,1);	/* display it */ 756. 	}  757.      }  758.  }  759.   760.  void 761. do_mapping 762. {  763.      register int zx, zy; 764.     int uw = u.uinwater; 765.  766.      u.uinwater = 0; 767.     for (zx = 1; zx < COLNO; zx++) 768. 	for (zy = 0; zy < ROWNO; zy++) 769. 	    show_map_spot(zx, zy); 770.     exercise(A_WIS, TRUE); 771.     u.uinwater = uw; 772.     if (!level.flags.hero_memory || Underwater) { 773. 	flush_screen(1);			/* flush temp screen */ 774. 	display_nhwindow(WIN_MAP, TRUE);	/* wait */ 775. 	docrt; 776.     }  777.  }  778.   779.  void 780. do_vicinity_map 781. {  782.      register int zx, zy; 783.     int lo_y = (u.uy-5 < 0 ? 0 : u.uy-5), 784. 	hi_y = (u.uy+6 > ROWNO ? ROWNO : u.uy+6), 785. 	lo_x = (u.ux-9 < 1 ? 1 : u.ux-9),	/* avoid column 0 */ 786. 	hi_x = (u.ux+10 > COLNO ? COLNO : u.ux+10); 787.  788.      for (zx = lo_x; zx < hi_x; zx++) 789. 	for (zy = lo_y; zy < hi_y; zy++) 790. 	    show_map_spot(zx, zy); 791.  792.      if (!level.flags.hero_memory || Underwater) { 793. 	flush_screen(1);			/* flush temp screen */ 794. 	display_nhwindow(WIN_MAP, TRUE);	/* wait */ 795. 	docrt; 796.     }  797.  }  798.   799.  int 800. exposed_sdoor_mask(lev) 801. struct rm *lev; 802. {  803.  #ifdef REINCARNATION 804. 	if (Is_rogue_level(&u.uz)) 805. 		/* rogue didn't have doors, only doorways */ 806. 		return (lev->doormask & ~WM_MASK); 807. 	else 808. #endif 809. 		/* newly exposed door is closed */ 810. 		return ((lev->doormask & ~WM_MASK) | SDOOR_BITS); 811. }  812.   813.   814.  STATIC_PTR void 815. findone(zx,zy,num) 816. int zx,zy; 817. genericptr_t num; 818. {  819.  	register struct trap *ttmp; 820. 	register struct monst *mtmp; 821.  822.  	if(levl[zx][zy].typ == SDOOR) { 823. 		levl[zx][zy].typ = DOOR; 824. 		levl[zx][zy].doormask = exposed_sdoor_mask(&levl[zx][zy]); 825. 		newsym(zx, zy); 826. 		(*(int*)num)++; 827. 	} else if(levl[zx][zy].typ == SCORR) { 828. 		levl[zx][zy].typ = CORR; 829. 		newsym(zx, zy); 830. 		(*(int*)num)++; 831. 	} else if ((ttmp = t_at(zx, zy)) != 0) { 832. 		if(!ttmp->tseen && ttmp->ttyp != STATUE_TRAP) { 833. 			ttmp->tseen = 1; 834. 			newsym(zx,zy); 835. 			(*(int*)num)++; 836. 		}  837.  	} else if ((mtmp = m_at(zx, zy)) != 0) { 838. 		if(mtmp->m_ap_type) { 839. 			seemimic(mtmp); 840. 			(*(int*)num)++; 841. 		}  842.  		if (mtmp->mundetected &&  843.  		    (is_hider(mtmp->data) || mtmp->data->mlet == S_EEL)) { 844. 			mtmp->mundetected = 0; 845. 			newsym(zx, zy); 846. 			(*(int*)num)++; 847. 		}  848.  	}  849.  }  850.   851.  STATIC_PTR void 852. openone(zx,zy,num) 853. int zx,zy; 854. genericptr_t num; 855. {  856.  	register struct trap *ttmp; 857. 	register struct obj *otmp; 858.  859.  	if(OBJ_AT(zx, zy)) { 860. 		for(otmp = level.objects[zx][zy];  861.  				otmp; otmp = otmp->nexthere) { 862. 		    if(Is_box(otmp) && otmp->olocked) { 863. 			otmp->olocked = 0; 864. 			(*(int*)num)++; 865. 		    }  866.  		}  867.  		/* let it fall to the next cases. could be on trap. */ 868.  	}  869.  	if(levl[zx][zy].typ == SDOOR || (levl[zx][zy].typ == DOOR && 870. 		      (levl[zx][zy].doormask & (D_CLOSED|D_LOCKED)))) { 871. 		if(levl[zx][zy].typ == SDOOR) { 872. 		    levl[zx][zy].typ = DOOR; 873. 		    levl[zx][zy].doormask = exposed_sdoor_mask(&levl[zx][zy]); 874. 		}  875.  		if(levl[zx][zy].doormask & D_TRAPPED) { 876. 		    if(distu(zx, zy) < 3) b_trapped("door", 0); 877. 		    else Norep("You %s an explosion!",  878.  				cansee(zx, zy) ? "see" :  879.  				   (flags.soundok ? "hear" : 880. 						"feel the shock of")); 881. 		    wake_nearto(zx, zy, 11*11); 882. 		    levl[zx][zy].doormask = D_NODOOR; 883. 		} else 884. 		    levl[zx][zy].doormask = D_ISOPEN; 885. 		newsym(zx, zy); 886. 		(*(int*)num)++; 887. 	} else if(levl[zx][zy].typ == SCORR) { 888. 		levl[zx][zy].typ = CORR; 889. 		newsym(zx, zy); 890. 		(*(int*)num)++; 891. 	} else if ((ttmp = t_at(zx, zy)) != 0) { 892. 		if (!ttmp->tseen && ttmp->ttyp != STATUE_TRAP) { 893. 		    ttmp->tseen = 1; 894. 		    newsym(zx,zy); 895. 		    (*(int*)num)++; 896. 		}  897.  	} else if (find_drawbridge(&zx, &zy)) { 898. 		/* make sure it isn't an open drawbridge */ 899. 		open_drawbridge(zx, zy); 900. 		(*(int*)num)++; 901. 	}  902.  }  903.   904.  int 905. findit	/* returns number of things found */ 906. {  907.  	int num = 0; 908.  909.  	if(u.uswallow) return(0); 910. 	do_clear_area(u.ux, u.uy, BOLT_LIM, findone, (genericptr_t) &num); 911. 	return(num); 912. }  913.   914.  int 915. openit	/* returns number of things found and opened */ 916. {  917.  	int num = 0; 918.  919.  	if(u.uswallow) { 920. 		if (is_animal(u.ustuck->data)) { 921. 			if (Blind) pline("Its mouth opens!"); 922. 			else pline("%s opens its mouth!", Monnam(u.ustuck)); 923. 		}  924.  		expels(u.ustuck, u.ustuck->data, TRUE); 925. 		return(-1); 926. 	}  927.   928.  	do_clear_area(u.ux, u.uy, BOLT_LIM, openone, (genericptr_t) &num); 929. 	return(num); 930. }  931.   932.  int 933. dosearch0(aflag) 934. register int aflag; 935. {  936.  #ifdef GCC_BUG 937. /* some versions of gcc seriously muck up nested loops. if you get strange 938.    crashes while searching in a version compiled with gcc, try putting 939.    #define GCC_BUG in *conf.h (or adding -DGCC_BUG to CFLAGS in the  940.     makefile). 941.  */  942.  	volatile xchar x, y;  943. #else 944. 	register xchar x, y;  945. #endif 946. 	register struct trap *trap; 947. 	register struct monst *mtmp; 948.  949.  	if(u.uswallow) { 950. 		if (!aflag) 951. 			pline("What are you looking for?  The exit?"); 952. 	} else { 953. 	    int fund = (uwep && uwep->oartifact &&  954.  		    spec_ability(uwep, SPFX_SEARCH)) ? 955. 			((uwep->spe > 5) ? 5 : uwep->spe) : 0; 956. 	    for(x = u.ux-1; x < u.ux+2; x++) 957. 	      for(y = u.uy-1; y < u.uy+2; y++) { 958. 		if(!isok(x,y)) continue; 959. 		if(x != u.ux || y != u.uy) { 960. 		    if (Blind && !aflag) feel_location(x,y); 961. 		    if(levl[x][y].typ == SDOOR) { 962. 			if(rnl(7-fund)) continue; 963. 			levl[x][y].typ = DOOR; 964. 			levl[x][y].doormask = exposed_sdoor_mask(&levl[x][y]); 965. 			exercise(A_WIS, TRUE); 966. 			nomul(0); 967. 			if (Blind && !aflag) 968. 			    feel_location(x,y);	/* make sure it shows up */ 969. 			else 970. 			    newsym(x,y); 971. 		    } else if(levl[x][y].typ == SCORR) { 972. 			if(rnl(7-fund)) continue; 973. 			levl[x][y].typ = CORR; 974. 			unblock_point(x,y);	/* vision */ 975. 			exercise(A_WIS, TRUE); 976. 			nomul(0); 977. 			newsym(x,y); 978. 		    } else { 979. 		/* Be careful not to find anything in an SCORR or SDOOR */ 980. 			if(!aflag && (mtmp = m_at(x, y))) { 981. 			    if(mtmp->m_ap_type) { 982. 				seemimic(mtmp); 983. 				exercise(A_WIS, TRUE); 984. 				if (!canspotmon(mtmp)) 985. 				    You_feel("an invisible monster!"); 986. 				else 987. 				    You("find %s.", a_monnam(mtmp)); 988. 				return(1); 989. 			    }  990.  			    if(mtmp->mundetected &&  991.  			(is_hider(mtmp->data) || mtmp->data->mlet == S_EEL)) { 992. 				mtmp->mundetected = 0; 993. 				newsym(x,y); 994. 				exercise(A_WIS, TRUE); 995. 				if (!canspotmon(mtmp)) 996. 				    You_feel("an invisible monster!"); 997. 				else 998. 				    You("find %s.", a_monnam(mtmp)); 999. 				return(1); 1000. 			   }  1001. 			}  1002.  1003. 			if ((trap = t_at(x,y)) && !trap->tseen && !rnl(8)) { 1004. 			   nomul(0); 1005. 1006. 			    if (trap->ttyp == STATUE_TRAP) { 1007. 				activate_statue_trap(trap, x, y); 1008. 				if (MON_AT(x, y)) exercise(A_WIS, TRUE); 1009. 				return(1); 1010. 			   } else { 1011. 				You("find %s.", an(defsyms[ 1012. 				   trap_to_defsym(Hallucination ?  1013. 						rn1(TRAPNUM-3, 2) :  1014. 						trap->ttyp)].explanation)); 1015. 				trap->tseen = 1; 1016. 				exercise(A_WIS, TRUE); 1017. 				if(Blind) 1018. 				   feel_location(x,y); 1019. 				else 1020. 				   newsym(x,y); 1021. 			   }  1022. 			}  1023. 		    }  1024. 		}  1025. 	    }  1026. 	}  1027. 	return(1); 1028. } 1029.  1030. int 1031. dosearch 1032. { 1033. 	return(dosearch0(0)); 1034. } 1035.  1036. /*detect.c*/