OSDN Git Service

set trivial flags
[jnethack/source.git] / src / light.c
1 /* NetHack 3.6  light.c $NHDT-Date: 1446191876 2015/10/30 07:57:56 $  $NHDT-Branch: master $:$NHDT-Revision: 1.28 $ */
2 /* Copyright (c) Dean Luick, 1994                                       */
3 /* NetHack may be freely redistributed.  See license for details.       */
4
5 /* JNetHack Copyright */
6 /* For 3.6-, Copyright (c) SHIRAKATA Kentaro, 2002-2019            */
7 /* JNetHack may be freely redistributed.  See license for details. */
8
9 #include "hack.h"
10 #include "lev.h" /* for checking save modes */
11
12 /*
13  * Mobile light sources.
14  *
15  * This implementation minimizes memory at the expense of extra
16  * recalculations.
17  *
18  * Light sources are "things" that have a physical position and range.
19  * They have a type, which gives us information about them.  Currently
20  * they are only attached to objects and monsters.  Note well:  the
21  * polymorphed-player handling assumes that both youmonst.m_id and
22  * youmonst.mx will always remain 0.
23  *
24  * Light sources, like timers, either follow game play (RANGE_GLOBAL) or
25  * stay on a level (RANGE_LEVEL).  Light sources are unique by their
26  * (type, id) pair.  For light sources attached to objects, this id
27  * is a pointer to the object.
28  *
29  * The major working function is do_light_sources(). It is called
30  * when the vision system is recreating its "could see" array.  Here
31  * we add a flag (TEMP_LIT) to the array for all locations that are lit
32  * via a light source.  The bad part of this is that we have to
33  * re-calculate the LOS of each light source every time the vision
34  * system runs.  Even if the light sources and any topology (vision blocking
35  * positions) have not changed.  The good part is that no extra memory
36  * is used, plus we don't have to figure out how far the sources have moved,
37  * or if the topology has changed.
38  *
39  * The structure of the save/restore mechanism is amazingly similar to
40  * the timer save/restore.  This is because they both have the same
41  * principals of having pointers into objects that must be recalculated
42  * across saves and restores.
43  */
44
45 /* flags */
46 #define LSF_SHOW 0x1        /* display the light source */
47 #define LSF_NEEDS_FIXUP 0x2 /* need oid fixup */
48
49 static light_source *light_base = 0;
50
51 STATIC_DCL void FDECL(write_ls, (int, light_source *));
52 STATIC_DCL int FDECL(maybe_write_ls, (int, int, BOOLEAN_P));
53
54 /* imported from vision.c, for small circles */
55 extern char circle_data[];
56 extern char circle_start[];
57
58 /* Create a new light source.  */
59 void
60 new_light_source(x, y, range, type, id)
61 xchar x, y;
62 int range, type;
63 anything *id;
64 {
65     light_source *ls;
66
67     if (range > MAX_RADIUS || range < 1) {
68         impossible("new_light_source:  illegal range %d", range);
69         return;
70     }
71
72     ls = (light_source *) alloc(sizeof(light_source));
73
74     ls->next = light_base;
75     ls->x = x;
76     ls->y = y;
77     ls->range = range;
78     ls->type = type;
79     ls->id = *id;
80     ls->flags = 0;
81     light_base = ls;
82
83     vision_full_recalc = 1; /* make the source show up */
84 }
85
86 /*
87  * Delete a light source. This assumes only one light source is attached
88  * to an object at a time.
89  */
90 void
91 del_light_source(type, id)
92 int type;
93 anything *id;
94 {
95     light_source *curr, *prev;
96     anything tmp_id;
97
98     tmp_id = zeroany;
99     /* need to be prepared for dealing a with light source which
100        has only been partially restored during a level change
101        (in particular: chameleon vs prot. from shape changers) */
102     switch (type) {
103     case LS_OBJECT:
104         tmp_id.a_uint = id->a_obj->o_id;
105         break;
106     case LS_MONSTER:
107         tmp_id.a_uint = id->a_monst->m_id;
108         break;
109     default:
110         tmp_id.a_uint = 0;
111         break;
112     }
113
114     for (prev = 0, curr = light_base; curr; prev = curr, curr = curr->next) {
115         if (curr->type != type)
116             continue;
117         if (curr->id.a_obj
118             == ((curr->flags & LSF_NEEDS_FIXUP) ? tmp_id.a_obj : id->a_obj)) {
119             if (prev)
120                 prev->next = curr->next;
121             else
122                 light_base = curr->next;
123
124             free((genericptr_t) curr);
125             vision_full_recalc = 1;
126             return;
127         }
128     }
129     impossible("del_light_source: not found type=%d, id=%s", type,
130                fmt_ptr((genericptr_t) id->a_obj));
131 }
132
133 /* Mark locations that are temporarily lit via mobile light sources. */
134 void
135 do_light_sources(cs_rows)
136 char **cs_rows;
137 {
138     int x, y, min_x, max_x, max_y, offset;
139     char *limits;
140     short at_hero_range = 0;
141     light_source *ls;
142     char *row;
143
144     for (ls = light_base; ls; ls = ls->next) {
145         ls->flags &= ~LSF_SHOW;
146
147         /*
148          * Check for moved light sources.  It may be possible to
149          * save some effort if an object has not moved, but not in
150          * the current setup -- we need to recalculate for every
151          * vision recalc.
152          */
153         if (ls->type == LS_OBJECT) {
154             if (get_obj_location(ls->id.a_obj, &ls->x, &ls->y, 0))
155                 ls->flags |= LSF_SHOW;
156         } else if (ls->type == LS_MONSTER) {
157             if (get_mon_location(ls->id.a_monst, &ls->x, &ls->y, 0))
158                 ls->flags |= LSF_SHOW;
159         }
160
161         /* minor optimization: don't bother with duplicate light sources */
162         /* at hero */
163         if (ls->x == u.ux && ls->y == u.uy) {
164             if (at_hero_range >= ls->range)
165                 ls->flags &= ~LSF_SHOW;
166             else
167                 at_hero_range = ls->range;
168         }
169
170         if (ls->flags & LSF_SHOW) {
171             /*
172              * Walk the points in the circle and see if they are
173              * visible from the center.  If so, mark'em.
174              *
175              * Kevin's tests indicated that doing this brute-force
176              * method is faster for radius <= 3 (or so).
177              */
178             limits = circle_ptr(ls->range);
179             if ((max_y = (ls->y + ls->range)) >= ROWNO)
180                 max_y = ROWNO - 1;
181             if ((y = (ls->y - ls->range)) < 0)
182                 y = 0;
183             for (; y <= max_y; y++) {
184                 row = cs_rows[y];
185                 offset = limits[abs(y - ls->y)];
186                 if ((min_x = (ls->x - offset)) < 0)
187                     min_x = 0;
188                 if ((max_x = (ls->x + offset)) >= COLNO)
189                     max_x = COLNO - 1;
190
191                 if (ls->x == u.ux && ls->y == u.uy) {
192                     /*
193                      * If the light source is located at the hero, then
194                      * we can use the COULD_SEE bits already calculated
195                      * by the vision system.  More importantly than
196                      * this optimization, is that it allows the vision
197                      * system to correct problems with clear_path().
198                      * The function clear_path() is a simple LOS
199                      * path checker that doesn't go out of its way
200                      * make things look "correct".  The vision system
201                      * does this.
202                      */
203                     for (x = min_x; x <= max_x; x++)
204                         if (row[x] & COULD_SEE)
205                             row[x] |= TEMP_LIT;
206                 } else {
207                     for (x = min_x; x <= max_x; x++)
208                         if ((ls->x == x && ls->y == y)
209                             || clear_path((int) ls->x, (int) ls->y, x, y))
210                             row[x] |= TEMP_LIT;
211                 }
212             }
213         }
214     }
215 }
216
217 /* (mon->mx == 0) implies migrating */
218 #define mon_is_local(mon) ((mon)->mx > 0)
219
220 struct monst *
221 find_mid(nid, fmflags)
222 unsigned nid;
223 unsigned fmflags;
224 {
225     struct monst *mtmp;
226
227     if (!nid)
228         return &youmonst;
229     if (fmflags & FM_FMON)
230         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
231             if (!DEADMONSTER(mtmp) && mtmp->m_id == nid)
232                 return mtmp;
233     if (fmflags & FM_MIGRATE)
234         for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon)
235             if (mtmp->m_id == nid)
236                 return mtmp;
237     if (fmflags & FM_MYDOGS)
238         for (mtmp = mydogs; mtmp; mtmp = mtmp->nmon)
239             if (mtmp->m_id == nid)
240                 return mtmp;
241     return (struct monst *) 0;
242 }
243
244 /* Save all light sources of the given range. */
245 void
246 save_light_sources(fd, mode, range)
247 int fd, mode, range;
248 {
249     int count, actual, is_global;
250     light_source **prev, *curr;
251
252     if (perform_bwrite(mode)) {
253         count = maybe_write_ls(fd, range, FALSE);
254         bwrite(fd, (genericptr_t) &count, sizeof count);
255         actual = maybe_write_ls(fd, range, TRUE);
256         if (actual != count)
257             panic("counted %d light sources, wrote %d! [range=%d]", count,
258                   actual, range);
259     }
260
261     if (release_data(mode)) {
262         for (prev = &light_base; (curr = *prev) != 0;) {
263             if (!curr->id.a_monst) {
264                 impossible("save_light_sources: no id! [range=%d]", range);
265                 is_global = 0;
266             } else
267                 switch (curr->type) {
268                 case LS_OBJECT:
269                     is_global = !obj_is_local(curr->id.a_obj);
270                     break;
271                 case LS_MONSTER:
272                     is_global = !mon_is_local(curr->id.a_monst);
273                     break;
274                 default:
275                     is_global = 0;
276                     impossible("save_light_sources: bad type (%d) [range=%d]",
277                                curr->type, range);
278                     break;
279                 }
280             /* if global and not doing local, or vice versa, remove it */
281             if (is_global ^ (range == RANGE_LEVEL)) {
282                 *prev = curr->next;
283                 free((genericptr_t) curr);
284             } else {
285                 prev = &(*prev)->next;
286             }
287         }
288     }
289 }
290
291 /*
292  * Pull in the structures from disk, but don't recalculate the object
293  * pointers.
294  */
295 void
296 restore_light_sources(fd)
297 int fd;
298 {
299     int count;
300     light_source *ls;
301
302     /* restore elements */
303     mread(fd, (genericptr_t) &count, sizeof count);
304
305     while (count-- > 0) {
306         ls = (light_source *) alloc(sizeof(light_source));
307         mread(fd, (genericptr_t) ls, sizeof(light_source));
308         ls->next = light_base;
309         light_base = ls;
310     }
311 }
312
313 /* to support '#stats' wizard-mode command */
314 void
315 light_stats(hdrfmt, hdrbuf, count, size)
316 const char *hdrfmt;
317 char *hdrbuf;
318 long *count, *size;
319 {
320     light_source *ls;
321
322     Sprintf(hdrbuf, hdrfmt, (long) sizeof (light_source));
323     *count = *size = 0L;
324     for (ls = light_base; ls; ls = ls->next) {
325         ++*count;
326         *size += (long) sizeof *ls;
327     }
328 }
329
330 /* Relink all lights that are so marked. */
331 void
332 relink_light_sources(ghostly)
333 boolean ghostly;
334 {
335     char which;
336     unsigned nid;
337     light_source *ls;
338
339     for (ls = light_base; ls; ls = ls->next) {
340         if (ls->flags & LSF_NEEDS_FIXUP) {
341             if (ls->type == LS_OBJECT || ls->type == LS_MONSTER) {
342                 if (ghostly) {
343                     if (!lookup_id_mapping(ls->id.a_uint, &nid))
344                         impossible("relink_light_sources: no id mapping");
345                 } else
346                     nid = ls->id.a_uint;
347                 if (ls->type == LS_OBJECT) {
348                     which = 'o';
349                     ls->id.a_obj = find_oid(nid);
350                 } else {
351                     which = 'm';
352                     ls->id.a_monst = find_mid(nid, FM_EVERYWHERE);
353                 }
354                 if (!ls->id.a_monst)
355                     impossible("relink_light_sources: cant find %c_id %d",
356                                which, nid);
357             } else
358                 impossible("relink_light_sources: bad type (%d)", ls->type);
359
360             ls->flags &= ~LSF_NEEDS_FIXUP;
361         }
362     }
363 }
364
365 /*
366  * Part of the light source save routine.  Count up the number of light
367  * sources that would be written.  If write_it is true, actually write
368  * the light source out.
369  */
370 STATIC_OVL int
371 maybe_write_ls(fd, range, write_it)
372 int fd, range;
373 boolean write_it;
374 {
375     int count = 0, is_global;
376     light_source *ls;
377
378     for (ls = light_base; ls; ls = ls->next) {
379         if (!ls->id.a_monst) {
380             impossible("maybe_write_ls: no id! [range=%d]", range);
381             continue;
382         }
383         switch (ls->type) {
384         case LS_OBJECT:
385             is_global = !obj_is_local(ls->id.a_obj);
386             break;
387         case LS_MONSTER:
388             is_global = !mon_is_local(ls->id.a_monst);
389             break;
390         default:
391             is_global = 0;
392             impossible("maybe_write_ls: bad type (%d) [range=%d]", ls->type,
393                        range);
394             break;
395         }
396         /* if global and not doing local, or vice versa, count it */
397         if (is_global ^ (range == RANGE_LEVEL)) {
398             count++;
399             if (write_it)
400                 write_ls(fd, ls);
401         }
402     }
403
404     return count;
405 }
406
407 void
408 light_sources_sanity_check()
409 {
410     light_source *ls;
411     struct monst *mtmp;
412     struct obj *otmp;
413     unsigned int auint;
414
415     for (ls = light_base; ls; ls = ls->next) {
416         if (!ls->id.a_monst)
417             panic("insane light source: no id!");
418         if (ls->type == LS_OBJECT) {
419             otmp = (struct obj *) ls->id.a_obj;
420             auint = otmp->o_id;
421             if (find_oid(auint) != otmp)
422                 panic("insane light source: can't find obj #%u!", auint);
423         } else if (ls->type == LS_MONSTER) {
424             mtmp = (struct monst *) ls->id.a_monst;
425             auint = mtmp->m_id;
426             if (find_mid(auint, FM_EVERYWHERE) != mtmp)
427                 panic("insane light source: can't find mon #%u!", auint);
428         } else {
429             panic("insane light source: bad ls type %d", ls->type);
430         }
431     }
432 }
433
434 /* Write a light source structure to disk. */
435 STATIC_OVL void
436 write_ls(fd, ls)
437 int fd;
438 light_source *ls;
439 {
440     anything arg_save;
441     struct obj *otmp;
442     struct monst *mtmp;
443
444     if (ls->type == LS_OBJECT || ls->type == LS_MONSTER) {
445         if (ls->flags & LSF_NEEDS_FIXUP) {
446             bwrite(fd, (genericptr_t) ls, sizeof(light_source));
447         } else {
448             /* replace object pointer with id for write, then put back */
449             arg_save = ls->id;
450             if (ls->type == LS_OBJECT) {
451                 otmp = ls->id.a_obj;
452                 ls->id = zeroany;
453                 ls->id.a_uint = otmp->o_id;
454                 if (find_oid((unsigned) ls->id.a_uint) != otmp)
455                     impossible("write_ls: can't find obj #%u!",
456                                ls->id.a_uint);
457             } else { /* ls->type == LS_MONSTER */
458                 mtmp = (struct monst *) ls->id.a_monst;
459                 ls->id = zeroany;
460                 ls->id.a_uint = mtmp->m_id;
461                 if (find_mid((unsigned) ls->id.a_uint, FM_EVERYWHERE) != mtmp)
462                     impossible("write_ls: can't find mon #%u!",
463                                ls->id.a_uint);
464             }
465             ls->flags |= LSF_NEEDS_FIXUP;
466             bwrite(fd, (genericptr_t) ls, sizeof(light_source));
467             ls->id = arg_save;
468             ls->flags &= ~LSF_NEEDS_FIXUP;
469         }
470     } else {
471         impossible("write_ls: bad type (%d)", ls->type);
472     }
473 }
474
475 /* Change light source's ID from src to dest. */
476 void
477 obj_move_light_source(src, dest)
478 struct obj *src, *dest;
479 {
480     light_source *ls;
481
482     for (ls = light_base; ls; ls = ls->next)
483         if (ls->type == LS_OBJECT && ls->id.a_obj == src)
484             ls->id.a_obj = dest;
485     src->lamplit = 0;
486     dest->lamplit = 1;
487 }
488
489 /* return true if there exist any light sources */
490 boolean
491 any_light_source()
492 {
493     return (boolean) (light_base != (light_source *) 0);
494 }
495
496 /*
497  * Snuff an object light source if at (x,y).  This currently works
498  * only for burning light sources.
499  */
500 void
501 snuff_light_source(x, y)
502 int x, y;
503 {
504     light_source *ls;
505     struct obj *obj;
506
507     for (ls = light_base; ls; ls = ls->next)
508         /*
509          * Is this position check valid??? Can I assume that the positions
510          * will always be correct because the objects would have been
511          * updated with the last vision update?  [Is that recent enough???]
512          */
513         if (ls->type == LS_OBJECT && ls->x == x && ls->y == y) {
514             obj = ls->id.a_obj;
515             if (obj_is_burning(obj)) {
516                 /* The only way to snuff Sunsword is to unwield it.  Darkness
517                  * scrolls won't affect it.  (If we got here because it was
518                  * dropped or thrown inside a monster, this won't matter
519                  * anyway because it will go out when dropped.)
520                  */
521                 if (artifact_light(obj))
522                     continue;
523                 end_burn(obj, obj->otyp != MAGIC_LAMP);
524                 /*
525                  * The current ls element has just been removed (and
526                  * ls->next is now invalid).  Return assuming that there
527                  * is only one light source attached to each object.
528                  */
529                 return;
530             }
531         }
532 }
533
534 /* Return TRUE if object sheds any light at all. */
535 boolean
536 obj_sheds_light(obj)
537 struct obj *obj;
538 {
539     /* so far, only burning objects shed light */
540     return obj_is_burning(obj);
541 }
542
543 /* Return TRUE if sheds light AND will be snuffed by end_burn(). */
544 boolean
545 obj_is_burning(obj)
546 struct obj *obj;
547 {
548     return (boolean) (obj->lamplit && (obj->otyp == MAGIC_LAMP
549                                        || ignitable(obj)
550                                        || artifact_light(obj)));
551 }
552
553 /* copy the light source(s) attached to src, and attach it/them to dest */
554 void
555 obj_split_light_source(src, dest)
556 struct obj *src, *dest;
557 {
558     light_source *ls, *new_ls;
559
560     for (ls = light_base; ls; ls = ls->next)
561         if (ls->type == LS_OBJECT && ls->id.a_obj == src) {
562             /*
563              * Insert the new source at beginning of list.  This will
564              * never interfere us walking down the list - we are already
565              * past the insertion point.
566              */
567             new_ls = (light_source *) alloc(sizeof(light_source));
568             *new_ls = *ls;
569             if (Is_candle(src)) {
570                 /* split candles may emit less light than original group */
571                 ls->range = candle_light_range(src);
572                 new_ls->range = candle_light_range(dest);
573                 vision_full_recalc = 1; /* in case range changed */
574             }
575             new_ls->id.a_obj = dest;
576             new_ls->next = light_base;
577             light_base = new_ls;
578             dest->lamplit = 1; /* now an active light source */
579         }
580 }
581
582 /* light source `src' has been folded into light source `dest';
583    used for merging lit candles and adding candle(s) to lit candelabrum */
584 void
585 obj_merge_light_sources(src, dest)
586 struct obj *src, *dest;
587 {
588     light_source *ls;
589
590     /* src == dest implies adding to candelabrum */
591     if (src != dest)
592         end_burn(src, TRUE); /* extinguish candles */
593
594     for (ls = light_base; ls; ls = ls->next)
595         if (ls->type == LS_OBJECT && ls->id.a_obj == dest) {
596             ls->range = candle_light_range(dest);
597             vision_full_recalc = 1; /* in case range changed */
598             break;
599         }
600 }
601
602 /* light source `obj' is being made brighter or dimmer */
603 void
604 obj_adjust_light_radius(obj, new_radius)
605 struct obj *obj;
606 int new_radius;
607 {
608     light_source *ls;
609
610     for (ls = light_base; ls; ls = ls->next)
611         if (ls->type == LS_OBJECT && ls->id.a_obj == obj) {
612             if (new_radius != ls->range)
613                 vision_full_recalc = 1;
614             ls->range = new_radius;
615             return;
616         }
617     impossible("obj_adjust_light_radius: can't find %s", xname(obj));
618 }
619
620 /* Candlelight is proportional to the number of candles;
621    minimum range is 2 rather than 1 for playability. */
622 int
623 candle_light_range(obj)
624 struct obj *obj;
625 {
626     int radius;
627
628     if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
629         /*
630          *      The special candelabrum emits more light than the
631          *      corresponding number of candles would.
632          *       1..3 candles, range 2 (minimum range);
633          *       4..6 candles, range 3 (normal lamp range);
634          *          7 candles, range 4 (bright).
635          */
636         radius = (obj->spe < 4) ? 2 : (obj->spe < 7) ? 3 : 4;
637     } else if (Is_candle(obj)) {
638         /*
639          *      Range is incremented by powers of 7 so that it will take
640          *      wizard mode quantities of candles to get more light than
641          *      from a lamp, without imposing an arbitrary limit.
642          *       1..6   candles, range 2;
643          *       7..48  candles, range 3;
644          *      49..342 candles, range 4; &c.
645          */
646         long n = obj->quan;
647
648         radius = 1; /* always incremented at least once */
649         do {
650             radius++;
651             n /= 7L;
652         } while (n > 0L);
653     } else {
654         /* we're only called for lit candelabrum or candles */
655         /* impossible("candlelight for %d?", obj->otyp); */
656         radius = 3; /* lamp's value */
657     }
658     return radius;
659 }
660
661 /* light emitting artifact's range depends upon its curse/bless state */
662 int
663 arti_light_radius(obj)
664 struct obj *obj;
665 {
666     /*
667      * Used by begin_burn() when setting up a new light source
668      * (obj->lamplit will already be set by this point) and
669      * also by bless()/unbless()/uncurse()/curse() to decide
670      * whether to call obj_adjust_light_radius().
671      */
672
673     /* sanity check [simplifies usage by bless()/curse()/&c] */
674     if (!obj->lamplit || !artifact_light(obj))
675         return 0;
676
677     /* cursed radius of 1 is not noticeable for an item that's
678        carried by the hero but is if it's carried by a monster
679        or left lit on the floor (not applicable for Sunsword) */
680     return (obj->blessed ? 3 : !obj->cursed ? 2 : 1);
681 }
682
683 /* adverb describing lit artifact's light; depends on curse/bless state */
684 const char *
685 arti_light_description(obj)
686 struct obj *obj;
687 {
688     switch (arti_light_radius(obj)) {
689     case 3:
690 #if 0 /*JP:T*/
691         return "brilliantly"; /* blessed */
692 #else
693         return "\83L\83\89\83L\83\89\82Æ"; /* blessed */
694 #endif
695     case 2:
696 #if 0 /*JP:T*/
697         return "brightly"; /* uncursed */
698 #else
699         return "\96¾\82é\82­"; /* uncursed */
700 #endif
701     case 1:
702 #if 0 /*JP:T*/
703         return "dimly"; /* cursed */
704 #else
705         return "\94\96\88Ã\82­"; /* cursed */
706 #endif
707     default:
708         break;
709     }
710 /*JP
711     return "strangely";
712 */
713     return "\95s\8ev\8bc\82É";
714 }
715
716 int
717 wiz_light_sources()
718 {
719     winid win;
720     char buf[BUFSZ];
721     light_source *ls;
722
723     win = create_nhwindow(NHW_MENU); /* corner text window */
724     if (win == WIN_ERR)
725         return 0;
726
727     Sprintf(buf, "Mobile light sources: hero @ (%2d,%2d)", u.ux, u.uy);
728     putstr(win, 0, buf);
729     putstr(win, 0, "");
730
731     if (light_base) {
732         putstr(win, 0, "location range flags  type    id");
733         putstr(win, 0, "-------- ----- ------ ----  -------");
734         for (ls = light_base; ls; ls = ls->next) {
735             Sprintf(buf, "  %2d,%2d   %2d   0x%04x  %s  %s", ls->x, ls->y,
736                     ls->range, ls->flags,
737                     (ls->type == LS_OBJECT
738                        ? "obj"
739                        : ls->type == LS_MONSTER
740                           ? (mon_is_local(ls->id.a_monst)
741                              ? "mon"
742                              : (ls->id.a_monst == &youmonst)
743                                 ? "you"
744                                 /* migrating monster */
745                                 : "<m>")
746                           : "???"),
747                     fmt_ptr(ls->id.a_void));
748             putstr(win, 0, buf);
749         }
750     } else
751         putstr(win, 0, "<none>");
752
753     display_nhwindow(win, FALSE);
754     destroy_nhwindow(win);
755
756     return 0;
757 }
758
759 /*light.c*/