]> granicus.if.org Git - nethack/commitdiff
#overview overhaul, part I (trunk only)
authornethack.rankin <nethack.rankin>
Thu, 2 Feb 2012 10:15:04 +0000 (10:15 +0000)
committernethack.rankin <nethack.rankin>
Thu, 2 Feb 2012 10:15:04 +0000 (10:15 +0000)
     Reformat the DUNGEON_OVERVIEW code in dungeon.c.  It's clear from the
way lines were wrapping that the original author used an editor that let
him set tab expansion to columns of four, and when they're treated as the
conventional eight then some longish lines won't fit.  Switch to using a
mix of tabs and four spaces instead of all tab characters.

     I've separated out my more interesting changes (which will come later).
However, there are a bunch of minor ones included:
 1) the lastseentyp array is reused for each level visited, but it wasn't
    being reinitialized when creating a new level, so remembered fountains,
    altars, and so forth could be erroneously propogated across levels
    (the original contributed patch may not have suffered from this because
    it handled last-seen data differently than the code which is in place);
 2) add 3.5.0 health food store to the list of recognized shop types;
 3) make an #annotate value of a single space delete any old annotation
    without adding a new one, the way monster and object naming works;
 4) the code to discard overview data for a branch of the dungeon which
    can no longer be reached (quest expulsion) wasn't capable of doing so
    for the very first level (a hypothetical problem since level 1 isn't in
    the quest...) and didn't free memory used for user-supplied annotations;
 5) reorganize dooverview() where Michael's compiler reported that a
    variable might be used before being initialized (it wasn't, but it also
    wasn't even needed to achieve the intended result);
 6) redo the #overview formatting macros so that they'll work with pre-ANSI
    compilers that don't support concatenation of adjacent string literals;
 7) function-like macro ADDNTOBUF() was used without terminating semi-colon,
    which confused emacs when indenting, so this rewrites it such that it
    expects ordinary termination and will work correctly if ever used in the
    form 'if (some_condition) ADDNTOBUF(args); else ...';
 8) comment out water/ice/lava with #if 0 ... #endif rather than /* ... */.

src/dungeon.c

index b692922e57a9986fafc516c15946cc9eec55ed3b..5583fffecd2e55b63a5705171d110aea595bb325 100644 (file)
@@ -1841,64 +1841,60 @@ xchar *rdgn;
  */
 void 
 recbranch_mapseen(source, dest)
-       d_level *source;
-       d_level *dest;
+d_level *source;
+d_level *dest;
 {
-       mapseen *mptr;
-       branch* br;
+    mapseen *mptr;
+    branch* br;
 
-       /* not a branch */
-       if (source->dnum == dest->dnum) return;
+    /* not a branch */
+    if (source->dnum == dest->dnum) return;
 
-       /* we only care about forward branches */
-       for (br = branches; br; br = br->next) {
-               if (on_level(source, &br->end1) && on_level(dest, &br->end2)) break;
-               if (on_level(source, &br->end2) && on_level(dest, &br->end1)) return;
-       }
+    /* we only care about forward branches */
+    for (br = branches; br; br = br->next) {
+        if (on_level(source, &br->end1) && on_level(dest, &br->end2)) break;
+        if (on_level(source, &br->end2) && on_level(dest, &br->end1)) return;
+    }
 
-       /* branch not found, so not a real branch. */
-       if (!br) return;
-  
-       if ((mptr = find_mapseen(source)) != 0) {
-               if (mptr->br && br != mptr->br)
-                       impossible("Two branches on the same level?");
-               mptr->br = br;
-       } else {
-               impossible("Can't note branch for unseen level (%d, %d)", 
-                       source->dnum, source->dlevel);
-       }
+    /* branch not found, so not a real branch. */
+    if (!br) return;
+
+    if ((mptr = find_mapseen(source)) != 0) {
+       if (mptr->br && br != mptr->br)
+           impossible("Two branches on the same level?");
+       mptr->br = br;
+    } else {
+       impossible("Can't note branch for unseen level (%d, %d)", 
+                  source->dnum, source->dlevel);
+    }
 }
 
 /* add a custom name to the current level */
 int
 donamelevel()
 {
-       mapseen *mptr;
-       char qbuf[QBUFSZ];      /* Buffer for query text */
-       char nbuf[BUFSZ];       /* Buffer for response */
-       int len;
-
-       if (!(mptr = find_mapseen(&u.uz))) return 0;
+    mapseen *mptr;
+    char qbuf[QBUFSZ];         /* Buffer for query text */
+    char nbuf[BUFSZ];          /* Buffer for response */
 
-       Sprintf(qbuf,"What do you want to call this dungeon level? ");
-       getlin(qbuf, nbuf);
+    if (!(mptr = find_mapseen(&u.uz))) return 0;
 
-       if (index(nbuf, '\033')) return 0;
+    Sprintf(qbuf,"What do you want to call this dungeon level? ");
+    getlin(qbuf, nbuf);
+    if (index(nbuf, '\033')) return 0;
 
-       len = strlen(nbuf) + 1;
-       if (mptr->custom) {
-               free((genericptr_t)mptr->custom);
-               mptr->custom = (char *)0;
-               mptr->custom_lth = 0;
-       }
-       
-       if (*nbuf) {
-               mptr->custom = (char *) alloc(sizeof(char) * len);
-               mptr->custom_lth = len;
-               strcpy(mptr->custom, nbuf);
-       }
-   
-       return 0;
+    /* discard old annotation, if any */
+    if (mptr->custom) {
+       free((genericptr_t)mptr->custom);
+       mptr->custom = (char *)0;
+       mptr->custom_lth = 0;
+    }
+    /* add new annotation, unless it's empty or a single space */
+    if (*nbuf && strcmp(nbuf, " ")) {
+       mptr->custom = dupstr(nbuf);
+       mptr->custom_lth = strlen(mptr->custom);
+    }
+    return 0;
 }
 
 /* find the particular mapseen object in the chain */
