diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index 0ba33d377..e47b86f3a 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -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 diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 0c07fe374..5dd07be14 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -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 diff --git a/doc/window.doc b/doc/window.doc index 96d665555..b24e06f86 100644 --- a/doc/window.doc +++ b/doc/window.doc @@ -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. diff --git a/include/flag.h b/include/flag.h index 0f9f7cbfd..ddc607080 100644 --- a/include/flag.h +++ b/include/flag.h @@ -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 diff --git a/include/winprocs.h b/include/winprocs.h index ac7d056c4..87a21ca05 100644 --- a/include/winprocs.h +++ b/include/winprocs.h @@ -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 diff --git a/src/options.c b/src/options.c index 2f9a46490..00662750c 100644 --- a/src/options.c +++ b/src/options.c @@ -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); diff --git a/sys/winnt/defaults.nh b/sys/winnt/defaults.nh index 65af9b9b9..954d30296 100644 --- a/sys/winnt/defaults.nh +++ b/sys/winnt/defaults.nh @@ -13,38 +13,6 @@ # for tty window-port. OPTIONS=IBMGraphics -# Set some options to control graphical window-port (these will -# be safely and silently ignored by the tty port) -# -# Map window settings -# possible map_mode options include: tiles|ascii4x6|ascii6x8|ascii8x8|ascii16x8| -# ascii7x12|ascii8x12|ascii16x12|ascii12x16| -# 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 - -# 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 @@ -68,12 +36,40 @@ 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) +# +# Map window settings +# possible map_mode options include: tiles|ascii4x6|ascii6x8|ascii8x8|ascii16x8| +# ascii7x12|ascii8x12|ascii16x12|ascii12x16| +# 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 # #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 # diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c index 11ae2b685..97b8267fe 100644 --- a/win/win32/mswproc.c +++ b/win/win32/mswproc.c @@ -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)