From 48cd573e327dfe84e71b69556425499f89053b42 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 31 May 2019 03:42:06 -0700 Subject: [PATCH 1/3] Planes of Water and Air Make the Plane of Water be water all the way to edge instead of having stone on left, top, and right. The Plane of Air already has air all the way to edge (including unused/unuseable column #0) but does so via code rather than the level description file so Water does that now too. The edges of the Plane of Air were cloudless (3 columns on the left, 2 rows on the top, and 2 columns on the right; don't recall about the bottom) and that looked pretty strange. Those rows and columns are beyond the range of bubble/cloud movement so just make some of those spots randomly be sight-blocking cloud terrain instead of all open air. It isn't integrated with the moving clouds but looks fairly good when the hero moves along the edge of the level. Using wizard mode to leave Water or Air and later return resulted in no clouds on the Air level and bubbles as usual on the Water level. I still don't understand why, but on return to those levels run the bubble creation routine as if the old discarded bubbles or clouds were being restored. --- doc/fixes36.3 | 4 ++- src/do.c | 9 ++++-- src/mkmaze.c | 78 ++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 65 insertions(+), 26 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 640903d5b..fbb80dd07 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.27 $ $NHDT-Date: 1559130050 2019/05/29 11:40:50 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.28 $ $NHDT-Date: 1559299314 2019/05/31 10:41:54 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -33,6 +33,8 @@ if hero dies while a thrown or kicked object is in transit, put that object fix a memory leak that occurred if player used wizard mode to leave and return to the Plane of Air or Plane of Water (not possible in normal play) free sortloot data if object handling is short-circuited by cockatrice corpse +on the Plane of Water, make water go all the way to the edges of the level +on the Plane of Air, make clouds disrupt line of sight along the edges Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository diff --git a/src/do.c b/src/do.c index 9c887c037..c899676ef 100644 --- a/src/do.c +++ b/src/do.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 do.c $NHDT-Date: 1559088523 2019/05/29 00:08:43 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.190 $ */ +/* NetHack 3.6 do.c $NHDT-Date: 1559299314 2019/05/31 10:41:54 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.191 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1374,7 +1374,7 @@ boolean at_stairs, falling, portal; created instead), we need to discard them to avoid a memory leak; so bubbles are now discarded as we leave the level they're used on */ if (Is_waterlevel(&u.uz) || Is_airlevel(&u.uz)) - save_waterlevel(fd, FREE_SAVE); /* note: doesn't use 'fd' */ + save_waterlevel(-1, FREE_SAVE); bclose(fd); if (cant_go_back) { /* discard unreachable levels; keep #0 */ @@ -1434,6 +1434,11 @@ boolean at_stairs, falling, portal; reseed_random(rn2_on_display_rng); minit(); /* ZEROCOMP */ getlev(fd, hackpid, new_ledger, FALSE); + /* when in wizard mode, it is possible to leave from and return to + any level in the endgame; above, we discarded bubble/cloud info + when leaving Plane of Water or Air so recreate some now */ + if (Is_waterlevel(&u.uz) || Is_airlevel(&u.uz)) + restore_waterlevel(-1); (void) nhclose(fd); oinit(); /* reassign level dependent obj probabilities */ } diff --git a/src/mkmaze.c b/src/mkmaze.c index a660faf99..bdab684ef 100644 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mkmaze.c $NHDT-Date: 1559227829 2019/05/30 14:50:29 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.72 $ */ +/* NetHack 3.6 mkmaze.c $NHDT-Date: 1559299316 2019/05/31 10:41:56 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.73 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Pasi Kallinen, 2018. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1493,10 +1493,22 @@ movebubbles() } } } else if (Is_airlevel(&u.uz)) { - for (x = 0; x < COLNO; x++) - for (y = 0; y < ROWNO; y++) { + boolean xedge, yedge; + + for (x = 1; x <= (COLNO - 1); x++) + for (y = 0; y <= (ROWNO - 1); y++) { levl[x][y] = air_pos; unblock_point(x, y); + /* all air or all cloud around the perimeter of the Air + level tends to look strange; break up the pattern */ + xedge = (boolean) (x < bxmin || x > bxmax); + yedge = (boolean) (y < bymin || y > bymax); + if (xedge || yedge) { + if (!rn2(xedge ? 3 : 5)) { + levl[x][y].typ = CLOUD; + block_point(x, y); + } + } } } @@ -1589,6 +1601,14 @@ int fd; if (!Is_waterlevel(&u.uz) && !Is_airlevel(&u.uz)) return; + if (fd == -1) { /* special handling for restore in goto_level() */ + if (!wizard) + impossible("restore_waterlevel: returning to %s?", + Is_waterlevel(&u.uz) ? "Water" : "Air"); + setup_waterlevel(); + return; + } + set_wportal(); mread(fd, (genericptr_t) &n, sizeof n); mread(fd, (genericptr_t) &xmin, sizeof xmin); @@ -1655,26 +1675,37 @@ set_wportal() STATIC_OVL void setup_waterlevel() { - int x, y; - int xskip, yskip; - int water_glyph = cmap_to_glyph(S_water), - air_glyph = cmap_to_glyph(S_air); + int x, y, xskip, yskip, typ, glyph; - /* ouch, hardcoded... */ + if (!Is_waterlevel(&u.uz) && !Is_airlevel(&u.uz)) + panic("setup_waterlevel(): [%d:%d] neither 'Water' nor 'Air'", + (int) u.uz.dnum, (int) u.uz.dlevel); + /* ouch, hardcoded... (file scope statics and used in bxmin,bymax,&c) */ xmin = 3; ymin = 1; + /* use separate statements so that compiler won't complain about min() + comparing two constants; the alternative is to do this in the + preprocessor: #if (20 > ROWNO-1) ymax=ROWNO-1 #else ymax=20 #endif */ xmax = 78; + xmax = min(xmax, (COLNO - 1) - 1); ymax = 20; + ymax = min(ymax, (ROWNO - 1)); - /* set hero's memory to water */ + /* entire level is remembered as one glyph and any unspecified portion + should default to level's base element rather than to usual stone */ + glyph = cmap_to_glyph(Is_waterlevel(&u.uz) ? S_water : S_air); + typ = Is_waterlevel(&u.uz) ? WATER : AIR; - for (x = xmin; x <= xmax; x++) - for (y = ymin; y <= ymax; y++) - levl[x][y].glyph = Is_waterlevel(&u.uz) ? water_glyph : air_glyph; + /* set unspecified terrain (stone) and hero's memory to water or air */ + for (x = 1; x <= COLNO - 1; x++) + for (y = 0; y <= ROWNO - 1; y++) { + levl[x][y].glyph = glyph; + if (levl[x][y].typ == STONE) + levl[x][y].typ = typ; + } /* make bubbles */ - if (Is_waterlevel(&u.uz)) { xskip = 10 + rn2(10); yskip = 4 + rn2(4); @@ -1694,7 +1725,6 @@ unsetup_waterlevel() struct bubble *b, *bb; /* free bubbles */ - for (b = bbubbles; b; b = bb) { bb = b->next; free((genericptr_t) b); @@ -1713,14 +1743,15 @@ int x, y, n; * in situ, either. The first two elements tell the dimensions of * the bubble's bounding box. */ - static uchar bm2[] = { 2, 1, 0x3 }, - bm3[] = { 3, 2, 0x7, 0x7 }, - bm4[] = { 4, 3, 0x6, 0xf, 0x6 }, - bm5[] = { 5, 3, 0xe, 0x1f, 0xe }, - bm6[] = { 6, 4, 0x1e, 0x3f, 0x3f, 0x1e }, - bm7[] = { 7, 4, 0x3e, 0x7f, 0x7f, 0x3e }, - bm8[] = { 8, 4, 0x7e, 0xff, 0xff, 0x7e }, - *bmask[] = { bm2, bm3, bm4, bm5, bm6, bm7, bm8 }; + static const uchar + bm2[] = { 2, 1, 0x3 }, + bm3[] = { 3, 2, 0x7, 0x7 }, + bm4[] = { 4, 3, 0x6, 0xf, 0x6 }, + bm5[] = { 5, 3, 0xe, 0x1f, 0xe }, + bm6[] = { 6, 4, 0x1e, 0x3f, 0x3f, 0x1e }, + bm7[] = { 7, 4, 0x3e, 0x7f, 0x7f, 0x3e }, + bm8[] = { 8, 4, 0x7e, 0xff, 0xff, 0x7e }, + *const bmask[] = { bm2, bm3, bm4, bm5, bm6, bm7, bm8 }; struct bubble *b; if (x >= bxmax || y >= bymax) @@ -1911,7 +1942,8 @@ boolean ini; b->dy = -b->dy; break; case 3: - b->dy = -b->dy; /* fall through */ + b->dy = -b->dy; + /*FALLTHRU*/ case 2: b->dx = -b->dx; break; From a09973851ee3bc4805a855bce74ae2ca96b9f372 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 31 May 2019 07:35:37 -0700 Subject: [PATCH 2/3] edge of map feedback When testing Planes of Air and Water, I found it odd that trying to move off the edge of a level uses a turn but provides no feedback. If 'mention_walls' is On, report that you can't go any farther in whichever direction you're trying to move. Moving diagonally is only blocked in one of the two combined directions unless you're in the very corner, so if you try to move southwest while in the middle of the bottom row, for instance, it says you can't go farther south rather than southwest. --- doc/fixes36.3 | 4 +++- src/hack.c | 19 ++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index fbb80dd07..83199ee84 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.28 $ $NHDT-Date: 1559299314 2019/05/31 10:41:54 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.29 $ $NHDT-Date: 1559313320 2019/05/31 14:35:20 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -75,6 +75,8 @@ General New Features -------------------- classify sources as released, beta, or work-in-progress via NH_DEVEL_STATUS rather than just released vs beta via BETA +if you reach the edge of a level (relatively uncommon) and try to move off, + report that you can't go farther if the 'mention_walls' option is set NetHack Community Patches (or Variation) Included diff --git a/src/hack.c b/src/hack.c index 6f2489197..7c80a8c1e 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 hack.c $NHDT-Date: 1551137618 2019/02/25 23:33:38 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.208 $ */ +/* NetHack 3.6 hack.c $NHDT-Date: 1559313320 2019/05/31 14:35:20 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.212 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1158,6 +1158,7 @@ int x,y; int ty = u.ty; boolean ret; int g = glyph_at(x,y); + if (x == u.ux && y == u.uy) return TRUE; if (isok(x,y) && glyph_is_cmap(g) && S_stone == glyph_to_cmap(g) @@ -1458,6 +1459,21 @@ domove_core() } } if (!isok(x, y)) { + if (iflags.mention_walls) { + int dx = u.dx, dy = u.dy; + + if (dx && dy) { /* diagonal */ + /* only as far as possible diagonally if in very + corner; otherwise just report whichever of the + cardinal directions has reached its limit */ + if (isok(x, u.uy)) + dx = 0; + else if (isok(u.ux, y)) + dy = 0; + } + You("have already gone as far %s as possible.", + directionname(xytod(dx, dy))); + } nomul(0); return; } @@ -2720,6 +2736,7 @@ lookaround() if (x == u.ux + u.dx && y == u.uy + u.dy) { if (iflags.mention_walls) { int tt = what_trap(trap->ttyp, rn2_on_display_rng); + You("stop in front of %s.", an(defsyms[trap_to_defsym(tt)].explanation)); } From cdb4a9e8b372e9956e945d1729cc1adde23c5eb9 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 31 May 2019 10:11:45 -0700 Subject: [PATCH 3/3] fix github issue #193 - curses: menu search Fixes #193 Under curses interface, make characters which are both entry selectors and menu commands function as a selector. Needed to support using ':' to look inside a container when applying/looting it via menu, instead of performing a menu search operation. (There was another case like this but I can't remember what the circumstances are. The fix is general enough to cover it, whatever it is.) For menus which don't have ':' as a choice, make sure search prompt doesn't offer garbage default input when built with EDIT_GETLIN. Bug? If player has 'popup_dialog' option On, EDIT_GETLIN is ignored. Plain curses I/O doesn't seem to offer a way to implement it. --- win/curses/cursdial.c | 212 ++++++++++++++++++++++-------------------- win/curses/cursmain.c | 1 + 2 files changed, 113 insertions(+), 100 deletions(-) diff --git a/win/curses/cursdial.c b/win/curses/cursdial.c index 18eaec465..2f2f5fcce 100644 --- a/win/curses/cursdial.c +++ b/win/curses/cursdial.c @@ -97,7 +97,8 @@ static char menu_get_accel(boolean first); static void menu_determine_pages(nhmenu *menu); static boolean menu_is_multipage(nhmenu *menu, int width, int height); static void menu_win_size(nhmenu *menu); -static void menu_display_page(nhmenu *menu, WINDOW * win, int page_num); +static void menu_display_page(nhmenu *menu, WINDOW * win, int page_num, + char *); static int menu_get_selections(WINDOW * win, nhmenu *menu, int how); static void menu_select_deselect(WINDOW * win, nhmenu_item *item, menu_op operation); @@ -116,7 +117,7 @@ static nhmenu *nhmenus = NULL; /* NetHack menu array */ /* Get a line of text from the player, such as asking for a character name - or a wish */ + or a wish. Note: EDIT_GETLIN not supported for popup prompting. */ void curses_line_input_dialog(const char *prompt, char *answer, int buffer) @@ -133,8 +134,8 @@ curses_line_input_dialog(const char *prompt, char *answer, int buffer) re-activate them now that input is being requested */ curses_got_input(); - if (buffer >= (int) sizeof input) - buffer = (int) sizeof input - 1; + if (buffer > (int) sizeof input) + buffer = (int) sizeof input; maxwidth = term_cols - 2; if (iflags.window_inited) { @@ -1059,7 +1060,7 @@ menu_win_size(nhmenu *menu) /* Displays menu selections in the given window */ static void -menu_display_page(nhmenu *menu, WINDOW * win, int page_num) +menu_display_page(nhmenu *menu, WINDOW * win, int page_num, char *selectors) { nhmenu_item *menu_item_ptr; int count, curletter, entry_cols, start_col, num_lines; @@ -1068,6 +1069,10 @@ menu_display_page(nhmenu *menu, WINDOW * win, int page_num) int color = NO_COLOR, attr = A_NORMAL; boolean menu_color = FALSE; + /* letters assigned to entries on current page */ + if (selectors) + (void) memset((genericptr_t) selectors, 0, 256); + /* Cycle through entries until we are on the correct page */ menu_item_ptr = menu->entries; @@ -1117,6 +1122,9 @@ menu_display_page(nhmenu *menu, WINDOW * win, int page_num) } menu_item_ptr->accelerator = curletter; } + /* we have a selector letter; tell caller about it */ + if (selectors) + selectors[(unsigned) (curletter & 0xFF)]++; if (menu_item_ptr->selected) { curses_toggle_color_attr(win, HIGHLIGHT_COLOR, A_REVERSE, ON); @@ -1222,10 +1230,10 @@ menu_get_selections(WINDOW * win, nhmenu *menu, int how) int curpage = !menu->bottom_heavy ? 1 : menu->num_pages; int num_selected = 0; boolean dismiss = FALSE; - char search_key[BUFSZ]; + char search_key[BUFSZ], selectors[256]; nhmenu_item *menu_item_ptr = menu->entries; - menu_display_page(menu, win, curpage); + menu_display_page(menu, win, curpage, selectors); while (!dismiss) { curletter = getch(); @@ -1253,25 +1261,27 @@ menu_get_selections(WINDOW * win, nhmenu *menu, int how) } break; case PICK_ANY: - switch (curletter) { - case MENU_SELECT_PAGE: - (void) menu_operation(win, menu, SELECT, curpage); - break; - case MENU_SELECT_ALL: - curpage = menu_operation(win, menu, SELECT, 0); - break; - case MENU_UNSELECT_PAGE: - (void) menu_operation(win, menu, DESELECT, curpage); - break; - case MENU_UNSELECT_ALL: - curpage = menu_operation(win, menu, DESELECT, 0); - break; - case MENU_INVERT_PAGE: - (void) menu_operation(win, menu, INVERT, curpage); - break; - case MENU_INVERT_ALL: - curpage = menu_operation(win, menu, INVERT, 0); - break; + if (curletter <= 0 || curletter >= 256 || !selectors[curletter]) { + switch (curletter) { + case MENU_SELECT_PAGE: + (void) menu_operation(win, menu, SELECT, curpage); + break; + case MENU_SELECT_ALL: + curpage = menu_operation(win, menu, SELECT, 0); + break; + case MENU_UNSELECT_PAGE: + (void) menu_operation(win, menu, DESELECT, curpage); + break; + case MENU_UNSELECT_ALL: + curpage = menu_operation(win, menu, DESELECT, 0); + break; + case MENU_INVERT_PAGE: + (void) menu_operation(win, menu, INVERT, curpage); + break; + case MENU_INVERT_ALL: + curpage = menu_operation(win, menu, INVERT, 0); + break; + } } /*FALLTHRU*/ default: @@ -1286,86 +1296,88 @@ menu_get_selections(WINDOW * win, nhmenu *menu, int how) } } - switch (curletter) { - case KEY_ESC: - num_selected = -1; - dismiss = TRUE; - break; - case '\n': - case '\r': - dismiss = TRUE; - break; - case KEY_RIGHT: - case KEY_NPAGE: - case MENU_NEXT_PAGE: - case ' ': - if (curpage < menu->num_pages) { - curpage++; - menu_display_page(menu, win, curpage); - } else if (curletter == ' ') { + if (curletter <= 0 || curletter >= 256 || !selectors[curletter]) { + switch (curletter) { + case KEY_ESC: + num_selected = -1; dismiss = TRUE; break; - } - break; - case KEY_LEFT: - case KEY_PPAGE: - case MENU_PREVIOUS_PAGE: - if (curpage > 1) { - curpage--; - menu_display_page(menu, win, curpage); - } - break; - case KEY_END: - case MENU_LAST_PAGE: - if (curpage != menu->num_pages) { - curpage = menu->num_pages; - menu_display_page(menu, win, curpage); - } - break; - case KEY_HOME: - case MENU_FIRST_PAGE: - if (curpage != 1) { - curpage = 1; - menu_display_page(menu, win, curpage); - } - break; - case MENU_SEARCH: - curses_line_input_dialog("Search for:", search_key, BUFSZ); - - refresh(); - touchwin(win); - wrefresh(win); - - if (!*search_key) { + case '\n': + case '\r': + dismiss = TRUE; break; - } + case KEY_RIGHT: + case KEY_NPAGE: + case MENU_NEXT_PAGE: + case ' ': + if (curpage < menu->num_pages) { + curpage++; + menu_display_page(menu, win, curpage, selectors); + } else if (curletter == ' ') { + dismiss = TRUE; + break; + } + break; + case KEY_LEFT: + case KEY_PPAGE: + case MENU_PREVIOUS_PAGE: + if (curpage > 1) { + curpage--; + menu_display_page(menu, win, curpage, selectors); + } + break; + case KEY_END: + case MENU_LAST_PAGE: + if (curpage != menu->num_pages) { + curpage = menu->num_pages; + menu_display_page(menu, win, curpage, selectors); + } + break; + case KEY_HOME: + case MENU_FIRST_PAGE: + if (curpage != 1) { + curpage = 1; + menu_display_page(menu, win, curpage, selectors); + } + break; + case MENU_SEARCH: + search_key[0] = '\0'; + curses_line_input_dialog("Search for:", search_key, BUFSZ); - menu_item_ptr = menu->entries; + refresh(); + touchwin(win); + wrefresh(win); - while (menu_item_ptr != NULL) { - if (menu_item_ptr->identifier.a_void != NULL - && strstri(menu_item_ptr->str, search_key)) { - if (how == PICK_ONE) { - menu_clear_selections(menu); - menu_select_deselect(win, menu_item_ptr, SELECT); - num_selected = 1; - dismiss = TRUE; - break; - } else { - menu_select_deselect(win, menu_item_ptr, INVERT); + if (!*search_key) + break; + + menu_item_ptr = menu->entries; + + while (menu_item_ptr != NULL) { + if (menu_item_ptr->identifier.a_void != NULL + && strstri(menu_item_ptr->str, search_key)) { + if (how == PICK_ONE) { + menu_clear_selections(menu); + menu_select_deselect(win, menu_item_ptr, SELECT); + num_selected = 1; + dismiss = TRUE; + break; + } else { + menu_select_deselect(win, menu_item_ptr, INVERT); + } } + + menu_item_ptr = menu_item_ptr->next_item; } - menu_item_ptr = menu_item_ptr->next_item; - } - - menu_item_ptr = menu->entries; - break; - default: - if (how == PICK_NONE) { - num_selected = 0; - dismiss = TRUE; + menu_item_ptr = menu->entries; break; + default: + if (how == PICK_NONE) { + num_selected = 0; + dismiss = TRUE; + break; + } } } @@ -1379,7 +1391,7 @@ menu_get_selections(WINDOW * win, nhmenu *menu, int how) && curletter == menu_item_ptr->group_accel)) { if (curpage != menu_item_ptr->page_num) { curpage = menu_item_ptr->page_num; - menu_display_page(menu, win, curpage); + menu_display_page(menu, win, curpage, selectors); } if (how == PICK_ONE) { @@ -1479,7 +1491,7 @@ menu_operation(WINDOW * win, nhmenu *menu, menu_op current_page = first_page; if (page_num == 0) { - menu_display_page(menu, win, current_page); + menu_display_page(menu, win, current_page, (char *) 0); } if (menu_item_ptr == NULL) { /* Page not found */ @@ -1494,7 +1506,7 @@ menu_operation(WINDOW * win, nhmenu *menu, menu_op } current_page = menu_item_ptr->page_num; - menu_display_page(menu, win, current_page); + menu_display_page(menu, win, current_page, (char *) 0); } if (menu_item_ptr->identifier.a_void != NULL) { diff --git a/win/curses/cursmain.c b/win/curses/cursmain.c index ada703de4..931de9569 100644 --- a/win/curses/cursmain.c +++ b/win/curses/cursmain.c @@ -202,6 +202,7 @@ curses_player_selection() void curses_askname() { + plname[0] = '\0'; curses_line_input_dialog("Who are you?", plname, PL_NSIZ); }