@@ -1907,38 +1903,37 @@ STATIC_OVL mapseen *
 find_mapseen(lev)
 d_level *lev;
 {
-       mapseen *mptr;
+    mapseen *mptr;
 
-       for (mptr = mapseenchn; mptr; mptr = mptr->next)
-               if (on_level(&(mptr->lev), lev)) break;
+    for (mptr = mapseenchn; mptr; mptr = mptr->next)
+       if (on_level(&(mptr->lev), lev)) break;
 
-       return mptr;
+    return mptr;
 }
 
 void
 forget_mapseen(ledger_num)
 int ledger_num;
 {
-       mapseen *mptr;
+    mapseen *mptr;
 
-       for (mptr = mapseenchn; mptr; mptr = mptr->next)
-               if (dungeons[mptr->lev.dnum].ledger_start + 
-                       mptr->lev.dlevel == ledger_num) break;
+    for (mptr = mapseenchn; mptr; mptr = mptr->next)
+       if (dungeons[mptr->lev.dnum].ledger_start + 
+           mptr->lev.dlevel == ledger_num) break;
 
-       /* if not found, then nothing to forget */
-       if (mptr) {
-               mptr->feat.forgot = 1;
-               mptr->br = (branch *)0;
+    /* if not found, then nothing to forget */
+    if (mptr) {
+       mptr->feat.forgot = 1;
+       mptr->br = (branch *)0;
 
-               /* custom names are erased, not forgotten until revisted */
-               if (mptr->custom) {
-                       mptr->custom_lth = 0;
-                       free((genericptr_t)mptr->custom);
-                       mptr->custom = (char *)0;
-               }
-
-               memset((genericptr_t) mptr->rooms, 0, sizeof(mptr->rooms));
+       /* custom names are erased, not just forgotten until revisted */
+       if (mptr->custom) {
+            mptr->custom_lth = 0;
+            free((genericptr_t)mptr->custom);
+            mptr->custom = (char *)0;
        }
+       (void) memset((genericptr_t) mptr->rooms, 0, sizeof mptr->rooms);
+    }
 }
 
 STATIC_OVL void
@@ -1946,54 +1941,54 @@ save_mapseen(fd, mptr)
 int fd;
 mapseen *mptr;
 {
-       branch *curr;
-       int count;
+    branch *curr;
+    int count;
 
-       count = 0;
-       for (curr = branches; curr; curr = curr->next) {
-               if (curr == mptr->br) break;
-               count++;
-       }
+    count = 0;
+    for (curr = branches; curr; curr = curr->next) {
+       if (curr == mptr->br) break;
+       count++;
+    }
 
-       bwrite(fd, (genericptr_t) &count, sizeof(int));
-       bwrite(fd, (genericptr_t) &mptr->lev, sizeof(d_level));
-       bwrite(fd, (genericptr_t) &mptr->feat, sizeof(mapseen_feat));
-       bwrite(fd, (genericptr_t) &mptr->custom_lth, sizeof(unsigned));
-       if (mptr->custom_lth)
-               bwrite(fd, (genericptr_t) mptr->custom, 
-               sizeof(char) * mptr->custom_lth);
-       bwrite(fd, (genericptr_t) &mptr->rooms, sizeof(mptr->rooms));
+    bwrite(fd, (genericptr_t) &count, sizeof(int));
+    bwrite(fd, (genericptr_t) &mptr->lev, sizeof(d_level));
+    bwrite(fd, (genericptr_t) &mptr->feat, sizeof(mapseen_feat));
+    bwrite(fd, (genericptr_t) &mptr->custom_lth, sizeof(unsigned));
+    if (mptr->custom_lth)
+       bwrite(fd, (genericptr_t) mptr->custom, 
+              sizeof(char) * mptr->custom_lth);
+    bwrite(fd, (genericptr_t) &mptr->rooms, sizeof(mptr->rooms));
 }
 
 STATIC_OVL mapseen *
 load_mapseen(fd)
 int fd;
 {
-       int branchnum, count;
-       mapseen *load;
-       branch *curr;
+    int branchnum, count;
+    mapseen *load;
+    branch *curr;
 
-       load = (mapseen *) alloc(sizeof(mapseen));
-       mread(fd, (genericptr_t) &branchnum, sizeof(int));
+    load = (mapseen *) alloc(sizeof(mapseen));
+    mread(fd, (genericptr_t) &branchnum, sizeof(int));
 
-       count = 0;
-       for (curr = branches; curr; curr = curr->next) {
-               if (count == branchnum) break;
-               count++;
-       }
-       load->br = curr;
+    count = 0;
+    for (curr = branches; curr; curr = curr->next) {
+       if (count == branchnum) break;
+       count++;
+    }
+    load->br = curr;
 
-       mread(fd, (genericptr_t) &load->lev, sizeof(d_level));
-       mread(fd, (genericptr_t) &load->feat, sizeof(mapseen_feat));
-       mread(fd, (genericptr_t) &load->custom_lth, sizeof(unsigned));
-       if (load->custom_lth > 0) {
-               load->custom = (char *) alloc(sizeof(char) * load->custom_lth);
-               mread(fd, (genericptr_t) load->custom, 
-                       sizeof(char) * load->custom_lth);
-       } else load->custom = (char *) 0;
-       mread(fd, (genericptr_t) &load->rooms, sizeof(load->rooms));
+    mread(fd, (genericptr_t) &load->lev, sizeof(d_level));
+    mread(fd, (genericptr_t) &load->feat, sizeof(mapseen_feat));
+    mread(fd, (genericptr_t) &load->custom_lth, sizeof(unsigned));
+    if (load->custom_lth > 0) {
+       load->custom = (char *) alloc(sizeof(char) * load->custom_lth);
+       mread(fd, (genericptr_t) load->custom, 
+             sizeof(char) * load->custom_lth);
+    } else load->custom = (char *) 0;
+    mread(fd, (genericptr_t) &load->rooms, sizeof(load->rooms));
 
-       return load;
+    return load;
 }
 
 /* Remove all mapseen objects for a particular dnum.
@@ -2003,56 +1998,60 @@ void
 remdun_mapseen(dnum)
 int dnum;
 {
-       mapseen *mptr, *prev;
-       
-       prev = mapseenchn;
-       if (!prev) return;
-       mptr = prev->next;
-
-       for (; mptr; prev = mptr, mptr = mptr->next) {
-               if (mptr->lev.dnum == dnum) {
-                       prev->next = mptr->next;
-                       free((genericptr_t) mptr);
-                       mptr = prev;
-               }
-       }
+    mapseen *mptr, **mptraddr;
+
+    mptraddr = &mapseenchn;
+    while ((mptr = *mptraddr) != 0) {
+       if (mptr->lev.dnum == dnum) {
+           *mptraddr = mptr->next;
+           if (mptr->custom)
+               free((genericptr_t) mptr->custom);
+           free((genericptr_t) mptr);
+       } else
+           mptraddr = &mptr->next;
+    }
 }
 
 void
 init_mapseen(lev)
 d_level *lev;
 {
-       /* Create a level and insert in "sorted" order.  This is an insertion
-        * sort first by dungeon (in order of discovery) and then by level number.
-        */
-       mapseen *mptr;
-       mapseen *init;
-       mapseen *old;
-       
-       init = (mapseen *) alloc(sizeof(mapseen));
-       (void) memset((genericptr_t)init, 0, sizeof(mapseen));
-       init->lev.dnum = lev->dnum;
-       init->lev.dlevel = lev->dlevel;
-
-       if (!mapseenchn) {
-               mapseenchn = init;
-               return;
-       }
+    /* Create a level and insert in "sorted" order.  This is an insertion
+     * sort first by dungeon (in order of discovery) and then by level number.
+     */
+    mapseen *mptr, *init, *old;
+
+    init = (mapseen *) alloc(sizeof *init);
+    (void) memset((genericptr_t)init, 0, sizeof *init);
+    /* memset is fine for feature bits and rooms array;
+       explicitly initialize pointers to null */
+    init->next = 0, init->br = 0, init->custom = 0;
+    /* lastseentyp[][] is reused for each level, so get rid of
+       previous level's data */
+    (void) memset((genericptr_t)lastseentyp, 0, sizeof lastseentyp);
+
+    init->lev.dnum = lev->dnum;
+    init->lev.dlevel = lev->dlevel;
+
+    if (!mapseenchn) {
+       mapseenchn = init;
+       return;
+    }
 
-       /* walk until we get to the place where we should
-        * insert init between mptr and mptr->next
-        */
-       for (mptr = mapseenchn; mptr->next; mptr = mptr->next) {
-               if (mptr->next->lev.dnum == init->lev.dnum) break;
-       }
-       for (; mptr->next; mptr = mptr->next) {
-               if ((mptr->next->lev.dnum != init->lev.dnum) ||
-                       (mptr->next->lev.dlevel > init->lev.dlevel)) break;
-       }
+    /* walk until we get to the place where we should
+     * insert init between mptr and mptr->next
+     */
+    for (mptr = mapseenchn; mptr->next; mptr = mptr->next) {
+       if (mptr->next->lev.dnum == init->lev.dnum) break;
+    }
+    for (; mptr->next; mptr = mptr->next) {
+       if ((mptr->next->lev.dnum != init->lev.dnum) ||
+           (mptr->next->lev.dlevel > init->lev.dlevel)) break;
+    }
 
-       old = mptr->next;
-       mptr->next = init;
-       init->next = old;
+    old = mptr->next;
+    mptr->next = init;
+    init->next = old;
 }
 
 #define INTEREST(feat) \
