Source:NetHack 3.4.3/src/detect.c

From NetHackWiki
Revision as of 21:37, 3 March 2008 by Kernigh bot (talk | contribs) (Detect.c moved to Source:Detect.c: Robot: moved page)
Jump to navigation Jump to search

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

Top of file

1.    /*	SCCS Id: @(#)detect.c	3.4	2003/08/13	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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_DCL void FDECL(do_dknown_of, (struct obj *));
16.   STATIC_DCL boolean FDECL(check_map_spot, (int,int,CHAR_P,unsigned));
17.   STATIC_DCL boolean FDECL(clear_stale_map, (CHAR_P,unsigned));
18.   STATIC_DCL void FDECL(sense_trap, (struct trap *,XCHAR_P,XCHAR_P,int));
19.   STATIC_DCL 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.   

o_in

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.   

o_material

43.   /* Recursively search obj for an object made of specified material and return 1st found */
44.   struct obj *
45.   o_material(obj, material)
46.   struct obj* obj;
47.   unsigned material;
48.   {
49.       register struct obj* otmp;
50.       struct obj *temp;
51.   
52.       if (objects[obj->otyp].oc_material == material) return obj;
53.   
54.       if (Has_contents(obj)) {
55.   	for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
56.   	    if (objects[otmp->otyp].oc_material == material) return otmp;
57.   	    else if (Has_contents(otmp) && (temp = o_material(otmp, material)))
58.   		return temp;
59.       }
60.       return (struct obj *) 0;
61.   }
62.   

do_dknown_of

63.   STATIC_OVL void
64.   do_dknown_of(obj)
65.   struct obj *obj;
66.   {
67.       struct obj *otmp;
68.   
69.       obj->dknown = 1;
70.       if (Has_contents(obj)) {
71.   	for(otmp = obj->cobj; otmp; otmp = otmp->nobj)
72.   	    do_dknown_of(otmp);
73.       }
74.   }
75.   

check_map_spot

76.   /* Check whether the location has an outdated object displayed on it. */
77.   STATIC_OVL boolean
78.   check_map_spot(x, y, oclass, material)
79.   int x, y;
80.   register char oclass;
81.   unsigned material;
82.   {
83.   	register int glyph;
84.   	register struct obj *otmp;
85.   	register struct monst *mtmp;
86.   
87.   	glyph = glyph_at(x,y);
88.   	if (glyph_is_object(glyph)) {
89.   	    /* there's some object shown here */
90.   	    if (oclass == ALL_CLASSES) {
91.   		return((boolean)( !(level.objects[x][y] ||     /* stale if nothing here */
92.   			    ((mtmp = m_at(x,y)) != 0 &&
93.   				(
94.   #ifndef GOLDOBJ
95.   				 mtmp->mgold ||
96.   #endif
97.   						 mtmp->minvent)))));
98.   	    } else {
99.   		if (material && objects[glyph_to_obj(glyph)].oc_material == material) {
100.  			/* the object shown here is of interest because material matches */
101.  			for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
102.  				if (o_material(otmp, GOLD)) return FALSE;
103.  			/* didn't find it; perhaps a monster is carrying it */
104.  			if ((mtmp = m_at(x,y)) != 0) {
105.  				for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
106.  					if (o_material(otmp, GOLD)) return FALSE;
107.  		        }
108.  			/* detection indicates removal of this object from the map */
109.  			return TRUE;
110.  		}
111.  	        if (oclass && objects[glyph_to_obj(glyph)].oc_class == oclass) {
112.  			/* the object shown here is of interest because its class matches */
113.  			for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
114.  				if (o_in(otmp, oclass)) return FALSE;
115.  			/* didn't find it; perhaps a monster is carrying it */
116.  #ifndef GOLDOBJ
117.  			if ((mtmp = m_at(x,y)) != 0) {
118.  				if (oclass == COIN_CLASS && mtmp->mgold)
119.  					return FALSE;
120.  				else for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
121.  					if (o_in(otmp, oclass)) return FALSE;
122.  		        }
123.  #else
124.  			if ((mtmp = m_at(x,y)) != 0) {
125.  				for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
126.  					if (o_in(otmp, oclass)) return FALSE;
127.  		        }
128.  #endif
129.  			/* detection indicates removal of this object from the map */
130.  			return TRUE;
131.  	        }
132.  	    }
133.  	}
134.  	return FALSE;
135.  }
136.  

clear_stale_map

137.  /*
138.     When doing detection, remove stale data from the map display (corpses
139.     rotted away, objects carried away by monsters, etc) so that it won't
140.     reappear after the detection has completed.  Return true if noticeable
141.     change occurs.
142.   */
143.  STATIC_OVL boolean
144.  clear_stale_map(oclass, material)
145.  register char oclass;
146.  unsigned material;
147.  {
148.  	register int zx, zy;
149.  	register boolean change_made = FALSE;
150.  
151.  	for (zx = 1; zx < COLNO; zx++)
152.  	    for (zy = 0; zy < ROWNO; zy++)
153.  		if (check_map_spot(zx, zy, oclass,material)) {
154.  		    unmap_object(zx, zy);
155.  		    change_made = TRUE;
156.  		}
157.  
158.  	return change_made;
159.  }
160.  

gold_detect

