]> granicus.if.org Git - nethack/commitdiff
beta feedback - add more wc options
authornethack.allison <nethack.allison>
Tue, 12 Mar 2002 05:15:40 +0000 (05:15 +0000)
committernethack.allison <nethack.allison>
Tue, 12 Mar 2002 05:15:40 +0000 (05:15 +0000)
- splash_screen (boolean for whether to display splash screen at startup)
- player_selection:dialog|prompts

Also moves the font and window manipulation stuff in defaults.nh
further down the file, so that a tty users doesn't have to wade
through it all to find the character adjustment samples.

doc/Guidebook.mn
doc/Guidebook.tex
doc/window.doc
include/flag.h
include/winprocs.h
src/options.c
sys/winnt/defaults.nh
win/win32/mswproc.c

index 0ba33d377e9df9c3c288416ff7c3db852ed37927..e47b86f3a24014d6221cd2db2ada3fd15e8b693c 100644 (file)
@@ -4,7 +4,7 @@
 .ds vr "NetHack 3.4
 .ds f0 "\*(vr
 .ds f1
-.ds f2 "March 10, 2002
+.ds f2 "March 12, 2002
 .mt
 A Guide to the Mazes of Menace
 (Guidebook for NetHack)
@@ -2093,6 +2093,8 @@ with tiles, generally displays a heart symbol near pets.
 NetHack should use a large font.
 .lp map_mode   
 NetHack should display the map in the manner specified.
+.lp player_selection
+NetHack should pop up dialog boxes, or use prompts for character selection.
 .lp popup_dialog       
 NetHack should pop up dialog boxes for input.
 .lp preload_tiles
@@ -2104,6 +2106,8 @@ Cannot be set with the `O' command.
 .lp scroll_margin      
 NetHack should scroll the display when the hero or cursor
 is this number of cells away from the edge of the window.
+.lp splash_screen
+NetHack should display an opening splash screen when it starts up (default yes).
 .lp tiled_map  
 NetHack should display a tiled map if it can.
 .lp tile_file
index 0c07fe374b42cd1a8b2eb77007eafa40e4f64064..5dd07be1496166d73d726cc3d6c43023e9ba186d 100644 (file)
@@ -39,7 +39,7 @@
 %.au
 \author{Eric S. Raymond\\
 (Extensively edited and expanded for 3.4)}
-\date{March 10, 2002}
+\date{March 12, 2002}
 
 \maketitle
 
@@ -2577,6 +2577,9 @@ NetHack should use a large font.
 \item[\ib{map\_mode}]
 NetHack should display the map in the manner specified.
 %.lp
+\item[\ib{player\_selection}]
+NetHack should pop up dialog boxes or use prompts for character selection.
+%.lp
 \item[\ib{popup\_dialog}]
 NetHack should pop up dialog boxes for input.
 %.lp
@@ -2591,6 +2594,9 @@ Cannot be set with the `{\tt O}' command.
 NetHack should scroll the display when the hero or cursor
 is this number of cells away from the edge of the window.
 %.lp
+\item[\ib{splash\_screen}]
+NetHack should display an opening splash screen when it starts up (default yes).
+%.lp
 \item[\ib{tiled\_map}]
 NetHack should display a tiled map if it can.
 %.lp
index 96d6655553fe216661954279927254f57af01655..b24e06f8621aea662e9ead6fec3fb84ffe25a74b 100644 (file)
@@ -478,9 +478,11 @@ to support:
   |  hilite_pet        | WC_HILITE_PET      | wc_hilite_pet      |boolean |
   |  large_font        | WC_LARGE_FONT      | wc_large_font      |boolean |
   |  map_mode          | WC_MAP_MODE        | wc_map_mode        |int     |
+  |  player_selection  | WC_PLAYER_SELECTION| wc_player_selection|int     |
   |  popup_dialog      | WC_POPUP_DIALOG    | wc_popup_dialog    |boolean |
   |  preload_tiles     | WC_PRELOAD_TILES   | wc_preload_tiles   |boolean |
   |  scroll_margin     | WC_SCROLL_MARGIN   | wc_scroll_margin   |int     |