@@ -2074,165 +2073,148 @@ STATIC_OVL boolean
 interest_mapseen(mptr)
 mapseen *mptr;
 {
-       return on_level(&u.uz, &mptr->lev) ||
-           (!mptr->feat.forgot && (
-               INTEREST(mptr->feat) ||
-               (mptr->custom) || 
-               (mptr->br)
-               ));
+    return on_level(&u.uz, &mptr->lev) ||
+               (!mptr->feat.forgot &&
+                   (INTEREST(mptr->feat) || (mptr->custom) || (mptr->br)));
 }
 
 /* recalculate mapseen for the current level */
 void
 recalc_mapseen()
 {
-       mapseen *mptr;
-       struct monst *shkp;
-       unsigned int x, y, ridx;
+    mapseen *mptr;
+    struct monst *shkp;
+    unsigned int x, y, ridx;
 
-       /* Should not happen in general, but possible if in the process
-        * of being booted from the quest.  The mapseen object gets
-        * removed during the expulsion but prior to leaving the level
-        */
-       if (!(mptr = find_mapseen(&u.uz))) return;
+    /* Should not happen in general, but possible if in the process
+     * of being booted from the quest.  The mapseen object gets
+     * removed during the expulsion but prior to leaving the level
+     */
+    if (!(mptr = find_mapseen(&u.uz))) return;
 
-       /* reset all features */
-       memset((genericptr_t) &mptr->feat, 0, sizeof(mapseen_feat));
+    /* reset all features; mptr->feat.* = 0, mptr->feat.forgot = 0; */
+    memset((genericptr_t) &mptr->feat, 0, sizeof(mapseen_feat));
 
-       /* track rooms the hero is in */
-       for (x = 0; x < sizeof(u.urooms); x++) {
-               if (!u.urooms[x]) continue;
+    /* track rooms the hero is in */
+    for (x = 0; x < sizeof(u.urooms); x++) {
+       if (!u.urooms[x]) continue;
 
-               ridx = u.urooms[x] - ROOMOFFSET;
-               if (rooms[ridx].rtype < SHOPBASE ||
-                       ((shkp = shop_keeper(u.urooms[x])) && inhishop(shkp)))
-                       mptr->rooms[ridx] |= MSR_SEEN;
-               else
-                       /* shops without shopkeepers are no shops at all */
-                       mptr->rooms[ridx] &= ~MSR_SEEN;
-       }
+       ridx = u.urooms[x] - ROOMOFFSET;
+       if (rooms[ridx].rtype < SHOPBASE ||
+               ((shkp = shop_keeper(u.urooms[x])) && inhishop(shkp)))
+           mptr->rooms[ridx] |= MSR_SEEN;
+       else
+           /* shops without shopkeepers are no shops at all */
+           mptr->rooms[ridx] &= ~MSR_SEEN;
+    }
 
-       /* recalculate room knowledge: for now, just shops and temples
-        * this could be extended to an array of 0..SHOPBASE
-        */
-       for (x = 0; x < sizeof(mptr->rooms); x++) {
-               if (mptr->rooms[x] & MSR_SEEN) {
-                       if (rooms[x].rtype >= SHOPBASE) {
-                               if (!mptr->feat.nshop)
-                                       mptr->feat.shoptype = rooms[x].rtype;
-                               else if (mptr->feat.shoptype != (unsigned)rooms[x].rtype)
-                                       mptr->feat.shoptype = 0;
-                               mptr->feat.nshop = min(mptr->feat.nshop + 1, 3);
-                       } else if (rooms[x].rtype == TEMPLE)
-                               /* altar and temple alignment handled below */
-                               mptr->feat.ntemple = min(mptr->feat.ntemple + 1, 3);
-               }
+    /* recalculate room knowledge: for now, just shops and temples
+     * this could be extended to an array of 0..SHOPBASE
+     */
+    for (x = 0; x < sizeof(mptr->rooms); x++) {
+       if (mptr->rooms[x] & MSR_SEEN) {
+           if (rooms[x].rtype >= SHOPBASE) {
+               if (!mptr->feat.nshop)
+                   mptr->feat.shoptype = rooms[x].rtype;
+               else if (mptr->feat.shoptype != (unsigned)rooms[x].rtype)
+                   mptr->feat.shoptype = 0;
+               mptr->feat.nshop = min(mptr->feat.nshop + 1, 3);
+           } else if (rooms[x].rtype == TEMPLE)
+               /* altar and temple alignment handled below */
+               mptr->feat.ntemple = min(mptr->feat.ntemple + 1, 3);
        }
+    }
 
-       /* Update lastseentyp with typ if and only if it is in sight or the hero can
-        * feel it on their current location (i.e. not levitating).  This *should*
-        * give the "last known typ" for each dungeon location.  (At the very least,
-        * it's a better assumption than determining what the player knows from
-        * the glyph and the typ (which is isn't quite enough information in some
-        * cases).
-        *
-        * It was reluctantly added to struct rm to track.  Alternatively
-        * we could track "features" and then update them all here, and keep
-        * track of when new features are created or destroyed, but this
-        * seemed the most elegant, despite adding more data to struct rm.
-        *
-        * Although no current windowing systems (can) do this, this would add the
-        * ability to have non-dungeon glyphs float above the last known dungeon
-        * glyph (i.e. items on fountains).
-        */
-       if (!Levitation)
-               lastseentyp[u.ux][u.uy] = levl[u.ux][u.uy].typ;
-
-       for (x = 0; x < COLNO; x++) {
-               for (y = 0; y < ROWNO; y++) {
-                       if (cansee(x, y)) {
-                           struct monst *mtmp = m_at(x, y);
-
-                           lastseentyp[x][y] =
-           (mtmp && mtmp->m_ap_type == M_AP_FURNITURE && canseemon(mtmp)) ?
-                                       cmap_to_type(mtmp->mappearance) :
-                                       levl[x][y].typ;
-                       }
+    /* Update lastseentyp with typ if and only if it is in sight or the
+     * hero can feel it on their current location (i.e. not levitating).
+     * This *should* give the "last known typ" for each dungeon location.
+     * (At the very least, it's a better assumption than determining what
+     * the player knows from the glyph and the typ (which is isn't quite
+     * enough information in some cases)).
+     *
+     * It was reluctantly added to struct rm to track.  Alternatively
+     * we could track "features" and then update them all here, and keep
+     * track of when new features are created or destroyed, but this
+     * seemed the most elegant, despite adding more data to struct rm.
+     *
+     * Although no current windowing systems (can) do this, this would add
+     * the ability to have non-dungeon glyphs float above the last known
+     * dungeon glyph (i.e. items on fountains).
+     */
+    if (!Levitation)
+       lastseentyp[u.ux][u.uy] = levl[u.ux][u.uy].typ;
+
+    for (x = 0; x < COLNO; x++) {
+       for (y = 0; y < ROWNO; y++) {
+           if (cansee(x, y)) {
+               struct monst *mtmp = m_at(x, y);
+
+               lastseentyp[x][y] =
+             (mtmp && mtmp->m_ap_type == M_AP_FURNITURE && canseemon(mtmp)) ?
+                                   cmap_to_type(mtmp->mappearance) :
+                                   levl[x][y].typ;
+           }
 
-                       switch (lastseentyp[x][y]) {
-                       /*
-                       case ICE:
-                               mptr->feat.ice = 1;
-                               break;
-                       case POOL:
-                       case MOAT:
-                       case WATER:
-                               mptr->feat.water = 1;
-                               break;
-                       case LAVAPOOL:
-                               mptr->feat.lava = 1;
-                               break;
-                       */
-                       case TREE:
-                               mptr->feat.ntree = min(mptr->feat.ntree + 1, 3);
-                               break;
-                       case FOUNTAIN:
-                               mptr->feat.nfount = min(mptr->feat.nfount + 1, 3);
-                               break;
-                       case THRONE:
-                               mptr->feat.nthrone = min(mptr->feat.nthrone + 1, 3);
-                               break;
-                       case SINK:
-                               mptr->feat.nsink = min(mptr->feat.nsink + 1, 3);
-                               break;
-                       case ALTAR:
-                               if (!mptr->feat.naltar)
-                                       mptr->feat.msalign = Amask2msa(levl[x][y].altarmask);
-                               else if (mptr->feat.msalign != Amask2msa(levl[x][y].altarmask))
-                                       mptr->feat.msalign = MSA_NONE;
-                                               
-                               mptr->feat.naltar = min(mptr->feat.naltar + 1, 3);
-                               break;
-                       }
-               }
+           switch (lastseentyp[x][y]) {
+#if 0
+           case ICE:
+               mptr->feat.ice = 1;
+               break;
+           case POOL:
+           case MOAT:
+           case WATER:
+               mptr->feat.water = 1;
+               break;
+           case LAVAPOOL:
+               mptr->feat.lava = 1;
+               break;
+#endif
+           case TREE:
+               mptr->feat.ntree = min(mptr->feat.ntree + 1, 3);
+               break;
+           case FOUNTAIN:
+               mptr->feat.nfount = min(mptr->feat.nfount + 1, 3);
+               break;
+           case THRONE:
+               mptr->feat.nthrone = min(mptr->feat.nthrone + 1, 3);
+               break;
+           case SINK:
+               mptr->feat.nsink = min(mptr->feat.nsink + 1, 3);
+               break;
+           case ALTAR:
+               if (!mptr->feat.naltar)
+                   mptr->feat.msalign = Amask2msa(levl[x][y].altarmask);
+               else if (mptr->feat.msalign != Amask2msa(levl[x][y].altarmask))
+                   mptr->feat.msalign = MSA_NONE;
+               mptr->feat.naltar = min(mptr->feat.naltar + 1, 3);
+               break;
+           }
        }
+    }
 }
 
 int
 dooverview()
 {
-       winid win;
-       mapseen *mptr;
-       boolean first;
-       boolean printdun;
-       int lastdun;
-
-       first = TRUE;
-
-       /* lazy intialization */
-       (void) recalc_mapseen();
-
-       win = create_nhwindow(NHW_MENU);
-
-       for (mptr = mapseenchn; mptr; mptr = mptr->next) {
-
-               /* only print out info for a level or a dungeon if interest */
-               if (interest_mapseen(mptr)) {
-                       printdun = (first || lastdun != mptr->lev.dnum);
-                       /* if (!first) putstr(win, 0, ""); */
-                       print_mapseen(win, mptr, printdun);
-
-                       if (printdun) {
-                               first = FALSE;
-                               lastdun = mptr->lev.dnum;
-                       }
-               }
+    winid win;
+    mapseen *mptr;
+    int lastdun = -1;
+
+    /* lazy intialization */
+    (void) recalc_mapseen();
+
+    win = create_nhwindow(NHW_MENU);
+    for (mptr = mapseenchn; mptr; mptr = mptr->next) {
+       /* only print out info for a level or a dungeon if interest */
+       if (interest_mapseen(mptr)) {
+           print_mapseen(win, mptr, (boolean)(mptr->lev.dnum != lastdun));
+           lastdun = mptr->lev.dnum;
        }
+    }
+    display_nhwindow(win, TRUE);
+    destroy_nhwindow(win);
 
-       display_nhwindow(win, TRUE);
-       destroy_nhwindow(win);
-
-       return 0;
+    return 0;
 }
 
 STATIC_OVL const char *
@@ -2240,16 +2222,16 @@ seen_string(x, obj)
 xchar x;
 const char *obj;
 {
-       /* players are computer scientists: 0, 1, 2, n */
-       switch(x) {
-       case 0: return "no";
-       /* an() returns too much.  index is ok in this case */
-       case 1: return index(vowels, *obj) ? "an" : "a";
-       case 2: return "some";
-       case 3: return "many";
-       }
+    /* players are computer scientists: 0, 1, 2, n */
+    switch (x) {
+    case 0: return "no";
+        /* an() returns too much.  index is ok in this case */
+    case 1: return index(vowels, *obj) ? "an" : "a";
+    case 2: return "some";
+    case 3: return "many";
+    }
 
-       return "(unknown)";
+    return "(unknown)";
 }
 
 /* better br_string */
@@ -2257,64 +2239,78 @@ STATIC_OVL const char *
 br_string2(br)
 branch *br;
 {
-       /* Special case: quest portal says closed if kicked from quest */
-       boolean closed_portal = 
-               (br->end2.dnum == quest_dnum && u.uevent.qexpelled);
-       switch(br->type)
-       {
-       case BR_PORTAL:  return closed_portal ? "Sealed portal" : "Portal";
-       case BR_NO_END1: return "Connection";
-       case BR_NO_END2: return (br->end1_up) ? "One way stairs up" : 
-               "One way stairs down";
-       case BR_STAIR:   return (br->end1_up) ? "Stairs up" : "Stairs down";
-       }
+    /* Special case: quest portal says closed if kicked from quest */
+    boolean closed_portal = 
+                       (br->end2.dnum == quest_dnum && u.uevent.qexpelled);
+
+    switch (br->type) {
+    case BR_PORTAL:  return closed_portal ? "Sealed portal" : "Portal";
+    case BR_NO_END1: return "Connection";
+    case BR_NO_END2: return (br->end1_up) ? "One way stairs up" : 
+                                           "One way stairs down";
+    case BR_STAIR:   return (br->end1_up) ? "Stairs up" : "Stairs down";
+    }
 
-       return "(unknown)";
+    return "(unknown)";
 }
 
 STATIC_OVL const char*
 shop_string(rtype)
 int rtype;
 {
-       /* Yuck, redundancy...but shclass.name doesn't cut it as a noun */
-       switch(rtype) {
-               case SHOPBASE:
-                       return "general store";
-               case ARMORSHOP:
-                       return "armor shop";
-               case SCROLLSHOP:
-                       return "scroll shop";
-               case POTIONSHOP:
-                       return "potion shop";
-               case WEAPONSHOP:
-                       return "weapon shop";
-               case FOODSHOP:
-                       return "delicatessen";
-               case RINGSHOP:
-                       return "jewelers";
-               case WANDSHOP:
-                       return "wand shop";
-               case BOOKSHOP:
-                       return "bookstore";
-               case CANDLESHOP:
-                       return "lighting shop";
-               default:
-                       /* In case another patch adds a shop type that doesn't exist,
-                        * do something reasonable like "a shop".
-                        */
-                       return "shop";
-       }
+    /* Yuck, redundancy...but shclass.name doesn't cut it as a noun */
+    switch (rtype) {
+    case SHOPBASE:
+       return "general store";
+    case ARMORSHOP:
+       return "armor shop";
+    case SCROLLSHOP:
+       return "scroll shop";
+    case POTIONSHOP:
+       return "potion shop";
+    case WEAPONSHOP:
+       return "weapon shop";
+    case FOODSHOP:
+       return "delicatessen";
+    case RINGSHOP:
+       return "jewelers";
+    case WANDSHOP:
+       return "wand shop";
+    case BOOKSHOP:
+       return "bookstore";
+    case FODDERSHOP:
+       return "health food store";
+    case CANDLESHOP:
+       return "lighting shop";
+    default:
+       /* In case another patch adds a shop type that doesn't exist,
+        * do something reasonable like "a shop".
+        */
+       return "shop";
+    }
 }
 
 /* some utility macros for print_mapseen */
-#define TAB "   "
-#define BULLET ""
+#define TAB "   "              /* three spaces */
+#if 0
+#define BULLET ""              /* empty; otherwise output becomes cluttered */
 #define PREFIX TAB TAB BULLET
+#else /*!0*/
+/* K&R: don't require support for concatenation of adjacent string literals */
+#define PREFIX "      "                /* two TABs + empty BULLET: six spaces */
+#endif
 #define COMMA (i++ > 0 ? ", " : PREFIX)
-#define ADDNTOBUF(nam, var) { if (var) \
-       Sprintf(eos(buf), "%s%s " nam "%s", COMMA, seen_string((var), (nam)), \
-       ((var) != 1 ? "s" : "")); }
-#define ADDTOBUF(nam, var) { if (var) Sprintf(eos(buf), "%s " nam, COMMA); }
+/* "iterate" once; safe to use as ``if (cond) ADDTOBUF(); else whatever;'' */
+#define ADDNTOBUF(nam,var)  do {                                             \
+                               if (var)                                      \
+                                   Sprintf(eos(buf), "%s%s %s%s",            \
+                                           COMMA, seen_string((var), (nam)), \
+                                           (nam), plur(var));                \
+                           } while (0)
+#define ADDTOBUF(nam,var)   do {                                            \
+                               if (var)                                     \
+                                   Sprintf(eos(buf), "%s%s", COMMA, (nam)); \
+                           } while (0)
 
 STATIC_OVL void
 print_mapseen(win, mptr, printdun)