161.  /* look for gold, on the floor or in monsters' possession */
162.  int
163.  gold_detect(sobj)
164.  register struct obj *sobj;
165.  {
166.      register struct obj *obj;
167.      register struct monst *mtmp;
168.      int uw = u.uinwater;
169.      struct obj *temp;
170.      boolean stale;
171.  
172.      known = stale = clear_stale_map(COIN_CLASS,
173.  				(unsigned)(sobj->blessed ? GOLD : 0));
174.  
175.      /* look for gold carried by monsters (might be in a container) */
176.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
177.      	if (DEADMONSTER(mtmp)) continue;	/* probably not needed in this case but... */
178.  #ifndef GOLDOBJ
179.  	if (mtmp->mgold || monsndx(mtmp->data) == PM_GOLD_GOLEM) {
180.  #else
181.  	if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) {
182.  #endif
183.  	    known = TRUE;
184.  	    goto outgoldmap;	/* skip further searching */
185.  	} else for (obj = mtmp->minvent; obj; obj = obj->nobj)
186.  	    if (sobj->blessed && o_material(obj, GOLD)) {
187.  	    	known = TRUE;
188.  	    	goto outgoldmap;
189.  	    } else if (o_in(obj, COIN_CLASS)) {
190.  		known = TRUE;
191.  		goto outgoldmap;	/* skip further searching */
192.  	    }
193.      }
194.      
195.      /* look for gold objects */
196.      for (obj = fobj; obj; obj = obj->nobj) {
197.  	if (sobj->blessed && o_material(obj, GOLD)) {
198.  	    known = TRUE;
199.  	    if (obj->ox != u.ux || obj->oy != u.uy) goto outgoldmap;
200.  	} else if (o_in(obj, COIN_CLASS)) {
201.  	    known = TRUE;
202.  	    if (obj->ox != u.ux || obj->oy != u.uy) goto outgoldmap;
203.  	}
204.      }
205.  
206.      if (!known) {
207.  	/* no gold found on floor or monster's inventory.
208.  	   adjust message if you have gold in your inventory */
209.  	if (sobj) {
210.  		char buf[BUFSZ];
211.  		if (youmonst.data == &mons[PM_GOLD_GOLEM]) {
212.  			Sprintf(buf, "You feel like a million %s!",
213.  				currency(2L));
214.  		} else if (hidden_gold() ||
215.  #ifndef GOLDOBJ
216.  				u.ugold)
217.  #else
218.  			        money_cnt(invent))
219.  #endif
220.  			Strcpy(buf,
221.  				"You feel worried about your future financial situation.");
222.  		else
223.  			Strcpy(buf, "You feel materially poor.");
224.  		strange_feeling(sobj, buf);
225.          }
226.  	return(1);
227.      }
228.      /* only under me - no separate display required */
229.      if (stale) docrt();
230.      You("notice some gold between your %s.", makeplural(body_part(FOOT)));
231.      return(0);
232.  
233.  outgoldmap:
234.      cls();
235.  
236.      u.uinwater = 0;
237.      /* Discover gold locations. */
238.      for (obj = fobj; obj; obj = obj->nobj) {
239.      	if (sobj->blessed && (temp = o_material(obj, GOLD))) {
240.  	    if (temp != obj) {
241.  		temp->ox = obj->ox;
242.  		temp->oy = obj->oy;
243.  	    }
244.  	    map_object(temp,1);
245.  	} else if ((temp = o_in(obj, COIN_CLASS))) {
246.  	    if (temp != obj) {
247.  		temp->ox = obj->ox;
248.  		temp->oy = obj->oy;
249.  	    }
250.  	    map_object(temp,1);
251.  	}
252.      }
253.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
254.      	if (DEADMONSTER(mtmp)) continue;	/* probably overkill here */
255.  #ifndef GOLDOBJ
256.  	if (mtmp->mgold || monsndx(mtmp->data) == PM_GOLD_GOLEM) {
257.  #else
258.  	if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) {
259.  #endif
260.  	    struct obj gold;
261.  
262.  	    gold.otyp = GOLD_PIECE;
263.  	    gold.ox = mtmp->mx;
264.  	    gold.oy = mtmp->my;
265.  	    map_object(&gold,1);
266.  	} else for (obj = mtmp->minvent; obj; obj = obj->nobj)
267.  	    if (sobj->blessed && (temp = o_material(obj, GOLD))) {
268.  		temp->ox = mtmp->mx;
269.  		temp->oy = mtmp->my;
270.  		map_object(temp,1);
271.  		break;
272.  	    } else if ((temp = o_in(obj, COIN_CLASS))) {
273.  		temp->ox = mtmp->mx;
274.  		temp->oy = mtmp->my;
275.  		map_object(temp,1);
276.  		break;
277.  	    }
278.      }
279.      
280.      newsym(u.ux,u.uy);
281.      You_feel("very greedy, and sense gold!");
282.      exercise(A_WIS, TRUE);
283.      display_nhwindow(WIN_MAP, TRUE);
284.      docrt();
285.      u.uinwater = uw;
286.      if (Underwater) under_water(2);
287.      if (u.uburied) under_ground(2);
288.      return(0);
289.  }
290.  

food_detect

291.  /* returns 1 if nothing was detected		*/
292.  /* returns 0 if something was detected		*/
293.  int
294.  food_detect(sobj)
295.  register struct obj	*sobj;
296.  {
297.      register struct obj *obj;
298.      register struct monst *mtmp;
299.      register int ct = 0, ctu = 0;
300.      boolean confused = (Confusion || (sobj && sobj->cursed)), stale;
301.      char oclass = confused ? POTION_CLASS : FOOD_CLASS;
302.      const char *what = confused ? something : "food";
303.      int uw = u.uinwater;
304.  
305.      stale = clear_stale_map(oclass, 0);
306.  
307.      for (obj = fobj; obj; obj = obj->nobj)
308.  	if (o_in(obj, oclass)) {
309.  	    if (obj->ox == u.ux && obj->oy == u.uy) ctu++;
310.  	    else ct++;
311.  	}
312.      for (mtmp = fmon; mtmp && !ct; mtmp = mtmp->nmon) {
313.  	/* no DEADMONSTER(mtmp) check needed since dmons never have inventory */
314.  	for (obj = mtmp->minvent; obj; obj = obj->nobj)
315.  	    if (o_in(obj, oclass)) {
316.  		ct++;
317.  		break;
318.  	    }
319.      }
320.      
321.      if (!ct && !ctu) {
322.  	known = stale && !confused;
323.  	if (stale) {
324.  	    docrt();
325.  	    You("sense a lack of %s nearby.", what);
326.  	    if (sobj && sobj->blessed) {
327.  		if (!u.uedibility) Your("%s starts to tingle.", body_part(NOSE));
328.  		u.uedibility = 1;
329.  	    }
330.  	} else if (sobj) {
331.  	    char buf[BUFSZ];
332.  	    Sprintf(buf, "Your %s twitches%s.", body_part(NOSE),
333.  			(sobj->blessed && !u.uedibility) ? " then starts to tingle" : "");
334.  	    if (sobj->blessed && !u.uedibility) {
335.  		boolean savebeginner = flags.beginner;	/* prevent non-delivery of */
336.  		flags.beginner = FALSE;			/* 	message            */
337.  		strange_feeling(sobj, buf);
338.  		flags.beginner = savebeginner;
339.  		u.uedibility = 1;
340.  	    } else
341.  		strange_feeling(sobj, buf);
342.  	}
343.  	return !stale;
344.      } else if (!ct) {
345.  	known = TRUE;
346.  	You("%s %s nearby.", sobj ? "smell" : "sense", what);
347.  	if (sobj && sobj->blessed) {
348.  		if (!u.uedibility) pline("Your %s starts to tingle.", body_part(NOSE));
349.  		u.uedibility = 1;
350.  	}
351.      } else {
352.  	struct obj *temp;
353.  	known = TRUE;
354.  	cls();
355.  	u.uinwater = 0;
356.  	for (obj = fobj; obj; obj = obj->nobj)
357.  	    if ((temp = o_in(obj, oclass)) != 0) {
358.  		if (temp != obj) {
359.  		    temp->ox = obj->ox;
360.  		    temp->oy = obj->oy;
361.  		}
362.  		map_object(temp,1);
363.  	    }
364.  	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
365.  	    /* no DEADMONSTER(mtmp) check needed since dmons never have inventory */
366.  	    for (obj = mtmp->minvent; obj; obj = obj->nobj)
367.  		if ((temp = o_in(obj, oclass)) != 0) {
368.  		    temp->ox = mtmp->mx;
369.  		    temp->oy = mtmp->my;
370.  		    map_object(temp,1);
371.  		    break;	/* skip rest of this monster's inventory */
372.  		}
373.  	newsym(u.ux,u.uy);
374.  	if (sobj) {
375.  	    if (sobj->blessed) {
376.  	    	Your("%s %s to tingle and you smell %s.", body_part(NOSE),
377.  	    		u.uedibility ? "continues" : "starts", what);
378.  		u.uedibility = 1;
379.  	    } else
380.  		Your("%s tingles and you smell %s.", body_part(NOSE), what);
381.  	}
382.  	else You("sense %s.", what);
383.  	display_nhwindow(WIN_MAP, TRUE);
384.  	exercise(A_WIS, TRUE);
385.  	docrt();
386.  	u.uinwater = uw;
387.  	if (Underwater) under_water(2);
388.  	if (u.uburied) under_ground(2);
389.      }
390.      return(0);
391.  }
392.  