+  |  splash_screen     | WC_SPLASH_SCREEN   | wc_splash_screen   |boolean |
   |  tiled_map         | WC_TILED_MAP       | wc_tiled_map       |boolean |
   |  tile_width        | WC_TILE_WIDTH      | wc_tile_width      |int     |
   |  tile_height       | WC_TILE_HEIGHT     | wc_tile_height     |int     |
@@ -516,10 +518,13 @@ font_text -- port should use a font by this name for text windows.
 hilite_pet     -- port should mark pets in some special way on the map.
 large_font     -- port should use a large font.
 map_mode       -- port should display the map in the manner specified.
+player_selection
+               -- dialog or prompts for choosing character.
 popup_dialog   -- port should pop up dialog boxes for input.
 preload_tiles  -- port should preload tiles into memory.
 scroll_margin  -- port should scroll the display when the hero or cursor
                   is this number of cells away from the edge of the window.
+splash_screen   -- port should/should not display an opening splashscreen.
 tiled_map      -- port should display a tiled map if it can.
 tile_width     -- port should display tiles with this width or round to closest
                   if it can.
index 0f9f7cbfd75aa6198e68822e1c074f5a1f4d5106..ddc607080001e1508fa70c7f0da4716f17b0e15c 100644 (file)
@@ -245,6 +245,8 @@ struct instance_flags {
                                                the edge */
        int     wc_map_mode;            /* specify map viewing options, mostly
                                                for backward compatibility */
+       int     wc_player_selection;    /* method of choosing character */
+       boolean wc_splash_screen;       /* display an opening splash screen or not */
        boolean wc_popup_dialog;        /* put queries in pop up dialogs instead of
                                                in the message window */
        boolean wc_large_font;          /* draw in larger fonts (say, 12pt instead
index ac7d056c4a723fcb4dfba693a28130697b011ba1..87a21ca0537bba2b308065b84e99c015e8e2604d 100644 (file)
@@ -157,19 +157,25 @@ extern NEARDATA struct window_procs windowprocs;
 #define WC_FONTSIZ_MENU         0x100000L      /* 21 supports specification of mnu win font */
 #define WC_FONTSIZ_TEXT         0x200000L      /* 22 supports specification of txt win font */
 #define WC_SCROLL_MARGIN 0x400000L     /* 23 supports setting scroll margin for map */
-#define WC_POPUP_DIALOG         0x800000L      /* 24 supports queries in pop dialogs        */
-#define WC_LARGE_FONT   0x1000000L     /* 25 Port supports large font               */
-#define WC_EIGHT_BIT_IN         0x2000000L     /* 26 8-bit character input                  */
-#define WC_PERM_INVENT  0x4000000L     /* 27 8-bit character input                  */
-#define WC_MAP_MODE     0x8000000L     /* 28 map_mode option                        */
-#define WC_WINDOWCOLORS  0x10000000L   /* 29 background color for message window    */
-                                       /* 3 free bits */
+#define WC_SPLASH_SCREEN 0x800000L     /* 24 supports setting scroll margin for map */
+#define WC_POPUP_DIALOG         0x1000000L     /* 25 supports queries in pop dialogs        */
+#define WC_LARGE_FONT   0x2000000L     /* 26 Port supports large font               */
+#define WC_EIGHT_BIT_IN         0x4000000L     /* 27 8-bit character input                  */
+#define WC_PERM_INVENT  0x8000000L     /* 28 8-bit character input                  */
+#define WC_MAP_MODE     0x10000000L    /* 29 map_mode option                        */
+#define WC_WINDOWCOLORS  0x20000000L   /* 30 background color for message window    */
+#define WC_PLAYER_SELECTION  0x40000000L /* 31 background color for message window    */
+                                       /* 1 free bit */
 
 #define ALIGN_LEFT     1
 #define ALIGN_RIGHT    2
 #define ALIGN_TOP      3
 #define ALIGN_BOTTOM   4
 
+/* player_selection */
+#define VIA_DIALOG     0
+#define VIA_PROMPTS    1
+
 /* map_mode settings - deprecated */
 #define MAP_MODE_TILES         0
 #define MAP_MODE_ASCII4x6      1
index 2f9a46490cb1bc55214e4cfbfb9a5ec096efd944..00662750c995e56cfb34757448c72220161d43a6 100644 (file)
@@ -167,6 +167,7 @@ static struct Bool_Opt
        {"sound", &flags.soundok, TRUE, SET_IN_GAME},
        {"sparkle", &flags.sparkle, TRUE, SET_IN_GAME},
        {"standout", &flags.standout, FALSE, SET_IN_GAME},
+       {"splash_screen",     &iflags.wc_splash_screen, TRUE, DISP_IN_GAME},    /*WC*/
        {"tiled_map",     &iflags.wc_tiled_map, FALSE, DISP_IN_GAME},   /*WC*/
        {"time", &flags.time, FALSE, SET_IN_GAME},
 #ifdef TIMED_DELAY
@@ -272,6 +273,8 @@ static struct Comp_Opt
                                                20, SET_IN_GAME },
        { "pickup_types", "types of objects to pick up automatically",
                                                MAXOCLASSES, SET_IN_GAME },
