Blindfold removal fix
[slashemextended.git] / src / display.c
blob1277c5e9a3a8954cdfad41a7acdd85c8fe7be4f4
1 /* SCCS Id: @(#)display.c 3.4 2003/02/19 */
2 /* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */
3 /* and Dave Cohrs, 1990. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /*
7 * THE NEW DISPLAY CODE
9 * The old display code has been broken up into three parts: vision, display,
10 * and drawing. Vision decides what locations can and cannot be physically
11 * seen by the hero. Display decides _what_ is displayed at a given location.
12 * Drawing decides _how_ to draw a monster, fountain, sword, etc.
14 * The display system uses information from the vision system to decide
15 * what to draw at a given location. The routines for the vision system
16 * can be found in vision.c and vision.h. The routines for display can
17 * be found in this file (display.c) and display.h. The drawing routines
18 * are part of the window port. See doc/window.doc for the drawing
19 * interface.
21 * The display system deals with an abstraction called a glyph. Anything
22 * that could possibly be displayed has a unique glyph identifier.
24 * What is seen on the screen is a combination of what the hero remembers
25 * and what the hero currently sees. Objects and dungeon features (walls
26 * doors, etc) are remembered when out of sight. Monsters and temporary
27 * effects are not remembered. Each location on the level has an
28 * associated glyph. This is the hero's _memory_ of what he or she has
29 * seen there before.
31 * Display rules:
33 * If the location is in sight, display in order:
34 * visible (or sensed) monsters
35 * visible objects
36 * known traps
37 * background
39 * If the location is out of sight, display in order:
40 * sensed monsters (telepathy)
41 * memory
45 * Here is a list of the major routines in this file to be used externally:
47 * newsym
49 * Possibly update the screen location (x,y). This is the workhorse routine.
50 * It is always correct --- where correct means following the in-sight/out-
51 * of-sight rules. **Most of the code should use this routine.** This
52 * routine updates the map and displays monsters.
55 * map_background
56 * map_object
57 * map_trap
58 * map_invisible
59 * unmap_object
61 * If you absolutely must override the in-sight/out-of-sight rules, there
62 * are two possibilities. First, you can mess with vision to force the
63 * location in sight then use newsym(), or you can use the map_* routines.
64 * The first has not been tried [no need] and the second is used in the
65 * detect routines --- detect object, magic mapping, etc. The map_*
66 * routines *change* what the hero remembers. All changes made by these
67 * routines will be sticky --- they will survive screen redraws. Do *not*
68 * use these for things that only temporarily change the screen. These
69 * routines are also used directly by newsym(). unmap_object is used to
70 * clear a remembered object when/if detection reveals it isn't there.
73 * show_glyph
75 * This is direct (no processing in between) buffered access to the screen.
76 * Temporary screen effects are run through this and its companion,
77 * flush_screen(). There is yet a lower level routine, print_glyph(),
78 * but this is unbuffered and graphic dependent (i.e. it must be surrounded
79 * by graphic set-up and tear-down routines). Do not use print_glyph().
82 * see_monsters
83 * see_objects
84 * see_traps
86 * These are only used when something affects all of the monsters or
87 * objects or traps. For objects and traps, the only thing is hallucination.
88 * For monsters, there are hallucination and changing from/to blindness, etc.
91 * tmp_at
93 * This is a useful interface for displaying temporary items on the screen.
94 * Its interface is different than previously, so look at it carefully.
98 * Parts of the rm structure that are used:
100 * typ - What is really there.
101 * glyph - What the hero remembers. This will never be a monster.
102 * Monsters "float" above this.
103 * lit - True if the position is lit. An optimization for
104 * lit/unlit rooms.
105 * waslit - True if the position was *remembered* as lit.
106 * seenv - A vector of bits representing the directions from which the
107 * hero has seen this position. The vector's primary use is
108 * determining how walls are seen. E.g. a wall sometimes looks
109 * like stone on one side, but is seen as a wall from the other.
110 * Other uses are for unmapping detected objects and felt
111 * locations, where we need to know if the hero has ever
112 * seen the location.
113 * flags - Additional information for the typ field. Different for
114 * each typ.
115 * horizontal - Indicates whether the wall or door is horizontal or
116 * vertical.
118 #include "hack.h"
119 #include "region.h"
121 STATIC_DCL void display_monster(XCHAR_P,XCHAR_P,struct monst *,int,XCHAR_P);
122 STATIC_DCL void display_monsterX(XCHAR_P,XCHAR_P,struct monst *,int,XCHAR_P);
123 STATIC_DCL int swallow_to_glyph(int, int);
124 STATIC_DCL void display_warning(struct monst *);
125 STATIC_DCL void display_warningX(struct monst *);
127 STATIC_DCL int check_pos(int, int, int);
128 #ifdef WA_VERBOSE
129 STATIC_DCL boolean more_than_one(int, int, int, int, int);
130 #endif
131 STATIC_DCL int set_twall(int,int, int,int, int,int, int,int);
132 STATIC_DCL int set_wall(int, int, int);
133 STATIC_DCL int set_corn(int,int, int,int, int,int, int,int);
134 STATIC_DCL int set_crosswall(int, int);
135 STATIC_DCL void set_seenv(struct rm *, int, int, int, int);
136 STATIC_DCL void t_warn(struct rm *);
137 STATIC_DCL int wall_angle(struct rm *);
138 STATIC_DCL int back_to_cmap(XCHAR_P, XCHAR_P);
140 STATIC_VAR boolean transp; /* cached transparency flag for current tileset */
142 STATIC_DCL int randomglyph(void);
145 * vobj_at()
147 * Returns a pointer to an object if the hero can see an object at the
148 * given location. This takes care of invisible objects. NOTE, this
149 * assumes that the hero is not blind and on top of the object pile.
150 * It does NOT take into account that the location is out of sight, or,
151 * say, one can see blessed, etc.
153 struct obj *
154 vobj_at(x,y)
155 xchar x,y;
157 register struct obj *obj = level.objects[x][y];
159 while (obj) {
160 if ((!obj->oinvis || See_invisible) && !obj->oinvisreal) return obj;
161 obj = obj->nexthere;
163 return ((struct obj *) 0);
167 randomglyph()
169 switch (rnd(5)) {
171 case 1:
172 return cmap_to_glyph(rnd(S_grayglyph));
173 case 2:
174 return cmap_to_glyph((S_arrow_trap + rn2(S_timerun_trap + 1 - S_arrow_trap)));
175 case 3:
176 return (GLYPH_MON_OFF + rn2(NUMMONS));
177 case 4:
178 return (GLYPH_OBJ_OFF + rn2(NUM_OBJECTS));
179 case 5:
180 return (GLYPH_WARNING_OFF + rn2(WARNCOUNT));
183 return cmap_to_glyph(rnd(S_grayglyph)); /* "non-void function does not return a value in all control paths" */
187 * magic_map_background()
189 * This function is similar to map_background (see below) except we pay
190 * attention to and correct unexplored, lit ROOM and CORR spots.
192 void
193 magic_map_background(x, y, show)
194 xchar x,y;
195 int show;
197 int cmap = back_to_cmap(x,y); /* assumes hero can see x,y */
198 struct rm *lev = &levl[x][y];
201 * Correct for out of sight lit corridors and rooms that the hero
202 * doesn't remember as lit.
204 if (!cansee(x,y) && !lev->waslit) {
205 /* Floor spaces are dark if unlit. Corridors are dark if unlit. */
206 if (lev->typ == ROOM && cmap == S_room)
207 cmap = S_darkroom;
208 else if (lev->typ == CORR && cmap == S_litcorr)
209 cmap = S_corr;
211 if (level.flags.hero_memory)
212 #ifdef DISPLAY_LAYERS
213 lev->mem_bg = cmap;
214 #else
215 lev->glyph = cmap_to_glyph(cmap);
216 #endif
217 if (show || transp) show_glyph(x,y, cmap_to_glyph(cmap));
221 * The routines map_background(), map_object(), and map_trap() could just
222 * as easily be:
224 * map_glyph(x,y,glyph,show)
226 * Which is called with the xx_to_glyph() in the call. Then I can get
227 * rid of 3 routines that don't do very much anyway. And then stop
228 * having to create fake objects and traps. However, I am reluctant to
229 * make this change.
231 /* FIXME: some of these use xchars for x and y, and some use ints. Make
232 * this consistent.
236 * map_background()
238 * Make the real background part of our map. This routine assumes that
239 * the hero can physically see the location. Update the screen if directed.
241 void
242 map_background(x, y, show)
243 register xchar x,y;
244 register int show;
246 register int cmap = back_to_cmap(x,y);
248 if (level.flags.hero_memory)
249 #ifdef DISPLAY_LAYERS
250 levl[x][y].mem_bg = cmap;
251 #else
252 levl[x][y].glyph = cmap_to_glyph(cmap);
253 #endif
254 if (show || transp) show_glyph(x,y, cmap_to_glyph(cmap));
258 * map_trap()
260 * Map the trap and print it out if directed. This routine assumes that the
261 * hero can physically see the location.
263 void
264 map_trap(trap, show)
265 register struct trap *trap;
266 register int show;
268 register int x = trap->tx, y = trap->ty;
269 register int cmap = trap_to_cmap(trap);
271 if (level.flags.hero_memory)
272 #ifdef DISPLAY_LAYERS
273 levl[x][y].mem_trap = 1 + cmap - MAXDCHARS;
274 #else
275 levl[x][y].glyph = cmap_to_glyph(cmap);
276 #endif
279 if (show || transp) {
281 if (KnowledgeBug || u.uprops[KNOWLEDGE_BUG].extrinsic || have_trapknowledgestone()) show_glyph(x, y, cmap_to_glyph(S_grayglyph));
282 else show_glyph(x, y, cmap_to_glyph(cmap));
288 * map_object()
290 * Map the given object. This routine assumes that the hero can physically
291 * see the location of the object. Update the screen if directed.
293 void
294 map_object(obj, show)
295 register struct obj *obj;
296 register int show;
298 register int x = obj->ox, y = obj->oy;
299 register int glyph = obj_to_glyph(obj);
301 /*pline("object type %d",obj->otyp);*/
303 if (level.flags.hero_memory)
304 #ifdef DISPLAY_LAYERS
305 if ((levl[x][y].mem_corpse = glyph_is_body(glyph)))
306 levl[x][y].mem_obj = 1 + glyph_to_body(glyph);
307 else
308 levl[x][y].mem_obj = 1 + glyph_to_obj(glyph);
309 #else
310 levl[x][y].glyph = glyph;
311 #endif
313 if (show) show_glyph(x, y, glyph);
317 * map_invisible()
319 * Make the hero remember that a square contains an invisible monster.
320 * This is a special case in that the square will continue to be displayed
321 * this way even when the hero is close enough to see it. To get rid of
322 * this and display the square's actual contents, use unmap_object() followed
323 * by newsym() if necessary.
325 void
326 map_invisible(x, y)
327 register xchar x, y;
329 if (x != u.ux || y != u.uy) { /* don't display I at hero's location */
330 if (level.flags.hero_memory)
331 #ifdef DISPLAY_LAYERS
332 levl[x][y].mem_invis = 1;
333 #else
334 levl[x][y].glyph = GLYPH_INVISIBLE;
335 #endif
336 if (!(UnderlayerBug || u.uprops[UNDERLAYER_BUG].extrinsic || have_underlaidstone())) show_glyph(x, y, GLYPH_INVISIBLE);
340 void
341 map_invisibleX(x, y)
342 register xchar x, y;
344 if (x != u.ux || y != u.uy) { /* don't display I at hero's location */
345 if (level.flags.hero_memory)
346 #ifdef DISPLAY_LAYERS
347 levl[x][y].mem_invis = 1;
348 #else
349 levl[x][y].glyph = GLYPH_INVISIBLE;
350 #endif
351 if (!(UnderlayerBug || u.uprops[UNDERLAYER_BUG].extrinsic || have_underlaidstone())) show_glyphX(x, y, GLYPH_INVISIBLE);
356 * unmap_object()
358 * Remove something from the map when the hero realizes it's not there any
359 * more. Replace it with background or known trap, but not with any other
360 * If this is used for detection, a full screen update is imminent anyway;
361 * if this is used to get rid of an invisible monster notation, we might have
362 * to call newsym().
364 void
365 unmap_object(x, y)
366 register int x, y;
368 #ifndef DISPLAY_LAYERS
369 register struct trap *trap;
370 #endif
372 if (!level.flags.hero_memory) return;
374 #ifdef DISPLAY_LAYERS
375 levl[x][y].mem_invis = levl[x][y].mem_corpse = levl[x][y].mem_obj = 0;
376 #else
377 if ((trap = t_at(x,y)) != 0 && trap->tseen && !covers_traps(x,y))
378 map_trap(trap, 0);
379 else if (levl[x][y].seenv) {
380 struct rm *lev = &levl[x][y];
382 map_background(x, y, 0);
384 /* turn remembered dark room squares dark */
385 if (!lev->waslit && lev->glyph == cmap_to_glyph(S_room) &&
386 lev->typ == ROOM)
387 lev->glyph = cmap_to_glyph(S_darkroom);
388 } else
389 levl[x][y].glyph = cmap_to_glyph(S_stone); /* default val */
390 #endif
393 #define DETECTED 2
394 #define PHYSICALLY_SEEN 1
395 #define is_worm_tail(mon) ((mon) && ((x != (mon)->mx) || (y != (mon)->my)))
398 * map_location()
400 * Make whatever at this location show up. This is only for non-living
401 * things. This will not handle feeling invisible objects correctly.
403 * Internal to display.c, this is a #define for speed.
405 #ifdef DISPLAY_LAYERS
406 #define _map_location(x,y,show) \
408 register struct obj *obj; \
409 register struct trap *trap; \
412 if (level.flags.hero_memory) { \
413 if ((obj = vobj_at(x, y)) && !covers_objects(x, y)) \
414 map_object(obj, FALSE); \
415 else \
416 levl[x][y].mem_corpse = levl[x][y].mem_obj = 0; \
417 if ((trap = t_at(x, y)) && trap->tseen && !covers_traps(x, y)) \
418 map_trap(trap, FALSE); \
419 else \
420 levl[x][y].mem_trap = 0; \
421 map_background(x, y, FALSE); \
422 if (show) show_glyph(x, y, memory_glyph(x, y)); \
423 } else if ((obj = vobj_at(x,y)) && !covers_objects(x,y)) \
424 map_object(obj,show); \
425 else if ((trap = t_at(x,y)) && trap->tseen && !covers_traps(x,y)) \
426 map_trap(trap,show); \
427 else \
428 map_background(x,y,show); \
429 if (ManlerIsChasing && x == u.manlerx && y == u.manlery) { \
430 show_glyph(x, y, (GLYPH_MON_OFF + rn2(NUMMONS))); \
431 return; \
433 if ((Quaversal || u.uprops[QUAVERSAL].extrinsic || (uimplant && uimplant->oartifact == ART_ND_D___N_NDMNN_ND___NDMN_N) || have_quaversalstone() || autismweaponcheck(ART_OMGHAXERETH) ) && isok(u.ux, u.uy) && !isimportantlocation(x, y) && !(levl[u.ux][u.uy].wall_info & W_QUASAROK)) { \
434 show_glyph(x, y, cmap_to_glyph(S_stone)); \
435 return; \
437 if ((uarmh && itemhasappearance(uarmh, APP_HARDCORE_CLOTH)) && !facingtile(x, y)) { \
438 show_glyph(x, y, cmap_to_glyph(S_stone)); \
439 return; \
441 if (Race_if(PM_SLYER_ALIEN) && !facingtile(x, y)) { \
442 show_glyph(x, y, cmap_to_glyph(S_stone)); \
443 return; \
445 if (!u.seesilverspell && SpellColorSilver && !isimportantlocation(x, y)) { \
446 show_glyph(x, y, cmap_to_glyph(S_stone)); \
447 return; \
449 if ((GrayoutBug || u.uprops[GRAYOUT_BUG].extrinsic || have_grayoutstone() || (uarmc && uarmc->oartifact == ART_DOEDOEDOEDOEDOEDOEDOE_TEST) || autismweaponcheck(ART_PWNHAMMER) ) && grayoutobscuration() ) { \
450 show_glyph(x, y, cmap_to_glyph(S_grayglyph)); \
451 return; \
453 if ((GrayCenterBug || u.uprops[GRAY_CENTER_BUG].extrinsic || have_graycenterstone()) && distu(x, y) < (GrayCenterXtra ? 9 : 4) ) { \
454 show_glyph(x, y, cmap_to_glyph(S_grayglyph)); \
455 return; \
457 if ((CheckerboardBug || u.uprops[CHECKERBOARD_BUG].extrinsic || autismweaponcheck(ART_SAY__CHESS_) || have_checkerboardstone()) && ( ((x + y) % (CheckerboardXtra ? 4 : 2) ) != (moves % (CheckerboardXtra ? 4 : 2) ) ) ) { \
458 show_glyph(x, y, cmap_to_glyph(S_grayglyph)); \
459 return; \
461 if ( (QuasarVision || u.uprops[QUASAR_BUG].extrinsic || have_quasarstone() ) && !isimportantlocation(x, y) && !(levl[x][y].wall_info & W_QUASAROK) ) { \
462 show_glyph(x, y, cmap_to_glyph(S_stone)); \
463 return; \
465 if (Yawming && (distu(x,y) > yawm_distance())) { \
466 show_glyph(x, y, cmap_to_glyph(S_stone)); \
467 return; \
469 if (StupidMojibake && !rn2(MojibakeXtra ? 3 : 10)) { \
470 show_glyph(x, y, randomglyph() ); \
471 return; \
473 if (SpellColorBlue && !rn2(10)) { \
474 show_glyph(x, y, cmap_to_glyph(S_room)); \
475 return; \
477 if (SpellColorOrange && (distu(x,y) > 100)) { \
478 show_glyph(x, y, cmap_to_glyph(S_grayglyph)); \
479 return; \
481 if (SpellColorPlatinum && !rn2(10)) { \
482 show_glyph(x, y, cmap_to_glyph(S_bars)); \
483 return; \
485 if (SpellColorBrightCyan && cyanspellok(x,y)) { \
486 show_glyph(x, y, cmap_to_glyph(S_grayglyph)); \
487 return; \
489 if (FemtrapActiveNicole && nicolesquareok(x,y)) { \
490 show_glyph(x, y, cmap_to_glyph(S_stone)); \
491 return; \
493 if (SpellColorBrown && (distu(x,y) % 3 == 0)) { \
494 show_glyph(x, y, cmap_to_glyph(S_pile_of_shit)); \
495 return; \
498 #else /* DISPLAY_LAYERS */
499 #define _map_location(x,y,show) \
501 register struct obj *obj; \
502 register struct trap *trap; \
504 if ((obj = vobj_at(x,y)) && !covers_objects(x,y)) \
505 map_object(obj,show); \
506 else if ((trap = t_at(x,y)) && trap->tseen && !covers_traps(x,y)) \
507 map_trap(trap,show); \
508 else \
509 map_background(x,y,show); \
511 #endif /* DISPLAY_LAYERS */
513 void
514 map_location(x,y,show)
515 int x, y, show;
517 _map_location(x,y,show);
520 int memory_glyph(x, y)
521 int x, y;
523 #ifdef DISPLAY_LAYERS
525 if (ManlerIsChasing && x == u.manlerx && y == u.manlery) {
526 return (GLYPH_MON_OFF + rn2(NUMMONS));
529 if ((Quaversal || u.uprops[QUAVERSAL].extrinsic || (uimplant && uimplant->oartifact == ART_ND_D___N_NDMNN_ND___NDMN_N) || have_quaversalstone() || autismweaponcheck(ART_OMGHAXERETH) ) && isok(u.ux, u.uy) && !isimportantlocation(x, y) && !(levl[u.ux][u.uy].wall_info & W_QUASAROK)) {
530 return cmap_to_glyph(S_stone);
533 if ((uarmh && itemhasappearance(uarmh, APP_HARDCORE_CLOTH)) && !facingtile(x, y)) {
534 return cmap_to_glyph(S_stone);
537 if (Race_if(PM_SLYER_ALIEN) && !facingtile(x, y)) {
538 return cmap_to_glyph(S_stone);
541 if (!u.seesilverspell && SpellColorSilver && !isimportantlocation(x, y)) {
542 return cmap_to_glyph(S_stone);
545 if ((GrayoutBug || u.uprops[GRAYOUT_BUG].extrinsic || have_grayoutstone() || (uarmc && uarmc->oartifact == ART_DOEDOEDOEDOEDOEDOEDOE_TEST) || autismweaponcheck(ART_PWNHAMMER) ) && grayoutobscuration() ) {
546 return cmap_to_glyph(S_grayglyph);
549 if ((GrayCenterBug || u.uprops[GRAY_CENTER_BUG].extrinsic || have_graycenterstone()) && distu(x, y) < (GrayCenterXtra ? 9 : 4)) {
550 return cmap_to_glyph(S_grayglyph);
553 if ((CheckerboardBug || u.uprops[CHECKERBOARD_BUG].extrinsic || autismweaponcheck(ART_SAY__CHESS_) || have_checkerboardstone()) && ( ((x + y) % (CheckerboardXtra ? 4 : 2) ) != (moves % (CheckerboardXtra ? 4 : 2) ) ) ) {
554 return cmap_to_glyph(S_grayglyph);
557 if ( (QuasarVision || u.uprops[QUASAR_BUG].extrinsic || have_quasarstone() ) && !isimportantlocation(x, y) && !(levl[x][y].wall_info & W_QUASAROK) ) { return cmap_to_glyph(S_stone); }
559 if (Yawming && (distu(x,y) > yawm_distance())) { return cmap_to_glyph(S_stone); }
561 if (StupidMojibake && !rn2(MojibakeXtra ? 3 : 10)) {
562 return randomglyph();
565 if (SpellColorBlue && !rn2(10)) {
566 return cmap_to_glyph(S_room);
569 if (SpellColorOrange && (distu(x,y) > 100)) {
570 return cmap_to_glyph(S_grayglyph);
573 if (SpellColorPlatinum && !rn2(10)) {
574 return cmap_to_glyph(S_bars);
577 if (SpellColorBrightCyan && cyanspellok(x,y)) {
578 return cmap_to_glyph(S_grayglyph);
581 if (FemtrapActiveNicole && nicolesquareok(x,y)) {
582 return cmap_to_glyph(S_stone);
585 if (SpellColorBrown && (distu(x,y) % 3 == 0)) {
586 return cmap_to_glyph(S_pile_of_shit);
589 if (levl[x][y].mem_invis && !(UnderlayerBug || u.uprops[UNDERLAYER_BUG].extrinsic || have_underlaidstone()) )
590 return GLYPH_INVISIBLE;
591 else if (levl[x][y].mem_obj)
592 if (levl[x][y].mem_corpse)
593 return body_to_glyph(levl[x][y].mem_obj - 1);
594 else
595 return objnum_to_glyph(levl[x][y].mem_obj - 1);
596 else if (levl[x][y].mem_trap) {
598 if (KnowledgeBug || u.uprops[KNOWLEDGE_BUG].extrinsic || have_trapknowledgestone()) {
599 return cmap_to_glyph(S_grayglyph);
600 } else return cmap_to_glyph(levl[x][y].mem_trap - 1 + MAXDCHARS);
602 else
603 return cmap_to_glyph(levl[x][y].mem_bg);
604 #else
605 return levl[x][y].glyph;
606 #endif
609 void clear_memory_glyph(x, y, to)
610 int x, y, to;
612 #ifdef DISPLAY_LAYERS
613 levl[x][y].mem_bg = to;
614 levl[x][y].mem_trap = 0;
615 levl[x][y].mem_obj = 0;
616 levl[x][y].mem_corpse = 0;
617 levl[x][y].mem_invis = 0;
618 #else
619 levl[x][y].glyph = cmap_to_glyph(to);
620 #endif
624 * display_monster()
626 * Note that this is *not* a map_XXXX() function! Monsters sort of float
627 * above everything.
629 * Yuck. Display body parts by recognizing that the display position is
630 * not the same as the monster position. Currently the only body part is
631 * a worm tail.
634 STATIC_OVL void
635 display_monster(x, y, mon, sightflags, worm_tail)
636 register xchar x, y; /* display position */
637 register struct monst *mon; /* monster to display */
638 int sightflags; /* 1 if the monster is physically seen */
639 /* 2 if detected using Detect_monsters */
640 register xchar worm_tail; /* mon is actually a worm tail */
642 register boolean mon_mimic = (mon->m_ap_type != M_AP_NOTHING);
643 register int sensed = mon_mimic &&
644 ( (Protection_from_shape_changers && !permamimic(mon->data) && !(mon->egotype_permamimic) ) || sensemon(mon));
646 * We must do the mimic check first. If the mimic is mimicing something,
647 * and the location is in sight, we have to change the hero's memory
648 * so that when the position is out of sight, the hero remembers what
649 * the mimic was mimicing.
652 if (mon_mimic && (sightflags == PHYSICALLY_SEEN)) {
653 switch (mon->m_ap_type) {
654 default:
655 impossible("display_monster: bad m_ap_type value [ = %d ]",
656 (int) mon->m_ap_type);
657 case M_AP_NOTHING:
658 show_glyph(x, y, mon_to_glyph(mon));
659 break;
661 case M_AP_FURNITURE: {
663 * This is a poor man's version of map_background(). I can't
664 * use map_background() because we are overriding what is in
665 * the 'typ' field. Maybe have map_background()'s parameters
666 * be (x,y,glyph) instead of just (x,y).
668 * mappearance is currently set to an S_ index value in
669 * makemon.c.
671 register int glyph = cmap_to_glyph(mon->mappearance);
672 #ifdef DISPLAY_LAYERS
673 levl[x][y].mem_bg = mon->mappearance;
674 #else
675 levl[x][y].glyph = glyph;
676 #endif
677 if (!sensed) show_glyph(x,y, glyph);
678 break;
681 case M_AP_OBJECT: {
682 struct obj obj; /* Make a fake object to send */
683 /* to map_object(). */
684 obj.ox = x;
685 obj.oy = y;
686 obj.otyp = mon->mappearance;
687 obj.corpsenm = PM_TENGU; /* if mimicing a corpse */
688 map_object(&obj,!sensed);
689 break;
692 case M_AP_MONSTER:
693 show_glyph(x,y, monnum_to_glyph(what_mon((int)mon->mappearance)));
694 break;
699 /* If the mimic is unsucessfully mimicing something, display the monster */
700 if (!mon_mimic || sensed) {
701 int num;
703 if (StarlitBug || u.uprops[STARLIT_BUG].extrinsic || have_starlitskystone() || autismweaponcheck(ART_STARRING_INFERNO) || (uarmf && uarmf->oartifact == ART_STAR_SOLES) || (uimplant && uimplant->oartifact == ART_ARABELLA_S_SEXY_CHARM) || (uarmg && uarmg->oartifact == ART_RAAAAAAAARRRRRRGH) ) {
704 show_glyph(x,y,cmap_to_glyph(S_grayglyph));
705 return;
708 /* [ALI] Only use detected glyphs when monster wouldn't be
709 * visible by any other means.
711 if (sightflags == DETECTED) {
712 if (worm_tail)
713 num = detected_monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL));
714 else
715 num = detected_mon_to_glyph(mon);
716 } else if (mon->mtame && !Hallucination) {
717 if (worm_tail)
718 num = petnum_to_glyph(PM_LONG_WORM_TAIL);
719 else
720 num = pet_to_glyph(mon);
721 } else {
722 if (worm_tail)
723 num = monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL));
724 else
725 num = mon_to_glyph(mon);
727 show_glyph(x,y,num);
731 STATIC_OVL void
732 display_monsterX(x, y, mon, sightflags, worm_tail)
733 register xchar x, y; /* display position */
734 register struct monst *mon; /* monster to display */
735 int sightflags; /* 1 if the monster is physically seen */
736 /* 2 if detected using Detect_monsters */
737 register xchar worm_tail; /* mon is actually a worm tail */
739 register boolean mon_mimic = (mon->m_ap_type != M_AP_NOTHING);
740 register int sensed = mon_mimic &&
741 ( (Protection_from_shape_changers && !permamimic(mon->data) && !(mon->egotype_permamimic) ) || sensemon(mon));
743 * We must do the mimic check first. If the mimic is mimicing something,
744 * and the location is in sight, we have to change the hero's memory
745 * so that when the position is out of sight, the hero remembers what
746 * the mimic was mimicing.
749 if (mon_mimic && (sightflags == PHYSICALLY_SEEN)) {
750 switch (mon->m_ap_type) {
751 default:
752 impossible("display_monster: bad m_ap_type value [ = %d ]",
753 (int) mon->m_ap_type);
754 case M_AP_NOTHING:
755 show_glyphX(x, y, mon_to_glyph(mon));
756 break;
758 case M_AP_FURNITURE: {
760 * This is a poor man's version of map_background(). I can't
761 * use map_background() because we are overriding what is in
762 * the 'typ' field. Maybe have map_background()'s parameters
763 * be (x,y,glyph) instead of just (x,y).
765 * mappearance is currently set to an S_ index value in
766 * makemon.c.
768 register int glyph = cmap_to_glyph(mon->mappearance);
769 #ifdef DISPLAY_LAYERS
770 levl[x][y].mem_bg = mon->mappearance;
771 #else
772 levl[x][y].glyph = glyph;
773 #endif
774 if (!sensed) show_glyphX(x,y, glyph);
775 break;
778 case M_AP_OBJECT: {
779 struct obj obj; /* Make a fake object to send */
780 /* to map_object(). */
781 obj.ox = x;
782 obj.oy = y;
783 obj.otyp = mon->mappearance;
784 obj.corpsenm = PM_TENGU; /* if mimicing a corpse */
785 map_object(&obj,!sensed);
786 break;
789 case M_AP_MONSTER:
790 show_glyphX(x,y, monnum_to_glyph(what_mon((int)mon->mappearance)));
791 break;
796 /* If the mimic is unsucessfully mimicing something, display the monster */
797 if (!mon_mimic || sensed) {
798 int num;
800 if (StarlitBug || u.uprops[STARLIT_BUG].extrinsic || have_starlitskystone() || autismweaponcheck(ART_STARRING_INFERNO) || (uarmf && uarmf->oartifact == ART_STAR_SOLES) || (uimplant && uimplant->oartifact == ART_ARABELLA_S_SEXY_CHARM) || (uarmg && uarmg->oartifact == ART_RAAAAAAAARRRRRRGH) ) {
801 show_glyph(x,y,cmap_to_glyph(S_grayglyph));
802 return;
805 /* [ALI] Only use detected glyphs when monster wouldn't be
806 * visible by any other means.
808 if (sightflags == DETECTED) {
809 if (worm_tail)
810 num = detected_monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL));
811 else
812 num = detected_mon_to_glyph(mon);
813 } else if (mon->mtame && !Hallucination) {
814 if (worm_tail)
815 num = petnum_to_glyph(PM_LONG_WORM_TAIL);
816 else
817 num = pet_to_glyph(mon);
818 } else {
819 if (worm_tail)
820 num = monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL));
821 else
822 num = mon_to_glyph(mon);
824 show_glyphX(x,y,num);
828 * display_warning()
830 * This is also *not* a map_XXXX() function! Monster warnings float
831 * above everything just like monsters do, but only if the monster
832 * is not showing.
834 * Do not call for worm tails.
836 STATIC_OVL void
837 display_warning(mon)
838 register struct monst *mon;
840 int x = mon->mx, y = mon->my;
841 int wl = (int) (mon->m_lev / 6);
842 int glyph;
844 if (mon && (mon->data->msound == MS_DEEPSTATE)) return;
845 if (mon && mon->egotype_deepstatemember) return;
847 if (mon_warning(mon)) {
848 if (wl > WARNCOUNT - 1) wl = WARNCOUNT - 1;
849 /* 3.4.1: this really ought to be rn2(WARNCOUNT), but value "0"
850 isn't handled correctly by the what_is routine so avoid it
851 if (Hallucination) wl = rn1(WARNCOUNT-1,1);*/
852 if (Hallucination) wl = rn2(WARNCOUNT); /* seems the error was a 1 in pager.c where it's supposed to be a 0 --Amy */
853 glyph = warning_to_glyph(wl);
854 } else if (MATCH_WARN_OF_MON(mon)) {
855 glyph = mon_to_glyph(mon);
856 } else {
857 impossible("display_warning did not match warning type?");
858 return;
860 show_glyph(x, y, glyph);
863 STATIC_OVL void
864 display_warningX(mon)
865 register struct monst *mon;
867 int x = mon->mx, y = mon->my;
868 int wl = (int) (mon->m_lev / 6);
869 int glyph;
871 if (mon && (mon->data->msound == MS_DEEPSTATE)) return;
872 if (mon && mon->egotype_deepstatemember) return;
874 if (mon_warning(mon)) {
875 if (wl > WARNCOUNT - 1) wl = WARNCOUNT - 1;
876 /* 3.4.1: this really ought to be rn2(WARNCOUNT), but value "0"
877 isn't handled correctly by the what_is routine so avoid it
878 if (Hallucination) wl = rn1(WARNCOUNT-1,1);*/
879 if (Hallucination) wl = rn2(WARNCOUNT); /* seems the error was a 1 in pager.c where it's supposed to be a 0 --Amy */
880 glyph = warning_to_glyph(wl);
881 } else if (MATCH_WARN_OF_MON(mon)) {
882 glyph = mon_to_glyph(mon);
883 } else {
884 impossible("display_warning did not match warning type?");
885 return;
887 show_glyphX(x, y, glyph);
891 * feel_location()
893 * Feel the given location. This assumes that the hero is blind and that
894 * the given position is either the hero's or one of the eight squares
895 * adjacent to the hero (except for a boulder push).
897 void
898 feel_location(x, y)
899 xchar x, y;
901 struct rm *lev = &(levl[x][y]);
902 struct obj *boulder;
903 register struct monst *mon;
905 /* If the hero's memory of an invisible monster is accurate, we want to keep
906 * him from detecting the same monster over and over again on each turn.
907 * We must return (so we don't erase the monster). (We must also, in the
908 * search function, be sure to skip over previously detected 'I's.)
910 if (memory_is_invisible(x,y) && m_at(x,y)) return;
912 /* The hero can't feel non pool locations while under water. */
913 if (Underwater && !Swimming && !Is_waterlevel(&u.uz) && !is_waterypool(x,y) && !is_watertunnel(x,y) && !is_lava(x,y) && !is_shiftingsand(x,y) && !is_styxriver(x,y) )
914 return;
916 /* Set the seen vector as if the hero had seen it. It doesn't matter */
917 /* if the hero is levitating or not. */
918 set_seenv(lev, u.ux, u.uy, x, y);
920 if (Levitation && !Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) {
922 * Levitation Rules. It is assumed that the hero can feel the state
923 * of the walls around herself and can tell if she is in a corridor,
924 * room, or doorway. Boulders are felt because they are large enough.
925 * Anything else is unknown because the hero can't reach the ground.
926 * This makes things difficult.
928 * Check (and display) in order:
930 * + Stone, walls, and closed doors.
931 * + Boulders. [see a boulder before a doorway]
932 * + Doors.
933 * + Room/water positions
934 * + Everything else (hallways!)
936 if (IS_ROCK(lev->typ) || (IS_DOOR(lev->typ) &&
937 (lev->doormask & (D_LOCKED | D_CLOSED)))) {
938 map_background(x, y, 1);
939 } else if ((boulder = sobj_at(BOULDER,x,y)) != 0) {
940 map_object(boulder, 1);
941 } else if (IS_DOOR(lev->typ)) {
942 map_background(x, y, 1);
943 } else if (IS_ROOM(lev->typ) || IS_POOL(lev->typ)) {
945 * An open room or water location. Normally we wouldn't touch
946 * this, but we have to get rid of remembered boulder symbols.
947 * This will only occur in rare occations when the hero goes
948 * blind and doesn't find a boulder where expected (something
949 * came along and picked it up). We know that there is not a
950 * boulder at this location. Show fountains, pools, etc.
951 * underneath if already seen. Otherwise, show the appropriate
952 * floor symbol.
954 * Similarly, if the hero digs a hole in a wall or feels a location
955 * that used to contain an unseen monster. In these cases,
956 * there's no reason to assume anything was underneath, so
957 * just show the appropriate floor symbol. If something was
958 * embedded in the wall, the glyph will probably already
959 * reflect that. Don't change the symbol in this case.
961 * This isn't quite correct. If the boulder was on top of some
962 * other objects they should be seen once the boulder is removed.
963 * However, we have no way of knowing that what is there now
964 * was there then. So we let the hero have a lapse of memory.
965 * We could also just display what is currently on the top of the
966 * object stack (if anything).
968 if (remembered_object(x, y) == BOULDER) {
969 if (lev->typ != ROOM && lev->seenv) {
970 map_background(x, y, 1);
971 } else {
973 #ifdef DISPLAY_LAYERS
974 /*lev->mem_bg = lev->waslit ? S_room : S_stone;*/
975 lev->mem_bg = (!lev->waslit) ? S_darkroom : S_room;
976 #else
977 lev->glyph = (!lev->waslit) ? cmap_to_glyph(S_darkroom) : cmap_to_glyph(S_room);
978 /*lev->glyph = lev->waslit ? cmap_to_glyph(S_room) :
979 cmap_to_glyph(S_stone);*/
980 #endif
981 show_glyph(x, y, memory_glyph(x, y));
983 #ifdef DISPLAY_LAYERS
984 } else if ((lev->mem_bg >= S_stone && lev->mem_bg < S_darkroom) ||
985 memory_is_invisible(x, y)) {
986 lev->mem_bg = (!lev->waslit ? S_darkroom : S_room);
987 #else
988 } else if ((lev->glyph >= cmap_to_glyph(S_stone) &&
989 lev->glyph < cmap_to_glyph(S_darkroom)) ||
990 glyph_is_invisible(levl[x][y].glyph)) {
991 lev->glyph = (!cansee(x,y) && !lev->waslit) ? cmap_to_glyph(S_darkroom) :
992 cmap_to_glyph(S_room);
993 /*lev->glyph = lev->waslit ? cmap_to_glyph(S_room) :
994 cmap_to_glyph(S_stone);*/
995 #endif
996 show_glyph(x, y, memory_glyph(x, y));
998 } else {
999 /* We feel it (I think hallways are the only things left). */
1000 map_background(x, y, 1);
1001 /* Corridors are never felt as lit (unless remembered that way) */
1002 /* (lit_corridor only). */
1003 #ifdef DISPLAY_LAYERS
1004 if (lev->typ == CORR && lev->mem_bg == S_litcorr && !lev->waslit)
1005 show_glyph(x, y, cmap_to_glyph(lev->mem_bg = S_corr));
1006 #else
1007 if (lev->typ == CORR &&
1008 lev->glyph == cmap_to_glyph(S_litcorr) && !lev->waslit)
1009 show_glyph(x, y, lev->glyph = cmap_to_glyph(S_corr));
1010 #endif
1012 } else {
1013 _map_location(x, y, 1);
1015 if (Punished) {
1017 * A ball or chain is only felt if it is first on the object
1018 * location list. Otherwise, we need to clear the felt bit ---
1019 * something has been dropped on the ball/chain. If the bit is
1020 * not cleared, then when the ball/chain is moved it will drop
1021 * the wrong glyph.
1022 * Amy edit: there's the bug that the chain can be removed due to errors, in which case we don't want to try to
1023 * place it. In fact we should probably unpunish the player in that case and print an error message...
1025 if (uchain && uchain->ox == x && uchain->oy == y) {
1026 if (level.objects[x][y] == uchain)
1027 u.bc_felt |= BC_CHAIN;
1028 else
1029 u.bc_felt &= ~BC_CHAIN; /* do not feel the chain */
1031 if (!carried(uball) && uball->ox == x && uball->oy == y) {
1032 if (level.objects[x][y] == uball)
1033 u.bc_felt |= BC_BALL;
1034 else
1035 u.bc_felt &= ~BC_BALL; /* do not feel the ball */
1039 /* Floor spaces are dark if unlit. Corridors are dark if unlit. */
1040 #ifdef DISPLAY_LAYERS
1041 if (lev->typ == ROOM && lev->mem_bg == S_room && !lev->waslit) {
1042 lev->mem_bg = S_darkroom;
1043 show_glyph(x,y, memory_glyph(x, y));
1044 } else if (lev->typ == CORR &&
1045 lev->mem_bg == S_litcorr && !lev->waslit) {
1046 lev->mem_bg = S_corr;
1047 show_glyph(x,y, memory_glyph(x, y));
1049 #else
1050 if (lev->typ == ROOM &&
1051 lev->glyph == cmap_to_glyph(S_room) && !lev->waslit)
1052 show_glyph(x,y, lev->glyph = cmap_to_glyph(S_darkroom));
1053 else if (lev->typ == CORR &&
1054 lev->glyph == cmap_to_glyph(S_litcorr) && !lev->waslit)
1055 show_glyph(x,y, lev->glyph = cmap_to_glyph(S_corr));
1056 #endif
1058 /* draw monster on top if we can sense it */
1059 if ((x != u.ux || y != u.uy) && (mon = m_at(x,y)) && sensemon(mon))
1060 display_monster(x, y, mon,
1061 (tp_sensemon(mon) || MATCH_WARN_OF_MON(mon)) ? PHYSICALLY_SEEN : DETECTED,
1062 is_worm_tail(mon));
1066 * newsym()
1068 * Possibly put a new glyph at the given location.
1070 void
1071 newsym(x,y)
1072 register int x,y;
1074 register struct monst *mon;
1075 register struct rm *lev = &(levl[x][y]);
1076 register int see_it;
1077 register xchar worm_tail;
1079 if (in_mklev) return;
1081 if (program_state.done_hup)
1082 return;
1084 if (ManlerIsChasing && x == u.manlerx && y == u.manlery) {
1085 show_glyph(x, y, GLYPH_MON_OFF + rn2(NUMMONS));
1086 return;
1089 if ((Quaversal || u.uprops[QUAVERSAL].extrinsic || (uimplant && uimplant->oartifact == ART_ND_D___N_NDMNN_ND___NDMN_N) || have_quaversalstone() || autismweaponcheck(ART_OMGHAXERETH) ) && isok(u.ux, u.uy) && !isimportantlocation(x, y) && !(levl[u.ux][u.uy].wall_info & W_QUASAROK)) {
1090 show_glyph(x, y, cmap_to_glyph(S_stone));
1091 return;
1094 if ((uarmh && itemhasappearance(uarmh, APP_HARDCORE_CLOTH)) && !facingtile(x, y)) {
1095 show_glyph(x, y, cmap_to_glyph(S_stone));
1096 return;
1099 if (Race_if(PM_SLYER_ALIEN) && !facingtile(x, y)) {
1100 show_glyph(x, y, cmap_to_glyph(S_stone));
1101 return;
1104 if (!u.seesilverspell && SpellColorSilver && !isimportantlocation(x, y)) {
1105 show_glyph(x, y, cmap_to_glyph(S_stone));
1106 return;
1109 if ((GrayoutBug || u.uprops[GRAYOUT_BUG].extrinsic || have_grayoutstone() || (uarmc && uarmc->oartifact == ART_DOEDOEDOEDOEDOEDOEDOE_TEST) || autismweaponcheck(ART_PWNHAMMER) ) && grayoutobscuration() ) {
1110 show_glyph(x, y, cmap_to_glyph(S_grayglyph));
1111 return;
1114 if ((GrayCenterBug || u.uprops[GRAY_CENTER_BUG].extrinsic || have_graycenterstone()) && distu(x, y) < (GrayCenterXtra ? 9 : 4)) {
1115 show_glyph(x, y, cmap_to_glyph(S_grayglyph));
1116 return;
1119 if ((CheckerboardBug || u.uprops[CHECKERBOARD_BUG].extrinsic || autismweaponcheck(ART_SAY__CHESS_) || have_checkerboardstone()) && ( ((x + y) % (CheckerboardXtra ? 4 : 2) ) != (moves % (CheckerboardXtra ? 4 : 2) ) ) ) {
1120 show_glyph(x, y, cmap_to_glyph(S_grayglyph));
1121 return;
1124 if ( (QuasarVision || u.uprops[QUASAR_BUG].extrinsic || have_quasarstone() ) && !isimportantlocation(x, y) && !(levl[x][y].wall_info & W_QUASAROK) ) {
1125 show_glyph(x, y, cmap_to_glyph(S_stone));
1126 return;
1129 if (Yawming && (distu(x,y) > yawm_distance())) {
1130 show_glyph(x, y, cmap_to_glyph(S_stone));
1131 return;
1134 if (StupidMojibake && !rn2(MojibakeXtra ? 3 : 10)) {
1135 show_glyph(x, y, randomglyph());
1136 return;
1139 if (SpellColorBlue && !rn2(10)) {
1140 show_glyph(x, y, cmap_to_glyph(S_room));
1141 return;
1144 if (SpellColorOrange && (distu(x,y) > 100)) {
1145 show_glyph(x, y, cmap_to_glyph(S_grayglyph));
1146 return;
1149 if (SpellColorPlatinum && !rn2(10)) {
1150 show_glyph(x, y, cmap_to_glyph(S_bars));
1151 return;
1154 if (SpellColorBrightCyan && cyanspellok(x,y)) {
1155 show_glyph(x, y, cmap_to_glyph(S_grayglyph));
1156 return;
1159 if (FemtrapActiveNicole && nicolesquareok(x,y)) {
1160 show_glyph(x, y, cmap_to_glyph(S_stone));
1161 return;
1164 if (SpellColorBrown && (distu(x,y) % 3 == 0)) {
1165 show_glyph(x, y, cmap_to_glyph(S_pile_of_shit));
1166 return;
1169 if ( (Superscroller || (uarm && uarm->oartifact == ART_VOLUME_ARMAMENT) || (uarm && uarm->oartifact == ART_SPLINTER_ARMAMENT) || (uarm && uarm->oartifact == ART_TAPE_ARMAMENT) || (uarmc && uarmc->oartifact == ART_VEIL_OF_LATONA) || (uarmc && uarmc->oartifact == ART_VEIL_OF_MINISTRY) || u.uprops[SUPERSCROLLER_ACTIVE].extrinsic || have_superscrollerstone() ) && !isimportantlocation(x, y) && rn2(10) ) { show_glyph(x, y, cmap_to_glyph(S_stone)); return;}
1171 /* only permit updating the hero when swallowed */
1172 if (u.uswallow) {
1173 if (x == u.ux && y == u.uy) display_self();
1174 return;
1176 if (Underwater && !Swimming && !Is_waterlevel(&u.uz)) {
1177 /* don't do anything unless (x,y) is an adjacent underwater position */
1178 int dx, dy;
1179 if (!is_waterypool(x,y) && !is_watertunnel(x,y) && !is_lava(x,y) && !is_shiftingsand(x,y) && !is_styxriver(x,y)) return;
1180 dx = x - u.ux; if (dx < 0) dx = -dx;
1181 dy = y - u.uy; if (dy < 0) dy = -dy;
1182 if (dx > 1 || dy > 1) return;
1185 /* Can physically see the location. */
1186 if (cansee(x,y)) {
1187 NhRegion* reg = visible_region_at(x,y);
1189 * Don't use templit here: E.g.
1191 * lev->waslit = !!(lev->lit || templit(x,y));
1193 * Otherwise we have the "light pool" problem, where non-permanently
1194 * lit areas just out of sight stay remembered as lit. They should
1195 * re-darken.
1197 * Perhaps ALL areas should revert to their "unlit" look when
1198 * out of sight.
1200 lev->waslit = (lev->lit!=0); /* remember lit condition */
1202 if (reg != NULL && ACCESSIBLE(lev->typ)) {
1203 show_region(reg,x,y);
1204 return;
1206 if (x == u.ux && y == u.uy) {
1207 if (senseself()) {
1208 _map_location(x,y,0); /* map *under* self */
1209 display_self();
1210 } else
1211 /* we can see what is there */
1212 _map_location(x,y,1);
1214 else {
1215 mon = m_at(x,y);
1216 worm_tail = is_worm_tail(mon);
1217 see_it = mon && !(uarmh && uarmh->oartifact == ART_RADAR_NOT_WORKING && !mon_visible(mon) ) && !(isselfhybrid && (moves % 3 == 0) ) && (worm_tail
1218 ? ((!mon->minvis || (See_invisible && (StrongSee_invisible || mon->seeinvisble) ) ) && !mon->minvisreal)
1219 : (mon_visible(mon)) ||
1220 tp_sensemon(mon) ||
1221 MATCH_WARN_OF_MON(mon) ||
1222 (Role_if(PM_ACTIVISTOR) && mon->data == &mons[PM_TOPMODEL]) ||
1223 (Race_if(PM_PEACEMAKER) && mon->data == &mons[PM_TOPMODEL]) ||
1224 (Role_if(PM_ACTIVISTOR) && type_is_pname(mon->data) && uwep && is_quest_artifact(uwep) ) ||
1225 (uamul && uamul->otyp == AMULET_OF_POISON_WARNING && poisonous(mon->data) ) ||
1226 (uamul && uamul->otyp == AMULET_OF_OWN_RACE_WARNING && your_race(mon->data) ) ||
1227 (Role_if(PM_PALADIN) && is_demon(mon->data) ) ||
1228 (uarms && uarms->oartifact == ART_SHIELD_OF_THE_PALADIN && is_demon(mon->data) ) ||
1229 (uarms && uarms->oartifact == ART_SHIELD_OF_THE_CHEVALIER__W && is_demon(mon->data) ) ||
1230 (uarmc && uarmc->oartifact == ART_DEMONIC_UNDEAD_RADAR && is_demon(mon->data) ) ||
1231 (uwep && uwep->oartifact == ART_DAEDRA_SEEKER && mon->data->mlet == S_DEMON ) ||
1232 (Race_if(PM_VORTEX) && unsolid(mon->data) ) ||
1233 (Race_if(PM_VORTEX) && nolimbs(mon->data) ) ||
1234 (Race_if(PM_CORTEX) && unsolid(mon->data) ) ||
1235 (Race_if(PM_CORTEX) && nolimbs(mon->data) ) ||
1236 (uamul && uamul->otyp == AMULET_OF_COVETOUS_WARNING && (is_covetous(mon->data) || mon->egotype_covetous) ) ||
1237 (uarmh && uarmh->oartifact == ART_THAT_GIVES_IT_NOT && (is_covetous(mon->data) || mon->egotype_covetous) ) ||
1238 (uarmh && uarmh->oartifact == ART_HEARING_EAR && (is_covetous(mon->data) || mon->egotype_covetous) ) ||
1239 (ublindf && ublindf->otyp == BOSS_VISOR && (is_covetous(mon->data) || mon->egotype_covetous) ) ||
1240 (uarmf && uarmf->oartifact == ART_FINAL_EXAM_TIME && (mon->data->geno & G_UNIQ)) ||
1241 (Stunnopathy && Stunned && always_hostile(mon->data) && mon->stunnovisible && distu(mon->mx, mon->my) < (StrongStunnopathy ? 401 : 226) ) ||
1242 (uarm && uarm->oartifact == ART_JEFFERSON_S_LOOKAROUND && bigmonst(mon->data) && distu(mon->mx, mon->my) < 101) ||
1243 ( (uarmh && itemhasappearance(uarmh, APP_INTERNET_HELMET) ) && mon->internetvisible) ||
1244 (RngeInternetAccess && mon->internetvisible) ||
1245 (uarmh && uarmh->oartifact == ART_WEB_RADIO && mon->internetvisible) ||
1246 (Numbopathy && Numbed && (avoid_player(mon->data) || mon->egotype_avoider) && distu(mon->mx, mon->my) < (StrongNumbopathy ? 901 : 626) ) ||
1247 (Sickopathy && Sick && extra_nasty(mon->data) && distu(mon->mx, mon->my) < (StrongSickopathy ? 901 : 401) ) ||
1248 (Freezopathy && Frozen && mon->data->mcolor == CLR_WHITE && distu(mon->mx, mon->my) < (StrongFreezopathy ? 626 : 401) ) ||
1249 (StrongStunnopathy && Stunned && dmgtype(mon->data, AD_STUN)) ||
1250 (StrongNumbopathy && Numbed && (dmgtype(mon->data, AD_NUMB) || dmgtype(mon->data, AD_PLYS) ) ) ||
1251 (StrongDimmopathy && Dimmed && (dmgtype(mon->data, AD_DIMN) || mon->data->msound == MS_CUSS ) ) ||
1252 (StrongFreezopathy && Frozen && (dmgtype(mon->data, AD_FRZE) || dmgtype(mon->data, AD_ICEB) ) ) ||
1253 (StrongCorrosivity && Slimed && acidic(mon->data) && distu(mon->mx, mon->my) < 226 ) ||
1254 (StrongBurnopathy && Burned && (dmgtype(mon->data, AD_BURN) || dmgtype(mon->data, AD_FLAM) ) ) ||
1255 (uarm && uarm->oartifact == ART_RNG_CESSATION && (dmgtype(mon->data, AD_RBRE) || dmgtype(mon->data, AD_RNG) ) ) ||
1256 (StrongSickopathy && Sick && (dmgtype(mon->data, AD_DISE) || dmgtype(mon->data, AD_PEST) ) ) ||
1257 (uarmh && uarmh->otyp == HELM_OF_UNLIVING_ESP && mon->data->mlet == S_GOLEM && distu(mon->mx, mon->my) < 626) ||
1258 (uarmh && uarmh->otyp == HELM_OF_UNLIVING_ESP && mindless(mon->data) && distu(mon->mx, mon->my) < 26) ||
1259 (uarmf && uarmf->oartifact == ART_VERA_S_FREEZER && mon->data->mcolor == CLR_WHITE) ||
1260 (Burnopathy && Burned && infravision(mon->data) && distu(mon->mx, mon->my) < (StrongBurnopathy ? 170 : 101) ) ||
1261 (Dimmopathy && Dimmed && mon->m_lev > u.ulevel && distu(mon->mx, mon->my) < (StrongDimmopathy ? 226 : 101) ) ||
1262 (ScentView && distu(mon->mx, mon->my) < 101 && mon->scentvisible && (is_animal(mon->data) || mon->data->msound == MS_STENCH) ) ||
1263 (uwep && uwep->oartifact == ART_SWISS_AMY_KNIFE && mon->data->msound == MS_SHOE) ||
1264 (uwep && uwep->oartifact == ART_JENNY_S_PROTECTER && uwep->lamplit && mon->data->msound == MS_MOLEST) ||
1265 (EcholocationActive && distu(mon->mx, mon->my) < 626 && mon->echolocatevisible && (dmgtype(mon->data, AD_SOUN) || mon->data->msound == MS_SOUND || mon->data->msound == MS_SHRIEK || mon->data->msound == MS_FART_NORMAL || mon->data->msound == MS_FART_LOUD || mon->data->msound == MS_FART_QUIET ) ) ||
1266 (Race_if(PM_RODNEYAN) && mon_has_amulet(mon)) ||
1267 (Race_if(PM_RODNEYAN) && mon_has_special(mon)) ||
1268 (Race_if(PM_LEVITATOR) && (is_flyer(mon->data) || mon->egotype_flying) ) ||
1269 (isselfhybrid && strongmonst(mon->data) && is_wanderer(mon->data) ) ||
1270 (uarm && uarm->oartifact == ART_JOKE_S_OVER && is_jokemonster(mon->data) ) ||
1271 (have_maybrittclick() && is_jokemonster(mon->data) ) ||
1272 (uwep && uwep->oartifact == ART_TIGATOR_S_THORN && is_pokemon(mon->data) ) ||
1273 (haveartileash(ART_PETCAMERA) && mon->mleashed) ||
1274 (haveartileash(ART_ANNOYING_PET_MONITOR) && mon->mtame) ||
1275 (uarmc && uarmc->oartifact == ART_SITHE_DED && mon->data->mlet == S_MUMMY) ||
1276 (uarm && uarm->oartifact == ART_PATROL_S_ORDERS && (mon->data->mlet == S_ORC || mon->data->mlet == S_OGRE) ) ||
1277 (uarmh && uarmh->oartifact == ART_CLIERVOYENS && distu(mon->mx, mon->my) < 9 ) ||
1278 (uarm && uarm->oartifact == ART_PLAYER_RADAR && (is_mplayer(mon->data) || is_umplayer(mon->data)) ) ||
1279 (uarmf && uarmf->oartifact == ART_AWAY_YOU_STALKER && is_stalker(mon->data) ) ||
1280 (uarmf && uarmf->oartifact == ART_ELENETTES && (mon->mhp < (mon->mhpmax * 9 / 10)) ) ||
1281 (uarmh && itemhasappearance(uarmh, APP_SAGES_HELMET) && mon->minvis && mon->sagesvisible ) ||
1282 (ublindf && ublindf->oartifact == ART_BREATHER_SHOW && attacktype(mon->data, AT_BREA)) ||
1283 (uarmc && uarmc->oartifact == ART_POKEWALKER && is_pokemon(mon->data) ) ||
1284 (uarmc && uarmc->oartifact == ART_BUGNOSE && (mon->data->mlet == S_ANT || mon->data->mlet == S_XAN) ) ||
1285 (uamul && uamul->otyp == AMULET_OF_PET_VIEW && mon->mtame) ||
1286 (uarmu && uarmu->oartifact == ART_HEEEEELEEEEEN && mon->mtame) ||
1287 (uarmh && itemhasappearance(uarmh, APP_PETSENSE_HELMET) && mon->mtame) ||
1288 (uarmf && uarmf->oartifact == ART_SNAILHUNT && (mon->data->mlet == S_BLOB || mon->data->mlet == S_WORM) ) ||
1289 (uarmf && uarmf->oartifact == ART_CAMELIC_SCENT && (mon->data->mlet == S_ZOUTHERN || mon->data->mlet == S_YETI) ) ||
1290 (uwep && uwep->oartifact == ART_EGRID_BUG && mon->data->mlet == S_XAN) ||
1291 (uwep && uwep->oartifact == ART_FUYER_BREV && mon->data->mlet == S_FUNGUS) ||
1292 (uwep && uwep->oartifact == ART_SNICKERSNACK && mon->data->mlet == S_JABBERWOCK) ||
1293 (uarm && uarm->oartifact == ART_FUNGIRADAR && mon->data->mlet == S_FUNGUS) ||
1294 (uarmf && uarmf->oartifact == ART_BOOTS_OF_THE_MACHINE && (mon->data->mlet == S_GOLEM || nonliving(mon->data) ) ) ||
1295 (uarmf && uarmf->oartifact == ART_FD_DETH && (mon->data->mlet == S_DOG || mon->data->mlet == S_FELINE) ) ||
1296 (uarmh && uarmh->oartifact == ART_DOGGO_FRIENDSHIP && mon->data->mlet == S_DOG) ||
1297 (uarmg && uarmg->oartifact == ART_WHAT_S_UP_BITCHES && (mon->data->mlet == S_NYMPH) ) ||
1298 (uwep && uwep->oartifact == ART_FISHING_GRANDPA && mon->data->mlet == S_EEL) ||
1299 (uarmf && uarmf->oartifact == ART_PECTORAL_HEEL && distu(mon->mx, mon->my) < 101 && mon->data->mlet == S_EEL) ||
1300 (uwep && uwep->oartifact == ART_PEOPLE_EATING_TRIDENT && mon->data->mlet == S_HUMAN) ||
1301 (uwep && uwep->oartifact == ART_VAMPIREBANE && mon->data->mlet == S_VAMPIRE) ||
1302 (uwep && uwep->oartifact == ART_GOLEMBANE && mon->data->mlet == S_GOLEM) ||
1303 (uwep && uwep->oartifact == ART_EELBANE && mon->data->mlet == S_EEL) ||
1304 (uwep && uwep->oartifact == ART_MAUI_S_FISHHOOK && mon->data->mlet == S_EEL) ||
1305 (uarmf && uarmf->oartifact == ART_SUCH_A_LOVELY_SHARK && mon->data->mlet == S_EEL && mon->mpeaceful) ||
1306 (uwep && uwep->oartifact == ART_DEMONSTRANTS_GO_HOME && mon->data->mlet == S_HUMAN) ||
1307 (uarmu && uarmu->oartifact == ART_PEACE_ADVOCATE && mon->data->mlet == S_HUMAN) ||
1308 (uwep && uwep->oartifact == ART_DOCTOR_JONES__AID && mon->data->mlet == S_SNAKE) ||
1309 (uarmc && uarmc->oartifact == ART_KILO_MEGA_GIGA_TERA_PETA_E && (mon->data->mlet == S_KOP || mon->data->msound == MS_TREESQUAD) ) ||
1310 (ublindf && ublindf->oartifact == ART_SEEING_THE_PERSON_ANYWAY && mon->data->maligntyp < 0 && distu(mon->mx, mon->my) < 26) ||
1311 (uarmh && uarmh->otyp == GOOD_ESP_HELMET && mon->data->maligntyp > 0 && distu(mon->mx, mon->my) < 26) ||
1312 (uwep && uwep->oartifact == ART_GOODBYE_TROLLS && mon->data->mlet == S_TROLL) ||
1313 (uwep && uwep->oartifact == ART_ANTINSTANT_DEATH && mon->data->mlet == S_ANT) ||
1314 (uwep && uwep->oartifact == ART_DRAGONLANCE && mon->data->mlet == S_DRAGON) ||
1315 (uwep && uwep->oartifact == ART_MINI_PEOPLE_EATER && humanoid(mon->data)) ||
1316 (uwep && uwep->oartifact == ART_INDIGENOUS_FUN && humanoid(mon->data)) ||
1317 (uwep && uwep->oartifact == ART_ANIMALBANE && is_animal(mon->data)) ||
1318 (uwep && uwep->oartifact == ART_SEE_ANIMALS && is_animal(mon->data)) ||
1319 (isselfhybrid && monpolyok(mon->data) && !polyok(mon->data) && ((mon->data->mlevel < 30) || mon->selfhybridvisible) ) );
1321 if (mon && (mon->data->msound == MS_DEEPSTATE) && !mon_visible(mon) ) see_it = FALSE;
1322 if (mon && (mon->data->msound == MS_DEEPSTATE) && mon->minvis ) see_it = FALSE;
1323 if (mon && (mon->egotype_deepstatemember) && !mon_visible(mon) ) see_it = FALSE;
1324 if (mon && (mon->egotype_deepstatemember) && mon->minvis ) see_it = FALSE;
1326 if (mon && (see_it || (!worm_tail && Detect_monsters && (mon->data->msound != MS_DEEPSTATE) && !(mon->egotype_deepstatemember) ))) {
1327 if (mon->mtrapped) {
1328 struct trap *trap = t_at(x, y);
1329 int tt = trap ? trap->ttyp : NO_TRAP;
1331 /* if monster is in a physical trap, you see the trap too */
1332 if (trap && (tt == BEAR_TRAP || tt == PIT ||
1333 tt == SPIKED_PIT || tt == GIANT_CHASM || tt == SHIT_PIT || tt == MANA_PIT || tt == ANOXIC_PIT || tt == HYPOXIC_PIT || tt == ACID_PIT || tt == WEB) && (trap && !trap->hiddentrap)) {
1334 trap->tseen = TRUE;
1337 _map_location(x,y,0); /* map under the monster */
1338 /* also gets rid of any invisibility glyph */
1339 display_monster(x, y, mon, see_it? PHYSICALLY_SEEN : DETECTED, worm_tail);
1341 else if (mon && mon_warning(mon) && !is_worm_tail(mon))
1342 display_warning(mon);
1343 else if (memory_is_invisible(x,y))
1344 map_invisible(x, y);
1345 else
1346 _map_location(x,y,1); /* map the location */
1350 /* Can't see the location. */
1351 else {
1352 if (x == u.ux && y == u.uy) {
1353 feel_location(u.ux, u.uy); /* forces an update */
1355 if (senseself()) display_self();
1357 else if ((mon = m_at(x,y)) && !(uarmh && uarmh->oartifact == ART_RADAR_NOT_WORKING) && !(isselfhybrid && (moves % 3 == 0) )
1358 && ((see_it = (tp_sensemon(mon) ||
1359 MATCH_WARN_OF_MON(mon) ||
1360 (Role_if(PM_ACTIVISTOR) && mon->data == &mons[PM_TOPMODEL]) ||
1361 (Race_if(PM_PEACEMAKER) && mon->data == &mons[PM_TOPMODEL]) ||
1362 (Role_if(PM_ACTIVISTOR) && type_is_pname(mon->data) && uwep && is_quest_artifact(uwep) ) ||
1363 (uamul && uamul->otyp == AMULET_OF_POISON_WARNING && poisonous(mon->data) ) ||
1364 (uamul && uamul->otyp == AMULET_OF_OWN_RACE_WARNING && your_race(mon->data) ) ||
1365 (Role_if(PM_PALADIN) && is_demon(mon->data) ) ||
1366 (uarms && uarms->oartifact == ART_SHIELD_OF_THE_PALADIN && is_demon(mon->data) ) ||
1367 (uarms && uarms->oartifact == ART_SHIELD_OF_THE_CHEVALIER__W && is_demon(mon->data) ) ||
1368 (uarmc && uarmc->oartifact == ART_DEMONIC_UNDEAD_RADAR && is_demon(mon->data) ) ||
1369 (uwep && uwep->oartifact == ART_DAEDRA_SEEKER && mon->data->mlet == S_DEMON ) ||
1370 (Race_if(PM_VORTEX) && unsolid(mon->data) ) ||
1371 (Race_if(PM_VORTEX) && nolimbs(mon->data) ) ||
1372 (Race_if(PM_CORTEX) && unsolid(mon->data) ) ||
1373 (Race_if(PM_CORTEX) && nolimbs(mon->data) ) ||
1374 (ublindf && ublindf->otyp == BOSS_VISOR && (is_covetous(mon->data) || mon->egotype_covetous) ) ||
1375 (uarmf && uarmf->oartifact == ART_FINAL_EXAM_TIME && (mon->data->geno & G_UNIQ)) ||
1376 (uarm && uarm->oartifact == ART_JEFFERSON_S_LOOKAROUND && bigmonst(mon->data) && distu(mon->mx, mon->my) < 101) ||
1377 (uamul && uamul->otyp == AMULET_OF_COVETOUS_WARNING && (is_covetous(mon->data) || mon->egotype_covetous) ) ||
1378 (uarmh && uarmh->oartifact == ART_THAT_GIVES_IT_NOT && (is_covetous(mon->data) || mon->egotype_covetous) ) ||
1379 (uarmh && uarmh->oartifact == ART_HEARING_EAR && (is_covetous(mon->data) || mon->egotype_covetous) ) ||
1380 (Stunnopathy && Stunned && always_hostile(mon->data) && mon->stunnovisible && distu(mon->mx, mon->my) < (StrongStunnopathy ? 401 : 226)) ||
1381 ( (uarmh && itemhasappearance(uarmh, APP_INTERNET_HELMET) ) && mon->internetvisible) ||
1382 (RngeInternetAccess && mon->internetvisible) ||
1383 (uarmh && uarmh->oartifact == ART_WEB_RADIO && mon->internetvisible) ||
1384 (Numbopathy && Numbed && (avoid_player(mon->data) || mon->egotype_avoider) && distu(mon->mx, mon->my) < (StrongNumbopathy ? 901 : 626) ) ||
1385 (Sickopathy && Sick && extra_nasty(mon->data) && distu(mon->mx, mon->my) < (StrongSickopathy ? 901 : 401) ) ||
1386 (Freezopathy && Frozen && mon->data->mcolor == CLR_WHITE && distu(mon->mx, mon->my) < (StrongFreezopathy ? 626 : 401) ) ||
1387 (StrongStunnopathy && Stunned && dmgtype(mon->data, AD_STUN)) ||
1388 (StrongNumbopathy && Numbed && (dmgtype(mon->data, AD_NUMB) || dmgtype(mon->data, AD_PLYS) ) ) ||
1389 (StrongDimmopathy && Dimmed && (dmgtype(mon->data, AD_DIMN) || mon->data->msound == MS_CUSS ) ) ||
1390 (StrongFreezopathy && Frozen && (dmgtype(mon->data, AD_FRZE) || dmgtype(mon->data, AD_ICEB) ) ) ||
1391 (StrongCorrosivity && Slimed && acidic(mon->data) && distu(mon->mx, mon->my) < 226 ) ||
1392 (StrongBurnopathy && Burned && (dmgtype(mon->data, AD_BURN) || dmgtype(mon->data, AD_FLAM) ) ) ||
1393 (uarm && uarm->oartifact == ART_RNG_CESSATION && (dmgtype(mon->data, AD_RBRE) || dmgtype(mon->data, AD_RNG) ) ) ||
1394 (StrongSickopathy && Sick && (dmgtype(mon->data, AD_DISE) || dmgtype(mon->data, AD_PEST) ) ) ||
1395 (uarmh && uarmh->otyp == HELM_OF_UNLIVING_ESP && mon->data->mlet == S_GOLEM && distu(mon->mx, mon->my) < 626) ||
1396 (uarmh && uarmh->otyp == HELM_OF_UNLIVING_ESP && mindless(mon->data) && distu(mon->mx, mon->my) < 26) ||
1397 (uarmf && uarmf->oartifact == ART_VERA_S_FREEZER && mon->data->mcolor == CLR_WHITE) ||
1398 (Burnopathy && Burned && infravision(mon->data) && distu(mon->mx, mon->my) < (StrongBurnopathy ? 170 : 101) ) ||
1399 (Dimmopathy && Dimmed && mon->m_lev > u.ulevel && distu(mon->mx, mon->my) < (StrongDimmopathy ? 226 : 101) ) ||
1400 (ScentView && distu(mon->mx, mon->my) < 101 && mon->scentvisible && (is_animal(mon->data) || mon->data->msound == MS_STENCH) ) ||
1401 (uwep && uwep->oartifact == ART_SWISS_AMY_KNIFE && mon->data->msound == MS_SHOE) ||
1402 (uwep && uwep->oartifact == ART_JENNY_S_PROTECTER && uwep->lamplit && mon->data->msound == MS_MOLEST) ||
1403 (EcholocationActive && distu(mon->mx, mon->my) < 626 && mon->echolocatevisible && (dmgtype(mon->data, AD_SOUN) || mon->data->msound == MS_SOUND || mon->data->msound == MS_SHRIEK || mon->data->msound == MS_FART_NORMAL || mon->data->msound == MS_FART_LOUD || mon->data->msound == MS_FART_QUIET ) ) ||
1404 (Race_if(PM_RODNEYAN) && mon_has_amulet(mon)) ||
1405 (Race_if(PM_RODNEYAN) && mon_has_special(mon)) ||
1406 (Race_if(PM_LEVITATOR) && (is_flyer(mon->data) || mon->egotype_flying) ) ||
1407 (isselfhybrid && strongmonst(mon->data) && is_wanderer(mon->data) ) ||
1408 (uarm && uarm->oartifact == ART_JOKE_S_OVER && is_jokemonster(mon->data) ) ||
1409 (have_maybrittclick() && is_jokemonster(mon->data) ) ||
1410 (uwep && uwep->oartifact == ART_TIGATOR_S_THORN && is_pokemon(mon->data) ) ||
1411 (haveartileash(ART_PETCAMERA) && mon->mleashed) ||
1412 (haveartileash(ART_ANNOYING_PET_MONITOR) && mon->mtame) ||
1413 (uarmc && uarmc->oartifact == ART_SITHE_DED && mon->data->mlet == S_MUMMY) ||
1414 (uarm && uarm->oartifact == ART_PATROL_S_ORDERS && (mon->data->mlet == S_ORC || mon->data->mlet == S_OGRE) ) ||
1415 (uarmh && uarmh->oartifact == ART_CLIERVOYENS && distu(mon->mx, mon->my) < 9 ) ||
1416 (uarm && uarm->oartifact == ART_PLAYER_RADAR && (is_mplayer(mon->data) || is_umplayer(mon->data)) ) ||
1417 (uarmf && uarmf->oartifact == ART_AWAY_YOU_STALKER && is_stalker(mon->data) ) ||
1418 (uarmf && uarmf->oartifact == ART_ELENETTES && (mon->mhp < (mon->mhpmax * 9 / 10)) ) ||
1419 (uarmh && itemhasappearance(uarmh, APP_SAGES_HELMET) && mon->minvis && mon->sagesvisible ) ||
1420 (ublindf && ublindf->oartifact == ART_BREATHER_SHOW && attacktype(mon->data, AT_BREA)) ||
1421 (uarmc && uarmc->oartifact == ART_POKEWALKER && is_pokemon(mon->data) ) ||
1422 (uarmc && uarmc->oartifact == ART_BUGNOSE && (mon->data->mlet == S_ANT || mon->data->mlet == S_XAN) ) ||
1423 (uamul && uamul->otyp == AMULET_OF_PET_VIEW && mon->mtame) ||
1424 (uarmu && uarmu->oartifact == ART_HEEEEELEEEEEN && mon->mtame) ||
1425 (uarmh && itemhasappearance(uarmh, APP_PETSENSE_HELMET) && mon->mtame) ||
1426 (uarmf && uarmf->oartifact == ART_SNAILHUNT && (mon->data->mlet == S_BLOB || mon->data->mlet == S_WORM) ) ||
1427 (uarmf && uarmf->oartifact == ART_CAMELIC_SCENT && (mon->data->mlet == S_ZOUTHERN || mon->data->mlet == S_YETI) ) ||
1428 (uwep && uwep->oartifact == ART_EGRID_BUG && mon->data->mlet == S_XAN) ||
1429 (uwep && uwep->oartifact == ART_FUYER_BREV && mon->data->mlet == S_FUNGUS) ||
1430 (uwep && uwep->oartifact == ART_SNICKERSNACK && mon->data->mlet == S_JABBERWOCK) ||
1431 (uarm && uarm->oartifact == ART_FUNGIRADAR && mon->data->mlet == S_FUNGUS) ||
1432 (uarmf && uarmf->oartifact == ART_BOOTS_OF_THE_MACHINE && (mon->data->mlet == S_GOLEM || nonliving(mon->data) ) ) ||
1433 (uarmf && uarmf->oartifact == ART_FD_DETH && (mon->data->mlet == S_DOG || mon->data->mlet == S_FELINE) ) ||
1434 (uarmh && uarmh->oartifact == ART_DOGGO_FRIENDSHIP && mon->data->mlet == S_DOG) ||
1435 (uarmg && uarmg->oartifact == ART_WHAT_S_UP_BITCHES && (mon->data->mlet == S_NYMPH) ) ||
1436 (uwep && uwep->oartifact == ART_FISHING_GRANDPA && mon->data->mlet == S_EEL) ||
1437 (uarmf && uarmf->oartifact == ART_PECTORAL_HEEL && distu(mon->mx, mon->my) < 101 && mon->data->mlet == S_EEL) ||
1438 (uwep && uwep->oartifact == ART_PEOPLE_EATING_TRIDENT && mon->data->mlet == S_HUMAN) ||
1439 (uwep && uwep->oartifact == ART_VAMPIREBANE && mon->data->mlet == S_VAMPIRE) ||
1440 (uwep && uwep->oartifact == ART_GOLEMBANE && mon->data->mlet == S_GOLEM) ||
1441 (uwep && uwep->oartifact == ART_EELBANE && mon->data->mlet == S_EEL) ||
1442 (uwep && uwep->oartifact == ART_MAUI_S_FISHHOOK && mon->data->mlet == S_EEL) ||
1443 (uarmf && uarmf->oartifact == ART_SUCH_A_LOVELY_SHARK && mon->data->mlet == S_EEL && mon->mpeaceful) ||
1444 (uwep && uwep->oartifact == ART_DEMONSTRANTS_GO_HOME && mon->data->mlet == S_HUMAN) ||
1445 (uarmu && uarmu->oartifact == ART_PEACE_ADVOCATE && mon->data->mlet == S_HUMAN) ||
1446 (uwep && uwep->oartifact == ART_DOCTOR_JONES__AID && mon->data->mlet == S_SNAKE) ||
1447 (uarmc && uarmc->oartifact == ART_KILO_MEGA_GIGA_TERA_PETA_E && (mon->data->mlet == S_KOP || mon->data->msound == MS_TREESQUAD) ) ||
1448 (ublindf && ublindf->oartifact == ART_SEEING_THE_PERSON_ANYWAY && mon->data->maligntyp < 0 && distu(mon->mx, mon->my) < 26) ||
1449 (uarmh && uarmh->otyp == GOOD_ESP_HELMET && mon->data->maligntyp > 0 && distu(mon->mx, mon->my) < 26) ||
1450 (uwep && uwep->oartifact == ART_GOODBYE_TROLLS && mon->data->mlet == S_TROLL) ||
1451 (uwep && uwep->oartifact == ART_ANTINSTANT_DEATH && mon->data->mlet == S_ANT) ||
1452 (uwep && uwep->oartifact == ART_DRAGONLANCE && mon->data->mlet == S_DRAGON) ||
1453 (uwep && uwep->oartifact == ART_MINI_PEOPLE_EATER && humanoid(mon->data)) ||
1454 (uwep && uwep->oartifact == ART_INDIGENOUS_FUN && humanoid(mon->data)) ||
1455 (uwep && uwep->oartifact == ART_ANIMALBANE && is_animal(mon->data)) ||
1456 (uwep && uwep->oartifact == ART_SEE_ANIMALS && is_animal(mon->data)) ||
1457 (isselfhybrid && monpolyok(mon->data) && !polyok(mon->data) && ((mon->data->mlevel < 30) || mon->selfhybridvisible ) ) ||
1458 (see_with_infrared(mon) && mon_visible(mon))))
1459 || Detect_monsters)
1460 && !is_worm_tail(mon)) {
1461 /* Monsters are printed every time. */
1462 /* This also gets rid of any invisibility glyph */
1463 if (mon->data->msound != MS_DEEPSTATE && !(mon->egotype_deepstatemember)) display_monster(x, y, mon, see_it ? 0 : DETECTED, 0);
1465 else if ((mon = m_at(x,y)) && mon_warning(mon) &&
1466 !is_worm_tail(mon)) {
1467 display_warning(mon);
1471 * If the location is remembered as being both dark (waslit is false)
1472 * and lit (glyph is a lit room or lit corridor) then it was either:
1474 * (1) A dark location that the hero could see through night
1475 * vision.
1477 * (2) Darkened while out of the hero's sight. This can happen
1478 * when cursed scroll of light is read.
1480 * In either case, we have to manually correct the hero's memory to
1481 * match waslit. Deciding when to change waslit is non-trivial.
1483 * Note: If flags.lit_corridor is set, then corridors act like room
1484 * squares. That is, they light up if in night vision range.
1485 * If flags.lit_corridor is not set, then corridors will
1486 * remain dark unless lit by a light spell and may darken
1487 * again, as discussed above.
1489 * These checks and changes must be here and not in back_to_glyph().
1490 * They are dependent on the position being out of sight.
1492 else if (!lev->waslit) {
1493 #ifdef DISPLAY_LAYERS
1494 if (lev->mem_bg == S_litcorr && lev->typ == CORR) {
1495 lev->mem_bg = S_corr;
1496 show_glyph(x, y, memory_glyph(x, y));
1497 } else if (lev->mem_bg == S_room && lev->typ == ROOM) {
1498 lev->mem_bg = S_darkroom;
1499 show_glyph(x, y, memory_glyph(x, y));
1501 #else /* DISPLAY_LAYERS */
1502 if (lev->glyph == cmap_to_glyph(S_litcorr) && lev->typ == CORR)
1503 show_glyph(x, y, lev->glyph = cmap_to_glyph(S_corr));
1504 else if (lev->glyph == cmap_to_glyph(S_room) && lev->typ == ROOM)
1505 show_glyph(x, y, lev->glyph = cmap_to_glyph(S_darkroom));
1506 #endif /* DISPLAY_LAYERS */
1507 else
1508 goto show_mem;
1509 } else {
1510 show_mem:
1511 show_glyph(x, y, memory_glyph(x, y));
1516 void
1517 newsymX(x,y)
1518 register int x,y;
1520 register struct monst *mon;
1521 register struct rm *lev = &(levl[x][y]);
1522 register int see_it;
1523 register xchar worm_tail;
1525 if (in_mklev) return;
1527 if (program_state.done_hup)
1528 return;
1530 if (ManlerIsChasing && x == u.manlerx && y == u.manlery) {
1531 show_glyph(x, y, GLYPH_MON_OFF + rn2(NUMMONS));
1532 return;
1535 if ((Quaversal || u.uprops[QUAVERSAL].extrinsic || (uimplant && uimplant->oartifact == ART_ND_D___N_NDMNN_ND___NDMN_N) || have_quaversalstone() || autismweaponcheck(ART_OMGHAXERETH) ) && isok(u.ux, u.uy) && !isimportantlocation(x, y) && !(levl[u.ux][u.uy].wall_info & W_QUASAROK)) {
1536 show_glyph(x, y, cmap_to_glyph(S_stone));
1537 return;
1540 if ((uarmh && itemhasappearance(uarmh, APP_HARDCORE_CLOTH)) && !facingtile(x, y)) {
1541 show_glyph(x, y, cmap_to_glyph(S_stone));
1542 return;
1545 if (Race_if(PM_SLYER_ALIEN) && !facingtile(x, y)) {
1546 show_glyph(x, y, cmap_to_glyph(S_stone));
1547 return;
1550 if (!u.seesilverspell && SpellColorSilver && !isimportantlocation(x, y)) {
1551 show_glyph(x, y, cmap_to_glyph(S_stone));
1552 return;
1555 if ((GrayoutBug || u.uprops[GRAYOUT_BUG].extrinsic || have_grayoutstone() || (uarmc && uarmc->oartifact == ART_DOEDOEDOEDOEDOEDOEDOE_TEST) || autismweaponcheck(ART_PWNHAMMER) ) && grayoutobscuration() ) {
1556 show_glyph(x, y, cmap_to_glyph(S_grayglyph));
1557 return;
1560 if ((GrayCenterBug || u.uprops[GRAY_CENTER_BUG].extrinsic || have_graycenterstone()) && distu(x, y) < (GrayCenterXtra ? 9 : 4)) {
1561 show_glyph(x, y, cmap_to_glyph(S_grayglyph));
1562 return;
1565 if ((CheckerboardBug || u.uprops[CHECKERBOARD_BUG].extrinsic || autismweaponcheck(ART_SAY__CHESS_) || have_checkerboardstone()) && ( ((x + y) % (CheckerboardXtra ? 4 : 2) ) != (moves % (CheckerboardXtra ? 4 : 2) ) ) ) {
1566 show_glyph(x, y, cmap_to_glyph(S_grayglyph));
1567 return;
1570 if ( (QuasarVision || u.uprops[QUASAR_BUG].extrinsic || have_quasarstone() ) && !isimportantlocation(x, y) && !(levl[x][y].wall_info & W_QUASAROK) ) {
1571 show_glyph(x, y, cmap_to_glyph(S_stone));
1572 return;
1575 if (Yawming && (distu(x,y) > yawm_distance())) {
1576 show_glyph(x, y, cmap_to_glyph(S_stone));
1577 return;
1580 if (StupidMojibake && !rn2(MojibakeXtra ? 3 : 10)) {
1581 show_glyph(x, y, randomglyph());
1582 return;
1585 if (SpellColorBlue && !rn2(10)) {
1586 show_glyph(x, y, cmap_to_glyph(S_room));
1587 return;
1590 if (SpellColorOrange && (distu(x,y) > 100)) {
1591 show_glyph(x, y, cmap_to_glyph(S_grayglyph));
1592 return;
1595 if (SpellColorPlatinum && !rn2(10)) {
1596 show_glyph(x, y, cmap_to_glyph(S_bars));
1597 return;
1600 if (SpellColorBrightCyan && cyanspellok(x,y)) {
1601 show_glyph(x, y, cmap_to_glyph(S_grayglyph));
1602 return;
1605 if (FemtrapActiveNicole && nicolesquareok(x,y)) {
1606 show_glyph(x, y, cmap_to_glyph(S_stone));
1607 return;
1610 if (SpellColorBrown && (distu(x,y) % 3 == 0)) {
1611 show_glyph(x, y, cmap_to_glyph(S_pile_of_shit));
1612 return;
1615 if ( (Superscroller || (uarm && uarm->oartifact == ART_VOLUME_ARMAMENT) || (uarm && uarm->oartifact == ART_SPLINTER_ARMAMENT) || (uarm && uarm->oartifact == ART_TAPE_ARMAMENT) || (uarmc && uarmc->oartifact == ART_VEIL_OF_LATONA) || (uarmc && uarmc->oartifact == ART_VEIL_OF_MINISTRY) || u.uprops[SUPERSCROLLER_ACTIVE].extrinsic || have_superscrollerstone() ) && !isimportantlocation(x, y) && rn2(10) ) { show_glyphX(x, y, cmap_to_glyph(S_stone)); return;}
1617 /* only permit updating the hero when swallowed */
1618 if (u.uswallow) {
1619 if (x == u.ux && y == u.uy) display_self();
1620 return;
1622 if (Underwater && !Swimming && !Is_waterlevel(&u.uz)) {
1623 /* don't do anything unless (x,y) is an adjacent underwater position */
1624 int dx, dy;
1625 if (!is_waterypool(x,y) && !is_watertunnel(x,y) && !is_lava(x,y) && !is_shiftingsand(x,y) && !is_styxriver(x,y)) return;
1626 dx = x - u.ux; if (dx < 0) dx = -dx;
1627 dy = y - u.uy; if (dy < 0) dy = -dy;
1628 if (dx > 1 || dy > 1) return;
1631 /* Can physically see the location. */
1632 if (cansee(x,y)) {
1633 NhRegion* reg = visible_region_at(x,y);
1635 * Don't use templit here: E.g.
1637 * lev->waslit = !!(lev->lit || templit(x,y));
1639 * Otherwise we have the "light pool" problem, where non-permanently
1640 * lit areas just out of sight stay remembered as lit. They should
1641 * re-darken.
1643 * Perhaps ALL areas should revert to their "unlit" look when
1644 * out of sight.
1646 lev->waslit = (lev->lit!=0); /* remember lit condition */
1648 if (reg != NULL && ACCESSIBLE(lev->typ)) {
1649 show_region(reg,x,y);
1650 return;
1652 if (x == u.ux && y == u.uy) {
1653 if (senseself()) {
1654 _map_location(x,y,0); /* map *under* self */
1655 display_self();
1656 } else
1657 /* we can see what is there */
1658 _map_location(x,y,1);
1660 else {
1661 mon = m_at(x,y);
1662 worm_tail = is_worm_tail(mon);
1663 see_it = mon && !(uarmh && uarmh->oartifact == ART_RADAR_NOT_WORKING && !mon_visible(mon) ) && !(isselfhybrid && (moves % 3 == 0) ) && (worm_tail
1664 ? ((!mon->minvis || (See_invisible && (StrongSee_invisible || mon->seeinvisble) ) ) && !mon->minvisreal)
1665 : (mon_visible(mon)) ||
1666 tp_sensemon(mon) ||
1667 MATCH_WARN_OF_MON(mon) ||
1668 (Role_if(PM_ACTIVISTOR) && mon->data == &mons[PM_TOPMODEL]) ||
1669 (Race_if(PM_PEACEMAKER) && mon->data == &mons[PM_TOPMODEL]) ||
1670 (Role_if(PM_ACTIVISTOR) && type_is_pname(mon->data) && uwep && is_quest_artifact(uwep) ) ||
1671 (uamul && uamul->otyp == AMULET_OF_POISON_WARNING && poisonous(mon->data) ) ||
1672 (uamul && uamul->otyp == AMULET_OF_OWN_RACE_WARNING && your_race(mon->data) ) ||
1673 (Role_if(PM_PALADIN) && is_demon(mon->data) ) ||
1674 (uarms && uarms->oartifact == ART_SHIELD_OF_THE_PALADIN && is_demon(mon->data) ) ||
1675 (uarms && uarms->oartifact == ART_SHIELD_OF_THE_CHEVALIER__W && is_demon(mon->data) ) ||
1676 (uarmc && uarmc->oartifact == ART_DEMONIC_UNDEAD_RADAR && is_demon(mon->data) ) ||
1677 (uwep && uwep->oartifact == ART_DAEDRA_SEEKER && mon->data->mlet == S_DEMON ) ||
1678 (Race_if(PM_VORTEX) && unsolid(mon->data) ) ||
1679 (Race_if(PM_VORTEX) && nolimbs(mon->data) ) ||
1680 (Race_if(PM_CORTEX) && unsolid(mon->data) ) ||
1681 (Race_if(PM_CORTEX) && nolimbs(mon->data) ) ||
1682 (uamul && uamul->otyp == AMULET_OF_COVETOUS_WARNING && (is_covetous(mon->data) || mon->egotype_covetous) ) ||
1683 (uarmh && uarmh->oartifact == ART_THAT_GIVES_IT_NOT && (is_covetous(mon->data) || mon->egotype_covetous) ) ||
1684 (uarmh && uarmh->oartifact == ART_HEARING_EAR && (is_covetous(mon->data) || mon->egotype_covetous) ) ||
1685 (ublindf && ublindf->otyp == BOSS_VISOR && (is_covetous(mon->data) || mon->egotype_covetous) ) ||
1686 (uarmf && uarmf->oartifact == ART_FINAL_EXAM_TIME && (mon->data->geno & G_UNIQ)) ||
1687 (uarm && uarm->oartifact == ART_JEFFERSON_S_LOOKAROUND && bigmonst(mon->data) && distu(mon->mx, mon->my) < 101) ||
1688 (Stunnopathy && Stunned && always_hostile(mon->data) && mon->stunnovisible && distu(mon->mx, mon->my) < (StrongStunnopathy ? 401 : 226)) ||
1689 ( (uarmh && itemhasappearance(uarmh, APP_INTERNET_HELMET) ) && mon->internetvisible) ||
1690 (RngeInternetAccess && mon->internetvisible) ||
1691 (uarmh && uarmh->oartifact == ART_WEB_RADIO && mon->internetvisible) ||
1692 (Numbopathy && Numbed && (avoid_player(mon->data) || mon->egotype_avoider) && distu(mon->mx, mon->my) < (StrongNumbopathy ? 901 : 626) ) ||
1693 (Sickopathy && Sick && extra_nasty(mon->data) && distu(mon->mx, mon->my) < (StrongSickopathy ? 901 : 401) ) ||
1694 (Freezopathy && Frozen && mon->data->mcolor == CLR_WHITE && distu(mon->mx, mon->my) < (StrongFreezopathy ? 626 : 401) ) ||
1695 (StrongStunnopathy && Stunned && dmgtype(mon->data, AD_STUN)) ||
1696 (StrongNumbopathy && Numbed && (dmgtype(mon->data, AD_NUMB) || dmgtype(mon->data, AD_PLYS) ) ) ||
1697 (StrongDimmopathy && Dimmed && (dmgtype(mon->data, AD_DIMN) || mon->data->msound == MS_CUSS ) ) ||
1698 (StrongFreezopathy && Frozen && (dmgtype(mon->data, AD_FRZE) || dmgtype(mon->data, AD_ICEB) ) ) ||
1699 (StrongCorrosivity && Slimed && acidic(mon->data) && distu(mon->mx, mon->my) < 226 ) ||
1700 (StrongBurnopathy && Burned && (dmgtype(mon->data, AD_BURN) || dmgtype(mon->data, AD_FLAM) ) ) ||
1701 (uarm && uarm->oartifact == ART_RNG_CESSATION && (dmgtype(mon->data, AD_RBRE) || dmgtype(mon->data, AD_RNG) ) ) ||
1702 (StrongSickopathy && Sick && (dmgtype(mon->data, AD_DISE) || dmgtype(mon->data, AD_PEST) ) ) ||
1703 (uarmh && uarmh->otyp == HELM_OF_UNLIVING_ESP && mon->data->mlet == S_GOLEM && distu(mon->mx, mon->my) < 626) ||
1704 (uarmh && uarmh->otyp == HELM_OF_UNLIVING_ESP && mindless(mon->data) && distu(mon->mx, mon->my) < 26) ||
1705 (uarmf && uarmf->oartifact == ART_VERA_S_FREEZER && mon->data->mcolor == CLR_WHITE) ||
1706 (Burnopathy && Burned && infravision(mon->data) && distu(mon->mx, mon->my) < (StrongBurnopathy ? 170 : 101) ) ||
1707 (Dimmopathy && Dimmed && mon->m_lev > u.ulevel && distu(mon->mx, mon->my) < (StrongDimmopathy ? 226 : 101) ) ||
1708 (ScentView && distu(mon->mx, mon->my) < 101 && mon->scentvisible && (is_animal(mon->data) || mon->data->msound == MS_STENCH) ) ||
1709 (uwep && uwep->oartifact == ART_SWISS_AMY_KNIFE && mon->data->msound == MS_SHOE) ||
1710 (uwep && uwep->oartifact == ART_JENNY_S_PROTECTER && uwep->lamplit && mon->data->msound == MS_MOLEST) ||
1711 (EcholocationActive && distu(mon->mx, mon->my) < 626 && mon->echolocatevisible && (dmgtype(mon->data, AD_SOUN) || mon->data->msound == MS_SOUND || mon->data->msound == MS_SHRIEK || mon->data->msound == MS_FART_NORMAL || mon->data->msound == MS_FART_LOUD || mon->data->msound == MS_FART_QUIET ) ) ||
1712 (Race_if(PM_RODNEYAN) && mon_has_amulet(mon)) ||
1713 (Race_if(PM_RODNEYAN) && mon_has_special(mon)) ||
1714 (Race_if(PM_LEVITATOR) && (is_flyer(mon->data) || mon->egotype_flying) ) ||
1715 (isselfhybrid && strongmonst(mon->data) && is_wanderer(mon->data) ) ||
1716 (uarm && uarm->oartifact == ART_JOKE_S_OVER && is_jokemonster(mon->data) ) ||
1717 (have_maybrittclick() && is_jokemonster(mon->data) ) ||
1718 (uwep && uwep->oartifact == ART_TIGATOR_S_THORN && is_pokemon(mon->data) ) ||
1719 (haveartileash(ART_PETCAMERA) && mon->mleashed) ||
1720 (haveartileash(ART_ANNOYING_PET_MONITOR) && mon->mtame) ||
1721 (uarmc && uarmc->oartifact == ART_SITHE_DED && mon->data->mlet == S_MUMMY) ||
1722 (uarm && uarm->oartifact == ART_PATROL_S_ORDERS && (mon->data->mlet == S_ORC || mon->data->mlet == S_OGRE) ) ||
1723 (uarmh && uarmh->oartifact == ART_CLIERVOYENS && distu(mon->mx, mon->my) < 9 ) ||
1724 (uarm && uarm->oartifact == ART_PLAYER_RADAR && (is_mplayer(mon->data) || is_umplayer(mon->data)) ) ||
1725 (uarmf && uarmf->oartifact == ART_AWAY_YOU_STALKER && is_stalker(mon->data) ) ||
1726 (uarmf && uarmf->oartifact == ART_ELENETTES && (mon->mhp < (mon->mhpmax * 9 / 10)) ) ||
1727 (uarmh && itemhasappearance(uarmh, APP_SAGES_HELMET) && mon->minvis && mon->sagesvisible ) ||
1728 (ublindf && ublindf->oartifact == ART_BREATHER_SHOW && attacktype(mon->data, AT_BREA)) ||
1729 (uarmc && uarmc->oartifact == ART_POKEWALKER && is_pokemon(mon->data) ) ||
1730 (uarmc && uarmc->oartifact == ART_BUGNOSE && (mon->data->mlet == S_ANT || mon->data->mlet == S_XAN) ) ||
1731 (uamul && uamul->otyp == AMULET_OF_PET_VIEW && mon->mtame) ||
1732 (uarmu && uarmu->oartifact == ART_HEEEEELEEEEEN && mon->mtame) ||
1733 (uarmh && itemhasappearance(uarmh, APP_PETSENSE_HELMET) && mon->mtame) ||
1734 (uarmf && uarmf->oartifact == ART_SNAILHUNT && (mon->data->mlet == S_BLOB || mon->data->mlet == S_WORM) ) ||
1735 (uarmf && uarmf->oartifact == ART_CAMELIC_SCENT && (mon->data->mlet == S_ZOUTHERN || mon->data->mlet == S_YETI) ) ||
1736 (uwep && uwep->oartifact == ART_EGRID_BUG && mon->data->mlet == S_XAN) ||
1737 (uwep && uwep->oartifact == ART_FUYER_BREV && mon->data->mlet == S_FUNGUS) ||
1738 (uwep && uwep->oartifact == ART_SNICKERSNACK && mon->data->mlet == S_JABBERWOCK) ||
1739 (uarm && uarm->oartifact == ART_FUNGIRADAR && mon->data->mlet == S_FUNGUS) ||
1740 (uarmf && uarmf->oartifact == ART_BOOTS_OF_THE_MACHINE && (mon->data->mlet == S_GOLEM || nonliving(mon->data) ) ) ||
1741 (uarmf && uarmf->oartifact == ART_FD_DETH && (mon->data->mlet == S_DOG || mon->data->mlet == S_FELINE) ) ||
1742 (uarmh && uarmh->oartifact == ART_DOGGO_FRIENDSHIP && mon->data->mlet == S_DOG) ||
1743 (uarmg && uarmg->oartifact == ART_WHAT_S_UP_BITCHES && (mon->data->mlet == S_NYMPH) ) ||
1744 (uwep && uwep->oartifact == ART_FISHING_GRANDPA && mon->data->mlet == S_EEL) ||
1745 (uarmf && uarmf->oartifact == ART_PECTORAL_HEEL && distu(mon->mx, mon->my) < 101 && mon->data->mlet == S_EEL) ||
1746 (uwep && uwep->oartifact == ART_PEOPLE_EATING_TRIDENT && mon->data->mlet == S_HUMAN) ||
1747 (uwep && uwep->oartifact == ART_VAMPIREBANE && mon->data->mlet == S_VAMPIRE) ||
1748 (uwep && uwep->oartifact == ART_GOLEMBANE && mon->data->mlet == S_GOLEM) ||
1749 (uwep && uwep->oartifact == ART_EELBANE && mon->data->mlet == S_EEL) ||
1750 (uwep && uwep->oartifact == ART_MAUI_S_FISHHOOK && mon->data->mlet == S_EEL) ||
1751 (uarmf && uarmf->oartifact == ART_SUCH_A_LOVELY_SHARK && mon->data->mlet == S_EEL && mon->mpeaceful) ||
1752 (uwep && uwep->oartifact == ART_DEMONSTRANTS_GO_HOME && mon->data->mlet == S_HUMAN) ||
1753 (uarmu && uarmu->oartifact == ART_PEACE_ADVOCATE && mon->data->mlet == S_HUMAN) ||
1754 (uwep && uwep->oartifact == ART_DOCTOR_JONES__AID && mon->data->mlet == S_SNAKE) ||
1755 (uarmc && uarmc->oartifact == ART_KILO_MEGA_GIGA_TERA_PETA_E && (mon->data->mlet == S_KOP || mon->data->msound == MS_TREESQUAD) ) ||
1756 (ublindf && ublindf->oartifact == ART_SEEING_THE_PERSON_ANYWAY && mon->data->maligntyp < 0 && distu(mon->mx, mon->my) < 26) ||
1757 (uarmh && uarmh->otyp == GOOD_ESP_HELMET && mon->data->maligntyp > 0 && distu(mon->mx, mon->my) < 26) ||
1758 (uwep && uwep->oartifact == ART_GOODBYE_TROLLS && mon->data->mlet == S_TROLL) ||
1759 (uwep && uwep->oartifact == ART_ANTINSTANT_DEATH && mon->data->mlet == S_ANT) ||
1760 (uwep && uwep->oartifact == ART_DRAGONLANCE && mon->data->mlet == S_DRAGON) ||
1761 (uwep && uwep->oartifact == ART_MINI_PEOPLE_EATER && humanoid(mon->data)) ||
1762 (uwep && uwep->oartifact == ART_INDIGENOUS_FUN && humanoid(mon->data)) ||
1763 (uwep && uwep->oartifact == ART_ANIMALBANE && is_animal(mon->data)) ||
1764 (uwep && uwep->oartifact == ART_SEE_ANIMALS && is_animal(mon->data)) ||
1765 (isselfhybrid && monpolyok(mon->data) && !polyok(mon->data) && ((mon->data->mlevel < 30) || mon->selfhybridvisible ) ) );
1767 if (mon && (mon->data->msound == MS_DEEPSTATE) && !mon_visible(mon) ) see_it = FALSE;
1768 if (mon && (mon->data->msound == MS_DEEPSTATE) && mon->minvis ) see_it = FALSE;
1769 if (mon && (mon->egotype_deepstatemember) && !mon_visible(mon) ) see_it = FALSE;
1770 if (mon && (mon->egotype_deepstatemember) && mon->minvis ) see_it = FALSE;
1772 if (mon && (see_it || (!worm_tail && Detect_monsters && (mon->data->msound != MS_DEEPSTATE) && !(mon->egotype_deepstatemember) ))) {
1773 if (mon->mtrapped) {
1774 struct trap *trap = t_at(x, y);
1775 int tt = trap ? trap->ttyp : NO_TRAP;
1777 /* if monster is in a physical trap, you see the trap too */
1778 if (trap && (tt == BEAR_TRAP || tt == PIT ||
1779 tt == SPIKED_PIT || tt == GIANT_CHASM || tt == SHIT_PIT || tt == MANA_PIT || tt == ANOXIC_PIT || tt == HYPOXIC_PIT || tt == ACID_PIT || tt == WEB) && (trap && !trap->hiddentrap)) {
1780 trap->tseen = TRUE;
1783 _map_location(x,y,0); /* map under the monster */
1784 /* also gets rid of any invisibility glyph */
1785 display_monsterX(x, y, mon, see_it? PHYSICALLY_SEEN : DETECTED, worm_tail);
1787 else if (mon && mon_warning(mon) && !is_worm_tail(mon))
1788 display_warningX(mon);
1789 else if (memory_is_invisible(x,y))
1790 map_invisibleX(x, y);
1791 else
1792 _map_location(x,y,1); /* map the location */
1796 /* Can't see the location. */
1797 else {
1798 if (x == u.ux && y == u.uy) {
1799 feel_location(u.ux, u.uy); /* forces an update */
1801 if (senseself()) display_self();
1803 else if ((mon = m_at(x,y)) && !(uarmh && uarmh->oartifact == ART_RADAR_NOT_WORKING) && !(isselfhybrid && (moves % 3 == 0) )
1804 && ((see_it = (tp_sensemon(mon) ||
1805 MATCH_WARN_OF_MON(mon) ||
1806 (Role_if(PM_ACTIVISTOR) && mon->data == &mons[PM_TOPMODEL]) ||
1807 (Race_if(PM_PEACEMAKER) && mon->data == &mons[PM_TOPMODEL]) ||
1808 (Role_if(PM_ACTIVISTOR) && type_is_pname(mon->data) && uwep && is_quest_artifact(uwep) ) ||
1809 (uamul && uamul->otyp == AMULET_OF_POISON_WARNING && poisonous(mon->data) ) ||
1810 (uamul && uamul->otyp == AMULET_OF_OWN_RACE_WARNING && your_race(mon->data) ) ||
1811 (Role_if(PM_PALADIN) && is_demon(mon->data) ) ||
1812 (uarms && uarms->oartifact == ART_SHIELD_OF_THE_PALADIN && is_demon(mon->data) ) ||
1813 (uarms && uarms->oartifact == ART_SHIELD_OF_THE_CHEVALIER__W && is_demon(mon->data) ) ||
1814 (uarmc && uarmc->oartifact == ART_DEMONIC_UNDEAD_RADAR && is_demon(mon->data) ) ||
1815 (uwep && uwep->oartifact == ART_DAEDRA_SEEKER && mon->data->mlet == S_DEMON ) ||
1816 (Race_if(PM_VORTEX) && unsolid(mon->data) ) ||
1817 (Race_if(PM_VORTEX) && nolimbs(mon->data) ) ||
1818 (Race_if(PM_CORTEX) && unsolid(mon->data) ) ||
1819 (Race_if(PM_CORTEX) && nolimbs(mon->data) ) ||
1820 (ublindf && ublindf->otyp == BOSS_VISOR && (is_covetous(mon->data) || mon->egotype_covetous) ) ||
1821 (uarmf && uarmf->oartifact == ART_FINAL_EXAM_TIME && (mon->data->geno & G_UNIQ)) ||
1822 (uarm && uarm->oartifact == ART_JEFFERSON_S_LOOKAROUND && bigmonst(mon->data) && distu(mon->mx, mon->my) < 101) ||
1823 (uamul && uamul->otyp == AMULET_OF_COVETOUS_WARNING && (is_covetous(mon->data) || mon->egotype_covetous) ) ||
1824 (uarmh && uarmh->oartifact == ART_THAT_GIVES_IT_NOT && (is_covetous(mon->data) || mon->egotype_covetous) ) ||
1825 (uarmh && uarmh->oartifact == ART_HEARING_EAR && (is_covetous(mon->data) || mon->egotype_covetous) ) ||
1826 (Stunnopathy && Stunned && always_hostile(mon->data) && mon->stunnovisible && distu(mon->mx, mon->my) < (StrongStunnopathy ? 401 : 226)) ||
1827 ( (uarmh && itemhasappearance(uarmh, APP_INTERNET_HELMET) ) && mon->internetvisible) ||
1828 (RngeInternetAccess && mon->internetvisible) ||
1829 (uarmh && uarmh->oartifact == ART_WEB_RADIO && mon->internetvisible) ||
1830 (Numbopathy && Numbed && (avoid_player(mon->data) || mon->egotype_avoider) && distu(mon->mx, mon->my) < (StrongNumbopathy ? 901 : 626) ) ||
1831 (Sickopathy && Sick && extra_nasty(mon->data) && distu(mon->mx, mon->my) < (StrongSickopathy ? 901 : 401) ) ||
1832 (Freezopathy && Frozen && mon->data->mcolor == CLR_WHITE && distu(mon->mx, mon->my) < (StrongFreezopathy ? 626 : 401) ) ||
1833 (StrongStunnopathy && Stunned && dmgtype(mon->data, AD_STUN)) ||
1834 (StrongNumbopathy && Numbed && (dmgtype(mon->data, AD_NUMB) || dmgtype(mon->data, AD_PLYS) ) ) ||
1835 (StrongDimmopathy && Dimmed && (dmgtype(mon->data, AD_DIMN) || mon->data->msound == MS_CUSS ) ) ||
1836 (StrongFreezopathy && Frozen && (dmgtype(mon->data, AD_FRZE) || dmgtype(mon->data, AD_ICEB) ) ) ||
1837 (StrongCorrosivity && Slimed && acidic(mon->data) && distu(mon->mx, mon->my) < 226 ) ||
1838 (StrongBurnopathy && Burned && (dmgtype(mon->data, AD_BURN) || dmgtype(mon->data, AD_FLAM) ) ) ||
1839 (uarm && uarm->oartifact == ART_RNG_CESSATION && (dmgtype(mon->data, AD_RBRE) || dmgtype(mon->data, AD_RNG) ) ) ||
1840 (StrongSickopathy && Sick && (dmgtype(mon->data, AD_DISE) || dmgtype(mon->data, AD_PEST) ) ) ||
1841 (uarmh && uarmh->otyp == HELM_OF_UNLIVING_ESP && mon->data->mlet == S_GOLEM && distu(mon->mx, mon->my) < 626) ||
1842 (uarmh && uarmh->otyp == HELM_OF_UNLIVING_ESP && mindless(mon->data) && distu(mon->mx, mon->my) < 26) ||
1843 (uarmf && uarmf->oartifact == ART_VERA_S_FREEZER && mon->data->mcolor == CLR_WHITE) ||
1844 (Burnopathy && Burned && infravision(mon->data) && distu(mon->mx, mon->my) < (StrongBurnopathy ? 170 : 101) ) ||
1845 (Dimmopathy && Dimmed && mon->m_lev > u.ulevel && distu(mon->mx, mon->my) < (StrongDimmopathy ? 226 : 101) ) ||
1846 (ScentView && distu(mon->mx, mon->my) < 101 && mon->scentvisible && (is_animal(mon->data) || mon->data->msound == MS_STENCH) ) ||
1847 (uwep && uwep->oartifact == ART_SWISS_AMY_KNIFE && mon->data->msound == MS_SHOE) ||
1848 (uwep && uwep->oartifact == ART_JENNY_S_PROTECTER && uwep->lamplit && mon->data->msound == MS_MOLEST) ||
1849 (EcholocationActive && distu(mon->mx, mon->my) < 626 && mon->echolocatevisible && (dmgtype(mon->data, AD_SOUN) || mon->data->msound == MS_SOUND || mon->data->msound == MS_SHRIEK || mon->data->msound == MS_FART_NORMAL || mon->data->msound == MS_FART_LOUD || mon->data->msound == MS_FART_QUIET ) ) ||
1850 (Race_if(PM_RODNEYAN) && mon_has_amulet(mon)) ||
1851 (Race_if(PM_RODNEYAN) && mon_has_special(mon)) ||
1852 (Race_if(PM_LEVITATOR) && (is_flyer(mon->data) || mon->egotype_flying) ) ||
1853 (isselfhybrid && strongmonst(mon->data) && is_wanderer(mon->data) ) ||
1854 (uarm && uarm->oartifact == ART_JOKE_S_OVER && is_jokemonster(mon->data) ) ||
1855 (have_maybrittclick() && is_jokemonster(mon->data) ) ||
1856 (uwep && uwep->oartifact == ART_TIGATOR_S_THORN && is_pokemon(mon->data) ) ||
1857 (haveartileash(ART_PETCAMERA) && mon->mleashed) ||
1858 (haveartileash(ART_ANNOYING_PET_MONITOR) && mon->mtame) ||
1859 (uarmc && uarmc->oartifact == ART_SITHE_DED && mon->data->mlet == S_MUMMY) ||
1860 (uarm && uarm->oartifact == ART_PATROL_S_ORDERS && (mon->data->mlet == S_ORC || mon->data->mlet == S_OGRE) ) ||
1861 (uarmh && uarmh->oartifact == ART_CLIERVOYENS && distu(mon->mx, mon->my) < 9 ) ||
1862 (uarm && uarm->oartifact == ART_PLAYER_RADAR && (is_mplayer(mon->data) || is_umplayer(mon->data)) ) ||
1863 (uarmf && uarmf->oartifact == ART_AWAY_YOU_STALKER && is_stalker(mon->data) ) ||
1864 (uarmf && uarmf->oartifact == ART_ELENETTES && (mon->mhp < (mon->mhpmax * 9 / 10)) ) ||
1865 (uarmh && itemhasappearance(uarmh, APP_SAGES_HELMET) && mon->minvis && mon->sagesvisible ) ||
1866 (ublindf && ublindf->oartifact == ART_BREATHER_SHOW && attacktype(mon->data, AT_BREA)) ||
1867 (uarmc && uarmc->oartifact == ART_POKEWALKER && is_pokemon(mon->data) ) ||
1868 (uarmc && uarmc->oartifact == ART_BUGNOSE && (mon->data->mlet == S_ANT || mon->data->mlet == S_XAN) ) ||
1869 (uamul && uamul->otyp == AMULET_OF_PET_VIEW && mon->mtame) ||
1870 (uarmu && uarmu->oartifact == ART_HEEEEELEEEEEN && mon->mtame) ||
1871 (uarmh && itemhasappearance(uarmh, APP_PETSENSE_HELMET) && mon->mtame) ||
1872 (uarmf && uarmf->oartifact == ART_SNAILHUNT && (mon->data->mlet == S_BLOB || mon->data->mlet == S_WORM) ) ||
1873 (uarmf && uarmf->oartifact == ART_CAMELIC_SCENT && (mon->data->mlet == S_ZOUTHERN || mon->data->mlet == S_YETI) ) ||
1874 (uwep && uwep->oartifact == ART_EGRID_BUG && mon->data->mlet == S_XAN) ||
1875 (uwep && uwep->oartifact == ART_FUYER_BREV && mon->data->mlet == S_FUNGUS) ||
1876 (uwep && uwep->oartifact == ART_SNICKERSNACK && mon->data->mlet == S_JABBERWOCK) ||
1877 (uarm && uarm->oartifact == ART_FUNGIRADAR && mon->data->mlet == S_FUNGUS) ||
1878 (uarmf && uarmf->oartifact == ART_BOOTS_OF_THE_MACHINE && (mon->data->mlet == S_GOLEM || nonliving(mon->data) ) ) ||
1879 (uarmf && uarmf->oartifact == ART_FD_DETH && (mon->data->mlet == S_DOG || mon->data->mlet == S_FELINE) ) ||
1880 (uarmh && uarmh->oartifact == ART_DOGGO_FRIENDSHIP && mon->data->mlet == S_DOG) ||
1881 (uarmg && uarmg->oartifact == ART_WHAT_S_UP_BITCHES && (mon->data->mlet == S_NYMPH) ) ||
1882 (uwep && uwep->oartifact == ART_FISHING_GRANDPA && mon->data->mlet == S_EEL) ||
1883 (uarmf && uarmf->oartifact == ART_PECTORAL_HEEL && distu(mon->mx, mon->my) < 101 && mon->data->mlet == S_EEL) ||
1884 (uwep && uwep->oartifact == ART_PEOPLE_EATING_TRIDENT && mon->data->mlet == S_HUMAN) ||
1885 (uwep && uwep->oartifact == ART_VAMPIREBANE && mon->data->mlet == S_VAMPIRE) ||
1886 (uwep && uwep->oartifact == ART_GOLEMBANE && mon->data->mlet == S_GOLEM) ||
1887 (uwep && uwep->oartifact == ART_EELBANE && mon->data->mlet == S_EEL) ||
1888 (uwep && uwep->oartifact == ART_MAUI_S_FISHHOOK && mon->data->mlet == S_EEL) ||
1889 (uarmf && uarmf->oartifact == ART_SUCH_A_LOVELY_SHARK && mon->data->mlet == S_EEL && mon->mpeaceful) ||
1890 (uwep && uwep->oartifact == ART_DEMONSTRANTS_GO_HOME && mon->data->mlet == S_HUMAN) ||
1891 (uarmu && uarmu->oartifact == ART_PEACE_ADVOCATE && mon->data->mlet == S_HUMAN) ||
1892 (uwep && uwep->oartifact == ART_DOCTOR_JONES__AID && mon->data->mlet == S_SNAKE) ||
1893 (uarmc && uarmc->oartifact == ART_KILO_MEGA_GIGA_TERA_PETA_E && (mon->data->mlet == S_KOP || mon->data->msound == MS_TREESQUAD) ) ||
1894 (ublindf && ublindf->oartifact == ART_SEEING_THE_PERSON_ANYWAY && mon->data->maligntyp < 0 && distu(mon->mx, mon->my) < 26) ||
1895 (uarmh && uarmh->otyp == GOOD_ESP_HELMET && mon->data->maligntyp > 0 && distu(mon->mx, mon->my) < 26) ||
1896 (uwep && uwep->oartifact == ART_GOODBYE_TROLLS && mon->data->mlet == S_TROLL) ||
1897 (uwep && uwep->oartifact == ART_ANTINSTANT_DEATH && mon->data->mlet == S_ANT) ||
1898 (uwep && uwep->oartifact == ART_DRAGONLANCE && mon->data->mlet == S_DRAGON) ||
1899 (uwep && uwep->oartifact == ART_MINI_PEOPLE_EATER && humanoid(mon->data)) ||
1900 (uwep && uwep->oartifact == ART_INDIGENOUS_FUN && humanoid(mon->data)) ||
1901 (uwep && uwep->oartifact == ART_ANIMALBANE && is_animal(mon->data)) ||
1902 (uwep && uwep->oartifact == ART_SEE_ANIMALS && is_animal(mon->data)) ||
1903 (isselfhybrid && monpolyok(mon->data) && !polyok(mon->data) && ((mon->data->mlevel < 30) || mon->selfhybridvisible ) ) ||
1904 (see_with_infrared(mon) && mon_visible(mon))))
1905 || Detect_monsters)
1906 && !is_worm_tail(mon)) {
1907 /* Monsters are printed every time. */
1908 /* This also gets rid of any invisibility glyph */
1910 if (mon->data->msound != MS_DEEPSTATE && !(mon->egotype_deepstatemember)) display_monsterX(x, y, mon, see_it ? 0 : DETECTED, 0);
1913 else if ((mon = m_at(x,y)) && mon_warning(mon) &&
1914 !is_worm_tail(mon)) {
1915 display_warningX(mon);
1919 * If the location is remembered as being both dark (waslit is false)
1920 * and lit (glyph is a lit room or lit corridor) then it was either:
1922 * (1) A dark location that the hero could see through night
1923 * vision.
1925 * (2) Darkened while out of the hero's sight. This can happen
1926 * when cursed scroll of light is read.
1928 * In either case, we have to manually correct the hero's memory to
1929 * match waslit. Deciding when to change waslit is non-trivial.
1931 * Note: If flags.lit_corridor is set, then corridors act like room
1932 * squares. That is, they light up if in night vision range.
1933 * If flags.lit_corridor is not set, then corridors will
1934 * remain dark unless lit by a light spell and may darken
1935 * again, as discussed above.
1937 * These checks and changes must be here and not in back_to_glyph().
1938 * They are dependent on the position being out of sight.
1940 else if (!lev->waslit) {
1941 #ifdef DISPLAY_LAYERS
1942 if (lev->mem_bg == S_litcorr && lev->typ == CORR) {
1943 lev->mem_bg = S_corr;
1944 show_glyphX(x, y, memory_glyph(x, y));
1945 } else if (lev->mem_bg == S_room && lev->typ == ROOM) {
1946 lev->mem_bg = S_darkroom;
1947 show_glyphX(x, y, memory_glyph(x, y));
1949 #else /* DISPLAY_LAYERS */
1950 if (lev->glyph == cmap_to_glyph(S_litcorr) && lev->typ == CORR)
1951 show_glyphX(x, y, lev->glyph = cmap_to_glyph(S_corr));
1952 else if (lev->glyph == cmap_to_glyph(S_room) && lev->typ == ROOM)
1953 show_glyphX(x, y, lev->glyph = cmap_to_glyph(S_darkroom));
1954 #endif /* DISPLAY_LAYERS */
1955 else
1956 goto show_mem;
1957 } else {
1958 show_mem:
1959 show_glyphX(x, y, memory_glyph(x, y));
1964 #undef is_worm_tail
1967 * shieldeff()
1969 * Put magic shield pyrotechnics at the given location. This *could* be
1970 * pulled into a platform dependent routine for fancier graphics if desired.
1972 void
1973 shieldeff(x,y)
1974 xchar x,y;
1976 register int i;
1978 if (!flags.sparkle) return;
1979 if (cansee(x,y)) { /* Don't see anything if can't see the location */
1980 #ifdef ALLEG_FX
1981 if (iflags.usealleg) {
1982 newsym(x,y);
1983 if(alleg_shield(x,y))
1984 return;
1986 #endif
1987 for (i = 0; i < SHIELD_COUNT; i++) {
1988 show_glyph(x, y, cmap_to_glyph(shield_static[i]));
1989 flush_screen(1); /* make sure the glyph shows up */
1990 delay_output();
1992 newsym(x,y); /* restore the old information */
1998 * tmp_at()
2000 * Temporarily place glyphs on the screen. Do not call delay_output(). It
2001 * is up to the caller to decide if it wants to wait [presently, everyone
2002 * but explode() wants to delay].
2004 * Call:
2005 * (DISP_BEAM, glyph) open, initialize glyph
2006 * (DISP_BEAM_ALWAYS, glyph) open, initialize glyph
2007 * (DISP_FLASH, glyph) open, initialize glyph
2008 * (DISP_ALWAYS, glyph) open, initialize glyph
2009 * (DISP_CHANGE, glyph) change glyph
2010 * (DISP_END, 0) close & clean up (second argument doesn't
2011 * matter)
2012 * (DISP_FREEMEM, 0) only used to prevent memory leak during
2013 * exit)
2014 * (x, y) display the glyph at the location
2016 * DISP_BEAM - Display the given glyph at each location, but do not erase
2017 * any until the close call.
2018 * WAC added beam_always for lightning strikes
2019 * DISP_BEAM_ALWAYS- Like DISP_BEAM, but vision is not taken into account.
2020 * DISP_FLASH - Display the given glyph at each location, but erase the
2021 * previous location's glyph.
2022 * DISP_ALWAYS- Like DISP_FLASH, but vision is not taken into account.
2025 static struct tmp_glyph {
2026 coord saved[COLNO]; /* previously updated positions */
2027 int sidx; /* index of next unused slot in saved[] */
2028 int style; /* either DISP_BEAM or DISP_FLASH or DISP_ALWAYS */
2029 int glyph; /* glyph to use when printing */
2030 struct tmp_glyph *cont; /* Used if saved[] is full */
2031 struct tmp_glyph *prev;
2032 } tgfirst;
2033 static struct tmp_glyph *tglyph = (struct tmp_glyph *)0;
2035 void
2036 tmp_at(x, y)
2037 int x, y;
2039 struct tmp_glyph *tmp, *cont;
2041 switch (x) {
2042 case DISP_BEAM:
2043 case DISP_BEAM_ALWAYS:
2044 case DISP_FLASH:
2045 case DISP_ALWAYS:
2046 if (!tglyph)
2047 tmp = &tgfirst;
2048 else /* nested effect; we need dynamic memory */
2049 tmp = (struct tmp_glyph *)alloc(sizeof (struct tmp_glyph));
2050 tmp->prev = tglyph;
2051 tglyph = tmp;
2052 tglyph->sidx = 0;
2053 tglyph->style = x;
2054 tglyph->glyph = y;
2055 tglyph->cont = (struct tmp_glyph *)0;
2056 flush_screen(0); /* flush buffered glyphs */
2057 return;
2058 case DISP_FREEMEM: /* in case game ends with tmp_at() in progress */
2059 while (tglyph) {
2060 cont = tglyph->cont;
2061 while (cont) {
2062 tmp = cont->cont;
2063 if (cont != &tgfirst) free((void *)cont);
2064 cont = tmp;
2066 tmp = tglyph->prev;
2067 if (tglyph != &tgfirst) free((void *)tglyph);
2068 tglyph = tmp;
2070 return;
2072 default:
2073 break;
2076 if (!tglyph) panic("tmp_at: tglyph not initialized");
2078 switch (x) {
2079 case DISP_CHANGE:
2080 tglyph->glyph = y;
2081 break;
2083 case DISP_END:
2084 if (tglyph->style == DISP_BEAM || tglyph->style == DISP_BEAM_ALWAYS) {
2085 register int i;
2087 /* Erase (reset) from source to end */
2088 for (i = 0; i < tglyph->sidx; i++)
2089 newsym(tglyph->saved[i].x, tglyph->saved[i].y);
2090 cont = tglyph->cont;
2091 while (cont) {
2092 for (i = 0; i < cont->sidx; i++)
2093 newsym(cont->saved[i].x, cont->saved[i].y);
2094 tmp = cont->cont;
2095 if (cont != &tgfirst) free((void *)cont);
2096 cont = tmp;
2098 /* tglyph->cont = (struct tmp_glyph *)0; */
2099 } else { /* DISP_FLASH or DISP_ALWAYS */
2100 if (tglyph->sidx) /* been called at least once */
2101 newsym(tglyph->saved[0].x, tglyph->saved[0].y);
2103 /* tglyph->sidx = 0; -- about to be freed, so not necessary */
2104 tmp = tglyph->prev;
2105 if (tglyph != &tgfirst) free((void *)tglyph);
2106 tglyph = tmp;
2107 break;
2109 default: /* do it */
2110 if (tglyph->style == DISP_BEAM || tglyph->style == DISP_BEAM_ALWAYS) {
2111 if (!cansee(x,y) && tglyph->style == DISP_BEAM) break;
2112 /* save pos for later erasing */
2113 if (tglyph->sidx >= SIZE(tglyph->saved)) {
2114 tmp = (struct tmp_glyph *)alloc(sizeof (struct tmp_glyph));
2115 *tmp = *tglyph;
2116 tglyph->prev = (struct tmp_glyph *)0;
2117 tmp->cont = tglyph;
2118 tglyph = tmp;
2119 tglyph->sidx = 0;
2121 tglyph->saved[tglyph->sidx].x = x;
2122 tglyph->saved[tglyph->sidx].y = y;
2123 tglyph->sidx += 1;
2124 } else { /* DISP_FLASH/ALWAYS */
2125 if (tglyph->sidx) { /* not first call, so reset previous pos */
2126 newsym(tglyph->saved[0].x, tglyph->saved[0].y);
2127 tglyph->sidx = 0; /* display is presently up to date */
2129 if (!cansee(x,y) && tglyph->style != DISP_ALWAYS) break;
2130 tglyph->saved[0].x = x;
2131 tglyph->saved[0].y = y;
2132 tglyph->sidx = 1;
2135 show_glyph(x, y, tglyph->glyph); /* show it */
2136 flush_screen(0); /* make sure it shows up */
2137 break;
2138 } /* end case */
2141 #ifdef DISPLAY_LAYERS
2143 glyph_is_floating(glyph)
2144 int glyph;
2146 return glyph_is_monster(glyph) || glyph_is_explosion(glyph) ||
2147 glyph_is_zap_beam(glyph) || glyph_is_swallow(glyph) ||
2148 glyph_is_warning(glyph) || tglyph && glyph == tglyph->glyph;
2150 #endif
2153 * swallowed()
2155 * The hero is swallowed. Show a special graphics sequence for this. This
2156 * bypasses all of the display routines and messes with buffered screen
2157 * directly. This method works because both vision and display check for
2158 * being swallowed.
2160 void
2161 swallowed(first)
2162 int first;
2164 static xchar lastx, lasty; /* last swallowed position */
2165 int swallower, left_ok, rght_ok;
2167 if (first)
2168 cls();
2169 else {
2170 register int x, y;
2172 /* Clear old location */
2173 for (y = lasty-1; y <= lasty+1; y++)
2174 for (x = lastx-1; x <= lastx+1; x++)
2175 if (isok(x,y)) show_glyph(x,y,cmap_to_glyph(S_stone));
2178 #ifdef ALLEG_FX
2179 if(!iflags.usealleg || !alleg_swallowed(u.ux,u.uy)) {
2180 #endif
2181 swallower = monsndx(u.ustuck->data);
2182 /* assume isok(u.ux,u.uy) */
2183 left_ok = isok(u.ux-1,u.uy);
2184 rght_ok = isok(u.ux+1,u.uy);
2186 * Display the hero surrounded by the monster's stomach.
2188 if(isok(u.ux, u.uy-1)) {
2189 if (left_ok)
2190 show_glyph(u.ux-1, u.uy-1, swallow_to_glyph(swallower, S_sw_tl));
2191 show_glyph(u.ux , u.uy-1, swallow_to_glyph(swallower, S_sw_tc));
2192 if (rght_ok)
2193 show_glyph(u.ux+1, u.uy-1, swallow_to_glyph(swallower, S_sw_tr));
2196 if (left_ok)
2197 show_glyph(u.ux-1, u.uy , swallow_to_glyph(swallower, S_sw_ml));
2198 display_self();
2199 if (rght_ok)
2200 show_glyph(u.ux+1, u.uy , swallow_to_glyph(swallower, S_sw_mr));
2202 if(isok(u.ux, u.uy+1)) {
2203 if (left_ok)
2204 show_glyph(u.ux-1, u.uy+1, swallow_to_glyph(swallower, S_sw_bl));
2205 show_glyph(u.ux , u.uy+1, swallow_to_glyph(swallower, S_sw_bc));
2206 if (rght_ok)
2207 show_glyph(u.ux+1, u.uy+1, swallow_to_glyph(swallower, S_sw_br));
2209 #ifdef ALLEG_FX
2211 #endif
2213 /* Update the swallowed position. */
2214 lastx = u.ux;
2215 lasty = u.uy;
2219 * under_water()
2221 * Similar to swallowed() in operation. Shows hero when underwater
2222 * except when in water level. Special routines exist for that.
2224 void
2225 under_water(mode)
2226 int mode;
2228 static xchar lastx, lasty;
2229 static boolean dela;
2230 register int x, y;
2232 /* swallowing has a higher precedence than under water */
2233 if (Is_waterlevel(&u.uz) || u.uswallow) return;
2235 /* full update */
2236 if (mode == 1 || dela) {
2237 cls();
2238 dela = FALSE;
2240 /* delayed full update */
2241 else if (mode == 2) {
2242 dela = TRUE;
2243 return;
2245 /* limited update */
2246 else { /* mode == 0 */
2247 for (y = lasty-1; y <= lasty+1; y++)
2248 for (x = lastx-1; x <= lastx+1; x++)
2249 if (isok(x,y))
2250 show_glyph(x,y,cmap_to_glyph(S_stone));
2252 for (x = u.ux-1; x <= u.ux+1; x++)
2253 for (y = u.uy-1; y <= u.uy+1; y++)
2255 /* Amy edit: in vanilla, you wouldn't see adjacent lava, and die very unfairly. Here in the land of SLEX,
2256 * we assume that the dungeon can bend physics and have a 'barrier' where the water ends and the lava begins,
2257 * which isn't solid and can be seen through, so when you're underwater, you can see all adjacent types of
2258 * liquid terrain, not just watery ones. */
2260 if (isok(x,y) && (is_waterypool(x,y) || is_watertunnel(x,y) || is_lava(x,y) || is_shiftingsand(x,y) || is_styxriver(x,y) )) {
2261 if (Blind && !(x == u.ux && y == u.uy))
2262 show_glyph(x,y,cmap_to_glyph(S_stone));
2263 else
2264 newsym(x,y);
2266 lastx = u.ux;
2267 lasty = u.uy;
2271 * under_ground()
2273 * Very restricted display. You can only see yourself.
2275 void
2276 under_ground(mode)
2277 int mode;
2279 static boolean dela;
2281 /* swallowing has a higher precedence than under ground */
2282 if (u.uswallow) return;
2284 /* full update */
2285 if (mode == 1 || dela) {
2286 cls();
2287 dela = FALSE;
2289 /* delayed full update */
2290 else if (mode == 2) {
2291 dela = TRUE;
2292 return;
2294 /* limited update */
2295 else
2296 newsym(u.ux,u.uy);
2300 /* ========================================================================= */
2303 * Loop through all of the monsters and update them. Called when:
2304 * + going blind & telepathic
2305 * + regaining sight & telepathic
2306 * + getting and losing infravision
2307 * + hallucinating
2308 * + doing a full screen redraw
2309 * + see invisible times out or a ring of see invisible is taken off
2310 * + when a potion of see invisible is quaffed or a ring of see
2311 * invisible is put on
2312 * + gaining telepathy when blind [givit() in eat.c, pleased() in pray.c]
2313 * + losing telepathy while blind [xkilled() in mon.c, attrcurse() in
2314 * sit.c]
2316 void
2317 see_monsters()
2319 register struct monst *mon;
2321 if (defer_see_monsters) return;
2323 for (mon = fmon; mon; mon = mon->nmon) {
2324 if (DEADMONSTER(mon)) continue;
2325 newsym(mon->mx,mon->my);
2326 if (mon->wormno) see_wsegs(mon);
2328 /* when mounted, hero's location gets caught by monster loop */
2329 if (!u.usteed)
2330 newsym(u.ux, u.uy);
2333 void
2334 see_monstersX()
2336 register struct monst *mon;
2338 if (defer_see_monsters) return;
2340 for (mon = fmon; mon; mon = mon->nmon) {
2341 if (DEADMONSTER(mon)) continue;
2342 newsymX(mon->mx,mon->my);
2343 if (mon->wormno) see_wsegs(mon);
2345 /* when mounted, hero's location gets caught by monster loop */
2346 if (!u.usteed)
2347 newsymX(u.ux, u.uy);
2351 * Block/unblock light depending on what a mimic is mimicing and if it's
2352 * invisible or not. Should be called only when the state of See_invisible
2353 * changes.
2355 void
2356 set_mimic_blocking()
2358 register struct monst *mon;
2360 for (mon = fmon; mon; mon = mon->nmon) {
2361 if (DEADMONSTER(mon)) continue;
2362 if (mon->minvis &&
2363 ((mon->m_ap_type == M_AP_FURNITURE &&
2364 (mon->mappearance == S_vcdoor || mon->mappearance == S_hcdoor)) ||
2365 (mon->m_ap_type == M_AP_OBJECT && mon->mappearance == BOULDER))) {
2366 if(See_invisible)
2367 block_point(mon->mx, mon->my);
2368 else
2369 unblock_point(mon->mx, mon->my);
2375 * Loop through all of the object *locations* and update them. Called when
2376 * + hallucinating.
2378 void
2379 see_objects()
2381 register struct obj *obj;
2383 for(obj = fobj; obj; obj = obj->nobj)
2384 if (vobj_at(obj->ox,obj->oy) == obj) newsym(obj->ox, obj->oy);
2388 * Update hallucinated traps.
2390 void
2391 see_traps()
2393 struct trap *trap;
2394 int glyph;
2396 for (trap = ftrap; trap; trap = trap->ntrap) {
2397 glyph = glyph_at(trap->tx, trap->ty);
2398 if (glyph_is_trap(glyph))
2399 newsym(trap->tx, trap->ty);
2404 * Put the cursor on the hero. Flush all accumulated glyphs before doing it.
2406 void
2407 curs_on_u()
2409 flush_screen(1); /* Flush waiting glyphs & put cursor on hero */
2413 doredraw()
2415 docrt();
2416 if (InterfaceScrewed || u.uprops[INTERFACE_SCREW].extrinsic || have_interfacescrewstone()) vision_recalc(5);
2418 if (StuckAnnouncement || u.uprops[STUCK_ANNOUNCEMENT_BUG].extrinsic || have_stuckannouncementstone()) botreal();
2420 return 0;
2423 void
2424 docrt()
2426 register int x,y;
2427 register struct rm *lev;
2428 int i, glyph;
2430 if (!u.ux) return; /* display isn't ready yet */
2432 transp = FALSE;
2433 if (tileset[0])
2434 for(i = 0; i < no_tilesets; ++i)
2435 if (!strcmpi(tileset, tilesets[i].name)) {
2436 transp = !!(tilesets[i].flags & TILESET_TRANSPARENT);
2437 break;
2440 if (u.uswallow) {
2441 swallowed(1);
2442 return;
2444 if (Underwater && !Is_waterlevel(&u.uz) && !Swimming) {
2445 under_water(1);
2446 return;
2448 if (u.uburied) {
2449 under_ground(1);
2450 return;
2453 /* shut down vision */
2454 vision_recalc(2);
2457 * This routine assumes that cls() does the following:
2458 * + fills the physical screen with the symbol for rock
2459 * + clears the glyph buffer
2461 cls();
2463 /* display memory */
2464 for (x = 1; x < COLNO; x++) {
2465 lev = &levl[x][0];
2466 for (y = 0; y < ROWNO; y++, lev++)
2467 if ((glyph = memory_glyph(x,y)) != cmap_to_glyph(S_stone))
2468 show_glyphX(x,y,glyph);
2471 /* see what is to be seen */
2472 vision_recalc(0);
2474 /* overlay with monsters */
2475 see_monstersX();
2477 flags.botlx = 1; /* force a redraw of the bottom line */
2482 /* ========================================================================= */
2483 /* Glyph Buffering (3rd screen) ============================================ */
2485 typedef struct {
2486 xchar new; /* perhaps move this bit into the rm strucure. */
2487 int glyph;
2488 } gbuf_entry;
2490 static gbuf_entry gbuf[ROWNO][COLNO];
2491 static char gbuf_start[ROWNO];
2492 static char gbuf_stop[ROWNO];
2494 #ifdef DUMP_LOG
2495 /* D: Added to dump screen to output file */
2496 STATIC_PTR uchar get_glyph_char(glyph)
2497 int glyph;
2499 uchar ch;
2500 register int offset;
2502 if (glyph >= NO_GLYPH)
2503 return 0;
2506 * Map the glyph back to a character.
2508 * Warning: For speed, this makes an assumption on the order of
2509 * offsets. The order is set in display.h.
2511 if ((offset = (glyph - GLYPH_WARNING_OFF)) >= 0) { /* a warning flash */
2512 ch = def_warnsyms[offset].sym;
2513 } else if ((offset = (glyph - GLYPH_SWALLOW_OFF)) >= 0) { /* swallow */
2514 /* see swallow_to_glyph() in display.c */
2515 ch = (uchar) defsyms[S_sw_tl + (offset & 0x7)].sym;
2516 } else if ((offset = (glyph - GLYPH_ZAP_OFF)) >= 0) { /* zap beam */
2517 /* see zapdir_to_glyph() in display.c */
2518 ch = defsyms[S_vbeam + (offset & 0x3)].sym;
2519 } else if ((offset = (glyph - GLYPH_CMAP_OFF)) >= 0) { /* cmap */
2520 ch = defsyms[offset].sym;
2521 } else if ((offset = (glyph - GLYPH_OBJ_OFF)) >= 0) { /* object */
2522 ch = def_oc_syms[(int)objects[offset].oc_class];
2523 } else if ((offset = (glyph - GLYPH_RIDDEN_OFF)) >= 0) { /* mon ridden */
2524 ch = def_monsyms[(int)mons[offset].mlet];
2525 } else if ((offset = (glyph - GLYPH_BODY_OFF)) >= 0) { /* a corpse */
2526 ch = def_oc_syms[(int)objects[CORPSE].oc_class];
2527 } else if ((offset = (glyph - GLYPH_DETECT_OFF)) >= 0) { /* mon detect */
2528 ch = def_monsyms[(int)mons[offset].mlet];
2529 } else if ((offset = (glyph - GLYPH_INVIS_OFF)) >= 0) { /* invisible */
2530 ch = DEF_INVISIBLE;
2531 } else if ((offset = (glyph - GLYPH_PET_OFF)) >= 0) { /* a pet */
2532 ch = def_monsyms[(int)mons[offset].mlet];
2533 } else { /* a monster */
2534 ch = monsyms[(int)mons[glyph].mlet];
2536 return ch;
2539 #ifdef TTY_GRAPHICS
2540 extern const char * compress_str(const char *);
2541 #else
2542 const char*
2543 compress_str(str) /* copied from win/tty/wintty.c */
2544 const char *str;
2546 static char cbuf[BUFSZ];
2547 /* compress in case line too long */
2548 if((int)strlen(str) >= 80) {
2549 register const char *bp0 = str;
2550 register char *bp1 = cbuf;
2552 do {
2553 if(*bp0 != ' ' || bp0[1] != ' ')
2554 *bp1++ = *bp0;
2555 } while(*bp0++);
2556 } else
2557 return str;
2558 return cbuf;
2560 #endif /* TTY_GRAPHICS */
2562 /* Take a screen dump */
2563 void dump_screen()
2565 register int x,y;
2566 int lastc;
2567 /* D: botl.c has a closer approximation to the size, but we'll go with
2568 * this */
2569 char buf[300], *ptr;
2571 for (y = 0; y < ROWNO; y++) {
2572 lastc = 0;
2573 ptr = buf;
2574 for (x = 1; x < COLNO; x++) {
2575 uchar c = get_glyph_char(gbuf[y][x].glyph);
2576 *ptr++ = c;
2577 if (c != ' ')
2578 lastc = x;
2580 buf[lastc] = '\0';
2581 dump("", buf);
2583 dump("", "");
2584 bot1str(buf);
2585 ptr = (char *) compress_str((const char *) buf);
2586 dump("", ptr);
2587 bot2str(buf);
2588 dump("", buf);
2589 dump("", "");
2590 dump("", "");
2592 #endif /* DUMP_LOG */
2595 * Store the glyph in the 3rd screen for later flushing.
2597 void
2598 show_glyph(x,y,glyph)
2599 int x, y, glyph;
2602 * Check for bad positions and glyphs.
2605 if (InterfaceScrewed || u.uprops[INTERFACE_SCREW].extrinsic || have_interfacescrewstone()) return;
2607 if (!isok(x, y)) {
2608 const char *text;
2609 int offset;
2611 /* column 0 is invalid, but it's often used as a flag, so ignore it */
2612 if (x == 0) return;
2615 * This assumes an ordering of the offsets. See display.h for
2616 * the definition.
2619 if (glyph >= GLYPH_WARNING_OFF) { /* a warning */
2620 text = "warning"; offset = glyph - GLYPH_WARNING_OFF;
2621 } else if (glyph >= GLYPH_SWALLOW_OFF) { /* swallow border */
2622 text = "swallow border"; offset = glyph - GLYPH_SWALLOW_OFF;
2623 } else if (glyph >= GLYPH_ZAP_OFF) { /* zap beam */
2624 text = "zap beam"; offset = glyph - GLYPH_ZAP_OFF;
2625 } else if (glyph >= GLYPH_EXPLODE_OFF) { /* explosion */
2626 text = "explosion"; offset = glyph - GLYPH_EXPLODE_OFF;
2627 } else if (glyph >= GLYPH_CMAP_OFF) { /* cmap */
2628 text = "cmap_index"; offset = glyph - GLYPH_CMAP_OFF;
2629 } else if (glyph >= GLYPH_OBJ_OFF) { /* object */
2630 text = "object"; offset = glyph - GLYPH_OBJ_OFF;
2631 } else if (glyph >= GLYPH_RIDDEN_OFF) { /* ridden mon */
2632 text = "ridden mon"; offset = glyph - GLYPH_RIDDEN_OFF;
2633 } else if (glyph >= GLYPH_BODY_OFF) { /* a corpse */
2634 text = "corpse"; offset = glyph - GLYPH_BODY_OFF;
2635 } else if (glyph >= GLYPH_DETECT_OFF) { /* detected mon */
2636 text = "detected mon"; offset = glyph - GLYPH_DETECT_OFF;
2637 } else if (glyph >= GLYPH_INVIS_OFF) { /* invisible mon */
2638 text = "invisible mon"; offset = glyph - GLYPH_INVIS_OFF;
2639 } else if (glyph >= GLYPH_PET_OFF) { /* a pet */
2640 text = "pet"; offset = glyph - GLYPH_PET_OFF;
2641 } else { /* a monster */
2642 text = "monster"; offset = glyph;
2645 impossible("show_glyph: bad pos %d %d with glyph %d [%s %d].",
2646 x, y, glyph, text, offset);
2647 return;
2650 if ( RightMouseButtonDoesNotGo && glyph >= GLYPH_OBJ_OFF && !(glyph >= GLYPH_CMAP_OFF && glyph < (GLYPH_CMAP_OFF + 13) ) && !(glyph >= (GLYPH_CMAP_OFF + 24) && glyph < (GLYPH_CMAP_OFF + 28) ) && !isimportantlocation(x, y) && !(glyph == (GLYPH_CMAP_OFF + 47) ) )
2651 glyph = cmap_to_glyph(S_stone);
2653 if ( (NotSeenBug || u.uprops[NOT_SEEN_BUG].extrinsic || have_nonseeingstone()) && !isimportantlocation(x, y) && ((glyph >= GLYPH_CMAP_OFF && glyph < (GLYPH_CMAP_OFF + 13) ) || (glyph == (GLYPH_CMAP_OFF + 47) ) ) )
2654 glyph = cmap_to_glyph(S_stone);
2656 if (!flags.wallglyph && !isimportantlocation(x, y) && glyph == (GLYPH_CMAP_OFF + 47)) glyph = cmap_to_glyph(S_stone);
2658 if (glyph >= MAX_GLYPH) {
2659 impossible("show_glyph: bad glyph %d [max %d] at (%d,%d).",
2660 glyph, MAX_GLYPH, x, y);
2661 return;
2664 /* [ALI] In transparent mode it is not sufficient just to consider
2665 * the foreground glyph, we also need to consider the background.
2666 * Rather than extend the display module to do this, for the time
2667 * being we just turn off optimization and rely on the windowing port
2668 * to ignore redundant calls to print_glyph().
2670 if (transp || gbuf[y][x].glyph != glyph) {
2671 gbuf[y][x].glyph = glyph;
2672 gbuf[y][x].new = 1;
2673 if (gbuf_start[y] > x) gbuf_start[y] = x;
2674 if (gbuf_stop[y] < x) gbuf_stop[y] = x;
2678 /* show_glyph function for interface screw trap --Amy */
2679 void
2680 show_glyphX(x,y,glyph)
2681 int x, y, glyph;
2684 * Check for bad positions and glyphs.
2686 if (!isok(x, y)) {
2687 const char *text;
2688 int offset;
2690 /* column 0 is invalid, but it's often used as a flag, so ignore it */
2691 if (x == 0) return;
2694 * This assumes an ordering of the offsets. See display.h for
2695 * the definition.
2698 if (glyph >= GLYPH_WARNING_OFF) { /* a warning */
2699 text = "warning"; offset = glyph - GLYPH_WARNING_OFF;
2700 } else if (glyph >= GLYPH_SWALLOW_OFF) { /* swallow border */
2701 text = "swallow border"; offset = glyph - GLYPH_SWALLOW_OFF;
2702 } else if (glyph >= GLYPH_ZAP_OFF) { /* zap beam */
2703 text = "zap beam"; offset = glyph - GLYPH_ZAP_OFF;
2704 } else if (glyph >= GLYPH_EXPLODE_OFF) { /* explosion */
2705 text = "explosion"; offset = glyph - GLYPH_EXPLODE_OFF;
2706 } else if (glyph >= GLYPH_CMAP_OFF) { /* cmap */
2707 text = "cmap_index"; offset = glyph - GLYPH_CMAP_OFF;
2708 } else if (glyph >= GLYPH_OBJ_OFF) { /* object */
2709 text = "object"; offset = glyph - GLYPH_OBJ_OFF;
2710 } else if (glyph >= GLYPH_RIDDEN_OFF) { /* ridden mon */
2711 text = "ridden mon"; offset = glyph - GLYPH_RIDDEN_OFF;
2712 } else if (glyph >= GLYPH_BODY_OFF) { /* a corpse */
2713 text = "corpse"; offset = glyph - GLYPH_BODY_OFF;
2714 } else if (glyph >= GLYPH_DETECT_OFF) { /* detected mon */
2715 text = "detected mon"; offset = glyph - GLYPH_DETECT_OFF;
2716 } else if (glyph >= GLYPH_INVIS_OFF) { /* invisible mon */
2717 text = "invisible mon"; offset = glyph - GLYPH_INVIS_OFF;
2718 } else if (glyph >= GLYPH_PET_OFF) { /* a pet */
2719 text = "pet"; offset = glyph - GLYPH_PET_OFF;
2720 } else { /* a monster */
2721 text = "monster"; offset = glyph;
2724 impossible("show_glyph: bad pos %d %d with glyph %d [%s %d].",
2725 x, y, glyph, text, offset);
2726 return;
2729 if ( RightMouseButtonDoesNotGo && glyph >= GLYPH_OBJ_OFF && !(glyph >= GLYPH_CMAP_OFF && glyph < (GLYPH_CMAP_OFF + 13) ) && !(glyph >= (GLYPH_CMAP_OFF + 24) && glyph < (GLYPH_CMAP_OFF + 28) ) && !isimportantlocation(x, y) && !(glyph == (GLYPH_CMAP_OFF + 47) ) )
2730 glyph = cmap_to_glyph(S_stone);
2732 if ( (NotSeenBug || u.uprops[NOT_SEEN_BUG].extrinsic || have_nonseeingstone()) && !isimportantlocation(x, y) && ((glyph >= GLYPH_CMAP_OFF && glyph < (GLYPH_CMAP_OFF + 13) ) || (glyph == (GLYPH_CMAP_OFF + 47) ) ) )
2733 glyph = cmap_to_glyph(S_stone);
2735 if (!flags.wallglyph && !isimportantlocation(x, y) && glyph == (GLYPH_CMAP_OFF + 47)) glyph = cmap_to_glyph(S_stone);
2737 if (glyph >= MAX_GLYPH) {
2738 impossible("show_glyph: bad glyph %d [max %d] at (%d,%d).",
2739 glyph, MAX_GLYPH, x, y);
2740 return;
2743 /* [ALI] In transparent mode it is not sufficient just to consider
2744 * the foreground glyph, we also need to consider the background.
2745 * Rather than extend the display module to do this, for the time
2746 * being we just turn off optimization and rely on the windowing port
2747 * to ignore redundant calls to print_glyph().
2749 if (transp || gbuf[y][x].glyph != glyph) {
2750 gbuf[y][x].glyph = glyph;
2751 gbuf[y][x].new = 1;
2752 if (gbuf_start[y] > x) gbuf_start[y] = x;
2753 if (gbuf_stop[y] < x) gbuf_stop[y] = x;
2758 * Reset the changed glyph borders so that none of the 3rd screen has
2759 * changed.
2761 #define reset_glyph_bbox() \
2763 int i; \
2765 for (i = 0; i < ROWNO; i++) { \
2766 gbuf_start[i] = COLNO-1; \
2767 gbuf_stop[i] = 0; \
2772 static gbuf_entry nul_gbuf = { 0, cmap_to_glyph(S_stone) };
2774 * Turn the 3rd screen into stone.
2776 void
2777 clear_glyph_buffer()
2779 register int x, y;
2780 register gbuf_entry *gptr;
2782 for (y = 0; y < ROWNO; y++) {
2783 gptr = &gbuf[y][0];
2784 for (x = COLNO; x; x--) {
2785 *gptr++ = nul_gbuf;
2788 reset_glyph_bbox();
2792 * Assumes that the indicated positions are filled with S_stone glyphs.
2794 void
2795 row_refresh(start,stop,y)
2796 int start,stop,y;
2798 register int x;
2800 for (x = start; x <= stop; x++)
2801 if (gbuf[y][x].glyph != cmap_to_glyph(S_stone))
2802 print_glyph(WIN_MAP,x,y,gbuf[y][x].glyph);
2805 void
2806 cls()
2809 if (SpellColorYellow) return;
2811 display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */
2812 flags.botlx = 1; /* force update of botl window */
2813 clear_nhwindow(WIN_MAP); /* clear physical screen */
2814 clear_glyph_buffer(); /* this is sort of an extra effort, but OK */
2818 * Synch the third screen with the display.
2820 void
2821 flush_screen(cursor_on_u)
2822 int cursor_on_u;
2824 /* Prevent infinite loops on errors:
2825 * flush_screen->print_glyph->impossible->pline->flush_screen
2827 static boolean flushing = 0;
2828 static boolean delay_flushing = 0;
2829 register int x,y;
2831 if (cursor_on_u == -1) delay_flushing = !delay_flushing;
2832 if (delay_flushing) return;
2833 if (flushing) return; /* if already flushing then return */
2834 flushing = 1;
2836 if (program_state.done_hup)
2837 return;
2839 for (y = 0; y < ROWNO; y++) {
2840 register gbuf_entry *gptr = &gbuf[y][x = gbuf_start[y]];
2841 for (; x <= gbuf_stop[y]; gptr++, x++)
2842 if (gptr->new) {
2843 print_glyph(WIN_MAP,x,y,gptr->glyph);
2844 gptr->new = 0;
2848 if (cursor_on_u) curs(WIN_MAP, u.ux,u.uy); /* move cursor to the hero */
2849 display_nhwindow(WIN_MAP, FALSE);
2850 reset_glyph_bbox();
2851 #ifdef ALLEG_FX
2852 if (iflags.usealleg) alleg_vid_refresh();
2853 #endif
2854 flushing = 0;
2855 if(flags.botl || flags.botlx) bot();
2858 /* ========================================================================= */
2861 * back_to_cmap()
2863 * Use the information in the rm structure at the given position to create
2864 * a glyph of a background.
2866 * I had to add a field in the rm structure (horizontal) so that we knew
2867 * if open doors and secret doors were horizontal or vertical. Previously,
2868 * the screen symbol had the horizontal/vertical information set at
2869 * level generation time.
2871 * I used the 'ladder' field (really doormask) for deciding if stairwells
2872 * were up or down. I didn't want to check the upstairs and dnstairs
2873 * variables.
2875 STATIC_OVL int
2876 back_to_cmap(x,y)
2877 xchar x,y;
2879 int idx;
2880 struct rm *ptr = &(levl[x][y]);
2882 switch (ptr->typ) {
2883 /* KMH -- support arboreal levels */
2884 case SCORR:
2885 case STONE:
2886 idx = level.flags.arboreal ? S_tree : /*S_stone*/S_dungwall;
2887 break;
2888 case ROOM:
2890 if (MapTrapEffect || u.uprops[MAPBUG].extrinsic || have_mapstone()) idx = S_stone;
2892 else idx = (!cansee(x,y) && !ptr->waslit) ? S_darkroom : S_room;
2893 break;
2894 case CORR:
2896 if (MapTrapEffect || u.uprops[MAPBUG].extrinsic || have_mapstone()) idx = S_stone;
2898 else idx = (ptr->waslit || flags.lit_corridor) ? S_litcorr : S_corr;
2899 break;
2900 case HWALL:
2901 case VWALL:
2902 case TLCORNER:
2903 case TRCORNER:
2904 case BLCORNER:
2905 case BRCORNER:
2906 case CROSSWALL:
2907 case TUWALL:
2908 case TDWALL:
2909 case TLWALL:
2910 case TRWALL:
2911 case SDOOR:
2912 idx = ptr->seenv ? wall_angle(ptr) : /*S_stone*/S_dungwall;
2913 break;
2914 case IRONBARS: idx = S_bars; break;
2915 case DOOR:
2916 if (ptr->doormask) {
2917 if (ptr->doormask & D_BROKEN)
2918 idx = S_ndoor;
2919 else if (ptr->doormask & D_ISOPEN)
2920 idx = (ptr->horizontal) ? S_hodoor : S_vodoor;
2921 else /* else is closed */
2922 idx = (ptr->horizontal) ? S_hcdoor : S_vcdoor;
2923 } else
2924 idx = S_ndoor;
2925 break;
2926 case TREE: idx = S_tree; break;
2927 case POOL:
2928 case MOAT: idx = S_pool; break;
2929 case STAIRS:
2930 idx = (ptr->ladder & LA_DOWN) ? S_dnstair : S_upstair;
2931 break;
2932 case LADDER:
2933 idx = (ptr->ladder & LA_DOWN) ? S_dnladder : S_upladder;
2934 break;
2935 case FOUNTAIN: idx = S_fountain; break;
2936 case SINK: idx = S_sink; break;
2937 case TOILET: idx = S_toilet; break;
2938 case GRAVE: idx = S_grave; break;
2939 case ALTAR: idx = S_altar; break;
2940 case THRONE: idx = S_throne; break;
2941 case LAVAPOOL: idx = S_lava; break;
2942 case ICE: idx = S_ice; break;
2943 case AIR: idx = S_air; break;
2944 case CLOUD: idx = S_cloud; break;
2945 case WATER: idx = S_water; break;
2947 case ROCKWALL: idx = S_rockwall; break;
2948 case GRAVEWALL: idx = S_gravewall; break;
2949 case TUNNELWALL: idx = S_tunnelwall; break;
2950 case FARMLAND: idx = S_farmland; break;
2951 case MOUNTAIN: idx = S_mountain; break;
2952 case WATERTUNNEL: idx = S_watertunnel; break;
2953 case CRYSTALWATER: idx = S_crystalwater; break;
2954 case MOORLAND: idx = S_moorland; break;
2955 case URINELAKE: idx = S_urinelake; break;
2956 case SHIFTINGSAND: idx = S_shiftingsand; break;
2957 case STYXRIVER: idx = S_styxriver; break;
2958 case PENTAGRAM: idx = S_pentagram; break;
2959 case WELL: idx = S_well; break;
2960 case POISONEDWELL: idx = S_poisonedwell; break;
2961 case WAGON: idx = S_wagon; break;
2962 case BURNINGWAGON: idx = S_burningwagon; break;
2963 case WOODENTABLE: idx = S_woodentable; break;
2964 case CARVEDBED: idx = S_carvedbed; break;
2965 case STRAWMATTRESS: idx = S_strawmattress; break;
2966 case SNOW: idx = S_snow; break;
2967 case ASH: idx = S_ash; break;
2968 case SAND: idx = S_sand; break;
2969 case PAVEDFLOOR: idx = S_pavedfloor; break;
2970 case HIGHWAY: idx = S_highway; break;
2971 case GRASSLAND: idx = S_grassland; break;
2972 case NETHERMIST: idx = S_nethermist; break;
2973 case STALACTITE: idx = S_stalactite; break;
2974 case CRYPTFLOOR: idx = S_cryptfloor; break;
2975 case BUBBLES: idx = S_bubbles; break;
2976 case RAINCLOUD: idx = S_raincloud; break;
2978 case DBWALL:
2979 idx = (ptr->horizontal) ? S_hcdbridge : S_vcdbridge;
2980 break;
2981 case DRAWBRIDGE_UP:
2982 switch(ptr->drawbridgemask & DB_UNDER) {
2983 case DB_MOAT: idx = S_pool; break;
2984 case DB_LAVA: idx = S_lava; break;
2985 case DB_ICE: idx = S_ice; break;
2986 case DB_FLOOR: idx = (!cansee(x,y) && !ptr->waslit) ? S_darkroom : S_room; break;
2987 default:
2988 impossible("Strange db-under: %d",
2989 ptr->drawbridgemask & DB_UNDER);
2990 idx = (!cansee(x,y) && !ptr->waslit) ? S_darkroom : S_room; /* something is better than nothing */
2991 break;
2993 break;
2994 case DRAWBRIDGE_DOWN:
2995 idx = (ptr->horizontal) ? S_hodbridge : S_vodbridge;
2996 break;
2997 default:
2998 impossible("back_to_glyph: unknown level type [ = %d ]",ptr->typ);
2999 idx = (!cansee(x,y) && !ptr->waslit) ? S_darkroom : S_room;
3000 break;
3002 return idx;
3006 back_to_glyph(x,y)
3007 xchar x,y;
3009 return cmap_to_glyph(back_to_cmap(x,y));
3014 * swallow_to_glyph()
3016 * Convert a monster number and a swallow location into the correct glyph.
3017 * If you don't want a patchwork monster while hallucinating, decide on
3018 * a random monster in swallowed() and don't use what_mon() here.
3020 STATIC_OVL int
3021 swallow_to_glyph(mnum, loc)
3022 int mnum;
3023 int loc;
3025 if (loc < S_sw_tl || S_sw_br < loc) {
3026 impossible("swallow_to_glyph: bad swallow location");
3027 loc = S_sw_br;
3029 return ((int) (what_mon(mnum)<<3) | (loc - S_sw_tl)) + GLYPH_SWALLOW_OFF;
3035 * zapdir_to_glyph()
3037 * Change the given zap direction and beam type into a glyph. Each beam
3038 * type has four glyphs, one for each of the symbols below. The order of
3039 * the zap symbols [0-3] as defined in rm.h are:
3041 * | S_vbeam ( 0, 1) or ( 0,-1)
3042 * - S_hbeam ( 1, 0) or (-1, 0)
3043 * \ S_lslant ( 1, 1) or (-1,-1)
3044 * / S_rslant (-1, 1) or ( 1,-1)
3047 zapdir_to_glyph(dx, dy, beam_type)
3048 register int dx, dy;
3049 int beam_type;
3051 if (beam_type >= NUM_ZAP) {
3052 impossible("zapdir_to_glyph: illegal beam type");
3053 beam_type = 0;
3055 dx = (dx == dy) ? 2 : (dx && dy) ? 3 : dx ? 1 : 0;
3057 return ((int) ((beam_type << 2) | dx)) + GLYPH_ZAP_OFF;
3062 * Utility routine for dowhatis() used to find out the glyph displayed at
3063 * the location. This isn't necessarily the same as the glyph in the levl
3064 * structure, so we must check the "third screen".
3067 glyph_at(x, y)
3068 xchar x,y;
3070 if(x < 0 || y < 0 || x >= COLNO || y >= ROWNO)
3071 return cmap_to_glyph(S_room); /* XXX */
3072 return gbuf[y][x].glyph;
3076 /* ------------------------------------------------------------------------- */
3077 /* Wall Angle -------------------------------------------------------------- */
3079 /*#define WA_VERBOSE*/ /* give (x,y) locations for all "bad" spots */
3081 #ifdef WA_VERBOSE
3083 static const char *type_to_name(int);
3084 static void error4(int,int,int,int,int,int);
3086 static int bad_count[MAX_TYPE]; /* count of positions flagged as bad */
3087 static const char *type_names[MAX_TYPE] = {
3088 "STONE", "VWALL", "HWALL", "TLCORNER",
3089 "TRCORNER", "BLCORNER", "BRCORNER", "CROSSWALL",
3090 "TUWALL", "TDWALL", "TLWALL", "TRWALL",
3091 "DBWALL", "ROCKWALL", "GRAVEWALL", "TUNNELWALL", "SDOOR", "SCORR", "POOL",
3092 "MOAT", "WATER", "WATERTUNNEL", "CRYSTALWATER",
3093 "MOORLAND", "URINELAKE", "DRAWBRIDGE_UP", "SHIFTINGSAND", "LAVAPOOL",
3094 "STYXRIVER", "DOOR", "CORR", "ROOM", "STAIRS",
3095 "LADDER", "FOUNTAIN", "THRONE", "SINK",
3096 "ALTAR", "PENTAGRAM", "WELL", "POISONEDWELL",
3097 "WAGON", "BURNINGWAGON", "WOODENTABLE", "CARVEDBED", "STRAWMATTRESS",
3098 "ICE", "SNOW", "ASH", "SAND", "PAVEDFLOOR",
3099 "HIGHWAY", "GRASSLAND", "NETHERMIST", "STALACTITE", "CRYPTFLOOR",
3100 "DRAWBRIDGE_DOWN", "AIR",
3101 "CLOUD", "BUBBLES", "RAINCLOUD"
3105 static const char *
3106 type_to_name(type)
3107 int type;
3109 return (type < 0 || type > MAX_TYPE) ? "unknown" : type_names[type];
3112 STATIC_OVL void
3113 error4(x, y, a, b, c, dd)
3114 int x, y, a, b, c, dd;
3116 pline("set_wall_state: %s @ (%d,%d) %s%s%s%s",
3117 type_to_name(levl[x][y].typ), x, y,
3118 a ? "1":"", b ? "2":"", c ? "3":"", dd ? "4":"");
3119 bad_count[levl[x][y].typ]++;
3121 #endif /* WA_VERBOSE */
3124 * Return 'which' if position is implies an unfinshed exterior. Return
3125 * zero otherwise. Unfinished implies outer area is rock or a corridor.
3127 * Things that are ambigious: lava
3129 STATIC_OVL int
3130 check_pos(x, y, which)
3131 int x, y, which;
3133 int type;
3134 if (!isok(x,y)) return which;
3135 type = levl[x][y].typ;
3136 if (IS_ROCK(type) || type == CORR || type == SCORR) return which;
3137 return 0;
3140 /* Return TRUE if more than one is non-zero. */
3141 /*ARGSUSED*/
3142 #ifdef WA_VERBOSE
3143 STATIC_OVL boolean
3144 more_than_one(x, y, a, b, c)
3145 int x, y, a, b, c;
3147 #if defined(MAC_MPW)
3148 # pragma unused ( x,y )
3149 #endif
3150 if ((a && (b|c)) || (b && (a|c)) || (c && (a|b))) {
3151 error4(x,y,a,b,c,0);
3152 return TRUE;
3154 return FALSE;
3156 #else
3157 #define more_than_one(x, y, a, b, c) (((a) && ((b)|(c))) || ((b) && ((a)|(c))) || ((c) && ((a)|(b))))
3158 #endif
3160 /* Return the wall mode for a T wall. */
3161 STATIC_OVL int
3162 set_twall(x0,y0, x1,y1, x2,y2, x3,y3)
3163 int x0,y0, x1,y1, x2,y2, x3,y3;
3165 int wmode, is_1, is_2, is_3;
3167 is_1 = check_pos(x1, y1, WM_T_LONG);
3168 is_2 = check_pos(x2, y2, WM_T_BL);
3169 is_3 = check_pos(x3, y3, WM_T_BR);
3170 if (more_than_one(x0, y0, is_1, is_2, is_3)) {
3171 wmode = 0;
3172 } else {
3173 wmode = is_1 + is_2 + is_3;
3175 return wmode;
3178 /* Return wall mode for a horizontal or vertical wall. */
3179 STATIC_OVL int
3180 set_wall(x, y, horiz)
3181 int x, y, horiz;
3183 int wmode, is_1, is_2;
3185 if (horiz) {
3186 is_1 = check_pos(x,y-1, WM_W_TOP);
3187 is_2 = check_pos(x,y+1, WM_W_BOTTOM);
3188 } else {
3189 is_1 = check_pos(x-1,y, WM_W_LEFT);
3190 is_2 = check_pos(x+1,y, WM_W_RIGHT);
3192 if (more_than_one(x, y, is_1, is_2, 0)) {
3193 wmode = 0;
3194 } else {
3195 wmode = is_1 + is_2;
3197 return wmode;
3201 * If an invisible monster has gone away, that will be discovered. If an
3202 * invisible monster has appeared, this will _not_ be discovered since
3203 * searching only finds one monster per turn so we must check that separately.
3205 * Return a wall mode for a corner wall. (x4,y4) is the "inner" position.
3207 STATIC_OVL int
3208 set_corn(x1,y1, x2,y2, x3,y3, x4,y4)
3209 int x1, y1, x2, y2, x3, y3, x4, y4;
3211 int wmode, is_1, is_2, is_3, is_4;
3213 is_1 = check_pos(x1, y1, 1);
3214 is_2 = check_pos(x2, y2, 1);
3215 is_3 = check_pos(x3, y3, 1);
3216 is_4 = check_pos(x4, y4, 1); /* inner location */
3219 * All 4 should not be true. So if the inner location is rock,
3220 * use it. If all of the outer 3 are true, use outer. We currently
3221 * can't cover the case where only part of the outer is rock, so
3222 * we just say that all the walls are finished (if not overridden
3223 * by the inner section).
3225 if (is_4) {
3226 wmode = WM_C_INNER;
3227 } else if (is_1 && is_2 && is_3)
3228 wmode = WM_C_OUTER;
3229 else
3230 wmode = 0; /* finished walls on all sides */
3232 return wmode;
3235 /* Return mode for a crosswall. */
3236 STATIC_OVL int
3237 set_crosswall(x, y)
3238 int x, y;
3240 int wmode, is_1, is_2, is_3, is_4;
3242 is_1 = check_pos(x-1, y-1, 1);
3243 is_2 = check_pos(x+1, y-1, 1);
3244 is_3 = check_pos(x+1, y+1, 1);
3245 is_4 = check_pos(x-1, y+1, 1);
3247 wmode = is_1+is_2+is_3+is_4;
3248 if (wmode > 1) {
3249 if (is_1 && is_3 && (is_2+is_4 == 0)) {
3250 wmode = WM_X_TLBR;
3251 } else if (is_2 && is_4 && (is_1+is_3 == 0)) {
3252 wmode = WM_X_BLTR;
3253 } else {
3254 #ifdef WA_VERBOSE
3255 error4(x,y,is_1,is_2,is_3,is_4);
3256 #endif
3257 wmode = 0;
3259 } else if (is_1)
3260 wmode = WM_X_TL;
3261 else if (is_2)
3262 wmode = WM_X_TR;
3263 else if (is_3)
3264 wmode = WM_X_BR;
3265 else if (is_4)
3266 wmode = WM_X_BL;
3268 return wmode;
3271 /* Called from mklev. Scan the level and set the wall modes. */
3272 void
3273 set_wall_state()
3275 int x, y;
3276 int wmode;
3277 struct rm *lev;
3279 #ifdef WA_VERBOSE
3280 for (x = 0; x < MAX_TYPE; x++) bad_count[x] = 0;
3281 #endif
3283 for (x = 0; x < COLNO; x++)
3284 for (lev = &levl[x][0], y = 0; y < ROWNO; y++, lev++) {
3285 switch (lev->typ) {
3286 case SDOOR:
3287 wmode = set_wall(x, y, (int) lev->horizontal);
3288 break;
3289 case VWALL:
3290 wmode = set_wall(x, y, 0);
3291 break;
3292 case HWALL:
3293 wmode = set_wall(x, y, 1);
3294 break;
3295 case TDWALL:
3296 wmode = set_twall(x,y, x,y-1, x-1,y+1, x+1,y+1);
3297 break;
3298 case TUWALL:
3299 wmode = set_twall(x,y, x,y+1, x+1,y-1, x-1,y-1);
3300 break;
3301 case TLWALL:
3302 wmode = set_twall(x,y, x+1,y, x-1,y-1, x-1,y+1);
3303 break;
3304 case TRWALL:
3305 wmode = set_twall(x,y, x-1,y, x+1,y+1, x+1,y-1);
3306 break;
3307 case TLCORNER:
3308 wmode = set_corn(x-1,y-1, x,y-1, x-1,y, x+1,y+1);
3309 break;
3310 case TRCORNER:
3311 wmode = set_corn(x,y-1, x+1,y-1, x+1,y, x-1,y+1);
3312 break;
3313 case BLCORNER:
3314 wmode = set_corn(x,y+1, x-1,y+1, x-1,y, x+1,y-1);
3315 break;
3316 case BRCORNER:
3317 wmode = set_corn(x+1,y, x+1,y+1, x,y+1, x-1,y-1);
3318 break;
3319 case CROSSWALL:
3320 wmode = set_crosswall(x, y);
3321 break;
3323 default:
3324 wmode = -1; /* don't set wall info */
3325 break;
3328 if (wmode >= 0)
3329 lev->wall_info = (lev->wall_info & ~WM_MASK) | wmode;
3332 #ifdef WA_VERBOSE
3333 /* check if any bad positions found */
3334 for (x = y = 0; x < MAX_TYPE; x++)
3335 if (bad_count[x]) {
3336 if (y == 0) {
3337 y = 1; /* only print once */
3338 pline("set_wall_type: wall mode problems with: ");
3340 pline("%s %d;", type_names[x], bad_count[x]);
3342 #endif /* WA_VERBOSE */
3345 /* ------------------------------------------------------------------------- */
3346 /* This matrix is used here and in vision.c. */
3347 unsigned char seenv_matrix[3][3] = { {SV2, SV1, SV0},
3348 {SV3, SVALL, SV7},
3349 {SV4, SV5, SV6} };
3351 #define sign(z) ((z) < 0 ? -1 : ((z) > 0 ? 1 : 0))
3353 /* Set the seen vector of lev as if seen from (x0,y0) to (x,y). */
3354 STATIC_OVL void
3355 set_seenv(lev, x0, y0, x, y)
3356 struct rm *lev;
3357 int x0, y0, x, y; /* from, to */
3359 int dx = x-x0, dy = y0-y;
3360 lev->seenv |= seenv_matrix[sign(dy)+1][sign(dx)+1];
3363 /* ------------------------------------------------------------------------- */
3365 /* T wall types, one for each row in wall_matrix[][]. */
3366 #define T_d 0
3367 #define T_l 1
3368 #define T_u 2
3369 #define T_r 3
3372 * These are the column names of wall_matrix[][]. They are the "results"
3373 * of a tdwall pattern match. All T walls are rotated so they become
3374 * a tdwall. Then we do a single pattern match, but return the
3375 * correct result for the original wall by using different rows for
3376 * each of the wall types.
3378 #define T_stone 0
3379 #define T_tlcorn 1
3380 #define T_trcorn 2
3381 #define T_hwall 3
3382 #define T_tdwall 4
3384 static const int wall_matrix[4][5] = {
3385 { S_stone, S_tlcorn, S_trcorn, S_hwall, S_tdwall }, /* tdwall */
3386 { S_stone, S_trcorn, S_brcorn, S_vwall, S_tlwall }, /* tlwall */
3387 { S_stone, S_brcorn, S_blcorn, S_hwall, S_tuwall }, /* tuwall */
3388 { S_stone, S_blcorn, S_tlcorn, S_vwall, S_trwall }, /* trwall */
3392 /* Cross wall types, one for each "solid" quarter. Rows of cross_matrix[][]. */
3393 #define C_bl 0
3394 #define C_tl 1
3395 #define C_tr 2
3396 #define C_br 3
3399 * These are the column names for cross_matrix[][]. They express results
3400 * in C_br (bottom right) terms. All crosswalls with a single solid
3401 * quarter are rotated so the solid section is at the bottom right.
3402 * We pattern match on that, but return the correct result depending
3403 * on which row we'ere looking at.
3405 #define C_trcorn 0
3406 #define C_brcorn 1
3407 #define C_blcorn 2
3408 #define C_tlwall 3
3409 #define C_tuwall 4
3410 #define C_crwall 5
3412 static const int cross_matrix[4][6] = {
3413 { S_brcorn, S_blcorn, S_tlcorn, S_tuwall, S_trwall, S_crwall },
3414 { S_blcorn, S_tlcorn, S_trcorn, S_trwall, S_tdwall, S_crwall },
3415 { S_tlcorn, S_trcorn, S_brcorn, S_tdwall, S_tlwall, S_crwall },
3416 { S_trcorn, S_brcorn, S_blcorn, S_tlwall, S_tuwall, S_crwall },
3419 /* for hardcore cloth etc.: is this tile "behind" you (meaning you cannot see it)? --Amy
3420 * return TRUE if you can "see" the tile, FALSE otherwise */
3421 boolean
3422 facingtile(tx, ty)
3423 int tx, ty;
3425 switch (u.trontrapdirection) {
3426 case 1: /* east */
3427 if (u.ux > tx) return FALSE;
3428 break;
3429 case 2: /* southeast */
3430 if (u.ux > tx && !(u.uy < ty && (abs(u.uy - ty) >= abs(u.ux - tx)) ) ) return FALSE;
3431 if (u.uy > ty && !(u.ux < tx && (abs(u.ux - tx) >= abs(u.uy - ty)) ) ) return FALSE;
3432 break;
3433 case 3: /* north */
3434 if (u.uy < ty) return FALSE;
3435 break;
3436 case 4: /* northwest */
3437 if (u.ux < tx && !(u.uy > ty && (abs(u.uy - ty) >= abs(u.ux - tx)) ) ) return FALSE;
3438 if (u.uy < ty && !(u.ux > tx && (abs(u.ux - tx) >= abs(u.uy - ty)) ) ) return FALSE;
3439 break;
3440 case 5: /* west */
3441 if (u.ux < tx) return FALSE;
3442 break;
3443 case 6: /* southwest */
3444 if (u.ux < tx && !(u.uy < ty && (abs(u.uy - ty) >= abs(u.ux - tx)) ) ) return FALSE;
3445 if (u.uy > ty && !(u.ux > tx && (abs(u.ux - tx) >= abs(u.uy - ty)) ) ) return FALSE;
3446 break;
3447 case 7: /* south */
3448 if (u.uy > ty) return FALSE;
3449 break;
3450 case 8: /* northeast */
3451 if (u.ux > tx && !(u.uy > ty && (abs(u.uy - ty) >= abs(u.ux - tx)) ) ) return FALSE;
3452 if (u.uy < ty && !(u.ux < tx && (abs(u.ux - tx) >= abs(u.uy - ty)) ) ) return FALSE;
3453 break;
3456 return TRUE;
3459 /* Print out a T wall warning and all interesting info. */
3460 STATIC_OVL void
3461 t_warn(lev)
3462 struct rm *lev;
3464 static const char warn_str[] = "wall_angle: %s: case %d: seenv = 0x%x";
3465 const char *wname;
3467 if (lev->typ == TUWALL) wname = "tuwall";
3468 else if (lev->typ == TLWALL) wname = "tlwall";
3469 else if (lev->typ == TRWALL) wname = "trwall";
3470 else if (lev->typ == TDWALL) wname = "tdwall";
3471 else wname = "unknown";
3472 impossible(warn_str, wname, lev->wall_info & WM_MASK,
3473 (unsigned int) lev->seenv);
3478 * Return the correct graphics character index using wall type, wall mode,
3479 * and the seen vector. It is expected that seenv is non zero.
3481 * All T-wall vectors are rotated to be TDWALL. All single crosswall
3482 * blocks are rotated to bottom right. All double crosswall are rotated
3483 * to W_X_BLTR. All results are converted back.
3485 * The only way to understand this is to take out pen and paper and
3486 * draw diagrams. See rm.h for more details on the wall modes and
3487 * seen vector (SV).
3489 STATIC_OVL int
3490 wall_angle(lev)
3491 struct rm *lev;
3493 register unsigned int seenv = lev->seenv & 0xff;
3494 const int *row;
3495 int col, idx;
3497 #define only(sv, bits) (((sv) & (bits)) && ! ((sv) & ~(bits)))
3498 switch (lev->typ) {
3499 case TUWALL:
3500 row = wall_matrix[T_u];
3501 seenv = (seenv >> 4 | seenv << 4) & 0xff;/* rotate to tdwall */
3502 goto do_twall;
3503 case TLWALL:
3504 row = wall_matrix[T_l];
3505 seenv = (seenv >> 2 | seenv << 6) & 0xff;/* rotate to tdwall */
3506 goto do_twall;
3507 case TRWALL:
3508 row = wall_matrix[T_r];
3509 seenv = (seenv >> 6 | seenv << 2) & 0xff;/* rotate to tdwall */
3510 goto do_twall;
3511 case TDWALL:
3512 row = wall_matrix[T_d];
3513 do_twall:
3514 switch (lev->wall_info & WM_MASK) {
3515 case 0:
3516 if (seenv == SV4) {
3517 col = T_tlcorn;
3518 } else if (seenv == SV6) {
3519 col = T_trcorn;
3520 } else if (seenv & (SV3|SV5|SV7) ||
3521 ((seenv & SV4) && (seenv & SV6))) {
3522 col = T_tdwall;
3523 } else if (seenv & (SV0|SV1|SV2)) {
3524 col = (seenv & (SV4|SV6) ? T_tdwall : T_hwall);
3525 } else {
3526 t_warn(lev);
3527 col = T_stone;
3529 break;
3530 case WM_T_LONG:
3531 if (seenv & (SV3|SV4) && !(seenv & (SV5|SV6|SV7))) {
3532 col = T_tlcorn;
3533 } else if (seenv&(SV6|SV7) && !(seenv&(SV3|SV4|SV5))) {
3534 col = T_trcorn;
3535 } else if ((seenv & SV5) ||
3536 ((seenv & (SV3|SV4)) && (seenv & (SV6|SV7)))) {
3537 col = T_tdwall;
3538 } else {
3539 /* only SV0|SV1|SV2 */
3540 if (! only(seenv, SV0|SV1|SV2) )
3541 t_warn(lev);
3542 col = T_stone;
3544 break;
3545 case WM_T_BL:
3546 #if 0 /* older method, fixed */
3547 if (only(seenv, SV4|SV5)) {
3548 col = T_tlcorn;
3549 } else if ((seenv & (SV0|SV1|SV2)) &&
3550 only(seenv, SV0|SV1|SV2|SV6|SV7)) {
3551 col = T_hwall;
3552 } else if (seenv & SV3 ||
3553 ((seenv & (SV0|SV1|SV2)) && (seenv & (SV4|SV5)))) {
3554 col = T_tdwall;
3555 } else {
3556 if (seenv != SV6)
3557 t_warn(lev);
3558 col = T_stone;
3560 #endif /* 0 */
3561 if (only(seenv, SV4|SV5))
3562 col = T_tlcorn;
3563 else if ((seenv & (SV0|SV1|SV2|SV7)) &&
3564 !(seenv & (SV3|SV4|SV5)))
3565 col = T_hwall;
3566 else if (only(seenv, SV6))
3567 col = T_stone;
3568 else
3569 col = T_tdwall;
3570 break;
3571 case WM_T_BR:
3572 #if 0 /* older method, fixed */
3573 if (only(seenv, SV5|SV6)) {
3574 col = T_trcorn;
3575 } else if ((seenv & (SV0|SV1|SV2)) &&
3576 only(seenv, SV0|SV1|SV2|SV3|SV4)) {
3577 col = T_hwall;
3578 } else if (seenv & SV7 ||
3579 ((seenv & (SV0|SV1|SV2)) && (seenv & (SV5|SV6)))) {
3580 col = T_tdwall;
3581 } else {
3582 if (seenv != SV4)
3583 t_warn(lev);
3584 col = T_stone;
3586 #endif /* 0 */
3587 if (only(seenv, SV5|SV6))
3588 col = T_trcorn;
3589 else if ((seenv & (SV0|SV1|SV2|SV3)) &&
3590 !(seenv & (SV5|SV6|SV7)))
3591 col = T_hwall;
3592 else if (only(seenv, SV4))
3593 col = T_stone;
3594 else
3595 col = T_tdwall;
3597 break;
3598 default:
3599 if (wizard) impossible("wall_angle: unknown T wall mode %d",
3600 lev->wall_info & WM_MASK);
3601 col = T_stone;
3602 break;
3604 idx = row[col];
3605 break;
3607 case SDOOR:
3608 if (lev->horizontal) goto horiz;
3609 /* fall through */
3610 case VWALL:
3611 switch (lev->wall_info & WM_MASK) {
3612 case 0: idx = seenv ? S_vwall : /*S_stone*/S_dungwall; break;
3613 case 1: idx = seenv & (SV1|SV2|SV3|SV4|SV5) ? S_vwall :
3614 /*S_stone*/S_dungwall;
3615 break;
3616 case 2: idx = seenv & (SV0|SV1|SV5|SV6|SV7) ? S_vwall :
3617 /*S_stone*/S_dungwall;
3618 break;
3619 default:
3620 if (wizard) impossible("wall_angle: unknown vwall mode %d",
3621 lev->wall_info & WM_MASK);
3622 idx = /*S_stone*/S_dungwall;
3623 break;
3625 break;
3627 case HWALL:
3628 horiz:
3629 switch (lev->wall_info & WM_MASK) {
3630 case 0: idx = seenv ? S_hwall : /*S_stone*/S_dungwall; break;
3631 case 1: idx = seenv & (SV3|SV4|SV5|SV6|SV7) ? S_hwall :
3632 /*S_stone*/S_dungwall;
3633 break;
3634 case 2: idx = seenv & (SV0|SV1|SV2|SV3|SV7) ? S_hwall :
3635 /*S_stone*/S_dungwall;
3636 break;
3637 default:
3638 if (wizard) impossible("wall_angle: unknown hwall mode %d",
3639 lev->wall_info & WM_MASK);
3640 idx = /*S_stone*/S_dungwall;
3641 break;
3643 break;
3645 #define set_corner(idx, lev, which, outer, inner, name) \
3646 switch ((lev)->wall_info & WM_MASK) { \
3647 case 0: idx = which; break; \
3648 case WM_C_OUTER: idx = seenv & (outer) ? which : /*S_stone*/S_dungwall; break; \
3649 case WM_C_INNER: idx = seenv & ~(inner) ? which : /*S_stone*/S_dungwall; break; \
3650 default: \
3651 if (wizard) impossible("wall_angle: unknown %s mode %d", name, \
3652 (lev)->wall_info & WM_MASK); \
3653 idx = /*S_stone*/S_dungwall; \
3654 break; \
3657 case TLCORNER:
3658 set_corner(idx, lev, S_tlcorn, (SV3|SV4|SV5), SV4, "tlcorn");
3659 break;
3660 case TRCORNER:
3661 set_corner(idx, lev, S_trcorn, (SV5|SV6|SV7), SV6, "trcorn");
3662 break;
3663 case BLCORNER:
3664 set_corner(idx, lev, S_blcorn, (SV1|SV2|SV3), SV2, "blcorn");
3665 break;
3666 case BRCORNER:
3667 set_corner(idx, lev, S_brcorn, (SV7|SV0|SV1), SV0, "brcorn");
3668 break;
3671 case CROSSWALL:
3672 switch (lev->wall_info & WM_MASK) {
3673 case 0:
3674 if (seenv == SV0)
3675 idx = S_brcorn;
3676 else if (seenv == SV2)
3677 idx = S_blcorn;
3678 else if (seenv == SV4)
3679 idx = S_tlcorn;
3680 else if (seenv == SV6)
3681 idx = S_trcorn;
3682 else if (!(seenv & ~(SV0|SV1|SV2)) &&
3683 (seenv & SV1 || seenv == (SV0|SV2)))
3684 idx = S_tuwall;
3685 else if (!(seenv & ~(SV2|SV3|SV4)) &&
3686 (seenv & SV3 || seenv == (SV2|SV4)))
3687 idx = S_trwall;
3688 else if (!(seenv & ~(SV4|SV5|SV6)) &&
3689 (seenv & SV5 || seenv == (SV4|SV6)))
3690 idx = S_tdwall;
3691 else if (!(seenv & ~(SV0|SV6|SV7)) &&
3692 (seenv & SV7 || seenv == (SV0|SV6)))
3693 idx = S_tlwall;
3694 else
3695 idx = S_crwall;
3696 break;
3698 case WM_X_TL:
3699 row = cross_matrix[C_tl];
3700 seenv = (seenv >> 4 | seenv << 4) & 0xff;
3701 goto do_crwall;
3702 case WM_X_TR:
3703 row = cross_matrix[C_tr];
3704 seenv = (seenv >> 6 | seenv << 2) & 0xff;
3705 goto do_crwall;
3706 case WM_X_BL:
3707 row = cross_matrix[C_bl];
3708 seenv = (seenv >> 2 | seenv << 6) & 0xff;
3709 goto do_crwall;
3710 case WM_X_BR:
3711 row = cross_matrix[C_br];
3712 do_crwall:
3713 if (seenv == SV4)
3714 idx = /*S_stone*/S_dungwall;
3715 else {
3716 seenv = seenv & ~SV4; /* strip SV4 */
3717 if (seenv == SV0) {
3718 col = C_brcorn;
3719 } else if (seenv & (SV2|SV3)) {
3720 if (seenv & (SV5|SV6|SV7))
3721 col = C_crwall;
3722 else if (seenv & (SV0|SV1))
3723 col = C_tuwall;
3724 else
3725 col = C_blcorn;
3726 } else if (seenv & (SV5|SV6)) {
3727 if (seenv & (SV1|SV2|SV3))
3728 col = C_crwall;
3729 else if (seenv & (SV0|SV7))
3730 col = C_tlwall;
3731 else
3732 col = C_trcorn;
3733 } else if (seenv & SV1) {
3734 col = seenv & SV7 ? C_crwall : C_tuwall;
3735 } else if (seenv & SV7) {
3736 col = seenv & SV1 ? C_crwall : C_tlwall;
3737 } else {
3738 if (wizard) impossible(
3739 "wall_angle: bottom of crwall check");
3740 col = C_crwall;
3743 idx = row[col];
3745 break;
3747 case WM_X_TLBR:
3748 if ( only(seenv, SV1|SV2|SV3) )
3749 idx = S_blcorn;
3750 else if ( only(seenv, SV5|SV6|SV7) )
3751 idx = S_trcorn;
3752 else if ( only(seenv, SV0|SV4) )
3753 idx = /*S_stone*/S_dungwall;
3754 else
3755 idx = S_crwall;
3756 break;
3758 case WM_X_BLTR:
3759 if ( only(seenv, SV0|SV1|SV7) )
3760 idx = S_brcorn;
3761 else if ( only(seenv, SV3|SV4|SV5) )
3762 idx = S_tlcorn;
3763 else if ( only(seenv, SV2|SV6) )
3764 idx = /*S_stone*/S_dungwall;
3765 else
3766 idx = S_crwall;
3767 break;
3769 default:
3770 if (wizard) impossible("wall_angle: unknown crosswall mode");
3771 idx = /*S_stone*/S_dungwall;
3772 break;
3774 break;
3776 default:
3777 if (wizard) impossible("wall_angle: unexpected wall type %d", lev->typ);
3778 idx = /*S_stone*/S_dungwall;
3780 return idx;
3783 boolean
3784 sensemon(mon)
3785 struct monst *mon;
3787 if (mon->data->msound == MS_DEEPSTATE) return FALSE;
3788 if (mon->egotype_deepstatemember) return FALSE;
3789 if (uarmh && uarmh->oartifact == ART_RADAR_NOT_WORKING) return FALSE;
3790 if (isselfhybrid && (moves % 3 == 0) ) return FALSE;
3792 if (tp_sensemon(mon)) return TRUE;
3793 if (Detect_monsters) return TRUE;
3794 if (MATCH_WARN_OF_MON(mon)) return TRUE;
3795 if (Role_if(PM_ACTIVISTOR) && mon->data == &mons[PM_TOPMODEL]) return TRUE;
3796 if (Race_if(PM_PEACEMAKER) && mon->data == &mons[PM_TOPMODEL]) return TRUE;
3797 if (Role_if(PM_ACTIVISTOR) && type_is_pname(mon->data) && uwep && is_quest_artifact(uwep) ) return TRUE;
3798 if (uamul && uamul->otyp == AMULET_OF_POISON_WARNING && poisonous(mon->data) ) return TRUE;
3799 if (Role_if(PM_PALADIN) && is_demon(mon->data) ) return TRUE;
3800 if (uarms && uarms->oartifact == ART_SHIELD_OF_THE_PALADIN && is_demon(mon->data) ) return TRUE;
3801 if (uarms && uarms->oartifact == ART_SHIELD_OF_THE_CHEVALIER__W && is_demon(mon->data) ) return TRUE;
3802 if (uarmc && uarmc->oartifact == ART_DEMONIC_UNDEAD_RADAR && is_demon(mon->data) ) return TRUE;
3803 if (uwep && uwep->oartifact == ART_DAEDRA_SEEKER && mon->data->mlet == S_DEMON ) return TRUE;
3804 if (Race_if(PM_VORTEX) && unsolid(mon->data) ) return TRUE;
3805 if (Race_if(PM_VORTEX) && nolimbs(mon->data) ) return TRUE;
3806 if (Race_if(PM_CORTEX) && unsolid(mon->data) ) return TRUE;
3807 if (Race_if(PM_CORTEX) && nolimbs(mon->data) ) return TRUE;
3808 if (uamul && uamul->otyp == AMULET_OF_OWN_RACE_WARNING && your_race(mon->data) ) return TRUE;
3809 if (uamul && uamul->otyp == AMULET_OF_COVETOUS_WARNING && (is_covetous(mon->data) || mon->egotype_covetous) ) return TRUE;
3810 if (uarmh && uarmh->oartifact == ART_THAT_GIVES_IT_NOT && (is_covetous(mon->data) || mon->egotype_covetous) ) return TRUE;
3811 if (uarmh && uarmh->oartifact == ART_HEARING_EAR && (is_covetous(mon->data) || mon->egotype_covetous) ) return TRUE;
3812 if (ublindf && ublindf->otyp == BOSS_VISOR && (is_covetous(mon->data) || mon->egotype_covetous) ) return TRUE;
3813 if (uarmf && uarmf->oartifact == ART_FINAL_EXAM_TIME && (mon->data->geno & G_UNIQ)) return TRUE;
3814 if (uarm && uarm->oartifact == ART_JEFFERSON_S_LOOKAROUND && bigmonst(mon->data) && distu(mon->mx, mon->my) < 101) return TRUE;
3815 if ((uarmh && itemhasappearance(uarmh, APP_INTERNET_HELMET) ) && mon->internetvisible) return TRUE;
3816 if (RngeInternetAccess && mon->internetvisible) return TRUE;
3817 if (uarmh && uarmh->oartifact == ART_WEB_RADIO && mon->internetvisible) return TRUE;
3818 if (Stunnopathy && Stunned && always_hostile(mon->data) && mon->stunnovisible && distu(mon->mx, mon->my) < (StrongStunnopathy ? 401 : 226)) return TRUE;
3819 if (Numbopathy && Numbed && (avoid_player(mon->data) || mon->egotype_avoider) && distu(mon->mx, mon->my) < (StrongNumbopathy ? 901 : 626) ) return TRUE;
3820 if (Sickopathy && Sick && extra_nasty(mon->data) && distu(mon->mx, mon->my) < (StrongSickopathy ? 901 : 401) ) return TRUE;
3821 if (Freezopathy && Frozen && mon->data->mcolor == CLR_WHITE && distu(mon->mx, mon->my) < (StrongFreezopathy ? 626 : 401) ) return TRUE;
3822 if (StrongStunnopathy && Stunned && dmgtype(mon->data, AD_STUN)) return TRUE;
3823 if (StrongNumbopathy && Numbed && (dmgtype(mon->data, AD_NUMB) || dmgtype(mon->data, AD_PLYS) ) ) return TRUE;
3824 if (StrongDimmopathy && Dimmed && (dmgtype(mon->data, AD_DIMN) || mon->data->msound == MS_CUSS ) ) return TRUE;
3825 if (StrongFreezopathy && Frozen && (dmgtype(mon->data, AD_FRZE) || dmgtype(mon->data, AD_ICEB) ) ) return TRUE;
3826 if (StrongCorrosivity && Slimed && acidic(mon->data) && distu(mon->mx, mon->my) < 226 ) return TRUE;
3827 if (StrongBurnopathy && Burned && (dmgtype(mon->data, AD_BURN) || dmgtype(mon->data, AD_FLAM) ) ) return TRUE;
3828 if (uarm && uarm->oartifact == ART_RNG_CESSATION && (dmgtype(mon->data, AD_RBRE) || dmgtype(mon->data, AD_RNG) ) ) return TRUE;
3829 if (StrongSickopathy && Sick && (dmgtype(mon->data, AD_DISE) || dmgtype(mon->data, AD_PEST) ) ) return TRUE;
3830 if (ScentView && distu(mon->mx, mon->my) < 101 && mon->scentvisible && (is_animal(mon->data) || mon->data->msound == MS_STENCH) ) return TRUE;
3831 if (uwep && uwep->oartifact == ART_SWISS_AMY_KNIFE && mon->data->msound == MS_SHOE) return TRUE;
3832 if (uwep && uwep->oartifact == ART_JENNY_S_PROTECTER && uwep->lamplit && mon->data->msound == MS_MOLEST) return TRUE;
3833 if (EcholocationActive && distu(mon->mx, mon->my) < 626 && mon->echolocatevisible && (dmgtype(mon->data, AD_SOUN) || mon->data->msound == MS_SOUND || mon->data->msound == MS_SHRIEK || mon->data->msound == MS_FART_NORMAL || mon->data->msound == MS_FART_LOUD || mon->data->msound == MS_FART_QUIET ) ) return TRUE;
3834 if (uarmh && uarmh->otyp == HELM_OF_UNLIVING_ESP && mon->data->mlet == S_GOLEM && distu(mon->mx, mon->my) < 626) return TRUE;
3835 if (uarmh && uarmh->otyp == HELM_OF_UNLIVING_ESP && mindless(mon->data) && distu(mon->mx, mon->my) < 26) return TRUE;
3836 if (uarmf && uarmf->oartifact == ART_VERA_S_FREEZER && mon->data->mcolor == CLR_WHITE) return TRUE;
3837 if (Burnopathy && Burned && infravision(mon->data) && distu(mon->mx, mon->my) < (StrongBurnopathy ? 170 : 101) ) return TRUE;
3838 if (Dimmopathy && Dimmed && mon->m_lev > u.ulevel && distu(mon->mx, mon->my) < (StrongDimmopathy ? 226 : 101) ) return TRUE;
3839 if (Race_if(PM_RODNEYAN) && mon_has_amulet(mon)) return TRUE;
3840 if (Race_if(PM_RODNEYAN) && mon_has_special(mon)) return TRUE;
3841 if (Race_if(PM_LEVITATOR) && (is_flyer(mon->data) || mon->egotype_flying) ) return TRUE;
3842 if (uarmf && uarmf->oartifact == ART_ELENETTES && (mon->mhp < (mon->mhpmax * 9 / 10)) ) return TRUE;
3843 if (isselfhybrid && strongmonst(mon->data) && is_wanderer(mon->data) ) return TRUE;
3844 if (uarm && uarm->oartifact == ART_JOKE_S_OVER && is_jokemonster(mon->data) ) return TRUE;
3845 if (have_maybrittclick() && is_jokemonster(mon->data) ) return TRUE;
3846 if (uwep && uwep->oartifact == ART_TIGATOR_S_THORN && is_pokemon(mon->data) ) return TRUE;
3847 if (haveartileash(ART_PETCAMERA) && mon->mleashed) return TRUE;
3848 if (haveartileash(ART_ANNOYING_PET_MONITOR) && mon->mtame) return TRUE;
3849 if (uarmc && uarmc->oartifact == ART_SITHE_DED && mon->data->mlet == S_MUMMY) return TRUE;
3850 if (uarm && uarm->oartifact == ART_PATROL_S_ORDERS && (mon->data->mlet == S_ORC || mon->data->mlet == S_OGRE) ) return TRUE;
3851 if (uarmh && uarmh->oartifact == ART_CLIERVOYENS && distu(mon->mx, mon->my) < 9 ) return TRUE;
3852 if (uarm && uarm->oartifact == ART_PLAYER_RADAR && (is_mplayer(mon->data) || is_umplayer(mon->data)) ) return TRUE;
3853 if (uarmf && uarmf->oartifact == ART_AWAY_YOU_STALKER && is_stalker(mon->data) ) return TRUE;
3854 if (uarmh && itemhasappearance(uarmh, APP_SAGES_HELMET) && mon->minvis && mon->sagesvisible ) return TRUE;
3855 if (ublindf && ublindf->oartifact == ART_BREATHER_SHOW && attacktype(mon->data, AT_BREA)) return TRUE;
3856 if (uarmc && uarmc->oartifact == ART_POKEWALKER && is_pokemon(mon->data) ) return TRUE;
3857 if (uwep && uwep->oartifact == ART_EGRID_BUG && mon->data->mlet == S_XAN) return TRUE;
3858 if (uarmc && uarmc->oartifact == ART_BUGNOSE && (mon->data->mlet == S_ANT || mon->data->mlet == S_XAN) ) return TRUE;
3859 if (uamul && uamul->otyp == AMULET_OF_PET_VIEW && mon->mtame) return TRUE;
3860 if (uarmu && uarmu->oartifact == ART_HEEEEELEEEEEN && mon->mtame) return TRUE;
3861 if (uarmh && itemhasappearance(uarmh, APP_PETSENSE_HELMET) && mon->mtame) return TRUE;
3862 if (uarmf && uarmf->oartifact == ART_SNAILHUNT && (mon->data->mlet == S_BLOB || mon->data->mlet == S_WORM) ) return TRUE;
3863 if (uarmf && uarmf->oartifact == ART_CAMELIC_SCENT && (mon->data->mlet == S_ZOUTHERN || mon->data->mlet == S_YETI) ) return TRUE;
3864 if (uwep && uwep->oartifact == ART_FUYER_BREV && mon->data->mlet == S_FUNGUS) return TRUE;
3865 if (uwep && uwep->oartifact == ART_SNICKERSNACK && mon->data->mlet == S_JABBERWOCK) return TRUE;
3866 if (uarm && uarm->oartifact == ART_FUNGIRADAR && mon->data->mlet == S_FUNGUS) return TRUE;
3867 if (uarmf && uarmf->oartifact == ART_BOOTS_OF_THE_MACHINE && (mon->data->mlet == S_GOLEM || nonliving(mon->data) ) ) return TRUE;
3868 if (uarmf && uarmf->oartifact == ART_FD_DETH && (mon->data->mlet == S_DOG || mon->data->mlet == S_FELINE) ) return TRUE;
3869 if (uarmh && uarmh->oartifact == ART_DOGGO_FRIENDSHIP && mon->data->mlet == S_DOG) return TRUE;
3870 if (uarmg && uarmg->oartifact == ART_WHAT_S_UP_BITCHES && (mon->data->mlet == S_NYMPH) ) return TRUE;
3871 if (uwep && uwep->oartifact == ART_FISHING_GRANDPA && mon->data->mlet == S_EEL) return TRUE;
3872 if (uarmf && uarmf->oartifact == ART_PECTORAL_HEEL && distu(mon->mx, mon->my) < 101 && mon->data->mlet == S_EEL) return TRUE;
3873 if (uwep && uwep->oartifact == ART_PEOPLE_EATING_TRIDENT && mon->data->mlet == S_HUMAN) return TRUE;
3874 if (uwep && uwep->oartifact == ART_VAMPIREBANE && mon->data->mlet == S_VAMPIRE) return TRUE;
3875 if (uwep && uwep->oartifact == ART_GOLEMBANE && mon->data->mlet == S_GOLEM) return TRUE;
3876 if (uwep && uwep->oartifact == ART_EELBANE && mon->data->mlet == S_EEL) return TRUE;
3877 if (uwep && uwep->oartifact == ART_MAUI_S_FISHHOOK && mon->data->mlet == S_EEL) return TRUE;
3878 if (uarmf && uarmf->oartifact == ART_SUCH_A_LOVELY_SHARK && mon->data->mlet == S_EEL && mon->mpeaceful) return TRUE;
3879 if (uwep && uwep->oartifact == ART_DEMONSTRANTS_GO_HOME && mon->data->mlet == S_HUMAN) return TRUE;
3880 if (uarmu && uarmu->oartifact == ART_PEACE_ADVOCATE && mon->data->mlet == S_HUMAN) return TRUE;
3881 if (uwep && uwep->oartifact == ART_DOCTOR_JONES__AID && mon->data->mlet == S_SNAKE) return TRUE;
3882 if (uarmc && uarmc->oartifact == ART_KILO_MEGA_GIGA_TERA_PETA_E && (mon->data->mlet == S_KOP || mon->data->msound == MS_TREESQUAD) ) return TRUE;
3883 if (ublindf && ublindf->oartifact == ART_SEEING_THE_PERSON_ANYWAY && mon->data->maligntyp < 0 && distu(mon->mx, mon->my) < 26) return TRUE;
3884 if (uarmh && uarmh->otyp == GOOD_ESP_HELMET && mon->data->maligntyp > 0 && distu(mon->mx, mon->my) < 26) return TRUE;
3885 if (uwep && uwep->oartifact == ART_GOODBYE_TROLLS && mon->data->mlet == S_TROLL) return TRUE;
3886 if (uwep && uwep->oartifact == ART_ANTINSTANT_DEATH && mon->data->mlet == S_ANT) return TRUE;
3887 if (uwep && uwep->oartifact == ART_DRAGONLANCE && mon->data->mlet == S_DRAGON) return TRUE;
3888 if (uwep && uwep->oartifact == ART_MINI_PEOPLE_EATER && humanoid(mon->data)) return TRUE;
3889 if (uwep && uwep->oartifact == ART_INDIGENOUS_FUN && humanoid(mon->data)) return TRUE;
3890 if (uwep && uwep->oartifact == ART_ANIMALBANE && is_animal(mon->data)) return TRUE;
3891 if (uwep && uwep->oartifact == ART_SEE_ANIMALS && is_animal(mon->data)) return TRUE;
3892 if (isselfhybrid && monpolyok(mon->data) && !polyok(mon->data) && ((mon->data->mlevel < 30) || mon->selfhybridvisible ) ) return TRUE;
3894 return FALSE; /* catchall */
3897 /*display.c*/