object_detect

393.  /*
394.   * Used for scrolls, potions, spells, and crystal balls.  Returns:
395.   *
396.   *	1 - nothing was detected
397.   *	0 - something was detected
398.   */
399.  int
400.  object_detect(detector, class)
401.  struct obj	*detector;	/* object doing the detecting */
402.  int		class;		/* an object class, 0 for all */
403.  {
404.      register int x, y;
405.      char stuff[BUFSZ];
406.      int is_cursed = (detector && detector->cursed);
407.      int do_dknown = (detector && (detector->oclass == POTION_CLASS ||
408.  				    detector->oclass == SPBOOK_CLASS) &&
409.  			detector->blessed);
410.      int ct = 0, ctu = 0;
411.      register struct obj *obj, *otmp = (struct obj *)0;
412.      register struct monst *mtmp;
413.      int uw = u.uinwater;
414.      int sym, boulder = 0;
415.  
416.      if (class < 0 || class >= MAXOCLASSES) {
417.  	impossible("object_detect:  illegal class %d", class);
418.  	class = 0;
419.      }
420.  
421.      /* Special boulder symbol check - does the class symbol happen
422.       * to match iflags.bouldersym which is a user-defined?
423.       * If so, that means we aren't sure what they really wanted to
424.       * detect. Rather than trump anything, show both possibilities.
425.       * We can exclude checking the buried obj chain for boulders below.
426.       */
427.      sym = class ? def_oc_syms[class] : 0;
428.      if (sym && iflags.bouldersym && sym == iflags.bouldersym)
429.      	boulder = ROCK_CLASS;
430.  
431.      if (Hallucination || (Confusion && class == SCROLL_CLASS))
432.  	Strcpy(stuff, something);
433.      else
434.      	Strcpy(stuff, class ? oclass_names[class] : "objects");
435.      if (boulder && class != ROCK_CLASS) Strcat(stuff, " and/or large stones");
436.  
437.      if (do_dknown) for(obj = invent; obj; obj = obj->nobj) do_dknown_of(obj);
438.  
439.      for (obj = fobj; obj; obj = obj->nobj) {
440.  	if ((!class && !boulder) || o_in(obj, class) || o_in(obj, boulder)) {
441.  	    if (obj->ox == u.ux && obj->oy == u.uy) ctu++;
442.  	    else ct++;
443.  	}
444.  	if (do_dknown) do_dknown_of(obj);
445.      }
446.  
447.      for (obj = level.buriedobjlist; obj; obj = obj->nobj) {
448.  	if (!class || o_in(obj, class)) {
449.  	    if (obj->ox == u.ux && obj->oy == u.uy) ctu++;
450.  	    else ct++;
451.  	}
452.  	if (do_dknown) do_dknown_of(obj);
453.      }
454.  
455.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
456.  	if (DEADMONSTER(mtmp)) continue;
457.  	for (obj = mtmp->minvent; obj; obj = obj->nobj) {
458.  	    if ((!class && !boulder) || o_in(obj, class) || o_in(obj, boulder)) ct++;
459.  	    if (do_dknown) do_dknown_of(obj);
460.  	}
461.  	if ((is_cursed && mtmp->m_ap_type == M_AP_OBJECT &&
462.  	    (!class || class == objects[mtmp->mappearance].oc_class)) ||
463.  #ifndef GOLDOBJ
464.  	    (mtmp->mgold && (!class || class == COIN_CLASS))) {
465.  #else
466.  	    (findgold(mtmp->minvent) && (!class || class == COIN_CLASS))) {
467.  #endif
468.  	    ct++;
469.  	    break;
470.  	}
471.      }
472.  
473.      if (!clear_stale_map(!class ? ALL_CLASSES : class, 0) && !ct) {
474.  	if (!ctu) {
475.  	    if (detector)
476.  		strange_feeling(detector, "You feel a lack of something.");
477.  	    return 1;
478.  	}
479.  
480.  	You("sense %s nearby.", stuff);
481.  	return 0;
482.      }
483.  
484.      cls();
485.  
486.      u.uinwater = 0;
487.  /*
488.   *	Map all buried objects first.
489.   */
490.      for (obj = level.buriedobjlist; obj; obj = obj->nobj)
491.  	if (!class || (otmp = o_in(obj, class))) {
492.  	    if (class) {
493.  		if (otmp != obj) {
494.  		    otmp->ox = obj->ox;
495.  		    otmp->oy = obj->oy;
496.  		}
497.  		map_object(otmp, 1);
498.  	    } else
499.  		map_object(obj, 1);
500.  	}
501.      /*
502.       * If we are mapping all objects, map only the top object of a pile or
503.       * the first object in a monster's inventory.  Otherwise, go looking
504.       * for a matching object class and display the first one encountered
505.       * at each location.
506.       *
507.       * Objects on the floor override buried objects.
508.       */
509.      for (x = 1; x < COLNO; x++)
510.  	for (y = 0; y < ROWNO; y++)
511.  	    for (obj = level.objects[x][y]; obj; obj = obj->nexthere)
512.  		if ((!class && !boulder) ||
513.  		    (otmp = o_in(obj, class)) || (otmp = o_in(obj, boulder))) {
514.  		    if (class || boulder) {
515.  			if (otmp != obj) {
516.  			    otmp->ox = obj->ox;
517.  			    otmp->oy = obj->oy;
518.  			}
519.  			map_object(otmp, 1);
520.  		    } else
521.  			map_object(obj, 1);
522.  		    break;
523.  		}
524.  
525.      /* Objects in the monster's inventory override floor objects. */
526.      for (mtmp = fmon ; mtmp ; mtmp = mtmp->nmon) {
527.  	if (DEADMONSTER(mtmp)) continue;
528.  	for (obj = mtmp->minvent; obj; obj = obj->nobj)
529.  	    if ((!class && !boulder) ||
530.  		 (otmp = o_in(obj, class)) || (otmp = o_in(obj, boulder))) {
531.  		if (!class && !boulder) otmp = obj;
532.  		otmp->ox = mtmp->mx;		/* at monster location */
533.  		otmp->oy = mtmp->my;
534.  		map_object(otmp, 1);
535.  		break;
536.  	    }
537.  	/* Allow a mimic to override the detected objects it is carrying. */
538.  	if (is_cursed && mtmp->m_ap_type == M_AP_OBJECT &&
539.  		(!class || class == objects[mtmp->mappearance].oc_class)) {
540.  	    struct obj temp;
541.  
542.  	    temp.otyp = mtmp->mappearance;	/* needed for obj_to_glyph() */
543.  	    temp.ox = mtmp->mx;
544.  	    temp.oy = mtmp->my;
545.  	    temp.corpsenm = PM_TENGU;		/* if mimicing a corpse */
546.  	    map_object(&temp, 1);
547.  #ifndef GOLDOBJ
548.  	} else if (mtmp->mgold && (!class || class == COIN_CLASS)) {
549.  #else
550.  	} else if (findgold(mtmp->minvent) && (!class || class == COIN_CLASS)) {
551.  #endif
552.  	    struct obj gold;
553.  
554.  	    gold.otyp = GOLD_PIECE;
555.  	    gold.ox = mtmp->mx;
556.  	    gold.oy = mtmp->my;
557.  	    map_object(&gold, 1);
558.  	}
559.      }
560.  
561.      newsym(u.ux,u.uy);
562.      You("detect the %s of %s.", ct ? "presence" : "absence", stuff);
563.      display_nhwindow(WIN_MAP, TRUE);
564.      /*
565.       * What are we going to do when the hero does an object detect while blind
566.       * and the detected object covers a known pool?
567.       */
568.      docrt();	/* this will correctly reset vision */
569.  
570.      u.uinwater = uw;
571.      if (Underwater) under_water(2);
572.      if (u.uburied) under_ground(2);
573.      return 0;
574.  }
575.  

