diff --git a/src/dungeon.c b/src/dungeon.c index b692922e5..5583fffec 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -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; + mapseen *mptr; + char qbuf[QBUFSZ]; /* Buffer for query text */ + char nbuf[BUFSZ]; /* Buffer for response */ - if (!(mptr = find_mapseen(&u.uz))) return 0; + if (!(mptr = find_mapseen(&u.uz))) return 0; - Sprintf(qbuf,"What do you want to call this dungeon level? "); - getlin(qbuf, nbuf); + Sprintf(qbuf,"What do you want to call this dungeon level? "); + getlin(qbuf, nbuf); + if (index(nbuf, '\033')) return 0; - 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; + mapseen *mptr, **mptraddr; - for (; mptr; prev = mptr, mptr = mptr->next) { - if (mptr->lev.dnum == dnum) { - prev->next = mptr->next; - free((genericptr_t) mptr); - mptr = prev; - } - } + 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; + /* 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; - if (!mapseenchn) { - mapseenchn = init; - return; - } + 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); - /* 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; - } + init->lev.dnum = lev->dnum; + init->lev.dlevel = lev->dlevel; - old = mptr->next; - mptr->next = init; - init->next = old; + 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; + } + + 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; - } - - 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; - } - } + /* 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]) { +#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; + winid win; + mapseen *mptr; + int lastdun = -1; - first = TRUE; + /* lazy intialization */ + (void) recalc_mapseen(); - /* 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; - } - } + 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); - return "(unknown)"; + 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)"; } 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; + 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); + } - 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); - } - - /* 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 :"] + */ + 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 */ + 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))); + /* 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) + /* 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)); + /* 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) - */ + 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); + } - /* capitalize afterwards */ - i = strlen(PREFIX); - buf[i] = highc(buf[i]); + /* print out branches */ + if (mptr->br) { + Sprintf(buf, "%s%s to %s", PREFIX, br_string2(mptr->br), + dungeons[mptr->br->end2.dnum].dname); - 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); - - /* 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 */