@@ -2322,122 +2318,125 @@ winid win;
 mapseen *mptr;
 boolean printdun;
 {
-       char buf[BUFSZ];
-       int i, depthstart;
+    char buf[BUFSZ];
+    int i, depthstart;
 
-       /* Damnable special cases */
-       /* The quest and knox should appear to be level 1 to match
-        * other text.
+    /* Damnable special cases */
+    /* The quest and knox should appear to be level 1 to match
+     * other text.
+     */
+    if (mptr->lev.dnum == quest_dnum || mptr->lev.dnum == knox_level.dnum)
+       depthstart = 1;
+    else
+       depthstart = dungeons[mptr->lev.dnum].depth_start;  
+
+    if (printdun) {
+       /* Sokoban lies about dunlev_ureached and we should
+        * suppress the negative numbers in the endgame.
         */
-       if (mptr->lev.dnum == quest_dnum || mptr->lev.dnum == knox_level.dnum)
-               depthstart = 1;
+       if (dungeons[mptr->lev.dnum].dunlev_ureached == 1 ||
+               mptr->lev.dnum == sokoban_dnum || In_endgame(&mptr->lev))
+           Sprintf(buf, "%s:", dungeons[mptr->lev.dnum].dname);
        else
-               depthstart = dungeons[mptr->lev.dnum].depth_start;  
-
-       if (printdun) {
-               /* Sokoban lies about dunlev_ureached and we should
-                * suppress the negative numbers in the endgame.
-                */
-               if (dungeons[mptr->lev.dnum].dunlev_ureached == 1 ||
-                       mptr->lev.dnum == sokoban_dnum || In_endgame(&mptr->lev))
-                       Sprintf(buf, "%s:", dungeons[mptr->lev.dnum].dname);
-               else
-                       Sprintf(buf, "%s: levels %d to %d", 
-                               dungeons[mptr->lev.dnum].dname,
-                               depthstart, depthstart + 
-                               dungeons[mptr->lev.dnum].dunlev_ureached - 1);
-               putstr(win, ATR_INVERSE, buf);
-       }
+           Sprintf(buf, "%s: levels %d to %d", 
+                   dungeons[mptr->lev.dnum].dname, depthstart,
+                   depthstart + dungeons[mptr->lev.dnum].dunlev_ureached - 1);
+       putstr(win, ATR_INVERSE, buf);
+    }
 
-       /* calculate level number */
-       i = depthstart + mptr->lev.dlevel - 1;
-       if (Is_astralevel(&mptr->lev))
-               Sprintf(buf, TAB "Astral Plane:");
-       else if (In_endgame(&mptr->lev))
-               /* Negative numbers are mildly confusing, since they are never
-                * shown to the player, except in wizard mode.  We could show
-                * "Level -1" for the earth plane, for example.  Instead,
-                * show "Plane 1" for the earth plane to differentiate from
-                * level 1.  There's not much to show, but maybe the player
-                * wants to #annotate them for some bizarre reason.
-                */
-               Sprintf(buf, TAB "Plane %i:", -i);
-       else
-               Sprintf(buf, TAB "Level %d:", i);
+    /* calculate level number */
+    i = depthstart + mptr->lev.dlevel - 1;
+    if (Is_astralevel(&mptr->lev))
+       Sprintf(buf, "%sAstral Plane:", TAB);
+    else if (In_endgame(&mptr->lev))
+       /* Negative numbers are mildly confusing, since they are never
+        * shown to the player, except in wizard mode.  We could show
+        * "Level -1" for the earth plane, for example.  Instead,
+        * show "Plane 1" for the earth plane to differentiate from
+        * level 1.  There's not much to show, but maybe the player
+        * wants to #annotate them for some reason such as keeping
+        * track of encounters with the Wizard.
+        * [TODO: change this to be "Plane of <element-name>:"]
+        */
+       Sprintf(buf, "%sPlane %i:", TAB, -i);
+    else
+       Sprintf(buf, "%sLevel %d:", TAB, i);
        
 #ifdef WIZARD
-       /* wizmode prints out proto dungeon names for clarity */
-       if (wizard) {
-               s_level *slev;
-               if ((slev = Is_special(&mptr->lev)) != 0)
-                       Sprintf(eos(buf), " [%s]", slev->proto);
-       }
+    /* wizmode prints out proto dungeon names for clarity */
+    if (wizard) {
+       s_level *slev;
+
+       if ((slev = Is_special(&mptr->lev)) != 0)
+           Sprintf(eos(buf), " [%s]", slev->proto);
+    }
 #endif
 
-       if (mptr->custom)
-               Sprintf(eos(buf), " (%s)", mptr->custom);
+    if (mptr->custom)
+       Sprintf(eos(buf), " (%s)", mptr->custom);
 
-       /* print out glyph or something more interesting? */
-       Sprintf(eos(buf), "%s", on_level(&u.uz, &mptr->lev) ? 
-               " <- You are here" : "");
-       putstr(win, ATR_BOLD, buf);
+    /* print out glyph or something more interesting? */
+    Sprintf(eos(buf), "%s",
+           on_level(&u.uz, &mptr->lev) ? " <- You are here" : "");
+    putstr(win, ATR_BOLD, buf);
 
-       if (mptr->feat.forgot) return;
+    if (mptr->feat.forgot) return;
 
-       if (INTEREST(mptr->feat)) {
-               buf[0] = 0;
+    if (INTEREST(mptr->feat)) {
+       buf[0] = 0;
                
-               i = 0; /* interest counter */
-
-               /* List interests in an order vaguely corresponding to
-                * how important they are.
-                */
-               if (mptr->feat.nshop > 1)
-                       ADDNTOBUF("shop", mptr->feat.nshop)
-               else if (mptr->feat.nshop == 1)
-                       Sprintf(eos(buf), "%s%s", COMMA, 
-                               an(shop_string(mptr->feat.shoptype)));
-
-               /* Temples + non-temple altars get munged into just "altars" */
-               if (!mptr->feat.ntemple || mptr->feat.ntemple != mptr->feat.naltar)
-                       ADDNTOBUF("altar", mptr->feat.naltar)
-               else
-                       ADDNTOBUF("temple", mptr->feat.ntemple)
-
-               /* only print out altar's god if they are all to your god */
-               if (Amask2align(Msa2amask(mptr->feat.msalign)) == u.ualign.type)
-                       Sprintf(eos(buf), " to %s", align_gname(u.ualign.type));
-
-               ADDNTOBUF("fountain", mptr->feat.nfount)
-               ADDNTOBUF("sink", mptr->feat.nsink)
-               ADDNTOBUF("throne", mptr->feat.nthrone)
-               ADDNTOBUF("tree", mptr->feat.ntree);
-               /*
-               ADDTOBUF("water", mptr->feat.water)
-               ADDTOBUF("lava", mptr->feat.lava)
-               ADDTOBUF("ice", mptr->feat.ice)
-               */
-
-               /* capitalize afterwards */
-               i = strlen(PREFIX);
-               buf[i] = highc(buf[i]);
+       i = 0;  /* interest counter */
 
-               putstr(win, 0, buf);
-       }
+       /* List interests in an order vaguely corresponding to
+        * how important they are.
+        */
+       if (mptr->feat.nshop > 1)
+           ADDNTOBUF("shop", mptr->feat.nshop);
+       else if (mptr->feat.nshop == 1)
+           Sprintf(eos(buf), "%s%s", COMMA, 
+                   an(shop_string(mptr->feat.shoptype)));
+
+       /* Temples + non-temple altars get munged into just "altars" */
+       if (!mptr->feat.ntemple || mptr->feat.ntemple != mptr->feat.naltar)
+           ADDNTOBUF("altar", mptr->feat.naltar);
+       else
+           ADDNTOBUF("temple", mptr->feat.ntemple);
+
+       /* only print out altar's god if they are all to your god */
+       if (Amask2align(Msa2amask(mptr->feat.msalign)) == u.ualign.type)
+           Sprintf(eos(buf), " to %s", align_gname(u.ualign.type));
+
+       ADDNTOBUF("throne", mptr->feat.nthrone);
+       ADDNTOBUF("fountain", mptr->feat.nfount);
+       ADDNTOBUF("sink", mptr->feat.nsink);
+       ADDNTOBUF("tree", mptr->feat.ntree);
+#if 0
+       ADDTOBUF("water", mptr->feat.water);
+       ADDTOBUF("lava", mptr->feat.lava);
+       ADDTOBUF("ice", mptr->feat.ice);
+#endif
+       /* capitalize afterwards */
+       i = strlen(PREFIX);
+       buf[i] = highc(buf[i]);
+       /* capitalizing it makes it a sentence; terminate with '.' */
+       Strcat(buf, ".");
+       putstr(win, 0, buf);
+    }
 
-       /* print out branches */
-       if (mptr->br) {
-               Sprintf(buf, PREFIX "%s to %s", br_string2(mptr->br), 
-                       dungeons[mptr->br->end2.dnum].dname);
+    /* print out branches */
+    if (mptr->br) {
+       Sprintf(buf, "%s%s to %s", PREFIX, br_string2(mptr->br), 
+               dungeons[mptr->br->end2.dnum].dname);
 
-               /* since mapseen objects are printed out in increasing order
-                * of dlevel, clarify which level this branch is going to
-                * if the branch goes upwards.  Unless it's the end game
-                */
-               if (mptr->br->end1_up && !In_endgame(&(mptr->br->end2)))
-                       Sprintf(eos(buf), ", level %d", depth(&(mptr->br->end2)));
-               putstr(win, 0, buf);
-       }
+       /* Since mapseen objects are printed out in increasing order
+        * of dlevel, clarify which level this branch is going to
+        * if the branch goes upwards.  Unless it's the end game.
+        */
+       if (mptr->br->end1_up && !In_endgame(&(mptr->br->end2)))
+           Sprintf(eos(buf), ", level %d", depth(&(mptr->br->end2)));
+       Strcat(buf, ".");
+       putstr(win, 0, buf);
+    }
 }
 #endif /* DUNGEON_OVERVIEW */