monster_detect

576.  /*
577.   * Used by: crystal balls, potions, fountains
578.   *
579.   * Returns 1 if nothing was detected.
580.   * Returns 0 if something was detected.
581.   */
582.  int
583.  monster_detect(otmp, mclass)
584.  register struct obj *otmp;	/* detecting object (if any) */
585.  int mclass;			/* monster class, 0 for all */
586.  {
587.      register struct monst *mtmp;
588.      int mcnt = 0;
589.  
590.  
591.      /* Note: This used to just check fmon for a non-zero value
592.       * but in versions since 3.3.0 fmon can test TRUE due to the
593.       * presence of dmons, so we have to find at least one
594.       * with positive hit-points to know for sure.
595.       */
596.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
597.      	if (!DEADMONSTER(mtmp)) {
598.  		mcnt++;
599.  		break;
600.  	}
601.  
602.      if (!mcnt) {
603.  	if (otmp)
604.  	    strange_feeling(otmp, Hallucination ?
605.  			    "You get the heebie jeebies." :
606.  			    "You feel threatened.");
607.  	return 1;
608.      } else {
609.  	boolean woken = FALSE;
610.  
611.  	cls();
612.  	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
613.  	    if (DEADMONSTER(mtmp)) continue;
614.  	    if (!mclass || mtmp->data->mlet == mclass ||
615.  		(mtmp->data == &mons[PM_LONG_WORM] && mclass == S_WORM_TAIL))
616.  		    if (mtmp->mx > 0) {
617.  		    	if (mclass && def_monsyms[mclass] == ' ')
618.  				show_glyph(mtmp->mx,mtmp->my,
619.  					detected_mon_to_glyph(mtmp));
620.  			else
621.  				show_glyph(mtmp->mx,mtmp->my,mon_to_glyph(mtmp));
622.  			/* don't be stingy - display entire worm */
623.  			if (mtmp->data == &mons[PM_LONG_WORM]) detect_wsegs(mtmp,0);
624.  		    }
625.  	    if (otmp && otmp->cursed &&
626.  		(mtmp->msleeping || !mtmp->mcanmove)) {
627.  		mtmp->msleeping = mtmp->mfrozen = 0;
628.  		mtmp->mcanmove = 1;
629.  		woken = TRUE;
630.  	    }
631.  	}
632.  	display_self();
633.  	You("sense the presence of monsters.");
634.  	if (woken)
635.  	    pline("Monsters sense the presence of you.");
636.  	display_nhwindow(WIN_MAP, TRUE);
637.  	docrt();
638.  	if (Underwater) under_water(2);
639.  	if (u.uburied) under_ground(2);
640.      }
641.      return 0;
642.  }
643.  

sense_trap

644.  STATIC_OVL void
645.  sense_trap(trap, x, y, src_cursed)
646.  struct trap *trap;
647.  xchar x, y;
648.  int src_cursed;
649.  {
650.      if (Hallucination || src_cursed) {
651.  	struct obj obj;			/* fake object */
652.  	if (trap) {
653.  	    obj.ox = trap->tx;
654.  	    obj.oy = trap->ty;
655.  	} else {
656.  	    obj.ox = x;
657.  	    obj.oy = y;
658.  	}
659.  	obj.otyp = (src_cursed) ? GOLD_PIECE : random_object();
660.  	obj.corpsenm = random_monster();	/* if otyp == CORPSE */
661.  	map_object(&obj,1);
662.      } else if (trap) {
663.  	map_trap(trap,1);
664.  	trap->tseen = 1;
665.      } else {
666.  	struct trap temp_trap;		/* fake trap */
667.  	temp_trap.tx = x;
668.  	temp_trap.ty = y;
669.  	temp_trap.ttyp = BEAR_TRAP;	/* some kind of trap */
670.  	map_trap(&temp_trap,1);
671.      }
672.  
673.  }
674.  