+       { "player_selection", "choose character via dialog or prompts",
+                                               12, DISP_IN_GAME },
        { "race",     "your starting race (e.g., Human, Elf)",
                                                PL_CSIZ, DISP_IN_GAME },
        { "role",     "your starting role (e.g., Barbarian, Valkyrie)",
@@ -1570,6 +1573,21 @@ goodfruit:
                }
                return;
        }
+       /* WINCAP
+        * player_selection: dialog | prompts */
+       fullname = "player_selection";
+       if (match_optname(opts, fullname, sizeof("player_selection")-1, TRUE)) {
+               op = string_for_opt(opts, negated);
+               if (op && !negated) {
+                   if (!strncmpi (op, "dialog", sizeof("dialog")-1))
+                       iflags.wc_player_selection = VIA_DIALOG;
+                   else if (!strncmpi (op, "prompt", sizeof("prompt")-1))
+                       iflags.wc_player_selection = VIA_PROMPTS;
+                   else
+                       badoption(opts);
+               } else if (negated) bad_negation(fullname, TRUE);
+               return;
+       }
 
        /* things to disclose at end of game */
        if (match_optname(opts, "disclose", 7, TRUE)) {
@@ -2606,6 +2624,8 @@ char *buf;
                if (iflags.wc_scroll_margin) Sprintf(buf, "%d",iflags.wc_scroll_margin);
                else Strcpy(buf, defopt);
        }
+       else if (!strcmp(optname, "player_selection"))
+               Sprintf(buf, "%s", iflags.wc_player_selection ? "prompts" : "dialog");
 #ifdef MSDOS
        else if (!strcmp(optname, "soundcard"))
                Sprintf(buf, "%s", to_be_done);
index 65af9b9b985e47b2520ec054d70e2b448361d935..954d3029663a3608e570ec6185b84bf0e150a81e 100644 (file)
 # for tty window-port.
 OPTIONS=IBMGraphics
 
+# *** Personal Preferences ***
+# Some options to set personal preferences.  Uncomment and change these to
+# suit your personal preference.  If several people are to use the same
+# configuration, options like these should not be set.
+#
+#OPTIONS=name:Janet,role:Valkyrie,race:Human,gender:female,align:lawful
+#OPTIONS=dogname:Fido,catname:Morris,fruit:guava
+#OPTIONS=horsename:Silver
+#OPTIONS=autopickup,pickup_types:$"=/!?+
+#OPTIONS=packorder:")[%?+/=!(*0_`
+#OPTIONS=scores:10 top/2 around/own
+#OPTIONS=nolegacy,noverbose
+#OPTIONS=menustyle:traditional
+
+#
+# General options.  You might also set "silent" so as not to attract
+# the boss's attention.
+#
+OPTIONS=time,noshowexp,number_pad,lit_corridor,rest_on_space
+#
+# If you want to get rid of "use #quit to quit..." use:
+#OPTIONS=suppress_alert:3.3.1
+#
 # Set some options to control graphical window-port (these will
 # be safely and silently ignored by the tty port)
 #
@@ -22,58 +45,31 @@ OPTIONS=IBMGraphics
 #                                    ascii10x18|fit_to_screen
 OPTIONS=map_mode:tiles,scroll_margin:5
 
