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. */
6 * Detection routines, including crystal ball, magic mapping, and search
13 extern boolean known
; /* from read.c */
15 STATIC_DCL
void do_dknown_of(struct obj
*);
16 STATIC_DCL boolean
check_map_spot(int,int,CHAR_P
,unsigned);
17 STATIC_DCL boolean
clear_stale_map(CHAR_P
,unsigned);
18 STATIC_DCL
void sense_trap(struct trap
*,XCHAR_P
,XCHAR_P
,int);
19 STATIC_DCL
void show_map_spot(int,int);
20 STATIC_DCL
void show_map_spotX(int,int);
21 STATIC_PTR
void findone(int,int,void *);
22 STATIC_PTR
void findoneX(int,int,void *);
23 STATIC_PTR
void openone(int,int,void *);
25 /* Recursively search obj for an object in class oclass and return 1st found */
31 register struct obj
* otmp
;
34 if (obj
->oclass
== oclass
) return obj
;
37 * Pills inside medical kits are specially handled (see apply.c).
38 * We don't want them to detect as food because then they will be
39 * shown as pink pills, which are something quite different. In
40 * practice the only other possible contents of medical kits are
41 * bandages and phials, neither of which is detectable by any
42 * means so we can simply avoid looking in medical kits.
44 if (Has_contents(obj
) && obj
->otyp
!= MEDICAL_KIT
) {
45 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
)
46 if (otmp
->oclass
== oclass
) return otmp
;
47 else if (Has_contents(otmp
) && otmp
->otyp
!= MEDICAL_KIT
&&
48 (temp
= o_in(otmp
, oclass
)))
51 return (struct obj
*) 0;
54 /* Recursively search obj for an object made of specified material and return 1st found */
56 o_material(obj
, material
)
60 register struct obj
* otmp
;
63 if (objects
[obj
->otyp
].oc_material
== material
) return obj
;
65 if (Has_contents(obj
)) {
66 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
)
67 if (objects
[otmp
->otyp
].oc_material
== material
) return otmp
;
68 else if (Has_contents(otmp
) && (temp
= o_material(otmp
, material
)))
71 return (struct obj
*) 0;
81 if (Has_contents(obj
)) {
82 for(otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
)
87 /* Check whether the location has an outdated object displayed on it. */
89 check_map_spot(x
, y
, oclass
, material
)
95 register struct obj
*otmp
;
96 register struct monst
*mtmp
;
98 glyph
= glyph_at(x
,y
);
99 if (glyph_is_object(glyph
)) {
100 /* there's some object shown here */
101 if (oclass
== ALL_CLASSES
) {
102 return((boolean
)( !(level
.objects
[x
][y
] || /* stale if nothing here */
103 ((mtmp
= m_at(x
,y
)) != 0 &&
110 if (material
&& objects
[glyph_to_obj(glyph
)].oc_material
== material
) {
111 /* the object shown here is of interest because material matches */
112 for (otmp
= level
.objects
[x
][y
]; otmp
; otmp
= otmp
->nexthere
)
113 if (o_material(otmp
, MT_GOLD
)) return FALSE
;
114 /* didn't find it; perhaps a monster is carrying it */
115 if ((mtmp
= m_at(x
,y
)) != 0) {
116 for (otmp
= mtmp
->minvent
; otmp
; otmp
= otmp
->nobj
)
117 if (o_material(otmp
, MT_GOLD
)) return FALSE
;
119 /* detection indicates removal of this object from the map */
122 if (oclass
&& objects
[glyph_to_obj(glyph
)].oc_class
== oclass
) {
123 /* the object shown here is of interest because its class matches */
124 for (otmp
= level
.objects
[x
][y
]; otmp
; otmp
= otmp
->nexthere
)
125 if (o_in(otmp
, oclass
)) return FALSE
;
126 /* didn't find it; perhaps a monster is carrying it */
128 if ((mtmp
= m_at(x
,y
)) != 0) {
129 if (oclass
== COIN_CLASS
&& mtmp
->mgold
)
131 else for (otmp
= mtmp
->minvent
; otmp
; otmp
= otmp
->nobj
)
132 if (o_in(otmp
, oclass
)) return FALSE
;
135 if ((mtmp
= m_at(x
,y
)) != 0) {
136 for (otmp
= mtmp
->minvent
; otmp
; otmp
= otmp
->nobj
)
137 if (o_in(otmp
, oclass
)) return FALSE
;
140 /* detection indicates removal of this object from the map */
149 When doing detection, remove stale data from the map display (corpses
150 rotted away, objects carried away by monsters, etc) so that it won't
151 reappear after the detection has completed. Return true if noticeable
155 clear_stale_map(oclass
, material
)
156 register char oclass
;
160 register boolean change_made
= FALSE
;
162 for (zx
= 1; zx
< COLNO
; zx
++)
163 for (zy
= 0; zy
< ROWNO
; zy
++)
164 if (check_map_spot(zx
, zy
, oclass
,material
)) {
165 unmap_object(zx
, zy
);
172 /* look for gold, on the floor or in monsters' possession */
175 register struct obj
*sobj
;
177 register struct obj
*obj
;
178 register struct monst
*mtmp
;
183 known
= stale
= clear_stale_map(COIN_CLASS
,
184 (unsigned)(sobj
->blessed
? MT_GOLD
: 0));
186 if (DetectionMethodsDontWork
) {
187 if (sobj
) strange_feeling(sobj
, "Huh.");
191 /* look for gold carried by monsters (might be in a container) */
192 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
193 if (DEADMONSTER(mtmp
)) continue; /* probably not needed in this case but... */
195 if (mtmp
->mgold
|| monsndx(mtmp
->data
) == PM_GOLD_GOLEM
) {
197 if (findgold(mtmp
->minvent
) || monsndx(mtmp
->data
) == PM_GOLD_GOLEM
) {
200 goto outgoldmap
; /* skip further searching */
201 } else for (obj
= mtmp
->minvent
; obj
; obj
= obj
->nobj
)
202 if (sobj
->blessed
&& o_material(obj
, MT_GOLD
)) {
205 } else if (o_in(obj
, COIN_CLASS
)) {
207 goto outgoldmap
; /* skip further searching */
211 /* look for gold objects */
212 for (obj
= fobj
; obj
; obj
= obj
->nobj
) {
213 if (sobj
->blessed
&& o_material(obj
, MT_GOLD
)) {
215 if (obj
->ox
!= u
.ux
|| obj
->oy
!= u
.uy
) goto outgoldmap
;
216 } else if (o_in(obj
, COIN_CLASS
)) {
218 if (obj
->ox
!= u
.ux
|| obj
->oy
!= u
.uy
) goto outgoldmap
;
223 /* no gold found on floor or monster's inventory.
224 adjust message if you have gold in your inventory */
227 if (youmonst
.data
== &mons
[PM_GOLD_GOLEM
]) {
228 sprintf(buf
, "You feel like a million %s!",
230 } else if (hidden_gold() ||
237 "You feel worried about your future financial situation.");
239 strcpy(buf
, "You feel materially poor.");
240 strange_feeling(sobj
, buf
);
244 /* only under me - no separate display required */
246 You("notice some gold between your %s.", makeplural(body_part(FOOT
)));
253 /* Discover gold locations. */
254 for (obj
= fobj
; obj
; obj
= obj
->nobj
) {
255 if (sobj
->blessed
&& (temp
= o_material(obj
, MT_GOLD
))) {
261 } else if ((temp
= o_in(obj
, COIN_CLASS
))) {
269 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
270 if (DEADMONSTER(mtmp
)) continue; /* probably overkill here */
272 if (mtmp
->mgold
|| monsndx(mtmp
->data
) == PM_GOLD_GOLEM
) {
274 if (findgold(mtmp
->minvent
) || monsndx(mtmp
->data
) == PM_GOLD_GOLEM
) {
278 gold
.otyp
= GOLD_PIECE
;
282 } else for (obj
= mtmp
->minvent
; obj
; obj
= obj
->nobj
)
283 if (sobj
->blessed
&& (temp
= o_material(obj
, MT_GOLD
))) {
288 } else if ((temp
= o_in(obj
, COIN_CLASS
))) {
297 You_feel("very greedy, and sense gold!");
298 exercise(A_WIS
, TRUE
);
299 display_nhwindow(WIN_MAP
, TRUE
);
302 if (Underwater
&& !Swimming
) under_water(2);
303 if (u
.uburied
) under_ground(2);
307 /* returns 1 if nothing was detected */
308 /* returns 0 if something was detected */
311 register struct obj
*sobj
;
313 register struct obj
*obj
;
314 register struct monst
*mtmp
;
315 register int ct
= 0, ctu
= 0;
316 boolean confused
= (Confusion
|| (sobj
&& sobj
->cursed
)), stale
;
317 char oclass
= confused
? POTION_CLASS
: FOOD_CLASS
;
318 const char *what
= confused
? something
: "food";
321 boolean stupiddetect
= (sobj
&& (sobj
->otyp
== SPE_DETECT_FOOD
));
322 boolean guaranteed
= (!sobj
|| (sobj
&& (sobj
->otyp
!= SPE_DETECT_FOOD
)) );
324 stale
= clear_stale_map(oclass
, 0);
326 if (DetectionMethodsDontWork
) {
327 if (sobj
) strange_feeling(sobj
, "Huh.");
331 for (obj
= fobj
; obj
; obj
= obj
->nobj
)
332 if (o_in(obj
, oclass
)) {
333 if (obj
->ox
== u
.ux
&& obj
->oy
== u
.uy
) ctu
++;
336 for (mtmp
= fmon
; mtmp
&& !ct
; mtmp
= mtmp
->nmon
) {
337 /* no DEADMONSTER(mtmp) check needed since dmons never have inventory */
338 for (obj
= mtmp
->minvent
; obj
; obj
= obj
->nobj
)
339 if (o_in(obj
, oclass
)) {
346 known
= stale
&& !confused
;
349 You("sense a lack of %s nearby.", what
);
350 if (sobj
&& sobj
->blessed
) {
351 if (!u
.urealedibility
) Your("%s starts to tingle.", body_part(NOSE
));
352 u
.urealedibility
+= 1;
356 sprintf(buf
, "Your %s twitches%s.", body_part(NOSE
),
357 (sobj
->blessed
&& !u
.urealedibility
) ? " then starts to tingle" : "");
358 if (sobj
->blessed
&& !u
.urealedibility
) {
359 boolean savebeginner
= flags
.beginner
; /* prevent non-delivery of */
360 flags
.beginner
= FALSE
; /* message */
361 strange_feeling(sobj
, buf
);
362 flags
.beginner
= savebeginner
;
363 u
.urealedibility
+= 1;
365 if (sobj
->blessed
) u
.urealedibility
+= 1;
366 strange_feeling(sobj
, buf
);
372 You("%s %s nearby.", sobj
? "smell" : "sense", what
);
373 if (sobj
&& sobj
->blessed
) {
374 if (!u
.urealedibility
) pline("Your %s starts to tingle.", body_part(NOSE
));
375 u
.urealedibility
+= 1;
382 for (obj
= fobj
; obj
; obj
= obj
->nobj
)
383 if ((temp
= o_in(obj
, oclass
)) != 0) {
388 if ( (guaranteed
|| rn2(2)) && !(stupiddetect
&& isok(temp
->ox
, temp
->oy
) && isok(u
.ux
, u
.uy
) && (dist2(u
.ux
, u
.uy
, temp
->ox
, temp
->oy
) > 1601) ) ) map_object(temp
, 1);
391 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
)
392 /* no DEADMONSTER(mtmp) check needed since dmons never have inventory */
393 for (obj
= mtmp
->minvent
; obj
; obj
= obj
->nobj
)
394 if ((temp
= o_in(obj
, oclass
)) != 0) {
398 if ( (guaranteed
|| rn2(2)) && !(stupiddetect
&& isok(temp
->ox
, temp
->oy
) && isok(u
.ux
, u
.uy
) && (dist2(u
.ux
, u
.uy
, temp
->ox
, temp
->oy
) > 1601) ) ) map_object(temp
,1);
399 break; /* skip rest of this monster's inventory */
404 Your("%s %s to tingle and you smell %s.", body_part(NOSE
),
405 u
.urealedibility
? "continues" : "starts", what
);
406 u
.urealedibility
+= 1;
408 Your("%s tingles and you smell %s.", body_part(NOSE
), what
);
410 else You("sense %s.", what
);
411 display_nhwindow(WIN_MAP
, TRUE
);
412 exercise(A_WIS
, TRUE
);
415 if (Underwater
&& !Swimming
) under_water(2);
416 if (u
.uburied
) under_ground(2);
422 * Used for scrolls, potions, spells, and crystal balls. Returns:
424 * 1 - nothing was detected
425 * 0 - something was detected
428 object_detect(detector
, class)
429 struct obj
*detector
; /* object doing the detecting */
430 int class; /* an object class, 0 for all */
434 int is_cursed
= (detector
&& detector
->cursed
);
435 int do_dknown
= (detector
&& (detector
->oclass
== POTION_CLASS
||
436 detector
->oclass
== SPBOOK_CLASS
||
437 detector
->oartifact
) &&
439 int guaranteed
= (detector
&& !(detector
->otyp
== SPE_DETECT_TREASURE
) && !(detector
->otyp
== SPE_RANDOM_DETECTION
) && !(detector
->otyp
== SPE_MAP_LEVEL
) && !(detector
->otyp
== SPE_MAGIC_MAPPING
));
440 boolean stupiddetect
= (detector
&& (detector
->otyp
== SPE_DETECT_TREASURE
|| detector
->otyp
== SPE_RANDOM_DETECTION
|| detector
->otyp
== SPE_MAGIC_MAPPING
));
441 int likely
= (detector
&& (detector
->otyp
== SPE_MAP_LEVEL
));
443 register struct obj
*obj
, *otmp
= (struct obj
*)0;
444 register struct monst
*mtmp
;
446 int sym
, boulder
= 0;
448 if (DetectionMethodsDontWork
) {
449 if (detector
) strange_feeling(detector
, "Huh.");
453 if (class < 0 || class >= MAXOCLASSES
) {
454 impossible("object_detect: illegal class %d", class);
458 /* Special boulder symbol check - does the class symbol happen
459 * to match iflags.bouldersym which is a user-defined?
460 * If so, that means we aren't sure what they really wanted to
461 * detect. Rather than trump anything, show both possibilities.
462 * We can exclude checking the buried obj chain for boulders below.
464 sym
= class ? def_oc_syms
[class] : 0;
465 if (sym
&& iflags
.bouldersym
&& sym
== iflags
.bouldersym
)
466 boulder
= ROCK_CLASS
;
468 if (Hallucination
|| (Confusion
&& class == SCROLL_CLASS
))
469 strcpy(stuff
, something
);
471 strcpy(stuff
, class ? oclass_names
[class] : "objects");
472 if (boulder
&& class != ROCK_CLASS
) strcat(stuff
, " and/or large stones");
474 if (do_dknown
) for(obj
= invent
; obj
; obj
= obj
->nobj
) {
475 if (guaranteed
|| (likely
&& rn2(2)) || !rn2(3)) do_dknown_of(obj
);
478 for (obj
= fobj
; obj
; obj
= obj
->nobj
) {
479 if ((!class && !boulder
) || o_in(obj
, class) || o_in(obj
, boulder
)) {
480 if (obj
->ox
== u
.ux
&& obj
->oy
== u
.uy
) ctu
++;
483 if (do_dknown
&& (guaranteed
|| (likely
&& rn2(2)) || !rn2(3)) ) do_dknown_of(obj
);
486 for (obj
= level
.buriedobjlist
; obj
; obj
= obj
->nobj
) {
487 if (!class || o_in(obj
, class)) {
488 if (obj
->ox
== u
.ux
&& obj
->oy
== u
.uy
) ctu
++;
491 if (do_dknown
&& (guaranteed
|| (likely
&& rn2(2)) || !rn2(3)) ) do_dknown_of(obj
);
494 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
495 if (DEADMONSTER(mtmp
)) continue;
496 for (obj
= mtmp
->minvent
; obj
; obj
= obj
->nobj
) {
497 if ((!class && !boulder
) || o_in(obj
, class) || o_in(obj
, boulder
)) ct
++;
498 if (do_dknown
&& (guaranteed
|| (likely
&& rn2(2)) || !rn2(3)) ) do_dknown_of(obj
);
500 if ((is_cursed
&& mtmp
->m_ap_type
== M_AP_OBJECT
&&
501 (!class || class == objects
[mtmp
->mappearance
].oc_class
)) ||
503 (mtmp
->mgold
&& (!class || class == COIN_CLASS
))) {
505 (findgold(mtmp
->minvent
) && (!class || class == COIN_CLASS
))) {
512 if (!clear_stale_map(!class ? ALL_CLASSES
: class, 0) && !ct
) {
515 strange_feeling(detector
, "You feel a lack of something.");
519 You("sense %s nearby.", stuff
);
527 * Map all buried objects first.
529 for (obj
= level
.buriedobjlist
; obj
; obj
= obj
->nobj
)
530 if (!class || (otmp
= o_in(obj
, class))) {
536 if ((guaranteed
|| (likely
&& rn2(2)) || !rn2(3)) && !(stupiddetect
&& isok(obj
->ox
, obj
->oy
) && isok(u
.ux
, u
.uy
) && (dist2(u
.ux
, u
.uy
, obj
->ox
, obj
->oy
) > 1226) ) ) map_object(otmp
, 1);
538 if ((guaranteed
|| (likely
&& rn2(2)) || !rn2(3)) && !(stupiddetect
&& isok(obj
->ox
, obj
->oy
) && isok(u
.ux
, u
.uy
) && (dist2(u
.ux
, u
.uy
, obj
->ox
, obj
->oy
) > 1226) ) ) map_object(obj
, 1);
541 * If we are mapping all objects, map only the top object of a pile or
542 * the first object in a monster's inventory. Otherwise, go looking
543 * for a matching object class and display the first one encountered
546 * Objects on the floor override buried objects.
548 for (x
= 1; x
< COLNO
; x
++)
549 for (y
= 0; y
< ROWNO
; y
++)
550 for (obj
= level
.objects
[x
][y
]; obj
; obj
= obj
->nexthere
)
551 if ((!class && !boulder
) ||
552 (otmp
= o_in(obj
, class)) || (otmp
= o_in(obj
, boulder
))) {
553 if (class || boulder
) {
558 if ((guaranteed
|| (likely
&& rn2(2)) || !rn2(3)) && !(stupiddetect
&& isok(obj
->ox
, obj
->oy
) && isok(u
.ux
, u
.uy
) && (dist2(u
.ux
, u
.uy
, obj
->ox
, obj
->oy
) > 1226) ) ) map_object(otmp
, 1);
560 if ((guaranteed
|| (likely
&& rn2(2)) || !rn2(3)) && !(stupiddetect
&& isok(obj
->ox
, obj
->oy
) && isok(u
.ux
, u
.uy
) && (dist2(u
.ux
, u
.uy
, obj
->ox
, obj
->oy
) > 1226) ) ) map_object(obj
, 1);
564 /* Objects in the monster's inventory override floor objects. */
565 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
566 if (DEADMONSTER(mtmp
)) continue;
567 for (obj
= mtmp
->minvent
; obj
; obj
= obj
->nobj
)
568 if ((!class && !boulder
) ||
569 (otmp
= o_in(obj
, class)) || (otmp
= o_in(obj
, boulder
))) {
570 if (!class && !boulder
) otmp
= obj
;
571 otmp
->ox
= mtmp
->mx
; /* at monster location */
573 if ((guaranteed
|| (likely
&& rn2(2)) || !rn2(3)) && !(stupiddetect
&& isok(obj
->ox
, obj
->oy
) && isok(u
.ux
, u
.uy
) && (dist2(u
.ux
, u
.uy
, obj
->ox
, obj
->oy
) > 1226) ) ) map_object(otmp
, 1);
576 /* Allow a mimic to override the detected objects it is carrying. */
577 if (is_cursed
&& mtmp
->m_ap_type
== M_AP_OBJECT
&&
578 (!class || class == objects
[mtmp
->mappearance
].oc_class
)) {
581 temp
.otyp
= mtmp
->mappearance
; /* needed for obj_to_glyph() */
584 temp
.corpsenm
= PM_TENGU
; /* if mimicing a corpse */
585 map_object(&temp
, 1);
587 } else if (mtmp
->mgold
&& (!class || class == COIN_CLASS
)) {
589 } else if (findgold(mtmp
->minvent
) && (!class || class == COIN_CLASS
)) {
593 gold
.otyp
= GOLD_PIECE
;
596 if ((guaranteed
|| (likely
&& rn2(2)) || !rn2(3)) && !(stupiddetect
&& isok(mtmp
->mx
, mtmp
->my
) && isok(u
.ux
, u
.uy
) && (dist2(u
.ux
, u
.uy
, mtmp
->mx
, mtmp
->my
) > 1226) ) ) map_object(&gold
, 1);
601 You("detect the %s of %s.", ct
? "presence" : "absence", stuff
);
602 display_nhwindow(WIN_MAP
, TRUE
);
604 * What are we going to do when the hero does an object detect while blind
605 * and the detected object covers a known pool?
607 docrt(); /* this will correctly reset vision */
610 if (Underwater
&& !Swimming
) under_water(2);
611 if (u
.uburied
) under_ground(2);
615 /* function by Amy: reveal "tileamount" random tiles on the current level */
617 displayrandomtiles(tileamount
)
622 if (tileamount
> 100000) tileamount
= 100000; /* sanity check */
624 if (tileamount
< 0) {
625 impossible("displayrandomtiles called with wrong argument %d?", tileamount
);
629 while (tileamount
> 0) {
635 if (isok(zx
, zy
)) show_map_spot(zx
, zy
);
637 pline("Part of the map has been revealed!");
641 * Used for artifact effects. Returns:
643 * 1 - nothing was detected
644 * 0 - something was detected
647 artifact_detect(detector
)
648 struct obj
*detector
; /* object doing the detecting */
652 int is_cursed
= (detector
&& detector
->cursed
);
653 int do_dknown
= (detector
&& (detector
->oclass
== POTION_CLASS
||
654 detector
->oclass
== SPBOOK_CLASS
||
655 detector
->oartifact
) &&
658 register struct obj
*obj
, *otmp
= (struct obj
*)0;
659 register struct monst
*mtmp
;
662 if (DetectionMethodsDontWork
) {
663 if (detector
) strange_feeling(detector
, "Huh.");
667 if (is_cursed
){ /* Possible false negative */
668 strange_feeling(detector
, "You feel a lack of something.");
673 strcpy(stuff
, something
);
675 strcpy(stuff
, "artifacts");
677 if (do_dknown
) for(obj
= invent
; obj
; obj
= obj
->nobj
) do_dknown_of(obj
);
679 for (obj
= fobj
; obj
; obj
= obj
->nobj
) {
680 if (obj
&& obj
->oartifact
) {
681 if (obj
->ox
!= u
.ux
|| obj
->oy
!= u
.uy
) ct
++;
683 if (do_dknown
) do_dknown_of(obj
);
686 for (obj
= level
.buriedobjlist
; obj
; obj
= obj
->nobj
) {
687 if (obj
&& obj
->oartifact
) {
688 if (obj
->ox
!= u
.ux
|| obj
->oy
!= u
.uy
) ct
++;
690 if (do_dknown
) do_dknown_of(obj
);
693 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
694 if (DEADMONSTER(mtmp
)) continue;
695 for (obj
= mtmp
->minvent
; obj
; obj
= obj
->nobj
) {
696 if (obj
&& obj
->oartifact
) ct
++;
697 if (do_dknown
) do_dknown_of(obj
);
701 if (!clear_stale_map(ALL_CLASSES
, 0) && !ct
) {
702 strange_feeling(detector
, "You feel a lack of something.");
710 * Map all buried objects first.
712 for (obj
= level
.buriedobjlist
; obj
; obj
= obj
->nobj
)
713 if (obj
&& obj
->oartifact
) {
717 * If we are mapping all objects, map only the top object of a pile or
718 * the first object in a monster's inventory. Otherwise, go looking
719 * for a matching object class and display the first one encountered
722 * Objects on the floor override buried objects.
724 for (x
= 1; x
< COLNO
; x
++)
725 for (y
= 0; y
< ROWNO
; y
++)
726 for (obj
= level
.objects
[x
][y
]; obj
; obj
= obj
->nexthere
)
727 if (obj
&& obj
->oartifact
) {
731 /* Objects in the monster's inventory override floor objects. */
732 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
733 if (DEADMONSTER(mtmp
)) continue;
734 for (obj
= mtmp
->minvent
; obj
; obj
= obj
->nobj
)
735 if (obj
&& obj
->oartifact
) {
742 You("detect the %s of %s.", ct
? "presence" : "absence", stuff
);
743 display_nhwindow(WIN_MAP
, TRUE
);
745 * What are we going to do when the hero does an object detect while blind
746 * and the detected object covers a known pool?
748 docrt(); /* this will correctly reset vision */
751 if (Underwater
&& !Swimming
) under_water(2);
752 if (u
.uburied
) under_ground(2);
761 int detectamount
= 0;
763 if (DetectionMethodsDontWork
) return;
765 for (zx
= 1; zx
< COLNO
; zx
++)
766 for (zy
= 0; zy
< ROWNO
; zy
++)
767 if (levl
[zx
][zy
].typ
== WATER
|| levl
[zx
][zy
].typ
== POOL
|| levl
[zx
][zy
].typ
== CRYSTALWATER
|| levl
[zx
][zy
].typ
== WATERTUNNEL
|| levl
[zx
][zy
].typ
== WELL
|| levl
[zx
][zy
].typ
== POISONEDWELL
|| levl
[zx
][zy
].typ
== RAINCLOUD
|| levl
[zx
][zy
].typ
== MOAT
|| levl
[zx
][zy
].typ
== FOUNTAIN
|| levl
[zx
][zy
].typ
== SINK
|| levl
[zx
][zy
].typ
== TOILET
) {
768 show_map_spot(zx
, zy
);
772 if (detectamount
) pline("You detect some water.");
773 else pline("This dungeon level does not seem watery at all.");
775 flush_screen(1); /* flush temp screen */
776 display_nhwindow(WIN_MAP
, TRUE
); /* wait */
782 water_detectX() /* for the spell, which is meant to be weaker than the scroll --Amy */
786 int detectamount
= 0;
788 if (DetectionMethodsDontWork
) return;
790 for (zx
= 1; zx
< COLNO
; zx
++)
791 for (zy
= 0; zy
< ROWNO
; zy
++)
792 if ((levl
[zx
][zy
].typ
== WATER
|| levl
[zx
][zy
].typ
== POOL
|| levl
[zx
][zy
].typ
== CRYSTALWATER
|| levl
[zx
][zy
].typ
== WATERTUNNEL
|| levl
[zx
][zy
].typ
== WELL
|| levl
[zx
][zy
].typ
== POISONEDWELL
|| levl
[zx
][zy
].typ
== RAINCLOUD
|| levl
[zx
][zy
].typ
== MOAT
|| levl
[zx
][zy
].typ
== FOUNTAIN
|| levl
[zx
][zy
].typ
== SINK
|| levl
[zx
][zy
].typ
== TOILET
) && rn2(2)) {
793 if (!(isok(zx
, zy
) && isok(u
.ux
, u
.uy
) && (dist2(u
.ux
, u
.uy
, zx
, zy
) > 901) ) ) show_map_spot(zx
, zy
);
797 if (detectamount
) pline("You detect some water.");
798 else pline("This dungeon level does not seem watery at all.");
800 flush_screen(1); /* flush temp screen */
801 display_nhwindow(WIN_MAP
, TRUE
); /* wait */
807 * Used by: crystal balls, potions, fountains
809 * Returns 1 if nothing was detected.
810 * Returns 0 if something was detected.
813 monster_detect(otmp
, mclass
)
814 register struct obj
*otmp
; /* detecting object (if any) */
815 int mclass
; /* monster class, 0 for all */
817 register struct monst
*mtmp
;
820 if (DetectionMethodsDontWork
) {
821 if (otmp
) strange_feeling(otmp
, "Huh.");
825 /* Note: This used to just check fmon for a non-zero value
826 * but in versions since 3.3.0 fmon can test TRUE due to the
827 * presence of dmons, so we have to find at least one
828 * with positive hit-points to know for sure.
830 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
)
831 if (!DEADMONSTER(mtmp
)) {
838 strange_feeling(otmp
, FunnyHallu
?
839 "You get the heebie jeebies." :
840 "You feel threatened.");
843 boolean woken
= FALSE
;
846 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
847 if (DEADMONSTER(mtmp
)) continue;
848 if (!mclass
|| mtmp
->data
->mlet
== mclass
||
849 (mtmp
->data
== &mons
[PM_LONG_WORM
] && mclass
== S_WORM_TAIL
))
850 if ((mtmp
->mx
> 0) && !(otmp
&& otmp
->oclass
== SPBOOK_CLASS
&& (mtmp
&& isok(u
.ux
, u
.uy
) && isok(mtmp
->mx
, mtmp
->my
) && (dist2(u
.ux
,u
.uy
,mtmp
->mx
,mtmp
->my
) > 101) ) ) && ( !(otmp
&& otmp
->oclass
== SPBOOK_CLASS
) || rn2(2) ) ) {
851 if (mclass
&& def_monsyms
[mclass
] == ' ')
852 show_glyph(mtmp
->mx
,mtmp
->my
,
853 detected_mon_to_glyph(mtmp
));
855 show_glyph(mtmp
->mx
,mtmp
->my
,mon_to_glyph(mtmp
));
856 /* don't be stingy - display entire worm */
857 if (mtmp
->data
== &mons
[PM_LONG_WORM
]) detect_wsegs(mtmp
,0);
859 if (otmp
&& otmp
->cursed
&&
860 (mtmp
->msleeping
|| !mtmp
->mcanmove
)) {
861 mtmp
->msleeping
= mtmp
->mfrozen
= mtmp
->masleep
= 0;
867 You("sense the presence of monsters.");
869 pline(FunnyHallu
? "They're after you! Now you know why you were always paranoid - they REALLY want to eat you alive!" : "Monsters sense the presence of you.");
870 display_nhwindow(WIN_MAP
, TRUE
);
872 if (Underwater
&& !Swimming
) under_water(2);
873 if (u
.uburied
) under_ground(2);
879 sense_trap(trap
, x
, y
, src_cursed
)
884 if (Hallucination
|| src_cursed
) {
885 struct obj obj
; /* fake object */
893 obj
.otyp
= (src_cursed
) ? GOLD_PIECE
: random_object();
894 obj
.corpsenm
= random_monster(); /* if otyp == CORPSE */
896 } else if (trap
&& !trap
->hiddentrap
) {
900 struct trap temp_trap
; /* fake trap */
903 temp_trap
.ttyp
= BEAR_TRAP
; /* some kind of trap */
904 map_trap(&temp_trap
,1);
909 /* the detections are pulled out so they can */
910 /* also be used in the crystal ball routine */
911 /* returns 1 if nothing was detected */
912 /* returns 0 if something was detected */
915 register struct obj
*sobj
;
916 /* sobj is null if crystal ball, *scroll if gold detection scroll */
918 register struct trap
*ttmp
;
919 register struct obj
*obj
;
922 boolean found
= FALSE
;
925 if (DetectionMethodsDontWork
) {
926 if (sobj
) strange_feeling(sobj
, "Huh.");
930 for (ttmp
= ftrap
; ttmp
; ttmp
= ttmp
->ntrap
) {
931 if (ttmp
->tx
!= u
.ux
|| ttmp
->ty
!= u
.uy
)
935 for (obj
= fobj
; obj
; obj
= obj
->nobj
) {
936 if ((obj
->otyp
==LARGE_BOX
|| obj
->otyp
==LEAD_BOX
|| obj
->otyp
==TOP_BOX
|| obj
->otyp
==TREASURE_CHEST
|| obj
->otyp
==LOOT_CHEST
|| obj
->otyp
==CHEST
|| obj
->otyp
==NANO_CHEST
|| obj
->otyp
==LARGE_BOX_OF_DIGESTION
|| obj
->otyp
==CHEST_OF_HOLDING
) && obj
->otrapped
) {
937 if (obj
->ox
!= u
.ux
|| obj
->oy
!= u
.uy
)
942 for (door
= 0; door
< doorindex
; door
++) {
945 if (levl
[x
][y
].doormask
& D_TRAPPED
) {
946 if (x
!= u
.ux
|| y
!= u
.uy
)
953 sprintf(buf
, "Your %s stop itching.", makeplural(body_part(TOE
)));
954 strange_feeling(sobj
,buf
);
957 /* traps exist, but only under me - no separate display required */
958 Your("%s itch.", makeplural(body_part(TOE
)));
963 /* nerf by Amy - only detect 50% of all traps, because trap detection is very powerful if you think about it... */
965 for (ttmp
= ftrap
; ttmp
; ttmp
= ttmp
->ntrap
)
966 if (rn2(2) && (ttmp
->trapdiff
< rnd(150)) && (!isfriday
|| (ttmp
->trapdiff
< rnd(150))) && (ttmp
->trapdiff
< rnd(150)) ) sense_trap(ttmp
, 0, 0, sobj
&& sobj
->cursed
);
968 for (obj
= fobj
; obj
; obj
= obj
->nobj
)
969 if ((obj
->otyp
==LARGE_BOX
|| obj
->otyp
==LEAD_BOX
|| obj
->otyp
==TOP_BOX
|| obj
->otyp
==TREASURE_CHEST
|| obj
->otyp
==LOOT_CHEST
|| obj
->otyp
==CHEST
|| obj
->otyp
==NANO_CHEST
|| obj
->otyp
==LARGE_BOX_OF_DIGESTION
|| obj
->otyp
==CHEST_OF_HOLDING
) && obj
->otrapped
)
970 if (rn2(2)) sense_trap((struct trap
*)0, obj
->ox
, obj
->oy
, sobj
&& sobj
->cursed
);
972 for (door
= 0; door
< doorindex
; door
++) {
975 if (levl
[x
][y
].doormask
& D_TRAPPED
)
976 if (rn2(2)) sense_trap((struct trap
*)0, x
, y
, sobj
&& sobj
->cursed
);
980 You_feel("%s.", sobj
&& sobj
->cursed
? "very greedy" : "entrapped");
981 display_nhwindow(WIN_MAP
, TRUE
);
984 if (Underwater
&& !Swimming
) under_water(2);
985 if (u
.uburied
) under_ground(2);
989 /* weaker trap detection, from spell; currently only the entrapping spell uses this --Amy */
992 register struct obj
*sobj
;
993 /* sobj is null if crystal ball, *scroll if gold detection scroll */
995 register struct trap
*ttmp
;
996 register struct obj
*obj
;
999 boolean found
= FALSE
;
1002 if (DetectionMethodsDontWork
) {
1003 if (sobj
) strange_feeling(sobj
, "Huh.");
1007 for (ttmp
= ftrap
; ttmp
; ttmp
= ttmp
->ntrap
) {
1008 if (ttmp
->tx
!= u
.ux
|| ttmp
->ty
!= u
.uy
)
1012 for (obj
= fobj
; obj
; obj
= obj
->nobj
) {
1013 if ((obj
->otyp
==LARGE_BOX
|| obj
->otyp
==LEAD_BOX
|| obj
->otyp
==TOP_BOX
|| obj
->otyp
==CHEST
|| obj
->otyp
==NANO_CHEST
|| obj
->otyp
==TREASURE_CHEST
|| obj
->otyp
==LOOT_CHEST
|| obj
->otyp
==LARGE_BOX_OF_DIGESTION
|| obj
->otyp
==CHEST_OF_HOLDING
) && obj
->otrapped
) {
1014 if (obj
->ox
!= u
.ux
|| obj
->oy
!= u
.uy
)
1019 for (door
= 0; door
< doorindex
; door
++) {
1022 if (levl
[x
][y
].doormask
& D_TRAPPED
) {
1023 if (x
!= u
.ux
|| y
!= u
.uy
)
1030 sprintf(buf
, "Your %s stop itching.", makeplural(body_part(TOE
)));
1031 strange_feeling(sobj
,buf
);
1034 /* traps exist, but only under me - no separate display required */
1035 Your("%s itch.", makeplural(body_part(TOE
)));
1040 /* nerf by Amy - only detect 50% of all traps, because trap detection is very powerful if you think about it... */
1042 for (ttmp
= ftrap
; ttmp
; ttmp
= ttmp
->ntrap
)
1043 if (!rn2(4) && !(isok(ttmp
->tx
, ttmp
->ty
) && isok(u
.ux
, u
.uy
) && (dist2(u
.ux
, u
.uy
, ttmp
->tx
, ttmp
->ty
) > 401) ) && (ttmp
->trapdiff
< rnd(150)) && (!isfriday
|| (ttmp
->trapdiff
< rnd(150))) && (ttmp
->trapdiff
< rnd(150)) ) sense_trap(ttmp
, 0, 0, sobj
&& sobj
->cursed
);
1045 for (obj
= fobj
; obj
; obj
= obj
->nobj
)
1046 if ((obj
->otyp
==LARGE_BOX
|| obj
->otyp
==LEAD_BOX
|| obj
->otyp
==TOP_BOX
|| obj
->otyp
==CHEST
|| obj
->otyp
==NANO_CHEST
|| obj
->otyp
==TREASURE_CHEST
|| obj
->otyp
==LOOT_CHEST
|| obj
->otyp
==LARGE_BOX_OF_DIGESTION
|| obj
->otyp
==CHEST_OF_HOLDING
) && obj
->otrapped
)
1047 if (!rn2(4) && !(isok(obj
->ox
, obj
->oy
) && isok(u
.ux
, u
.uy
) && (dist2(u
.ux
, u
.uy
, obj
->ox
, obj
->oy
) > 401) ))
1048 sense_trap((struct trap
*)0, obj
->ox
, obj
->oy
, sobj
&& sobj
->cursed
);
1050 for (door
= 0; door
< doorindex
; door
++) {
1053 if (levl
[x
][y
].doormask
& D_TRAPPED
)
1054 if (!rn2(4) && !(isok(x
, y
) && isok(u
.ux
, u
.uy
) && (dist2(u
.ux
, u
.uy
, x
, y
) > 401) )) sense_trap((struct trap
*)0, x
, y
, sobj
&& sobj
->cursed
);
1058 You_feel("%s.", sobj
&& sobj
->cursed
? "very greedy" : "entrapped");
1059 display_nhwindow(WIN_MAP
, TRUE
);
1062 if (Underwater
&& !Swimming
) under_water(2);
1063 if (u
.uburied
) under_ground(2);
1068 level_distance(where
)
1071 register schar ll
= depth(&u
.uz
) - depth(where
);
1072 register boolean indun
= (u
.uz
.dnum
== where
->dnum
);
1075 if (ll
< (-8 - rn2(3))) {
1076 if (!indun
) return "far away";
1077 else return "far below";
1080 if (!indun
) return "away below you";
1081 else return "below you";
1084 if (!indun
) return "in the distance";
1085 else return "just below";
1086 } else if (ll
> 0) {
1087 if (ll
> (8 + rn2(3))) {
1088 if (!indun
) return "far away";
1089 else return "far above";
1092 if (!indun
) return "away above you";
1093 else return "above you";
1096 if (!indun
) return "in the distance";
1097 else return "just above";
1099 if (!indun
) return "in the distance";
1100 else return "near you";
1103 static const struct {
1106 } level_detects
[] = {
1107 { "Delphi", &oracle_level
},
1108 { "Medusa's lair", &medusa_level
},
1109 { "a castle", &stronghold_level
},
1110 { "the Wizard of Yendor's tower", &wiz1_level
},
1114 use_crystal_ball(obj
)
1121 pline("Too bad you can't see %s.", the(xname(obj
)));
1124 oops
= (rnd(20) > ACURR(A_INT
) || obj
->cursed
);
1125 if (oops
&& (obj
->spe
> 0)) {
1126 switch (rnd((obj
->oartifact
&& rn2(100)) ? 4 : 5)) {
1127 case 1 : pline("%s too much to comprehend!", Tobjnam(obj
, "are"));
1129 case 2 : pline("%s you!", Tobjnam(obj
, "confuse"));
1130 make_confused(HConfusion
+ rnd(50),FALSE
);
1132 case 3 : if (!resists_blnd(&youmonst
)) {
1133 pline("%s your vision!", Tobjnam(obj
, "damage"));
1134 make_blinded(Blinded
+ rnd(50),FALSE
);
1135 if (!Blind
) Your("%s", vision_clears
);
1137 pline("%s your vision.", Tobjnam(obj
, "assault"));
1138 You("are unaffected!");
1141 case 4 : pline("%s your mind!", Tobjnam(obj
, "zap"));
1142 (void) make_hallucinated(HHallucination
+ rnd(50),FALSE
,0L);
1144 case 5 : pline("%s!", Tobjnam(obj
, "explode"));
1146 obj
= 0; /* it's gone */
1147 losehp(rnd(30), "exploding crystal ball", KILLED_BY_AN
);
1151 if (obj
) consume_obj_charge(obj
, TRUE
);
1155 if (Hallucination
) {
1157 pline("All you see is funky %s haze.", hcolor((char *)0));
1160 case 1 : You("grok some groovy globs of incandescent lava.");
1162 case 2 : pline("Whoa! Psychedelic colors, %s!",
1163 poly_gender() == 1 ? "babe" : "dude");
1165 case 3 : pline_The("crystal pulses with sinister %s light!",
1168 case 4 : You("see goldfish swimming above fluorescent rocks.");
1170 case 5 : You("see tiny snowflakes spinning around a miniature farmhouse.");
1172 default: pline("Oh wow... like a kaleidoscope!");
1175 consume_obj_charge(obj
, TRUE
);
1180 /* read a single character */
1181 if (flags
.verbose
) You("may look for an object or monster symbol.");
1182 ch
= yn_function("What do you look for?", (char *)0, '\0');
1183 /* Don't filter out ' ' here; it has a use */
1184 if ((ch
!= def_monsyms
[S_GHOST
]) && index(quitchars
,ch
)) {
1185 if (flags
.verbose
) pline("%s", Never_mind
);
1186 if (FailureEffects
|| u
.uprops
[FAILURE_EFFECTS
].extrinsic
|| have_failurestone()) {
1187 pline("Oh wait, actually I do mind...");
1192 You("peer into %s...", the(xname(obj
)));
1193 nomul(-rnd(10), "gazing into a crystal ball", TRUE
);
1196 pline_The("vision is unclear.");
1201 makeknown(CRYSTAL_BALL
);
1202 consume_obj_charge(obj
, TRUE
);
1204 /* special case: accept ']' as synonym for mimic
1205 * we have to do this before the def_char_to_objclass check
1207 if (ch
== DEF_MIMIC_DEF
) ch
= DEF_MIMIC
;
1209 if ((class = def_char_to_objclass(ch
)) != MAXOCLASSES
)
1210 ret
= object_detect((struct obj
*)0, class);
1211 else if ((class = def_char_to_monclass(ch
)) != MAXMCLASSES
)
1212 ret
= monster_detect((struct obj
*)0, class);
1213 else if (iflags
.bouldersym
&& (ch
== iflags
.bouldersym
))
1214 ret
= object_detect((struct obj
*)0, ROCK_CLASS
);
1217 ret
= trap_detect((struct obj
*)0);
1221 int i
= rn2(SIZE(level_detects
));
1223 level_detects
[i
].what
,
1224 level_distance(level_detects
[i
].where
));
1231 if (!rn2(100)) /* make them nervous */
1232 You("see the Wizard of Yendor gazing out at you.");
1233 else pline_The("vision is unclear.");
1243 register struct rm
*lev
;
1245 if (Confusion
&& rn2(7)) return;
1247 if (isfriday
&& !rn2(10)) return;
1253 /* Secret corridors are found, but not secret doors. */
1254 if (lev
->typ
== SCORR
) {
1259 /* if we don't remember an object or trap there, map it */
1260 #ifdef DISPLAY_LAYERS
1261 if (!lev
->mem_obj
&& !lev
->mem_trap
) {
1263 if (lev
->typ
== ROOM
?
1264 (glyph_is_cmap(lev
->glyph
) && !glyph_is_trap(lev
->glyph
) &&
1265 glyph_to_cmap(lev
->glyph
) != ROOM
) :
1266 (!glyph_is_object(lev
->glyph
) && !glyph_is_trap(lev
->glyph
))) {
1268 if (level
.flags
.hero_memory
) {
1269 magic_map_background(x
,y
,0);
1270 newsym(x
,y
); /* show it, if not blocked */
1272 magic_map_background(x
,y
,1); /* display it */
1278 show_map_spotX(x
, y
)
1281 register struct rm
*lev
;
1283 if (rn2(10)) return;
1285 if (isfriday
&& !rn2(10)) return;
1291 /* Secret corridors are found, but not secret doors. */
1292 if (lev
->typ
== SCORR
) {
1297 /* if we don't remember an object or trap there, map it */
1298 #ifdef DISPLAY_LAYERS
1299 if (!lev
->mem_obj
&& !lev
->mem_trap
) {
1301 if (lev
->typ
== ROOM
?
1302 (glyph_is_cmap(lev
->glyph
) && !glyph_is_trap(lev
->glyph
) &&
1303 glyph_to_cmap(lev
->glyph
) != ROOM
) :
1304 (!glyph_is_object(lev
->glyph
) && !glyph_is_trap(lev
->glyph
))) {
1306 if (level
.flags
.hero_memory
) {
1307 magic_map_background(x
,y
,0);
1308 newsym(x
,y
); /* show it, if not blocked */
1310 magic_map_background(x
,y
,1); /* display it */
1318 register int zx
, zy
;
1319 int uw
= u
.uinwater
;
1321 if (DetectionMethodsDontWork
) return;
1324 for (zx
= 1; zx
< COLNO
; zx
++)
1325 for (zy
= 0; zy
< ROWNO
; zy
++)
1326 show_map_spot(zx
, zy
);
1327 exercise(A_WIS
, TRUE
);
1329 if (!level
.flags
.hero_memory
|| Underwater
) {
1330 flush_screen(1); /* flush temp screen */
1331 display_nhwindow(WIN_MAP
, TRUE
); /* wait */
1337 do_mappingX() /* magic mapping spell and roadmap cloak - they don't reveal as much info --Amy */
1339 register int zx
, zy
;
1340 int uw
= u
.uinwater
;
1342 if (DetectionMethodsDontWork
) return;
1345 for (zx
= 1; zx
< COLNO
; zx
++)
1346 for (zy
= 0; zy
< ROWNO
; zy
++)
1347 if (!(isok(zx
, zy
) && isok(u
.ux
, u
.uy
) && (dist2(u
.ux
, u
.uy
, zx
, zy
) > 626) ) ) show_map_spotX(zx
, zy
);
1348 exercise(A_WIS
, TRUE
);
1350 if (!level
.flags
.hero_memory
|| Underwater
) {
1351 flush_screen(1); /* flush temp screen */
1352 display_nhwindow(WIN_MAP
, TRUE
); /* wait */
1360 register int zx
, zy
;
1361 int uw
= u
.uinwater
;
1363 if (DetectionMethodsDontWork
) return;
1366 for (zx
= 1; zx
< COLNO
; zx
++)
1367 for (zy
= 0; zy
< ROWNO
; zy
++)
1368 if (rn2(10)) show_map_spot(zx
, zy
);
1369 exercise(A_WIS
, TRUE
);
1371 if (!level
.flags
.hero_memory
|| Underwater
) {
1372 flush_screen(1); /* flush temp screen */
1373 display_nhwindow(WIN_MAP
, TRUE
); /* wait */
1381 register int zx
, zy
;
1382 int uw
= u
.uinwater
;
1384 if (DetectionMethodsDontWork
) return;
1387 for (zx
= 1; zx
< COLNO
; zx
++)
1388 for (zy
= 0; zy
< ROWNO
; zy
++)
1389 if (rn2(2)) show_map_spot(zx
, zy
);
1390 exercise(A_WIS
, TRUE
);
1392 if (!level
.flags
.hero_memory
|| Underwater
) {
1393 flush_screen(1); /* flush temp screen */
1394 display_nhwindow(WIN_MAP
, TRUE
); /* wait */
1403 if (DetectionMethodsDontWork
) return;
1404 if (level
.flags
.nommap
) {
1405 pline("Something blocks your clairvoyance!");
1409 register int zx
, zy
;
1410 int lo_y
= (u
.uy
-6 < 0 ? 0 : u
.uy
-6),
1411 hi_y
= (u
.uy
+7 > ROWNO
? ROWNO
: u
.uy
+7),
1412 lo_x
= (u
.ux
-6 < 1 ? 1 : u
.ux
-6), /* avoid column 0 */
1413 hi_x
= (u
.ux
+7 > COLNO
? COLNO
: u
.ux
+7);
1415 for (zx
= lo_x
; zx
< hi_x
; zx
++)
1416 for (zy
= lo_y
; zy
< hi_y
; zy
++)
1417 show_map_spot(zx
, zy
);
1419 if (!level
.flags
.hero_memory
|| Underwater
) {
1420 flush_screen(1); /* flush temp screen */
1421 display_nhwindow(WIN_MAP
, TRUE
); /* wait */
1430 if (DetectionMethodsDontWork
) return;
1431 if (level
.flags
.nommap
) {
1432 pline("Something blocks your clairvoyance!");
1436 register int zx
, zy
;
1437 int lo_y
= (u
.uy
-4 < 0 ? 0 : u
.uy
-4),
1438 hi_y
= (u
.uy
+5 > ROWNO
? ROWNO
: u
.uy
+5),
1439 lo_x
= (u
.ux
-4 < 1 ? 1 : u
.ux
-4), /* avoid column 0 */
1440 hi_x
= (u
.ux
+5 > COLNO
? COLNO
: u
.ux
+5);
1442 for (zx
= lo_x
; zx
< hi_x
; zx
++)
1443 for (zy
= lo_y
; zy
< hi_y
; zy
++)
1444 if (!rn2(5)) show_map_spot(zx
, zy
);
1446 if (!level
.flags
.hero_memory
|| Underwater
) {
1447 flush_screen(1); /* flush temp screen */
1448 display_nhwindow(WIN_MAP
, TRUE
); /* wait */
1453 /* convert a secret door into a normal door */
1455 cvt_sdoor_to_door(lev
)
1458 int newmask
= lev
->doormask
& ~WM_MASK
;
1460 #ifdef REINCARNATION
1461 if (Is_rogue_level(&u
.uz
))
1462 /* rogue didn't have doors, only doorways */
1466 /* newly exposed door is closed */
1467 if (!(newmask
& D_LOCKED
)) newmask
|= D_CLOSED
;
1470 lev
->doormask
= newmask
;
1478 register struct trap
*ttmp
;
1479 register struct monst
*mtmp
;
1481 int trapfindchance
= 150;
1483 if (!(PlayerCannotUseSkills
)) {
1484 switch (P_SKILL(P_SEARCHING
)) {
1486 case P_BASIC
: trapfindchance
= 160; break;
1487 case P_SKILLED
: trapfindchance
= 170; break;
1488 case P_EXPERT
: trapfindchance
= 180; break;
1489 case P_MASTER
: trapfindchance
= 200; break;
1490 case P_GRAND_MASTER
: trapfindchance
= 225; break;
1491 case P_SUPREME_MASTER
: trapfindchance
= 250; break;
1495 trapfindchance
+= (boost_power_value() * 3);
1497 /* there should be at least some stat that makes it more likely to find a trap! --Amy */
1498 if (ACURR(A_WIS
) > 14) trapfindchance
+= (ACURR(A_WIS
) - 14);
1500 if(levl
[zx
][zy
].typ
== SDOOR
) {
1501 cvt_sdoor_to_door(&levl
[zx
][zy
]); /* .typ = DOOR */
1502 You("find a secret door!");
1503 u
.cnd_searchsecretcount
++;
1504 use_skill(P_SEARCHING
,1);
1505 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1506 magic_map_background(zx
, zy
, 0);
1509 } else if(levl
[zx
][zy
].typ
== SCORR
) {
1510 levl
[zx
][zy
].typ
= CORR
;
1511 unblock_point(zx
,zy
);
1512 You("find a secret passage!");
1513 u
.cnd_searchsecretcount
++;
1514 use_skill(P_SEARCHING
,1);
1515 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1516 magic_map_background(zx
, zy
, 0);
1519 } else if ((ttmp
= t_at(zx
, zy
)) != 0) {
1520 if(!ttmp
->tseen
&& !ttmp
->hiddentrap
&& (ttmp
->trapdiff
< rnd(trapfindchance
)) && (!isfriday
|| (ttmp
->trapdiff
< rnd(trapfindchance
))) && (ttmp
->trapdiff
< rnd(trapfindchance
)) && ttmp
->ttyp
!= STATUE_TRAP
&& ttmp
->ttyp
!= SATATUE_TRAP
) {
1522 if (!ttmp
->tdetected
&& !rn2(3)) {
1523 use_skill(P_SEARCHING
,1);
1524 ttmp
->tdetected
= TRUE
;
1531 } else if ((mtmp
= m_at(zx
, zy
)) != 0) {
1532 if(mtmp
->m_ap_type
) {
1536 if (mtmp
->mundetected
&&
1537 (is_hider(mtmp
->data
) || mtmp
->egotype_hide
|| mtmp
->egotype_mimic
|| mtmp
->data
->mlet
== S_EEL
)) {
1538 mtmp
->mundetected
= 0;
1542 if (!canspotmon(mtmp
) && !(mtmp
->data
->msound
== MS_DEEPSTATE
) && !(mtmp
->egotype_deepstatemember
) &&
1543 !memory_is_invisible(zx
, zy
))
1544 map_invisible(zx
, zy
);
1545 } else if (memory_is_invisible(zx
, zy
)) {
1546 unmap_object(zx
, zy
);
1557 register struct trap
*ttmp
;
1558 register struct monst
*mtmp
;
1560 int trapfindchance
= 150;
1562 if (!(PlayerCannotUseSkills
)) {
1563 switch (P_SKILL(P_SEARCHING
)) {
1565 case P_BASIC
: trapfindchance
= 160; break;
1566 case P_SKILLED
: trapfindchance
= 170; break;
1567 case P_EXPERT
: trapfindchance
= 180; break;
1568 case P_MASTER
: trapfindchance
= 200; break;
1569 case P_GRAND_MASTER
: trapfindchance
= 225; break;
1570 case P_SUPREME_MASTER
: trapfindchance
= 250; break;
1574 trapfindchance
+= (boost_power_value() * 3);
1576 /* there should be at least some stat that makes it more likely to find a trap! --Amy */
1577 if (ACURR(A_WIS
) > 14) trapfindchance
+= (ACURR(A_WIS
) - 14);
1579 if(!rn2(3) && levl
[zx
][zy
].typ
== SDOOR
) {
1580 cvt_sdoor_to_door(&levl
[zx
][zy
]); /* .typ = DOOR */
1581 You("find a secret door!");
1582 u
.cnd_searchsecretcount
++;
1583 use_skill(P_SEARCHING
,1);
1584 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1585 magic_map_background(zx
, zy
, 0);
1588 } else if(!rn2(3) && levl
[zx
][zy
].typ
== SCORR
) {
1589 levl
[zx
][zy
].typ
= CORR
;
1590 unblock_point(zx
,zy
);
1591 You("find a secret passage!");
1592 u
.cnd_searchsecretcount
++;
1593 use_skill(P_SEARCHING
,1);
1594 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1595 magic_map_background(zx
, zy
, 0);
1598 } else if (!rn2(3) && (ttmp
= t_at(zx
, zy
)) != 0) {
1599 if(!ttmp
->tseen
&& !ttmp
->hiddentrap
&& (ttmp
->trapdiff
< rnd(trapfindchance
)) && (!isfriday
|| (ttmp
->trapdiff
< rnd(trapfindchance
))) && (ttmp
->trapdiff
< rnd(trapfindchance
)) && ttmp
->ttyp
!= STATUE_TRAP
&& ttmp
->ttyp
!= SATATUE_TRAP
) {
1601 if (!ttmp
->tdetected
&& !rn2(3)) {
1602 use_skill(P_SEARCHING
,1);
1603 ttmp
->tdetected
= TRUE
;
1610 } else if (!rn2(3) && (mtmp
= m_at(zx
, zy
)) != 0) {
1611 if(mtmp
->m_ap_type
) {
1615 if (mtmp
->mundetected
&&
1616 (is_hider(mtmp
->data
) || mtmp
->egotype_hide
|| mtmp
->egotype_mimic
|| mtmp
->data
->mlet
== S_EEL
)) {
1617 mtmp
->mundetected
= 0;
1621 if (!canspotmon(mtmp
) && !(mtmp
->data
->msound
== MS_DEEPSTATE
) && !(mtmp
->egotype_deepstatemember
) &&
1622 !memory_is_invisible(zx
, zy
))
1623 map_invisible(zx
, zy
);
1624 } else if (memory_is_invisible(zx
, zy
)) {
1625 unmap_object(zx
, zy
);
1636 register struct trap
*ttmp
;
1637 register struct obj
*otmp
;
1639 if(OBJ_AT(zx
, zy
)) {
1640 for(otmp
= level
.objects
[zx
][zy
];
1641 otmp
; otmp
= otmp
->nexthere
) {
1642 if(Is_box(otmp
) && otmp
->olocked
) {
1647 /* let it fall to the next cases. could be on trap. */
1649 if(levl
[zx
][zy
].typ
== SDOOR
|| (levl
[zx
][zy
].typ
== DOOR
&&
1650 (levl
[zx
][zy
].doormask
& (D_CLOSED
|D_LOCKED
)))) {
1651 if(levl
[zx
][zy
].typ
== SDOOR
)
1652 cvt_sdoor_to_door(&levl
[zx
][zy
]); /* .typ = DOOR */
1653 if(levl
[zx
][zy
].doormask
& D_TRAPPED
) {
1654 if(distu(zx
, zy
) < 3) b_trapped("door", 0);
1655 else Norep("You %s an explosion!",
1656 cansee(zx
, zy
) ? "see" :
1657 (flags
.soundok
? "hear" :
1658 "feel the shock of"));
1659 wake_nearto(zx
, zy
, 11*11);
1660 levl
[zx
][zy
].doormask
= D_NODOOR
;
1662 levl
[zx
][zy
].doormask
= D_ISOPEN
;
1663 unblock_point(zx
, zy
);
1666 } else if(levl
[zx
][zy
].typ
== SCORR
) {
1667 levl
[zx
][zy
].typ
= CORR
;
1668 unblock_point(zx
, zy
);
1671 } else if ((ttmp
= t_at(zx
, zy
)) != 0) {
1672 if (!ttmp
->tseen
&& !ttmp
->hiddentrap
&& (ttmp
->trapdiff
< rnd(150)) && (!isfriday
|| (ttmp
->trapdiff
< rnd(150))) && (ttmp
->trapdiff
< rnd(150)) && ttmp
->ttyp
!= STATUE_TRAP
&& ttmp
->ttyp
!= SATATUE_TRAP
) {
1677 } else if (find_drawbridge(&zx
, &zy
)) {
1678 /* make sure it isn't an open drawbridge */
1679 open_drawbridge(zx
, zy
);
1685 findit() /* returns number of things found */
1689 if(u
.uswallow
) return(0);
1690 do_clear_area(u
.ux
, u
.uy
, BOLT_LIM
, findone
, (void *) &num
);
1695 finditX() /* returns number of things found */
1699 if(u
.uswallow
) return(0);
1700 do_clear_area(u
.ux
, u
.uy
, 4 + rn2(2), findoneX
, (void *) &num
);
1705 openit() /* returns number of things found and opened */
1710 if (is_animal(u
.ustuck
->data
)) {
1711 if (Blind
) pline("Its mouth opens!");
1712 else pline("%s opens its mouth!", Monnam(u
.ustuck
));
1714 expels(u
.ustuck
, u
.ustuck
->data
, TRUE
);
1718 do_clear_area(u
.ux
, u
.uy
, BOLT_LIM
, openone
, (void *) &num
);
1726 int tt
= what_trap(trap
->ttyp
);
1727 boolean cleared
= FALSE
;
1729 if (trap
->hiddentrap
) return;
1732 exercise(A_WIS
, TRUE
);
1734 feel_location(trap
->tx
, trap
->ty
);
1736 if (!Blind
) newsym(trap
->tx
, trap
->ty
);
1738 #ifdef DISPLAY_LAYERS
1739 if (levl
[trap
->tx
][trap
->ty
].mem_obj
||
1740 memory_is_invisible(trap
->tx
, trap
->ty
)) {
1742 if (levl
[trap
->tx
][trap
->ty
].glyph
!= trap_to_glyph(trap
)) {
1744 /* There's too much clutter to see your find otherwise */
1751 You("find %s.", an(defsyms
[trap_to_defsym(tt
)].explanation
));
1752 u
.cnd_searchtrapcount
++;
1753 if (!trap
->tdetected
) {
1754 mightbooststat(A_WIS
);
1755 use_skill(P_SEARCHING
,1);
1756 trap
->tdetected
= TRUE
;
1760 display_nhwindow(WIN_MAP
, TRUE
); /* wait */
1770 /* some versions of gcc seriously muck up nested loops. if you get strange
1771 crashes while searching in a version compiled with gcc, try putting
1772 #define GCC_BUG in *conf.h (or adding -DGCC_BUG to CFLAGS in the
1775 volatile xchar x
, y
;
1777 register xchar x
, y
;
1779 register struct trap
*trap
;
1780 register struct monst
*mtmp
;
1782 if (AntisearchEffect
|| u
.uprops
[ANTISEARCH_EFFECT
].extrinsic
|| have_unfindablestone() || autismweaponcheck(ART_HER_UNREACHABLE_BROOK
) ) return(1);
1784 int fundxtrachange
= 10;
1785 if (!(PlayerCannotUseSkills
)) {
1786 switch (P_SKILL(P_SEARCHING
)) {
1788 case P_BASIC
: fundxtrachange
= 8; break;
1789 case P_SKILLED
: fundxtrachange
= 6; break;
1790 case P_EXPERT
: fundxtrachange
= 5; break;
1791 case P_MASTER
: fundxtrachange
= 4; break;
1792 case P_GRAND_MASTER
: fundxtrachange
= 3; break;
1793 case P_SUPREME_MASTER
: fundxtrachange
= 2; break;
1797 int trapdiffbonus
= 0;
1798 if (!(PlayerCannotUseSkills
)) {
1799 switch (P_SKILL(P_SEARCHING
)) {
1801 case P_BASIC
: trapdiffbonus
= rnd(10); break;
1802 case P_SKILLED
: trapdiffbonus
= rnd(20); break;
1803 case P_EXPERT
: trapdiffbonus
= rnd(35); break;
1804 case P_MASTER
: trapdiffbonus
= rnd(50); break;
1805 case P_GRAND_MASTER
: trapdiffbonus
= rnd(75); break;
1806 case P_SUPREME_MASTER
: trapdiffbonus
= rnd(100); break;
1809 if (ublindf
&& ublindf
->otyp
== SHIELD_PATE_GLASSES
) trapdiffbonus
+= rnd(50);
1813 pline(FunnyHallu
? "There must be some door here, allowing you to get out..." : "What are you looking for? The exit?");
1815 int fund
= (uwep
&& uwep
->oartifact
&&
1816 spec_ability(uwep
, SPFX_SEARCH
)) ?
1818 if (ublindf
&& ublindf
->otyp
== LENSES
&& !Blind
)
1819 fund
+= 2; /* JDS: lenses help searching */
1820 if (ublindf
&& ublindf
->otyp
== RADIOGLASSES
&& !Blind
)
1822 if (ublindf
&& ublindf
->otyp
== SHIELD_PATE_GLASSES
&& !Blind
)
1824 if (ublindf
&& ublindf
->otyp
== BOSS_VISOR
&& !Blind
)
1826 if (uarmh
&& uarmh
->otyp
== HELM_OF_DISCOVERY
&& !Blind
)
1827 fund
+= 1; /* Amy: helm of discovery also helps a bit */
1828 if (fund
> 5) fund
= 5;
1829 for(x
= u
.ux
-1; x
< u
.ux
+2; x
++)
1830 for(y
= u
.uy
-1; y
< u
.uy
+2; y
++) {
1831 if(!isok(x
,y
)) continue;
1832 if(x
!= u
.ux
|| y
!= u
.uy
) {
1833 if (/*Blind &&*/ (!aflag
|| !rn2(fundxtrachange
) || !rn2(fundxtrachange
)) ) feel_location(x
,y
);
1834 if(levl
[x
][y
].typ
== SDOOR
) {
1835 if(rnl(7-fund
) && rn2(fundxtrachange
) && (rn2(fundxtrachange
) || !rn2(2)) ) continue; /* better chance --Amy */
1836 cvt_sdoor_to_door(&levl
[x
][y
]); /* .typ = DOOR */
1837 You("find a secret door!");
1838 u
.cnd_searchsecretcount
++;
1839 use_skill(P_SEARCHING
,1);
1840 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1841 exercise(A_WIS
, TRUE
);
1843 if (/*Blind && */(!aflag
|| !rn2(fundxtrachange
) || !rn2(fundxtrachange
)) )
1844 feel_location(x
,y
); /* make sure it shows up */
1846 if (!Blind
) newsym(x
,y
);
1847 } else if(levl
[x
][y
].typ
== SCORR
) {
1848 if(rnl(7-fund
) && rn2(fundxtrachange
) && (rn2(fundxtrachange
) || !rn2(2)) ) continue; /* better chance --Amy */
1849 levl
[x
][y
].typ
= CORR
;
1850 unblock_point(x
,y
); /* vision */
1851 You("find a secret passage!");
1852 u
.cnd_searchsecretcount
++;
1853 use_skill(P_SEARCHING
,1);
1854 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1855 exercise(A_WIS
, TRUE
);
1859 /* Be careful not to find anything in an SCORR or SDOOR */
1860 if((mtmp
= m_at(x
, y
)) && (!aflag
|| !rn2(4)) ) {
1861 if(mtmp
->m_ap_type
) {
1863 find
: exercise(A_WIS
, TRUE
);
1864 if (!canspotmon(mtmp
)) {
1865 if (memory_is_invisible(x
, y
)) {
1866 /* found invisible monster in a square
1867 * which already has an 'I' in it.
1868 * Logically, this should still take
1869 * time and lead to a return(1), but if
1870 * we did that the player would keep
1871 * finding the same monster every turn.
1875 You_feel("an unseen monster!");
1876 if (!(mtmp
->data
->msound
== MS_DEEPSTATE
) && !(mtmp
->egotype_deepstatemember
)) map_invisible(x
, y
);
1878 } else if (!sensemon(mtmp
))
1879 You("find %s.", a_monnam(mtmp
));
1881 /* No idea why finding a monster stops searching the other squares. Bullshit, I say! --Amy */
1883 if (!rn2(20)) pline("Komanda poiska neozhidanno ostanovilas' iz-za oshibki v ispolnyayemom fayle sovetskogo l'da. Potomu chto v Sovetskoy Rossii vy nikogda ne smozhete nayti material, dazhe yesli on nakhoditsya ryadom s vami, kha-kha.");
1888 if(!canspotmon(mtmp
)) {
1889 if (mtmp
->mundetected
&&
1890 (is_hider(mtmp
->data
) || mtmp
->egotype_hide
|| mtmp
->egotype_mimic
|| mtmp
->data
->mlet
== S_EEL
))
1891 mtmp
->mundetected
= 0;
1897 /* see if an invisible monster has moved--if Blind,
1898 * feel_location() already did it
1900 if ( (!aflag
|| !rn2(4)) && !mtmp
&& !Blind
&&
1901 memory_is_invisible(x
, y
)) {
1906 /* finding traps is much too hard. Let's increase the chance. --Amy */
1907 if ((trap
= t_at(x
,y
)) && !trap
->tseen
&& !trap
->hiddentrap
&& (trap
->trapdiff
< rn2(100 + trapdiffbonus
) ) && (!isfriday
|| (trap
->trapdiff
< rn2(100 + trapdiffbonus
)) ) && (trap
->trapdiff
< rn2(100 + trapdiffbonus
+ trapdiffbonus
) ) && (!rnl(8-fund
) || !rn2(fundxtrachange
) || (!rn2(fundxtrachange
) && !rn2(2)) ) ) {
1910 if (trap
->ttyp
== STATUE_TRAP
|| trap
->ttyp
== SATATUE_TRAP
) {
1911 mtmp
= activate_statue_trap(trap
, x
, y
, FALSE
);
1912 if (mtmp
!= (struct monst
*)0) {
1913 u
.cnd_searchtrapcount
++;
1914 exercise(A_WIS
, TRUE
);
1915 mightbooststat(A_WIS
);
1916 use_skill(P_SEARCHING
,1); /* you found a trap, so the skill should train --Amy */
1919 /* bah, so they made an extra bullshit return for statue traps... --Amy */
1921 if (!rn2(20)) pline("Komanda poiska neozhidanno ostanovilas' iz-za oshibki v ispolnyayemom fayle sovetskogo l'da. Potomu chto v Sovetskoy Rossii vy nikogda ne smozhete nayti material, dazhe yesli on nakhoditsya ryadom s vami, kha-kha.");
1935 /* Pre-map the sokoban levels */
1939 register int x
, y
, randa
, randb
, randc
; /* randomly hide some stuff from view because I'm mean :D --Amy */
1940 register struct trap
*ttmp
;
1941 register struct obj
*obj
;
1943 randa
= rn2(isfriday
? 8 : 20);
1944 randb
= rn2(isfriday
? 4 : 10);
1945 randc
= rn2(isfriday
? 4 : 10);
1947 /* if you're such a ch3at0r who intentionally picks races that also cause other level types to be generated,
1948 * and actually think you'd still fully benefit from levels all being pre-mapped, tough luck :-P --Amy */
1950 if (ismazewalker
) badluckor
++;
1951 if (isspecialist
) badluckor
++;
1953 if (badluckor
== 1) {
1954 if (!rn2(2)) randa
= FALSE
;
1955 if (!rn2(2)) randb
= FALSE
;
1956 if (!rn2(2)) randc
= FALSE
;
1958 if (badluckor
== 2) {
1959 if (rn2(3)) randa
= FALSE
;
1960 if (rn2(3)) randb
= FALSE
;
1961 if (rn2(3)) randc
= FALSE
;
1964 /* Map the background and boulders */
1965 for (x
= 1; x
< COLNO
; x
++)
1966 for (y
= 0; y
< ROWNO
; y
++) {
1969 levl
[x
][y
].seenv
= SVALL
;
1970 levl
[x
][y
].waslit
= TRUE
;
1971 map_background(x
, y
, 1);
1974 for (obj
= level
.objects
[x
][y
]; obj
; obj
= obj
->nexthere
)
1975 if ((obj
->otyp
== BOULDER
) && randb
)
1980 for (ttmp
= ftrap
; ttmp
; ttmp
= ttmp
->ntrap
) {
1982 /* but only holes and pits --Amy */
1983 if ((ttmp
->ttyp
== HOLE
|| ttmp
->ttyp
== PIT
) && randc
&& !ttmp
->hiddentrap
) {
1994 if (uwep
&& uwep
->oartifact
== ART_VILEA_S_SECRET
&& !rn2(20)) {
1996 register struct monst
*mtmp
;
1998 for(mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
1999 if (DEADMONSTER(mtmp
)) continue;
2000 if (distu(mtmp
->mx
,mtmp
->my
) > 50) continue;
2001 if(cansee(mtmp
->mx
,mtmp
->my
)) {
2002 if (!resist(mtmp
, SCROLL_CLASS
, 0, NOTELL
))
2003 monflee(mtmp
, rnd(10), FALSE
, FALSE
);
2009 if (uarmh
&& uarmh
->oartifact
== ART_TEN_MINUTES_COLDER
&& !rn2(2)) {
2012 if (u
.mh
> u
.mhmax
) u
.mh
= u
.mhmax
;
2015 if (u
.uhp
> u
.uhpmax
) u
.uhp
= u
.uhpmax
;
2020 if ((TarmuStrokingNora
|| u
.uprops
[TARMU_STROKING_NORA
].extrinsic
|| (uarmh
&& uarmh
->oartifact
== ART_STROKING_COMBAT
) || have_tarmustrokingnorastone()) && u
.tarmustrokingturn
< 1) {
2021 u
.tarmustrokingturn
= rnd(100);
2025 boolean canbeinawall
= FALSE
;
2026 if (!rn2(Passes_walls
? 5 : 25)) canbeinawall
= TRUE
;
2028 for (tryct
= 0; tryct
< 2000; tryct
++) {
2032 if (isok(x
, y
) && ((levl
[x
][y
].typ
> DBWALL
) || canbeinawall
) && !(t_at(x
, y
)) ) {
2033 (void) maketrap(x
, y
, rndtrap(), 100, FALSE
);
2040 return(dosearch0(0));