trap_detect

675.  /* the detections are pulled out so they can	*/
676.  /* also be used in the crystal ball routine	*/
677.  /* returns 1 if nothing was detected		*/
678.  /* returns 0 if something was detected		*/
679.  int
680.  trap_detect(sobj)
681.  register struct obj *sobj;
682.  /* sobj is null if crystal ball, *scroll if gold detection scroll */
683.  {
684.      register struct trap *ttmp;
685.      register struct obj *obj;
686.      register int door;
687.      int uw = u.uinwater;
688.      boolean found = FALSE;
689.      coord cc;
690.  
691.      for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
692.  	if (ttmp->tx != u.ux || ttmp->ty != u.uy)
693.  	    goto outtrapmap;
694.  	else found = TRUE;
695.      }
696.      for (obj = fobj; obj; obj = obj->nobj) {
697.  	if ((obj->otyp==LARGE_BOX || obj->otyp==CHEST) && obj->otrapped) {
698.  	    if (obj->ox != u.ux || obj->oy != u.uy)
699.  		goto outtrapmap;
700.  	    else found = TRUE;
701.  	}
702.      }
703.      for (door = 0; door < doorindex; door++) {
704.  	cc = doors[door];
705.  	if (levl[cc.x][cc.y].doormask & D_TRAPPED) {
706.  	    if (cc.x != u.ux || cc.y != u.uy)
707.  		goto outtrapmap;
708.  	    else found = TRUE;
709.  	}
710.      }
711.      if (!found) {
712.  	char buf[42];
713.  	Sprintf(buf, "Your %s stop itching.", makeplural(body_part(TOE)));
714.  	strange_feeling(sobj,buf);
715.  	return(1);
716.      }
717.      /* traps exist, but only under me - no separate display required */
718.      Your("%s itch.", makeplural(body_part(TOE)));
719.      return(0);
720.  outtrapmap:
721.      cls();
722.  
723.      u.uinwater = 0;
724.      for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
725.  	sense_trap(ttmp, 0, 0, sobj && sobj->cursed);
726.  
727.      for (obj = fobj; obj; obj = obj->nobj)
728.  	if ((obj->otyp==LARGE_BOX || obj->otyp==CHEST) && obj->otrapped)
729.  	sense_trap((struct trap *)0, obj->ox, obj->oy, sobj && sobj->cursed);
730.  
731.      for (door = 0; door < doorindex; door++) {
732.  	cc = doors[door];
733.  	if (levl[cc.x][cc.y].doormask & D_TRAPPED)
734.  	sense_trap((struct trap *)0, cc.x, cc.y, sobj && sobj->cursed);
735.      }
736.  
737.      newsym(u.ux,u.uy);
738.      You_feel("%s.", sobj && sobj->cursed ? "very greedy" : "entrapped");
739.      display_nhwindow(WIN_MAP, TRUE);
740.      docrt();
741.      u.uinwater = uw;
742.      if (Underwater) under_water(2);
743.      if (u.uburied) under_ground(2);
744.      return(0);
745.  }
746.  

level_distance

747.  const char *
748.  level_distance(where)
749.  d_level *where;
750.  {
751.      register schar ll = depth(&u.uz) - depth(where);
752.      register boolean indun = (u.uz.dnum == where->dnum);
753.  
754.      if (ll < 0) {
755.  	if (ll < (-8 - rn2(3)))
756.  	    if (!indun)	return "far away";
757.  	    else	return "far below";
758.  	else if (ll < -1)
759.  	    if (!indun)	return "away below you";
760.  	    else	return "below you";
761.  	else
762.  	    if (!indun)	return "in the distance";
763.  	    else	return "just below";
764.      } else if (ll > 0) {
765.  	if (ll > (8 + rn2(3)))
766.  	    if (!indun)	return "far away";
767.  	    else	return "far above";
768.  	else if (ll > 1)
769.  	    if (!indun)	return "away above you";
770.  	    else	return "above you";
771.  	else
772.  	    if (!indun)	return "in the distance";
773.  	    else	return "just above";
774.      } else
775.  	    if (!indun)	return "in the distance";
776.  	    else	return "near you";
777.  }
778.  

use_crystal_ball