-#
 # Message window settings
 OPTIONS=font_message:Arial,font_size_message:9,align_message:top
 
-#
 # Menu settings
 OPTIONS=font_menu:Arial,font_size_menu:9
 
-#
 # Text settings
 OPTIONS=font_text:Courier New,font_size_text:9
 
-#
 # Status window settings
 OPTIONS=font_status:Courier New,font_size_status:10
 
-#
 # Other
 OPTIONS=hilite_pet
+#OPTIONS=!splash_screen,player_selection:prompts
 
 # Top Ten Window.  Highly Recommended.
-OPTIONS=toptenwin
-
-# *** Personal Preferences ***
-# Some options to set personal preferences.  Uncomment and change these to
-# suit your personal preference.  If several people are to use the same
-# configuration, options like these should not be set.
-#
-#OPTIONS=name:Janet,role:Valkyrie,race:Human,gender:female,align:lawful
-#OPTIONS=dogname:Fido,catname:Morris,fruit:guava
-#OPTIONS=horsename:Silver
-#OPTIONS=autopickup,pickup_types:$"=/!?+
-#OPTIONS=packorder:")[%?+/=!(*0_`
-#OPTIONS=scores:10 top/2 around/own
-#OPTIONS=nolegacy,noverbose
-#OPTIONS=menustyle:traditional
-
-#
-# General options.  You might also set "silent" so as not to attract
-# the boss's attention.
-#
-OPTIONS=time,noshowexp,number_pad,lit_corridor,rest_on_space
-#
-# If you want to get rid of "use #quit to quit..." use:
-#OPTIONS=suppress_alert:3.3.1
-#
+#OPTIONS=toptenwin
 
 #
 #HACKDIR=c:\games\nethack
 # 
-# Note: Under MSDOS ports HACKDIR defaults to the location 
-#       of the NetHack.exe file. Setting HACKDIR above will override that.
+# Note: On Windows HACKDIR defaults to the location 
+#       of the NetHack.exe or NetHackw.exe file. 
+#       Setting HACKDIR above will override that.
 #
 #   LEVELS and SAVE default to HACKDIR
 #
index 11ae2b685b43851e50f9dbade0480d94c5a9c637..97b8267fed305602cf8f282b0e2d803ec9221b7c 100644 (file)
@@ -36,6 +36,7 @@ void logDebug(const char *fmt, ...) { }
 static void mswin_main_loop(void);
 static BOOL initMapTiles(void);
 static void mswin_color_from_string(char *colorstring, HBRUSH* brushptr, COLORREF *colorptr);
+static void prompt_for_player_selection(void);
 
 #define TOTAL_BRUSHES  10
 HBRUSH brush_table[TOTAL_BRUSHES];
@@ -66,7 +67,8 @@ struct window_procs mswin_procs = {
        WC_INVERSE|WC_SCROLL_MARGIN|WC_MAP_MODE|
        WC_FONT_MESSAGE|WC_FONT_STATUS|WC_FONT_MENU|WC_FONT_TEXT|
        WC_FONTSIZ_MESSAGE|WC_FONTSIZ_STATUS|WC_FONTSIZ_MENU|WC_FONTSIZ_TEXT|
-       WC_TILE_WIDTH|WC_TILE_HEIGHT|WC_TILE_FILE|WC_VARY_MSGCOUNT|WC_WINDOWCOLORS,
+       WC_TILE_WIDTH|WC_TILE_HEIGHT|WC_TILE_FILE|WC_VARY_MSGCOUNT|
+       WC_WINDOWCOLORS|WC_PLAYER_SELECTION|WC_SPLASH_SCREEN,
     mswin_init_nhwindows,
     mswin_player_selection,
     mswin_askname,
@@ -219,7 +221,7 @@ void mswin_init_nhwindows(int* argc, char** argv)
        mswin_color_from_string(iflags.wc_backgrnd_status, &status_bg_brush, &status_bg_color);
        mswin_color_from_string(iflags.wc_backgrnd_text, &text_bg_brush, &text_bg_color);
 
-       mswin_display_splash_window();
+       if (iflags.wc_splash_screen) mswin_display_splash_window();
        iflags.window_inited = TRUE;
 }
 