779.  static const struct {
780.      const char *what;
781.      d_level *where;
782.  } level_detects[] = {
783.    { "Delphi", &oracle_level },
784.    { "Medusa's lair", &medusa_level },
785.    { "a castle", &stronghold_level },
786.    { "the Wizard of Yendor's tower", &wiz1_level },
787.  };
788.  
789.  void
790.  use_crystal_ball(obj)
791.  struct obj *obj;
792.  {
793.      char ch;
794.      int oops;
795.  
796.      if (Blind) {
797.  	pline("Too bad you can't see %s.", the(xname(obj)));
798.  	return;
799.      }
800.      oops = (rnd(20) > ACURR(A_INT) || obj->cursed);
801.      if (oops && (obj->spe > 0)) {
802.  	switch (rnd(obj->oartifact ? 4 : 5)) {
803.  	case 1 : pline("%s too much to comprehend!", Tobjnam(obj, "are"));
804.  	    break;
805.  	case 2 : pline("%s you!", Tobjnam(obj, "confuse"));
806.  	    make_confused(HConfusion + rnd(100),FALSE);
807.  	    break;
808.  	case 3 : if (!resists_blnd(&youmonst)) {
809.  		pline("%s your vision!", Tobjnam(obj, "damage"));
810.  		make_blinded(Blinded + rnd(100),FALSE);
811.  		if (!Blind) Your(vision_clears);
812.  	    } else {
813.  		pline("%s your vision.", Tobjnam(obj, "assault"));
814.  		You("are unaffected!");
815.  	    }
816.  	    break;
817.  	case 4 : pline("%s your mind!", Tobjnam(obj, "zap"));
818.  	    (void) make_hallucinated(HHallucination + rnd(100),FALSE,0L);
819.  	    break;
820.  	case 5 : pline("%s!", Tobjnam(obj, "explode"));
821.  	    useup(obj);
822.  	    obj = 0;	/* it's gone */
823.  	    losehp(rnd(30), "exploding crystal ball", KILLED_BY_AN);
824.  	    break;
825.  	}
826.  	if (obj) consume_obj_charge(obj, TRUE);
827.  	return;
828.      }
829.  
830.      if (Hallucination) {
831.  	if (!obj->spe) {
832.  	    pline("All you see is funky %s haze.", hcolor((char *)0));
833.  	} else {
834.  	    switch(rnd(6)) {
835.  	    case 1 : You("grok some groovy globs of incandescent lava.");
836.  		break;
837.  	    case 2 : pline("Whoa!  Psychedelic colors, %s!",
838.  			   poly_gender() == 1 ? "babe" : "dude");
839.  		break;
840.  	    case 3 : pline_The("crystal pulses with sinister %s light!",
841.  				hcolor((char *)0));
842.  		break;
843.  	    case 4 : You("see goldfish swimming above fluorescent rocks.");
844.  		break;
845.  	    case 5 : You("see tiny snowflakes spinning around a miniature farmhouse.");
846.  		break;
847.  	    default: pline("Oh wow... like a kaleidoscope!");
848.  		break;
849.  	    }
850.  	    consume_obj_charge(obj, TRUE);
851.  	}
852.  	return;
853.      }
854.  
855.      /* read a single character */
856.      if (flags.verbose) You("may look for an object or monster symbol.");
857.      ch = yn_function("What do you look for?", (char *)0, '\0');
858.      /* Don't filter out ' ' here; it has a use */
859.      if ((ch != def_monsyms[S_GHOST]) && index(quitchars,ch)) { 
860.  	if (flags.verbose) pline(Never_mind);
861.  	return;
862.      }
863.      You("peer into %s...", the(xname(obj)));
864.      nomul(-rnd(10));
865.      nomovemsg = "";
866.      if (obj->spe <= 0)
867.  	pline_The("vision is unclear.");
868.      else {
869.  	int class;
870.  	int ret = 0;
871.  
872.  	makeknown(CRYSTAL_BALL);
873.  	consume_obj_charge(obj, TRUE);
874.  
875.  	/* special case: accept ']' as synonym for mimic
876.  	 * we have to do this before the def_char_to_objclass check
877.  	 */
878.  	if (ch == DEF_MIMIC_DEF) ch = DEF_MIMIC;
879.  
880.  	if ((class = def_char_to_objclass(ch)) != MAXOCLASSES)
881.  		ret = object_detect((struct obj *)0, class);
882.  	else if ((class = def_char_to_monclass(ch)) != MAXMCLASSES)
883.  		ret = monster_detect((struct obj *)0, class);
884.  	else if (iflags.bouldersym && (ch == iflags.bouldersym))
885.  		ret = object_detect((struct obj *)0, ROCK_CLASS);
886.  	else switch(ch) {
887.  		case '^':
888.  		    ret = trap_detect((struct obj *)0);
889.  		    break;
890.  		default:
891.  		    {
892.  		    int i = rn2(SIZE(level_detects));
893.  		    You("see %s, %s.",
894.  			level_detects[i].what,
895.  			level_distance(level_detects[i].where));
896.  		    }
897.  		    ret = 0;
898.  		    break;
899.  	}
900.  
901.  	if (ret) {
902.  	    if (!rn2(100))  /* make them nervous */
903.  		You("see the Wizard of Yendor gazing out at you.");
904.  	    else pline_The("vision is unclear.");
905.  	}
906.      }
907.      return;
908.  }
909.  

show_map_spot

910.  STATIC_OVL void
911.  show_map_spot(x, y)
912.  register int x, y;
913.  {
914.      register struct rm *lev;
915.  
916.      if (Confusion && rn2(7)) return;
917.      lev = &levl[x][y];
918.  
919.      lev->seenv = SVALL;
920.  
921.      /* Secret corridors are found, but not secret doors. */
922.      if (lev->typ == SCORR) {
923.  	lev->typ = CORR;
924.  	unblock_point(x,y);
925.      }
926.  
927.      /* if we don't remember an object or trap there, map it */
928.      if (lev->typ == ROOM ?
929.  	    (glyph_is_cmap(lev->glyph) && !glyph_is_trap(lev->glyph) &&
930.  		glyph_to_cmap(lev->glyph) != ROOM) :
931.  	    (!glyph_is_object(lev->glyph) && !glyph_is_trap(lev->glyph))) {
932.  	if (level.flags.hero_memory) {
933.  	    magic_map_background(x,y,0);
934.  	    newsym(x,y);			/* show it, if not blocked */
935.  	} else {
936.  	    magic_map_background(x,y,1);	/* display it */
937.  	}
938.      }
939.  }
940.  

do_mapping

941.  void
942.  do_mapping()
943.  {
944.      register int zx, zy;
945.      int uw = u.uinwater;
946.  
947.      u.uinwater = 0;
948.      for (zx = 1; zx < COLNO; zx++)
949.  	for (zy = 0; zy < ROWNO; zy++)
950.  	    show_map_spot(zx, zy);
951.      exercise(A_WIS, TRUE);
952.      u.uinwater = uw;
953.      if (!level.flags.hero_memory || Underwater) {
954.  	flush_screen(1);			/* flush temp screen */
955.  	display_nhwindow(WIN_MAP, TRUE);	/* wait */
956.  	docrt();
957.      }
958.  }
959.  

do_vicinity_map

960.  void
961.  do_vicinity_map()
962.  {
963.      register int zx, zy;
964.      int lo_y = (u.uy-5 < 0 ? 0 : u.uy-5),
965.  	hi_y = (u.uy+6 > ROWNO ? ROWNO : u.uy+6),
966.  	lo_x = (u.ux-9 < 1 ? 1 : u.ux-9),	/* avoid column 0 */
967.  	hi_x = (u.ux+10 > COLNO ? COLNO : u.ux+10);
968.  
969.      for (zx = lo_x; zx < hi_x; zx++)
970.  	for (zy = lo_y; zy < hi_y; zy++)
971.  	    show_map_spot(zx, zy);
972.  
973.      if (!level.flags.hero_memory || Underwater) {
974.  	flush_screen(1);			/* flush temp screen */
975.  	display_nhwindow(WIN_MAP, TRUE);	/* wait */
976.  	docrt();
977.      }
978.  }
979.  

cvt_sdoor_to_door

980.  /* convert a secret door into a normal door */
981.  void
982.  cvt_sdoor_to_door(lev)
983.  struct rm *lev;
984.  {
985.  	int newmask = lev->doormask & ~WM_MASK;
986.  
987.  #ifdef REINCARNATION
988.  	if (Is_rogue_level(&u.uz))
989.  	    /* rogue didn't have doors, only doorways */
990.  	    newmask = D_NODOOR;
991.  	else
992.  #endif
993.  	    /* newly exposed door is closed */
994.  	    if (!(newmask & D_LOCKED)) newmask |= D_CLOSED;
995.  
996.  	lev->typ = DOOR;
997.  	lev->doormask = newmask;
998.  }
999.  
1000. 

findone

1001. STATIC_PTR void
1002. findone(zx,zy,num)
1003. int zx,zy;
1004. genericptr_t num;
1005. {
1006. 	register struct trap *ttmp;
1007. 	register struct monst *mtmp;
1008. 
1009. 	if(levl[zx][zy].typ == SDOOR) {
1010. 		cvt_sdoor_to_door(&levl[zx][zy]);	/* .typ = DOOR */
1011. 		magic_map_background(zx, zy, 0);
1012. 		newsym(zx, zy);
1013. 		(*(int*)num)++;
1014. 	} else if(levl[zx][zy].typ == SCORR) {
1015. 		levl[zx][zy].typ = CORR;
1016. 		unblock_point(zx,zy);
1017. 		magic_map_background(zx, zy, 0);
1018. 		newsym(zx, zy);
1019. 		(*(int*)num)++;
1020. 	} else if ((ttmp = t_at(zx, zy)) != 0) {
1021. 		if(!ttmp->tseen && ttmp->ttyp != STATUE_TRAP) {
1022. 			ttmp->tseen = 1;
1023. 			newsym(zx,zy);
1024. 			(*(int*)num)++;
1025. 		}
1026. 	} else if ((mtmp = m_at(zx, zy)) != 0) {
1027. 		if(mtmp->m_ap_type) {
1028. 			seemimic(mtmp);
1029. 			(*(int*)num)++;
1030. 		}
1031. 		if (mtmp->mundetected &&
1032. 		    (is_hider(mtmp->data) || mtmp->data->mlet == S_EEL)) {
1033. 			mtmp->mundetected = 0;
1034. 			newsym(zx, zy);
1035. 			(*(int*)num)++;
1036. 		}
1037. 		if (!canspotmon(mtmp) &&
1038. 				    !glyph_is_invisible(levl[zx][zy].glyph))
1039. 			map_invisible(zx, zy);
1040. 	} else if (glyph_is_invisible(levl[zx][zy].glyph)) {
1041. 		unmap_object(zx, zy);
1042. 		newsym(zx, zy);
1043. 		(*(int*)num)++;
1044. 	}
1045. }
1046. 

openone

1047. STATIC_PTR void
1048. openone(zx,zy,num)
1049. int zx,zy;
1050. genericptr_t num;
1051. {
1052. 	register struct trap *ttmp;
1053. 	register struct obj *otmp;
1054. 
1055. 	if(OBJ_AT(zx, zy)) {
1056. 		for(otmp = level.objects[zx][zy];
1057. 				otmp; otmp = otmp->nexthere) {
1058. 		    if(Is_box(otmp) && otmp->olocked) {
1059. 			otmp->olocked = 0;
1060. 			(*(int*)num)++;
1061. 		    }
1062. 		}
1063. 		/* let it fall to the next cases. could be on trap. */
1064. 	}
1065. 	if(levl[zx][zy].typ == SDOOR || (levl[zx][zy].typ == DOOR &&
1066. 		      (levl[zx][zy].doormask & (D_CLOSED|D_LOCKED)))) {
1067. 		if(levl[zx][zy].typ == SDOOR)
1068. 		    cvt_sdoor_to_door(&levl[zx][zy]);	/* .typ = DOOR */
1069. 		if(levl[zx][zy].doormask & D_TRAPPED) {
1070. 		    if(distu(zx, zy) < 3) b_trapped("door", 0);
1071. 		    else Norep("You %s an explosion!",
1072. 				cansee(zx, zy) ? "see" :
1073. 				   (flags.soundok ? "hear" :
1074. 						"feel the shock of"));
1075. 		    wake_nearto(zx, zy, 11*11);
1076. 		    levl[zx][zy].doormask = D_NODOOR;
1077. 		} else
1078. 		    levl[zx][zy].doormask = D_ISOPEN;
1079. 		unblock_point(zx, zy);
1080. 		newsym(zx, zy);
1081. 		(*(int*)num)++;
1082. 	} else if(levl[zx][zy].typ == SCORR) {
1083. 		levl[zx][zy].typ = CORR;
1084. 		unblock_point(zx, zy);
1085. 		newsym(zx, zy);
1086. 		(*(int*)num)++;
1087. 	} else if ((ttmp = t_at(zx, zy)) != 0) {
1088. 		if (!ttmp->tseen && ttmp->ttyp != STATUE_TRAP) {
1089. 		    ttmp->tseen = 1;
1090. 		    newsym(zx,zy);
1091. 		    (*(int*)num)++;
1092. 		}
1093. 	} else if (find_drawbridge(&zx, &zy)) {
1094. 		/* make sure it isn't an open drawbridge */
1095. 		open_drawbridge(zx, zy);
1096. 		(*(int*)num)++;
1097. 	}
1098. }
1099. 

findit

1100. int
1101. findit()	/* returns number of things found */
1102. {
1103. 	int num = 0;
1104. 
1105. 	if(u.uswallow) return(0);
1106. 	do_clear_area(u.ux, u.uy, BOLT_LIM, findone, (genericptr_t) &num);
1107. 	return(num);
1108. }
1109. 

openit

1110. int
1111. openit()	/* returns number of things found and opened */
1112. {
1113. 	int num = 0;
1114. 
1115. 	if(u.uswallow) {
1116. 		if (is_animal(u.ustuck->data)) {
1117. 			if (Blind) pline("Its mouth opens!");
1118. 			else pline("%s opens its mouth!", Monnam(u.ustuck));
1119. 		}
1120. 		expels(u.ustuck, u.ustuck->data, TRUE);
1121. 		return(-1);
1122. 	}
1123. 
1124. 	do_clear_area(u.ux, u.uy, BOLT_LIM, openone, (genericptr_t) &num);
1125. 	return(num);
1126. }
1127. 

find_trap