@@ -234,8 +236,9 @@ void mswin_player_selection(void)
 
        logDebug("mswin_player_selection()\n");
 
-       /* pick player type randomly (use pre-selected role/race/gender/alignment) */
-       if( flags.randomall ) {
+       if (iflags.wc_player_selection == VIA_DIALOG) {
+           /* pick player type randomly (use pre-selected role/race/gender/alignment) */
+           if( flags.randomall ) {
                if (flags.initrole < 0) {
                        flags.initrole = pick_role(flags.initrace, flags.initgend,
                                                        flags.initalign, PICK_RANDOM);
@@ -273,14 +276,358 @@ void mswin_player_selection(void)
                                flags.initalign = randalign(flags.initrole, flags.initrace);
                        }
                }
-       } else {
+           } else {
                /* select a role */
                if( mswin_player_selection_window( &nRole ) == IDCANCEL ) {
                        bail(0);
                }
+           }
+       } else { /* iflags.wc_player_selection == VIA_PROMPTS */
+           prompt_for_player_selection();
        }
 }
 
+void prompt_for_player_selection(void)
+{
+       int i, k, n;
+       char pick4u = 'n', thisch, lastch = 0;
+       char pbuf[QBUFSZ], plbuf[QBUFSZ];
+       winid win;
+       anything any;
+       menu_item *selected = 0;
+        DWORD box_result;
+
+       logDebug("prompt_for_player_selection()\n");
+
+       /* prevent an unnecessary prompt */
+       rigid_role_checks();
+
+       /* Should we randomly pick for the player? */
+       if (!flags.randomall &&
+           (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE ||
+            flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE)) {
+           /* int echoline; */
+           char *prompt = build_plselection_prompt(pbuf, QBUFSZ, flags.initrole,
+                               flags.initrace, flags.initgend, flags.initalign);
+
+           /* tty_putstr(BASE_WINDOW, 0, ""); */
+           /* echoline = wins[BASE_WINDOW]->cury; */
+            box_result = MessageBox(NULL, prompt, TEXT("NetHack for Windows"),
+                                       MB_YESNOCANCEL | MB_DEFBUTTON1);
+            pick4u = (box_result == IDYES) ? 'y' : (box_result == IDNO) ? 'n' : '\033';
+           /* tty_putstr(BASE_WINDOW, 0, prompt); */
+           do {
+               /* pick4u = lowc(readchar()); */
+               if (index(quitchars, pick4u)) pick4u = 'y';
+           } while(!index(ynqchars, pick4u));
+           if ((int)strlen(prompt) + 1 < CO) {
+               /* Echo choice and move back down line */
+               /* tty_putsym(BASE_WINDOW, (int)strlen(prompt)+1, echoline, pick4u); */
+               /* tty_putstr(BASE_WINDOW, 0, ""); */
+           } else
+               /* Otherwise it's hard to tell where to echo, and things are
+                * wrapping a bit messily anyway, so (try to) make sure the next
+                * question shows up well and doesn't get wrapped at the
+                * bottom of the window.
+                */
+               /* tty_clear_nhwindow(BASE_WINDOW) */ ;
+           
+           if (pick4u != 'y' && pick4u != 'n') {
+give_up:       /* Quit */
+               if (selected) free((genericptr_t) selected);
+               bail((char *)0);
+               /*NOTREACHED*/
+               return;
+           }
+       }
+
+       (void)  root_plselection_prompt(plbuf, QBUFSZ - 1,
+                       flags.initrole, flags.initrace, flags.initgend, flags.initalign);
+
+       /* Select a role, if necessary */
+       /* we'll try to be compatible with pre-selected race/gender/alignment,
+        * but may not succeed */
+       if (flags.initrole < 0) {
+           char rolenamebuf[QBUFSZ];
+           /* Process the choice */
+           if (pick4u == 'y' || flags.initrole == ROLE_RANDOM || flags.randomall) {
+               /* Pick a random role */
+               flags.initrole = pick_role(flags.initrace, flags.initgend,
+                                               flags.initalign, PICK_RANDOM);
+               if (flags.initrole < 0) {
+                   /* tty_putstr(BASE_WINDOW, 0, "Incompatible role!"); */
+                   flags.initrole = randrole();
+               }
+           } else {
+               /* tty_clear_nhwindow(BASE_WINDOW); */
+               /* tty_putstr(BASE_WINDOW, 0, "Choosing Character's Role"); */
+               /* Prompt for a role */
+               win = create_nhwindow(NHW_MENU);
+               start_menu(win);
+               any.a_void = 0;         /* zero out all bits */
+               for (i = 0; roles[i].name.m; i++) {
+                   if (ok_role(i, flags.initrace, flags.initgend,
+                                                       flags.initalign)) {
+                       any.a_int = i+1;        /* must be non-zero */
+                       thisch = lowc(roles[i].name.m[0]);
+                       if (thisch == lastch) thisch = highc(thisch);
+                       if (flags.initgend != ROLE_NONE && flags.initgend != ROLE_RANDOM) {
+                               if (flags.initgend == 1  && roles[i].name.f)
+                                       Strcpy(rolenamebuf, roles[i].name.f);
+                               else
+                                       Strcpy(rolenamebuf, roles[i].name.m);
+                       } else {
+                               if (roles[i].name.f) {
+                                       Strcpy(rolenamebuf, roles[i].name.m);
+                                       Strcat(rolenamebuf, "/");
+                                       Strcat(rolenamebuf, roles[i].name.f);
+                               } else 
+                                       Strcpy(rolenamebuf, roles[i].name.m);
+                       }       
+                       add_menu(win, NO_GLYPH, &any, thisch,
+                           0, ATR_NONE, an(rolenamebuf), MENU_UNSELECTED);
+                       lastch = thisch;
+                   }
+               }
+               any.a_int = pick_role(flags.initrace, flags.initgend,
+                                   flags.initalign, PICK_RANDOM)+1;
+               if (any.a_int == 0)     /* must be non-zero */
+                   any.a_int = randrole()+1;
+               add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
+                               "Random", MENU_UNSELECTED);
+               any.a_int = i+1;        /* must be non-zero */
+               add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
+                               "Quit", MENU_UNSELECTED);
+               Sprintf(pbuf, "Pick a role for your %s", plbuf);
+               end_menu(win, pbuf);
+               n = select_menu(win, PICK_ONE, &selected);
+               destroy_nhwindow(win);
+
+               /* Process the choice */
+               if (n != 1 || selected[0].item.a_int == any.a_int)
+                   goto give_up;               /* Selected quit */
+
+               flags.initrole = selected[0].item.a_int - 1;
+               free((genericptr_t) selected),  selected = 0;
+           }
+           (void)  root_plselection_prompt(plbuf, QBUFSZ - 1,
+                       flags.initrole, flags.initrace, flags.initgend, flags.initalign);
+       }
+       
+       /* Select a race, if necessary */
+       /* force compatibility with role, try for compatibility with
+        * pre-selected gender/alignment */
+       if (flags.initrace < 0 || !validrace(flags.initrole, flags.initrace)) {
+           /* pre-selected race not valid */
+           if (pick4u == 'y' || flags.initrace == ROLE_RANDOM || flags.randomall) {
+               flags.initrace = pick_race(flags.initrole, flags.initgend,
+                                                       flags.initalign, PICK_RANDOM);
+               if (flags.initrace < 0) {
+                   /* tty_putstr(BASE_WINDOW, 0, "Incompatible race!"); */
+                   flags.initrace = randrace(flags.initrole);
+               }
+           } else {    /* pick4u == 'n' */
+               /* Count the number of valid races */
+               n = 0;  /* number valid */
+               k = 0;  /* valid race */
+               for (i = 0; races[i].noun; i++) {
+                   if (ok_race(flags.initrole, i, flags.initgend,
+                                                       flags.initalign)) {
+                       n++;
+                       k = i;
+                   }
+               }
+               if (n == 0) {
+                   for (i = 0; races[i].noun; i++) {
+                       if (validrace(flags.initrole, i)) {
+                           n++;
+                           k = i;
+                       }
+                   }
+               }
+
+               /* Permit the user to pick, if there is more than one */
+               if (n > 1) {
+                   /* tty_clear_nhwindow(BASE_WINDOW); */
+                   /* tty_putstr(BASE_WINDOW, 0, "Choosing Race"); */
+                   win = create_nhwindow(NHW_MENU);
+                   start_menu(win);
+                   any.a_void = 0;         /* zero out all bits */
+                   for (i = 0; races[i].noun; i++)
+                       if (ok_race(flags.initrole, i, flags.initgend,
+                                                       flags.initalign)) {
+                           any.a_int = i+1;    /* must be non-zero */
+                           add_menu(win, NO_GLYPH, &any, races[i].noun[0],
+                               0, ATR_NONE, races[i].noun, MENU_UNSELECTED);
+                       }
+                   any.a_int = pick_race(flags.initrole, flags.initgend,
+                                       flags.initalign, PICK_RANDOM)+1;
+                   if (any.a_int == 0) /* must be non-zero */
+                       any.a_int = randrace(flags.initrole)+1;
+                   add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
+                                   "Random", MENU_UNSELECTED);
+                   any.a_int = i+1;    /* must be non-zero */
+                   add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
+                                   "Quit", MENU_UNSELECTED);
+                   Sprintf(pbuf, "Pick the race of your %s", plbuf);
+                   end_menu(win, pbuf);
+                   n = select_menu(win, PICK_ONE, &selected);
+                   destroy_nhwindow(win);
+                   if (n != 1 || selected[0].item.a_int == any.a_int)
+                       goto give_up;           /* Selected quit */
+
+                   k = selected[0].item.a_int - 1;
+                   free((genericptr_t) selected),      selected = 0;
+               }
+               flags.initrace = k;
+           }
+           (void)  root_plselection_prompt(plbuf, QBUFSZ - 1,
+                       flags.initrole, flags.initrace, flags.initgend, flags.initalign);
+       }
+
+       /* Select a gender, if necessary */
+       /* force compatibility with role/race, try for compatibility with
+        * pre-selected alignment */
+       if (flags.initgend < 0 || !validgend(flags.initrole, flags.initrace,
+                                               flags.initgend)) {
+           /* pre-selected gender not valid */
+           if (pick4u == 'y' || flags.initgend == ROLE_RANDOM || flags.randomall) {
+               flags.initgend = pick_gend(flags.initrole, flags.initrace,
+                                               flags.initalign, PICK_RANDOM);
+               if (flags.initgend < 0) {
+                   /* tty_putstr(BASE_WINDOW, 0, "Incompatible gender!"); */
+                   flags.initgend = randgend(flags.initrole, flags.initrace);
+               }
+           } else {    /* pick4u == 'n' */
+               /* Count the number of valid genders */
+               n = 0;  /* number valid */
+               k = 0;  /* valid gender */
+               for (i = 0; i < ROLE_GENDERS; i++) {
+                   if (ok_gend(flags.initrole, flags.initrace, i,
+                                                       flags.initalign)) {
+                       n++;
+                       k = i;
+                   }
+               }
+               if (n == 0) {
+                   for (i = 0; i < ROLE_GENDERS; i++) {
+                       if (validgend(flags.initrole, flags.initrace, i)) {
+                           n++;
+                           k = i;
+                       }
+                   }
+               }
+
+               /* Permit the user to pick, if there is more than one */
+               if (n > 1) {
+                   /* tty_clear_nhwindow(BASE_WINDOW); */
+                   /* tty_putstr(BASE_WINDOW, 0, "Choosing Gender"); */
+                   win = create_nhwindow(NHW_MENU);
+                   start_menu(win);
+                   any.a_void = 0;         /* zero out all bits */
+                   for (i = 0; i < ROLE_GENDERS; i++)
+                       if (ok_gend(flags.initrole, flags.initrace, i,
+                                                           flags.initalign)) {
+                           any.a_int = i+1;
+                           add_menu(win, NO_GLYPH, &any, genders[i].adj[0],
+                               0, ATR_NONE, genders[i].adj, MENU_UNSELECTED);
+                       }
+                   any.a_int = pick_gend(flags.initrole, flags.initrace,
+                                           flags.initalign, PICK_RANDOM)+1;
+                   if (any.a_int == 0) /* must be non-zero */
+                       any.a_int = randgend(flags.initrole, flags.initrace)+1;
+                   add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
+                                   "Random", MENU_UNSELECTED);
+                   any.a_int = i+1;    /* must be non-zero */
+                   add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
+                                   "Quit", MENU_UNSELECTED);
+                   Sprintf(pbuf, "Pick the gender of your %s", plbuf);
+                   end_menu(win, pbuf);
+                   n = select_menu(win, PICK_ONE, &selected);
+                   destroy_nhwindow(win);
+                   if (n != 1 || selected[0].item.a_int == any.a_int)
+                       goto give_up;           /* Selected quit */
+
+                   k = selected[0].item.a_int - 1;
+                   free((genericptr_t) selected),      selected = 0;
+               }
+               flags.initgend = k;
+           }
+           (void)  root_plselection_prompt(plbuf, QBUFSZ - 1,
+                       flags.initrole, flags.initrace, flags.initgend, flags.initalign);
+       }
+
+       /* Select an alignment, if necessary */
+       /* force compatibility with role/race/gender */
+       if (flags.initalign < 0 || !validalign(flags.initrole, flags.initrace,
+                                                       flags.initalign)) {
+           /* pre-selected alignment not valid */
+           if (pick4u == 'y' || flags.initalign == ROLE_RANDOM || flags.randomall) {
+               flags.initalign = pick_align(flags.initrole, flags.initrace,
+                                                       flags.initgend, PICK_RANDOM);
+               if (flags.initalign < 0) {
+                   /* tty_putstr(BASE_WINDOW, 0, "Incompatible alignment!"); */
+                   flags.initalign = randalign(flags.initrole, flags.initrace);
+               }
+           } else {    /* pick4u == 'n' */
+               /* Count the number of valid alignments */
+               n = 0;  /* number valid */
+               k = 0;  /* valid alignment */
+               for (i = 0; i < ROLE_ALIGNS; i++) {
+                   if (ok_align(flags.initrole, flags.initrace, flags.initgend,
+                                                       i)) {
+                       n++;
+                       k = i;
+                   }
+               }
+               if (n == 0) {
+                   for (i = 0; i < ROLE_ALIGNS; i++) {
+                       if (validalign(flags.initrole, flags.initrace, i)) {
+                           n++;
+                           k = i;
+                       }
+                   }
+               }
+
+               /* Permit the user to pick, if there is more than one */
+               if (n > 1) {
+                   /* tty_clear_nhwindow(BASE_WINDOW); */
+                   /* tty_putstr(BASE_WINDOW, 0, "Choosing Alignment"); */
+                   win = create_nhwindow(NHW_MENU);
+                   start_menu(win);
+                   any.a_void = 0;         /* zero out all bits */
+                   for (i = 0; i < ROLE_ALIGNS; i++)
+                       if (ok_align(flags.initrole, flags.initrace,
+                                                       flags.initgend, i)) {
+                           any.a_int = i+1;
+                           add_menu(win, NO_GLYPH, &any, aligns[i].adj[0],
+                                0, ATR_NONE, aligns[i].adj, MENU_UNSELECTED);
+                       }
+                   any.a_int = pick_align(flags.initrole, flags.initrace,
+                                           flags.initgend, PICK_RANDOM)+1;
+                   if (any.a_int == 0) /* must be non-zero */
+                       any.a_int = randalign(flags.initrole, flags.initrace)+1;
+                   add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE,
+                                   "Random", MENU_UNSELECTED);
+                   any.a_int = i+1;    /* must be non-zero */
+                   add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE,
+                                   "Quit", MENU_UNSELECTED);
+                   Sprintf(pbuf, "Pick the alignment of your %s", plbuf);
+                   end_menu(win, pbuf);
+                   n = select_menu(win, PICK_ONE, &selected);
+                   destroy_nhwindow(win);
+                   if (n != 1 || selected[0].item.a_int == any.a_int)
+                       goto give_up;           /* Selected quit */
+
+                   k = selected[0].item.a_int - 1;
+                   free((genericptr_t) selected),      selected = 0;
+               }
+               flags.initalign = k;
+           }
+       }
+       /* Success! */
+       /* tty_display_nhwindow(BASE_WINDOW, FALSE); */
+}
 
 /* Ask the user for a player name. */
 void mswin_askname(void)