1128. void
1129. find_trap(trap)
1130. struct trap *trap;
1131. {
1132.     int tt = what_trap(trap->ttyp);
1133.     boolean cleared = FALSE;
1134. 
1135.     trap->tseen = 1;
1136.     exercise(A_WIS, TRUE);
1137.     if (Blind)
1138. 	feel_location(trap->tx, trap->ty);
1139.     else
1140. 	newsym(trap->tx, trap->ty);
1141. 
1142.     if (levl[trap->tx][trap->ty].glyph != trap_to_glyph(trap)) {
1143.     	/* There's too much clutter to see your find otherwise */
1144. 	cls();
1145. 	map_trap(trap, 1);
1146. 	display_self();
1147. 	cleared = TRUE;
1148.     }
1149. 
1150.     You("find %s.", an(defsyms[trap_to_defsym(tt)].explanation));
1151. 
1152.     if (cleared) {
1153. 	display_nhwindow(WIN_MAP, TRUE);	/* wait */
1154. 	docrt();
1155.     }
1156. }
1157. 

dosearch0

1158. int
1159. dosearch0(aflag)
1160. register int aflag;
1161. {
1162. #ifdef GCC_BUG
1163. /* some versions of gcc seriously muck up nested loops. if you get strange
1164.    crashes while searching in a version compiled with gcc, try putting
1165.    #define GCC_BUG in *conf.h (or adding -DGCC_BUG to CFLAGS in the
1166.    makefile).
1167.  */
1168. 	volatile xchar x, y;
1169. #else
1170. 	register xchar x, y;
1171. #endif
1172. 	register struct trap *trap;
1173. 	register struct monst *mtmp;
1174. 
1175. 	if(u.uswallow) {
1176. 		if (!aflag)
1177. 			pline("What are you looking for?  The exit?");
1178. 	} else {
1179. 	    int fund = (uwep && uwep->oartifact &&
1180. 		    spec_ability(uwep, SPFX_SEARCH)) ?
1181. 		    uwep->spe : 0;
1182. 	    if (ublindf && ublindf->otyp == LENSES && !Blind)
1183. 		    fund += 2; /* JDS: lenses help searching */
1184. 	    if (fund > 5) fund = 5;
1185. 	    for(x = u.ux-1; x < u.ux+2; x++)
1186. 	      for(y = u.uy-1; y < u.uy+2; y++) {
1187. 		if(!isok(x,y)) continue;
1188. 		if(x != u.ux || y != u.uy) {
1189. 		    if (Blind && !aflag) feel_location(x,y);
1190. 		    if(levl[x][y].typ == SDOOR) {
1191. 			if(rnl(7-fund)) continue;
1192. 			cvt_sdoor_to_door(&levl[x][y]);	/* .typ = DOOR */
1193. 			exercise(A_WIS, TRUE);
1194. 			nomul(0);
1195. 			if (Blind && !aflag)
1196. 			    feel_location(x,y);	/* make sure it shows up */
1197. 			else
1198. 			    newsym(x,y);
1199. 		    } else if(levl[x][y].typ == SCORR) {
1200. 			if(rnl(7-fund)) continue;
1201. 			levl[x][y].typ = CORR;
1202. 			unblock_point(x,y);	/* vision */
1203. 			exercise(A_WIS, TRUE);
1204. 			nomul(0);
1205. 			newsym(x,y);
1206. 		    } else {
1207. 		/* Be careful not to find anything in an SCORR or SDOOR */
1208. 			if((mtmp = m_at(x, y)) && !aflag) {
1209. 			    if(mtmp->m_ap_type) {
1210. 				seemimic(mtmp);
1211. 		find:		exercise(A_WIS, TRUE);
1212. 				if (!canspotmon(mtmp)) {
1213. 				    if (glyph_is_invisible(levl[x][y].glyph)) {
1214. 					/* found invisible monster in a square
1215. 					 * which already has an 'I' in it.
1216. 					 * Logically, this should still take
1217. 					 * time and lead to a return(1), but if
1218. 					 * we did that the player would keep
1219. 					 * finding the same monster every turn.
1220. 					 */
1221. 					continue;
1222. 				    } else {
1223. 					You_feel("an unseen monster!");
1224. 					map_invisible(x, y);
1225. 				    }
1226. 				} else if (!sensemon(mtmp))
1227. 				    You("find %s.", a_monnam(mtmp));
1228. 				return(1);
1229. 			    }
1230. 			    if(!canspotmon(mtmp)) {
1231. 				if (mtmp->mundetected &&
1232. 				   (is_hider(mtmp->data) || mtmp->data->mlet == S_EEL))
1233. 					mtmp->mundetected = 0;
1234. 				newsym(x,y);
1235. 				goto find;
1236. 			    }
1237. 			}
1238. 
1239. 			/* see if an invisible monster has moved--if Blind,
1240. 			 * feel_location() already did it
1241. 			 */
1242. 			if (!aflag && !mtmp && !Blind &&
1243. 				    glyph_is_invisible(levl[x][y].glyph)) {
1244. 			    unmap_object(x,y);
1245. 			    newsym(x,y);
1246. 			}
1247. 
1248. 			if ((trap = t_at(x,y)) && !trap->tseen && !rnl(8)) {
1249. 			    nomul(0);
1250. 
1251. 			    if (trap->ttyp == STATUE_TRAP) {
1252. 				if (activate_statue_trap(trap, x, y, FALSE))
1253. 				    exercise(A_WIS, TRUE);
1254. 				return(1);
1255. 			    } else {
1256. 				find_trap(trap);
1257. 			    }
1258. 			}
1259. 		    }
1260. 		}
1261. 	    }
1262. 	}
1263. 	return(1);
1264. }
1265. 

dosearch

1266. int
1267. dosearch()
1268. {
1269. 	return(dosearch0(0));
1270. }
1271. 

sokoban_detect

1272. /* Pre-map the sokoban levels */
1273. void
1274. sokoban_detect()
1275. {
1276. 	register int x, y;
1277. 	register struct trap *ttmp;
1278. 	register struct obj *obj;
1279. 
1280. 	/* Map the background and boulders */
1281. 	for (x = 1; x < COLNO; x++)
1282. 	    for (y = 0; y < ROWNO; y++) {
1283. 	    	levl[x][y].seenv = SVALL;
1284. 	    	levl[x][y].waslit = TRUE;
1285. 	    	map_background(x, y, 1);
1286. 	    	for (obj = level.objects[x][y]; obj; obj = obj->nexthere)
1287. 	    	    if (obj->otyp == BOULDER)
1288. 	    	    	map_object(obj, 1);
1289. 	    }
1290. 
1291. 	/* Map the traps */
1292. 	for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
1293. 	    ttmp->tseen = 1;
1294. 	    map_trap(ttmp, 1);
1295. 	}
1296. }
1297. 
1298. 
1299. /*detect.c*/