tty-style role selection for curses
Move the tty role/race/&c selection from wintty.c to role.c and remove its references to BASE_WINDOW. Have curses call the same routine now so that the player has the option to choose role, race, gender, and alignment in any order and to confirm or override random settings prior to starting play. Also if you went through "who are you?" then final confirmation includes an extra menu choice to rename the hero. It still has the quirk of sometimes remembering some of the previous aspects when you re-pick a new value for some aspect which already been selected. The menus pop up on top of the copyright screen and that looks a bit strange. I don't think core code has any way to erase that base window without erasing the entire screen so to fix the strangeness the window ports would need to do that before calling the selection routine. I didn't do that because the very first prompt, "Shall I pick ... for you? [ynaq]" shows up in that window rather than in a popup over it, and having it be all by itself on an otherwise blank screen seemed to be even stranger. X11 and Qt both have more sophisticated selection routines so I haven't tried to switch either of them to use this. They both use a fancy role-selection-specific menu with all the aspects present at once so this wouldn't fit without more work than I care to tackle.
This commit is contained in:
@@ -2417,6 +2417,8 @@ extern void role_init(void);
|
||||
extern const char *Hello(struct monst *);
|
||||
extern const char *Goodbye(void);
|
||||
extern const struct Race *character_race(short);
|
||||
extern void genl_player_selection(void);
|
||||
extern int genl_player_setup(void);
|
||||
|
||||
/* ### rumors.c ### */
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ extern int curses_read_char(void);
|
||||
extern void curses_toggle_color_attr(WINDOW *win, int color, int attr,
|
||||
int onoff);
|
||||
extern void curses_menu_color_attr(WINDOW *, int, int, int);
|
||||
extern void curses_bail(const char *mesg);
|
||||
ATTRNORETURN extern void curses_bail(const char *mesg) NORETURN;
|
||||
extern winid curses_get_wid(int type);
|
||||
extern char *curses_copy_of(const char *s);
|
||||
extern int curses_num_lines(const char *str, int width);
|
||||
|
||||
842
src/role.c
842
src/role.c
@@ -2095,4 +2095,846 @@ character_race(short pmindex)
|
||||
return (const struct Race *) NULL;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* potential interface routine */
|
||||
void
|
||||
genl_player_selection(void)
|
||||
{
|
||||
if (genl_player_setup())
|
||||
return;
|
||||
|
||||
/* player cancelled role/race/&c selection, so quit */
|
||||
nh_terminate(EXIT_SUCCESS);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
#if defined(TTY_GRAPHICS) || defined(CURSES_GRAPHICS)
|
||||
/* ['#else' far below] */
|
||||
|
||||
static boolean reset_role_filtering(void);
|
||||
static winid plsel_startmenu(void);
|
||||
static void setup_rolemenu(winid, boolean, int, int, int);
|
||||
static void setup_racemenu(winid, boolean, int, int, int);
|
||||
static void setup_gendmenu(winid, boolean, int, int, int);
|
||||
static void setup_algnmenu(winid, boolean, int, int, int);
|
||||
|
||||
/* try to reduce clutter in the code below... */
|
||||
#define ROLE flags.initrole
|
||||
#define RACE flags.initrace
|
||||
#define GEND flags.initgend
|
||||
#define ALGN flags.initalign
|
||||
|
||||
/* guts of tty's player_selection() */
|
||||
int
|
||||
genl_player_setup(void)
|
||||
{
|
||||
char pbuf[QBUFSZ];
|
||||
anything any;
|
||||
int i, k, n, choice, nextpick;
|
||||
boolean getconfirmation, picksomething;
|
||||
winid win = WIN_ERR;
|
||||
menu_item *selected = 0;
|
||||
int clr = 0;
|
||||
char pick4u = 'n';
|
||||
|
||||
/* Used to avoid "Is this ok?" if player has already specified all
|
||||
* four facets of role.
|
||||
* Note that rigid_role_checks might force any unspecified facets to
|
||||
* have a specific value, but that will still require confirmation;
|
||||
* player can specify the forced ones if avoiding that is demanded.
|
||||
*/
|
||||
picksomething = (ROLE == ROLE_NONE || RACE == ROLE_NONE
|
||||
|| GEND == ROLE_NONE || ALGN == ROLE_NONE);
|
||||
/* Used for '-@';
|
||||
* choose randomly without asking for all unspecified facets.
|
||||
*/
|
||||
if (flags.randomall && picksomething) {
|
||||
if (ROLE == ROLE_NONE)
|
||||
ROLE = ROLE_RANDOM;
|
||||
if (RACE == ROLE_NONE)
|
||||
RACE = ROLE_RANDOM;
|
||||
if (GEND == ROLE_NONE)
|
||||
GEND = ROLE_RANDOM;
|
||||
if (ALGN == ROLE_NONE)
|
||||
ALGN = ROLE_RANDOM;
|
||||
}
|
||||
|
||||
/* prevent unnecessary prompting if role forces race (samurai) or gender
|
||||
(valkyrie) or alignment (rogue), or race forces alignment (orc), &c */
|
||||
rigid_role_checks();
|
||||
|
||||
if (ROLE == ROLE_NONE || RACE == ROLE_NONE
|
||||
|| GEND == ROLE_NONE || ALGN == ROLE_NONE) {
|
||||
char *prompt = build_plselection_prompt(pbuf, QBUFSZ,
|
||||
ROLE, RACE, GEND, ALGN);
|
||||
/* prompt[] contains "Shall I pick ... for you? [ynaq] "
|
||||
y - game picks role,&c then asks player to confirm;
|
||||
n - player manually chooses via menu selections;
|
||||
a - like 'y', but skips confirmation and starts game;
|
||||
q - quit
|
||||
*/
|
||||
#if 1
|
||||
trimspaces(prompt); /* 'prompt' is constructed with trailing space */
|
||||
/* accept any character and do validation ourselves so that we can
|
||||
shorten prompt; it will be "Shall I pick ... for you? [ynaq] "
|
||||
with final space appended by yn_function() [for tty at least] */
|
||||
do {
|
||||
pick4u = yn_function(prompt, (char *) 0, '\0', FALSE);
|
||||
pick4u = lowc(pick4u);
|
||||
if (pick4u == '\033' || pick4u == 'q') /* handle [q] */
|
||||
return 0;
|
||||
if (pick4u == ' ' || pick4u == '\n') /* default is 'y' */
|
||||
pick4u = 'y';
|
||||
else if (pick4u == '@') /* similar to '-@' on command line */
|
||||
pick4u = 'a';
|
||||
/* TODO? handle response of '?' */
|
||||
} while (pick4u != 'y' && pick4u != 'a' && pick4u != 'n'); /* [yna] */
|
||||
|
||||
#else /* slightly simpler but more likely to end up being wrapped */
|
||||
|
||||
char *p;
|
||||
/* strip choices off prompt string; yn_function() will show them */
|
||||
if ((p = strchr(prompt, '[')) != 0)
|
||||
*p = '\0';
|
||||
trimspaces(prompt); /* remove trailing space */
|
||||
/* prompt becomes "Shall I pick ... for you? [ynaq] (y) "
|
||||
with " [ynaq] (y) " appended by yn_function() which also changes
|
||||
user's <space> and <return> to 'y', <escape> to 'q' */
|
||||
pick4u = yn_function(prompt, ynaqchars, 'y', FALSE);
|
||||
if (pick4u != 'y' && pick4u != 'a' && pick4u != 'n')
|
||||
return 0; /* bail */
|
||||
#endif
|
||||
}
|
||||
|
||||
makepicks:
|
||||
nextpick = RS_ROLE;
|
||||
do {
|
||||
if (nextpick == RS_ROLE) {
|
||||
nextpick = RS_RACE;
|
||||
/* Select a role, if necessary;
|
||||
we'll try to be compatible with pre-selected
|
||||
race/gender/alignment, but may not succeed. */
|
||||
if (ROLE < 0) {
|
||||
/* process the choice */
|
||||
if (pick4u == 'y' || pick4u == 'a' || ROLE == ROLE_RANDOM) {
|
||||
/* pick a random role */
|
||||
k = pick_role(RACE, GEND, ALGN, PICK_RANDOM);
|
||||
if (k < 0) {
|
||||
pline("Incompatible role!");
|
||||
k = randrole(FALSE);
|
||||
}
|
||||
} else {
|
||||
/* prompt for a role */
|
||||
win = plsel_startmenu();
|
||||
/* populate the menu with role choices */
|
||||
setup_rolemenu(win, TRUE, RACE, GEND, ALGN);
|
||||
/* add miscellaneous menu entries */
|
||||
role_menu_extra(ROLE_RANDOM, win, TRUE);
|
||||
any = cg.zeroany; /* separator, not a choice */
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0,
|
||||
ATR_NONE, clr, "", MENU_ITEMFLAGS_NONE);
|
||||
role_menu_extra(RS_RACE, win, FALSE);
|
||||
role_menu_extra(RS_GENDER, win, FALSE);
|
||||
role_menu_extra(RS_ALGNMNT, win, FALSE);
|
||||
role_menu_extra(RS_filter, win, FALSE);
|
||||
role_menu_extra(ROLE_NONE, win, FALSE); /* quit */
|
||||
Strcpy(pbuf, "Pick a role or profession");
|
||||
end_menu(win, pbuf);
|
||||
n = select_menu(win, PICK_ONE, &selected);
|
||||
/*
|
||||
* PICK_ONE with preselected choice behaves strangely:
|
||||
* n == -1 -- <escape>, so use quit choice;
|
||||
* n == 0 -- explicitly chose preselected entry,
|
||||
* toggling it off, so use it;
|
||||
* n == 1 -- implicitly chose preselected entry
|
||||
* with <space> or <return>;
|
||||
* n == 2 -- explicitly chose a different entry, so
|
||||
* both it and preselected one are in list.
|
||||
*/
|
||||
if (n > 0) {
|
||||
choice = selected[0].item.a_int;
|
||||
if (n > 1 && choice == ROLE_RANDOM)
|
||||
choice = selected[1].item.a_int;
|
||||
} else
|
||||
choice = (n == 0) ? ROLE_RANDOM : ROLE_NONE;
|
||||
if (selected)
|
||||
free((genericptr_t) selected), selected = 0;
|
||||
destroy_nhwindow(win), win = WIN_ERR;
|
||||
|
||||
if (choice == ROLE_NONE) {
|
||||
return 0; /* selected quit */
|
||||
} else if (choice == RS_menu_arg(RS_ALGNMNT)) {
|
||||
ALGN = k = ROLE_NONE;
|
||||
nextpick = RS_ALGNMNT;
|
||||
} else if (choice == RS_menu_arg(RS_GENDER)) {
|
||||
GEND = k = ROLE_NONE;
|
||||
nextpick = RS_GENDER;
|
||||
} else if (choice == RS_menu_arg(RS_RACE)) {
|
||||
RACE = k = ROLE_NONE;
|
||||
nextpick = RS_RACE;
|
||||
} else if (choice == RS_menu_arg(RS_filter)) {
|
||||
ROLE = k = ROLE_NONE;
|
||||
(void) reset_role_filtering();
|
||||
nextpick = RS_ROLE;
|
||||
} else if (choice == ROLE_RANDOM) {
|
||||
k = pick_role(RACE, GEND, ALGN, PICK_RANDOM);
|
||||
if (k < 0)
|
||||
k = randrole(FALSE);
|
||||
} else {
|
||||
k = choice - 1;
|
||||
}
|
||||
}
|
||||
ROLE = k;
|
||||
} /* needed role */
|
||||
} /* picking role */
|
||||
|
||||
if (nextpick == RS_RACE) {
|
||||
nextpick = (ROLE < 0) ? RS_ROLE : RS_GENDER;
|
||||
/* Select a race, if necessary;
|
||||
force compatibility with role, try for compatibility
|
||||
with pre-selected gender/alignment. */
|
||||
if (RACE < 0 || !validrace(ROLE, RACE)) {
|
||||
/* no race yet, or pre-selected race not valid */
|
||||
if (pick4u == 'y' || pick4u == 'a' || RACE == ROLE_RANDOM) {
|
||||
k = pick_race(ROLE, GEND, ALGN, PICK_RANDOM);
|
||||
if (k < 0) {
|
||||
pline("Incompatible race!");
|
||||
k = randrace(ROLE);
|
||||
}
|
||||
} 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(ROLE, i, GEND, ALGN)) {
|
||||
n++;
|
||||
k = i;
|
||||
}
|
||||
if (n == 0) {
|
||||
for (i = 0; races[i].noun; i++)
|
||||
if (validrace(ROLE, i)) {
|
||||
n++;
|
||||
k = i;
|
||||
}
|
||||
}
|
||||
/* Permit the user to pick, if there is more than one */
|
||||
if (n > 1) {
|
||||
win = plsel_startmenu();
|
||||
any = cg.zeroany; /* zero out all bits */
|
||||
/* populate the menu with role choices */
|
||||
setup_racemenu(win, TRUE, ROLE, GEND, ALGN);
|
||||
/* add miscellaneous menu entries */
|
||||
role_menu_extra(ROLE_RANDOM, win, TRUE);
|
||||
any.a_int = 0; /* separator, not a choice */
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0,
|
||||
ATR_NONE, clr, "", MENU_ITEMFLAGS_NONE);
|
||||
role_menu_extra(RS_ROLE, win, FALSE);
|
||||
role_menu_extra(RS_GENDER, win, FALSE);
|
||||
role_menu_extra(RS_ALGNMNT, win, FALSE);
|
||||
role_menu_extra(RS_filter, win, FALSE);
|
||||
role_menu_extra(ROLE_NONE, win, FALSE); /* quit */
|
||||
Strcpy(pbuf, "Pick a race or species");
|
||||
end_menu(win, pbuf);
|
||||
n = select_menu(win, PICK_ONE, &selected);
|
||||
if (n > 0) {
|
||||
choice = selected[0].item.a_int;
|
||||
if (n > 1 && choice == ROLE_RANDOM)
|
||||
choice = selected[1].item.a_int;
|
||||
} else
|
||||
choice = (n == 0) ? ROLE_RANDOM : ROLE_NONE;
|
||||
if (selected)
|
||||
free((genericptr_t) selected), selected = 0;
|
||||
destroy_nhwindow(win), win = WIN_ERR;
|
||||
|
||||
if (choice == ROLE_NONE) {
|
||||
return 0; /* selected quit */
|
||||
} else if (choice == RS_menu_arg(RS_ALGNMNT)) {
|
||||
ALGN = k = ROLE_NONE;
|
||||
nextpick = RS_ALGNMNT;
|
||||
} else if (choice == RS_menu_arg(RS_GENDER)) {
|
||||
GEND = k = ROLE_NONE;
|
||||
nextpick = RS_GENDER;
|
||||
} else if (choice == RS_menu_arg(RS_ROLE)) {
|
||||
ROLE = k = ROLE_NONE;
|
||||
nextpick = RS_ROLE;
|
||||
} else if (choice == RS_menu_arg(RS_filter)) {
|
||||
RACE = k = ROLE_NONE;
|
||||
if (reset_role_filtering())
|
||||
nextpick = RS_ROLE;
|
||||
else
|
||||
nextpick = RS_RACE;
|
||||
} else if (choice == ROLE_RANDOM) {
|
||||
k = pick_race(ROLE, GEND, ALGN, PICK_RANDOM);
|
||||
if (k < 0)
|
||||
k = randrace(ROLE);
|
||||
} else {
|
||||
k = choice - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
RACE = k;
|
||||
} /* needed race */
|
||||
} /* picking race */
|
||||
|
||||
if (nextpick == RS_GENDER) {
|
||||
nextpick = (ROLE < 0) ? RS_ROLE : (RACE < 0) ? RS_RACE
|
||||
: RS_ALGNMNT;
|
||||
/* Select a gender, if necessary;
|
||||
force compatibility with role/race, try for compatibility
|
||||
with pre-selected alignment. */
|
||||
if (GEND < 0 || !validgend(ROLE, RACE, GEND)) {
|
||||
/* no gender yet, or pre-selected gender not valid */
|
||||
if (pick4u == 'y' || pick4u == 'a' || GEND == ROLE_RANDOM) {
|
||||
k = pick_gend(ROLE, RACE, ALGN, PICK_RANDOM);
|
||||
if (k < 0) {
|
||||
pline("Incompatible gender!");
|
||||
k = randgend(ROLE, RACE);
|
||||
}
|
||||
} 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(ROLE, RACE, i, ALGN)) {
|
||||
n++;
|
||||
k = i;
|
||||
}
|
||||
if (n == 0) {
|
||||
for (i = 0; i < ROLE_GENDERS; i++)
|
||||
if (validgend(ROLE, RACE, i)) {
|
||||
n++;
|
||||
k = i;
|
||||
}
|
||||
}
|
||||
/* Permit the user to pick, if there is more than one */
|
||||
if (n > 1) {
|
||||
win = plsel_startmenu();
|
||||
any = cg.zeroany; /* zero out all bits */
|
||||
/* populate the menu with gender choices */
|
||||
setup_gendmenu(win, TRUE, ROLE, RACE, ALGN);
|
||||
/* add miscellaneous menu entries */
|
||||
role_menu_extra(ROLE_RANDOM, win, TRUE);
|
||||
any.a_int = 0; /* separator, not a choice */
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0,
|
||||
ATR_NONE, clr, "", MENU_ITEMFLAGS_NONE);
|
||||
role_menu_extra(RS_ROLE, win, FALSE);
|
||||
role_menu_extra(RS_RACE, win, FALSE);
|
||||
role_menu_extra(RS_ALGNMNT, win, FALSE);
|
||||
role_menu_extra(RS_filter, win, FALSE);
|
||||
role_menu_extra(ROLE_NONE, win, FALSE); /* quit */
|
||||
Strcpy(pbuf, "Pick a gender or sex");
|
||||
end_menu(win, pbuf);
|
||||
n = select_menu(win, PICK_ONE, &selected);
|
||||
if (n > 0) {
|
||||
choice = selected[0].item.a_int;
|
||||
if (n > 1 && choice == ROLE_RANDOM)
|
||||
choice = selected[1].item.a_int;
|
||||
} else
|
||||
choice = (n == 0) ? ROLE_RANDOM : ROLE_NONE;
|
||||
if (selected)
|
||||
free((genericptr_t) selected), selected = 0;
|
||||
destroy_nhwindow(win), win = WIN_ERR;
|
||||
|
||||
if (choice == ROLE_NONE) {
|
||||
return 0; /* selected quit */
|
||||
} else if (choice == RS_menu_arg(RS_ALGNMNT)) {
|
||||
ALGN = k = ROLE_NONE;
|
||||
nextpick = RS_ALGNMNT;
|
||||
} else if (choice == RS_menu_arg(RS_RACE)) {
|
||||
RACE = k = ROLE_NONE;
|
||||
nextpick = RS_RACE;
|
||||
} else if (choice == RS_menu_arg(RS_ROLE)) {
|
||||
ROLE = k = ROLE_NONE;
|
||||
nextpick = RS_ROLE;
|
||||
} else if (choice == RS_menu_arg(RS_filter)) {
|
||||
GEND = k = ROLE_NONE;
|
||||
if (reset_role_filtering())
|
||||
nextpick = RS_ROLE;
|
||||
else
|
||||
nextpick = RS_GENDER;
|
||||
} else if (choice == ROLE_RANDOM) {
|
||||
k = pick_gend(ROLE, RACE, ALGN, PICK_RANDOM);
|
||||
if (k < 0)
|
||||
k = randgend(ROLE, RACE);
|
||||
} else {
|
||||
k = choice - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
GEND = k;
|
||||
} /* needed gender */
|
||||
} /* picking gender */
|
||||
|
||||
if (nextpick == RS_ALGNMNT) {
|
||||
nextpick = (ROLE < 0) ? RS_ROLE : (RACE < 0) ? RS_RACE : RS_GENDER;
|
||||
/* Select an alignment, if necessary;
|
||||
force compatibility with role/race/gender. */
|
||||
if (ALGN < 0 || !validalign(ROLE, RACE, ALGN)) {
|
||||
/* no alignment yet, or pre-selected alignment not valid */
|
||||
if (pick4u == 'y' || pick4u == 'a' || ALGN == ROLE_RANDOM) {
|
||||
k = pick_align(ROLE, RACE, GEND, PICK_RANDOM);
|
||||
if (k < 0) {
|
||||
pline("Incompatible alignment!");
|
||||
k = randalign(ROLE, RACE);
|
||||
}
|
||||
} 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(ROLE, RACE, GEND, i)) {
|
||||
n++;
|
||||
k = i;
|
||||
}
|
||||
if (n == 0) {
|
||||
for (i = 0; i < ROLE_ALIGNS; i++)
|
||||
if (validalign(ROLE, RACE, i)) {
|
||||
n++;
|
||||
k = i;
|
||||
}
|
||||
}
|
||||
/* Permit the user to pick, if there is more than one */
|
||||
if (n > 1) {
|
||||
win = plsel_startmenu();
|
||||
any = cg.zeroany; /* zero out all bits */
|
||||
setup_algnmenu(win, TRUE, ROLE, RACE, GEND);
|
||||
role_menu_extra(ROLE_RANDOM, win, TRUE);
|
||||
any.a_int = 0; /* separator, not a choice */
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0,
|
||||
ATR_NONE, clr, "", MENU_ITEMFLAGS_NONE);
|
||||
role_menu_extra(RS_ROLE, win, FALSE);
|
||||
role_menu_extra(RS_RACE, win, FALSE);
|
||||
role_menu_extra(RS_GENDER, win, FALSE);
|
||||
role_menu_extra(RS_filter, win, FALSE);
|
||||
role_menu_extra(ROLE_NONE, win, FALSE); /* quit */
|
||||
Strcpy(pbuf, "Pick an alignment or creed");
|
||||
end_menu(win, pbuf);
|
||||
n = select_menu(win, PICK_ONE, &selected);
|
||||
if (n > 0) {
|
||||
choice = selected[0].item.a_int;
|
||||
if (n > 1 && choice == ROLE_RANDOM)
|
||||
choice = selected[1].item.a_int;
|
||||
} else
|
||||
choice = (n == 0) ? ROLE_RANDOM : ROLE_NONE;
|
||||
if (selected)
|
||||
free((genericptr_t) selected), selected = 0;
|
||||
destroy_nhwindow(win), win = WIN_ERR;
|
||||
|
||||
if (choice == ROLE_NONE) {
|
||||
return 0; /* selected quit */
|
||||
} else if (choice == RS_menu_arg(RS_GENDER)) {
|
||||
GEND = k = ROLE_NONE;
|
||||
nextpick = RS_GENDER;
|
||||
} else if (choice == RS_menu_arg(RS_RACE)) {
|
||||
RACE = k = ROLE_NONE;
|
||||
nextpick = RS_RACE;
|
||||
} else if (choice == RS_menu_arg(RS_ROLE)) {
|
||||
ROLE = k = ROLE_NONE;
|
||||
nextpick = RS_ROLE;
|
||||
} else if (choice == RS_menu_arg(RS_filter)) {
|
||||
ALGN = k = ROLE_NONE;
|
||||
if (reset_role_filtering())
|
||||
nextpick = RS_ROLE;
|
||||
else
|
||||
nextpick = RS_ALGNMNT;
|
||||
} else if (choice == ROLE_RANDOM) {
|
||||
k = pick_align(ROLE, RACE, GEND, PICK_RANDOM);
|
||||
if (k < 0)
|
||||
k = randalign(ROLE, RACE);
|
||||
} else {
|
||||
k = choice - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
ALGN = k;
|
||||
} /* needed alignment */
|
||||
} /* picking alignment */
|
||||
|
||||
} while (ROLE < 0 || RACE < 0 || GEND < 0 || ALGN < 0);
|
||||
|
||||
/*
|
||||
* Role, race, &c have now been determined;
|
||||
* ask for confirmation and maybe go back to choose all over again.
|
||||
*
|
||||
* Uses ynaq for familiarity, although 'a' is usually a
|
||||
* superset of 'y' but here is an alternate form of 'n'.
|
||||
* Menu layout:
|
||||
* title: Is this ok? [ynaq]
|
||||
* blank:
|
||||
* text: $name, $alignment $gender $race $role
|
||||
* blank:
|
||||
* menu: y + yes; play
|
||||
* n - no; pick again
|
||||
* maybe: a - no; rename hero
|
||||
* q - quit
|
||||
* (end)
|
||||
*/
|
||||
getconfirmation = (picksomething && pick4u != 'a' && !flags.randomall);
|
||||
while (getconfirmation) {
|
||||
win = plsel_startmenu();
|
||||
any = cg.zeroany; /* zero out all bits */
|
||||
#if 0
|
||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
||||
any.a_int = 0;
|
||||
char plbuf[QBUFSZ];
|
||||
if (!roles[ROLE].name.f
|
||||
&& ((roles[ROLE].allow & ROLE_GENDMASK)
|
||||
== (ROLE_MALE | ROLE_FEMALE)))
|
||||
Sprintf(plbuf, " %s", genders[GEND].adj);
|
||||
else
|
||||
*plbuf = '\0'; /* omit redundant gender */
|
||||
Snprintf(pbuf, sizeof pbuf, "%s, %s%s %s %s", gp.plname,
|
||||
aligns[ALGN].adj, plbuf, races[RACE].adj,
|
||||
(GEND == 1 && roles[ROLE].name.f) ? roles[ROLE].name.f
|
||||
: roles[ROLE].name.m);
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE, clr, pbuf,
|
||||
MENU_ITEMFLAGS_NONE);
|
||||
/* blank separator */
|
||||
any.a_int = 0;
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0,
|
||||
ATR_NONE, clr, "", MENU_ITEMFLAGS_NONE);
|
||||
#endif
|
||||
/* [ynaq] menu choices */
|
||||
any.a_int = 1;
|
||||
add_menu(win, &nul_glyphinfo, &any, 'y', 0,
|
||||
ATR_NONE, clr, "Yes; start game", MENU_ITEMFLAGS_SELECTED);
|
||||
any.a_int = 2;
|
||||
add_menu(win, &nul_glyphinfo, &any, 'n', 0,
|
||||
ATR_NONE, clr, "No; choose role again", MENU_ITEMFLAGS_NONE);
|
||||
if (iflags.renameallowed) {
|
||||
any.a_int = 3;
|
||||
add_menu(win, &nul_glyphinfo, &any, 'a', 0, ATR_NONE,
|
||||
clr, "Not yet; choose another name", MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
any.a_int = -1;
|
||||
add_menu(win, &nul_glyphinfo, &any, 'q', 0,
|
||||
ATR_NONE, clr, "Quit", MENU_ITEMFLAGS_NONE);
|
||||
Sprintf(pbuf, "Is this ok? [yn%sq]", iflags.renameallowed ? "a" : "");
|
||||
end_menu(win, pbuf);
|
||||
n = select_menu(win, PICK_ONE, &selected);
|
||||
/* [pick-one menus with a preselected entry behave oddly...] */
|
||||
choice = (n > 0) ? selected[n - 1].item.a_int : (n == 0) ? 1 : -1;
|
||||
if (selected)
|
||||
free((genericptr_t) selected), selected = 0;
|
||||
destroy_nhwindow(win);
|
||||
|
||||
switch (choice) {
|
||||
default: /* 'q' or ESC */
|
||||
return 0; /* quit */
|
||||
break;
|
||||
case 3: { /* 'a' */
|
||||
/*
|
||||
* TODO: what, if anything, should be done if the name is
|
||||
* changed to or from "wizard" after port-specific startup
|
||||
* code has set flags.debug based on the original name?
|
||||
*/
|
||||
int saveROLE, saveRACE, saveGEND, saveALGN;
|
||||
|
||||
iflags.renameinprogress = TRUE;
|
||||
/* plnamesuffix() can change any or all of ROLE, RACE,
|
||||
GEND, ALGN; we'll override that and honor only the name */
|
||||
saveROLE = ROLE, saveRACE = RACE, saveGEND = GEND, saveALGN = ALGN;
|
||||
*gp.plname = '\0';
|
||||
plnamesuffix(); /* calls askname() when gp.plname[] is empty */
|
||||
ROLE = saveROLE, RACE = saveRACE, GEND = saveGEND, ALGN = saveALGN;
|
||||
break; /* getconfirmation is still True */
|
||||
}
|
||||
case 2: /* 'n' */
|
||||
/* start fresh, but bypass "shall I pick everything for you?"
|
||||
step; any partial role selection via config file, command
|
||||
line, or name suffix is discarded this time */
|
||||
pick4u = 'n';
|
||||
ROLE = RACE = GEND = ALGN = ROLE_NONE;
|
||||
goto makepicks;
|
||||
break;
|
||||
case 1: /* 'y' or Space or Return/Enter */
|
||||
/* success; drop out through end of function */
|
||||
getconfirmation = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Success! */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static boolean
|
||||
reset_role_filtering(void)
|
||||
{
|
||||
winid win;
|
||||
anything any;
|
||||
int i, n, clr = 0;
|
||||
char filterprompt[QBUFSZ];
|
||||
menu_item *selected = 0;
|
||||
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
||||
any = cg.zeroany;
|
||||
|
||||
/* no extra blank line preceding this entry; end_menu supplies one */
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE, clr,
|
||||
"Unacceptable roles", MENU_ITEMFLAGS_NONE);
|
||||
setup_rolemenu(win, FALSE, ROLE_NONE, ROLE_NONE, ROLE_NONE);
|
||||
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
|
||||
clr, "", MENU_ITEMFLAGS_NONE);
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
|
||||
clr, "Unacceptable races", MENU_ITEMFLAGS_NONE);
|
||||
setup_racemenu(win, FALSE, ROLE_NONE, ROLE_NONE, ROLE_NONE);
|
||||
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
|
||||
clr, "", MENU_ITEMFLAGS_NONE);
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
|
||||
clr, "Unacceptable genders", MENU_ITEMFLAGS_NONE);
|
||||
setup_gendmenu(win, FALSE, ROLE_NONE, ROLE_NONE, ROLE_NONE);
|
||||
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
|
||||
clr, "", MENU_ITEMFLAGS_NONE);
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
|
||||
clr, "Unacceptable alignments", MENU_ITEMFLAGS_NONE);
|
||||
setup_algnmenu(win, FALSE, ROLE_NONE, ROLE_NONE, ROLE_NONE);
|
||||
|
||||
Sprintf(filterprompt, "Pick all that apply%s",
|
||||
gotrolefilter() ? " and/or unpick any that no longer apply" : "");
|
||||
end_menu(win, filterprompt);
|
||||
n = select_menu(win, PICK_ANY, &selected);
|
||||
|
||||
if (n >= 0) { /* n==0: clear current filters and don't set new ones */
|
||||
clearrolefilter();
|
||||
for (i = 0; i < n; i++)
|
||||
setrolefilter(selected[i].item.a_string);
|
||||
|
||||
ROLE = RACE = GEND = ALGN = ROLE_NONE;
|
||||
}
|
||||
if (selected)
|
||||
free((genericptr_t) selected), selected = 0;
|
||||
destroy_nhwindow(win);
|
||||
return (n > 0) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/* start a menu; show role aspects specified so far as a header line */
|
||||
static winid
|
||||
plsel_startmenu(void)
|
||||
{
|
||||
char qbuf[QBUFSZ];
|
||||
winid win;
|
||||
anything any;
|
||||
const char *rolename;
|
||||
int clr = 0;
|
||||
|
||||
/* whatever aspect was just chosen might force others (Orc => chaotic,
|
||||
Samurai => Human+lawful, Valkyrie => female) */
|
||||
rigid_role_checks();
|
||||
|
||||
rolename = (ROLE < 0) ? "<role>"
|
||||
: (GEND == 1 && roles[ROLE].name.f) ? roles[ROLE].name.f
|
||||
: roles[ROLE].name.m;
|
||||
if (!*gp.plname || ROLE < 0 || RACE < 0 || GEND < 0 || ALGN < 0) {
|
||||
/* "<role> <race.noun> <gender> <alignment>" */
|
||||
Sprintf(qbuf, "%.20s %.20s %.20s %.20s",
|
||||
rolename,
|
||||
(RACE < 0) ? "<race>" : races[RACE].noun,
|
||||
(GEND < 0) ? "<gender>" : genders[GEND].adj,
|
||||
(ALGN < 0) ? "<alignment>" : aligns[ALGN].adj);
|
||||
} else {
|
||||
/* "<name> the <alignment> <gender> <race.adjective> <role>" */
|
||||
Sprintf(qbuf, "%.20s the %.20s %.20s %.20s %.20s",
|
||||
gp.plname,
|
||||
aligns[ALGN].adj,
|
||||
genders[GEND].adj,
|
||||
races[RACE].adj,
|
||||
rolename);
|
||||
}
|
||||
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
if (win == WIN_ERR)
|
||||
panic("could not create role selection window");
|
||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
||||
|
||||
any = cg.zeroany;
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE, clr,
|
||||
qbuf, MENU_ITEMFLAGS_NONE);
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE, clr,
|
||||
"", MENU_ITEMFLAGS_NONE);
|
||||
return win;
|
||||
}
|
||||
|
||||
#undef ROLE
|
||||
#undef RACE
|
||||
#undef GEND
|
||||
#undef ALGN
|
||||
|
||||
/* add entries a-Archeologist, b-Barbarian, &c to menu being built in 'win' */
|
||||
static void
|
||||
setup_rolemenu(
|
||||
winid win,
|
||||
boolean filtering, /* True => exclude filtered roles;
|
||||
* False => filter reset */
|
||||
int race, int gend, int algn) /* all ROLE_NONE for !filtering case */
|
||||
{
|
||||
anything any;
|
||||
int i;
|
||||
boolean role_ok;
|
||||
char thisch, lastch = '\0', rolenamebuf[50];
|
||||
int clr = 0;
|
||||
|
||||
any = cg.zeroany; /* zero out all bits */
|
||||
for (i = 0; roles[i].name.m; i++) {
|
||||
/* role can be constrained by any of race, gender, or alignment */
|
||||
role_ok = (ok_role(i, race, gend, algn)
|
||||
&& ok_race(i, race, gend, algn)
|
||||
&& ok_gend(i, race, gend, algn)
|
||||
&& ok_align(i, race, gend, algn));
|
||||
if (filtering && !role_ok)
|
||||
continue;
|
||||
if (filtering)
|
||||
any.a_int = i + 1;
|
||||
else
|
||||
any.a_string = roles[i].name.m;
|
||||
thisch = lowc(*roles[i].name.m);
|
||||
if (thisch == lastch)
|
||||
thisch = highc(thisch);
|
||||
Strcpy(rolenamebuf, roles[i].name.m);
|
||||
if (roles[i].name.f) {
|
||||
/* role has distinct name for female (C,P) */
|
||||
if (gend == 1) {
|
||||
/* female already chosen; replace male name */
|
||||
Strcpy(rolenamebuf, roles[i].name.f);
|
||||
} else if (gend < 0) {
|
||||
/* not chosen yet; append slash+female name */
|
||||
Strcat(rolenamebuf, "/");
|
||||
Strcat(rolenamebuf, roles[i].name.f);
|
||||
}
|
||||
}
|
||||
/* !filtering implies reset_role_filtering() where we want to
|
||||
mark this role as preseleted if current filter excludes it */
|
||||
add_menu(win, &nul_glyphinfo, &any, thisch, 0,
|
||||
ATR_NONE, clr, an(rolenamebuf),
|
||||
(!filtering && !role_ok)
|
||||
? MENU_ITEMFLAGS_SELECTED : MENU_ITEMFLAGS_NONE);
|
||||
lastch = thisch;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_racemenu(
|
||||
winid win,
|
||||
boolean filtering,
|
||||
int role, int gend, int algn)
|
||||
{
|
||||
anything any;
|
||||
boolean race_ok;
|
||||
int i;
|
||||
char this_ch;
|
||||
int clr = 0;
|
||||
|
||||
any = cg.zeroany;
|
||||
for (i = 0; races[i].noun; i++) {
|
||||
/* no ok_gend(); race isn't constrained by gender */
|
||||
race_ok = (ok_race(role, i, gend, algn)
|
||||
&& ok_role(role, i, gend, algn)
|
||||
&& ok_align(role, i, gend, algn));
|
||||
if (filtering && !race_ok)
|
||||
continue;
|
||||
if (filtering)
|
||||
any.a_int = i + 1;
|
||||
else
|
||||
any.a_string = races[i].noun;
|
||||
this_ch = *races[i].noun;
|
||||
/* filtering: picking race, so choose by first letter, with
|
||||
capital letter as unseen accelerator;
|
||||
!filtering: resetting filter rather than picking, choose by
|
||||
capital letter since lowercase role letters will be present */
|
||||
add_menu(win, &nul_glyphinfo, &any,
|
||||
filtering ? this_ch : highc(this_ch),
|
||||
filtering ? highc(this_ch) : 0,
|
||||
ATR_NONE, clr, races[i].noun,
|
||||
(!filtering && !race_ok)
|
||||
? MENU_ITEMFLAGS_SELECTED : MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_gendmenu(
|
||||
winid win,
|
||||
boolean filtering,
|
||||
int role, int race, int algn)
|
||||
{
|
||||
anything any;
|
||||
boolean gend_ok;
|
||||
int i;
|
||||
char this_ch;
|
||||
int clr = 0;
|
||||
|
||||
any = cg.zeroany;
|
||||
for (i = 0; i < ROLE_GENDERS; i++) {
|
||||
/* no ok_align(); gender isn't constrained by alignment */
|
||||
gend_ok = (ok_gend(role, race, i, algn)
|
||||
&& ok_role(role, race, i, algn)
|
||||
&& ok_race(role, race, i, algn));
|
||||
if (filtering && !gend_ok)
|
||||
continue;
|
||||
if (filtering)
|
||||
any.a_int = i + 1;
|
||||
else
|
||||
any.a_string = genders[i].adj;
|
||||
this_ch = *genders[i].adj;
|
||||
/* (see setup_racemenu for explanation of selector letters
|
||||
and setup_rolemenu for preselection) */
|
||||
add_menu(win, &nul_glyphinfo, &any,
|
||||
filtering ? this_ch : highc(this_ch),
|
||||
filtering ? highc(this_ch) : 0,
|
||||
ATR_NONE, clr, genders[i].adj,
|
||||
(!filtering && !gend_ok)
|
||||
? MENU_ITEMFLAGS_SELECTED : MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_algnmenu(
|
||||
winid win,
|
||||
boolean filtering,
|
||||
int role, int race, int gend)
|
||||
{
|
||||
anything any;
|
||||
boolean algn_ok;
|
||||
int i;
|
||||
char this_ch;
|
||||
int clr = 0;
|
||||
|
||||
any = cg.zeroany;
|
||||
for (i = 0; i < ROLE_ALIGNS; i++) {
|
||||
/* no ok_gend(); alignment isn't constrained by gender */
|
||||
algn_ok = (ok_align(role, race, gend, i)
|
||||
&& ok_role(role, race, gend, i)
|
||||
&& ok_race(role, race, gend, i));
|
||||
if (filtering && !algn_ok)
|
||||
continue;
|
||||
if (filtering)
|
||||
any.a_int = i + 1;
|
||||
else
|
||||
any.a_string = aligns[i].adj;
|
||||
this_ch = *aligns[i].adj;
|
||||
/* (see setup_racemenu for explanation of selector letters
|
||||
and setup_rolemenu for preselection) */
|
||||
add_menu(win, &nul_glyphinfo, &any,
|
||||
filtering ? this_ch : highc(this_ch),
|
||||
filtering ? highc(this_ch) : 0,
|
||||
ATR_NONE, clr, aligns[i].adj,
|
||||
(!filtering && !algn_ok)
|
||||
? MENU_ITEMFLAGS_SELECTED : MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* !TTY_GRAPHICS */
|
||||
|
||||
int
|
||||
genl_player_setup(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* ?TTY_GRAPHICS */
|
||||
|
||||
/* role.c */
|
||||
|
||||
@@ -365,6 +365,8 @@ curses_init_nhcolors(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0 /* curses_choose_character + curses_character_dialog no longer used */
|
||||
|
||||
/* Allow player to pick character's role, race, gender, and alignment.
|
||||
Borrowed from the Gnome window port. */
|
||||
void
|
||||
@@ -675,6 +677,7 @@ curses_choose_character(void)
|
||||
flags.initalign = sel;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Prompt user for character race, role, alignment, or gender */
|
||||
@@ -731,6 +734,8 @@ curses_character_dialog(const char **choices, const char *prompt)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* 0 */
|
||||
|
||||
/* Initialize and display options appropriately */
|
||||
void
|
||||
curses_init_options(void)
|
||||
|
||||
@@ -270,14 +270,21 @@ curses_init_nhwindows(int *argcp UNUSED,
|
||||
curses_display_splash_window();
|
||||
}
|
||||
|
||||
/* Do a window-port specific player type selection. If player_selection()
|
||||
offers a Quit option, it is its responsibility to clean up and terminate
|
||||
the process. You need to fill in pl_character[0].
|
||||
*/
|
||||
/* Use the general role/race/&c selection originally implemented for tty. */
|
||||
void
|
||||
curses_player_selection(void)
|
||||
{
|
||||
#if 1
|
||||
if (genl_player_setup())
|
||||
return; /* success */
|
||||
|
||||
/* quit/cancel */
|
||||
curses_bail((const char *) NULL);
|
||||
/*NOTREACHED*/
|
||||
#else
|
||||
/* still present cursinit.c but no longer used */
|
||||
curses_choose_character();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
771
win/tty/wintty.c
771
win/tty/wintty.c
@@ -229,12 +229,9 @@ static void process_menu_window(winid, struct WinDesc *);
|
||||
static void process_text_window(winid, struct WinDesc *);
|
||||
static tty_menu_item *reverse(tty_menu_item *);
|
||||
static const char *compress_str(const char *);
|
||||
#ifndef STATUS_HILITES
|
||||
static void tty_putsym(winid, int, int, char);
|
||||
static void setup_rolemenu(winid, boolean, int, int, int);
|
||||
static void setup_racemenu(winid, boolean, int, int, int);
|
||||
static void setup_gendmenu(winid, boolean, int, int, int);
|
||||
static void setup_algnmenu(winid, boolean, int, int, int);
|
||||
static boolean reset_role_filtering(void);
|
||||
#endif
|
||||
#ifdef STATUS_HILITES
|
||||
#define MAX_STATUS_ROWS 3
|
||||
static boolean check_fields(boolean forcefields, int sz[MAX_STATUS_ROWS]);
|
||||
@@ -575,772 +572,14 @@ tty_preference_update(const char *pref)
|
||||
return;
|
||||
}
|
||||
|
||||
/* try to reduce clutter in the code below... */
|
||||
#define ROLE flags.initrole
|
||||
#define RACE flags.initrace
|
||||
#define GEND flags.initgend
|
||||
#define ALGN flags.initalign
|
||||
|
||||
void
|
||||
tty_player_selection(void)
|
||||
{
|
||||
int i, k, n, choice, nextpick;
|
||||
boolean getconfirmation, picksomething;
|
||||
char pick4u = 'n';
|
||||
char pbuf[QBUFSZ], plbuf[QBUFSZ];
|
||||
winid win;
|
||||
anything any;
|
||||
menu_item *selected = 0;
|
||||
int clr = 0;
|
||||
if (genl_player_setup())
|
||||
return;
|
||||
|
||||
/* Used to avoid "Is this ok?" if player has already specified all
|
||||
* four facets of role.
|
||||
* Note that rigid_role_checks might force any unspecified facets to
|
||||
* have a specific value, but that will still require confirmation;
|
||||
* player can specify the forced ones if avoiding that is demanded.
|
||||
*/
|
||||
picksomething = (ROLE == ROLE_NONE || RACE == ROLE_NONE
|
||||
|| GEND == ROLE_NONE || ALGN == ROLE_NONE);
|
||||
/* Used for '-@';
|
||||
* choose randomly without asking for all unspecified facets.
|
||||
*/
|
||||
if (flags.randomall && picksomething) {
|
||||
if (ROLE == ROLE_NONE)
|
||||
ROLE = ROLE_RANDOM;
|
||||
if (RACE == ROLE_NONE)
|
||||
RACE = ROLE_RANDOM;
|
||||
if (GEND == ROLE_NONE)
|
||||
GEND = ROLE_RANDOM;
|
||||
if (ALGN == ROLE_NONE)
|
||||
ALGN = ROLE_RANDOM;
|
||||
}
|
||||
|
||||
/* prevent unnecessary prompting if role forces race (samurai) or gender
|
||||
(valkyrie) or alignment (rogue), or race forces alignment (orc), &c */
|
||||
rigid_role_checks();
|
||||
|
||||
/* Should we randomly pick for the player? */
|
||||
if (ROLE == ROLE_NONE || RACE == ROLE_NONE || GEND == ROLE_NONE
|
||||
|| ALGN == ROLE_NONE) {
|
||||
int echoline;
|
||||
char *prompt = build_plselection_prompt(pbuf, QBUFSZ,
|
||||
ROLE, RACE, GEND, ALGN);
|
||||
|
||||
/* this prompt string ends in "[ynaq]?":
|
||||
y - game picks role,&c then asks player to confirm;
|
||||
n - player manually chooses via menu selections;
|
||||
a - like 'y', but skips confirmation and starts game;
|
||||
q - quit
|
||||
*/
|
||||
tty_putstr(BASE_WINDOW, 0, "");
|
||||
echoline = wins[BASE_WINDOW]->cury;
|
||||
tty_putstr(BASE_WINDOW, 0, prompt);
|
||||
do {
|
||||
pick4u = lowc(readchar());
|
||||
if (strchr(quitchars, pick4u))
|
||||
pick4u = 'y';
|
||||
} while (!strchr(ynaqchars, 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 != 'a' && pick4u != 'n')
|
||||
goto give_up;
|
||||
}
|
||||
|
||||
makepicks:
|
||||
nextpick = RS_ROLE;
|
||||
do {
|
||||
if (nextpick == RS_ROLE) {
|
||||
nextpick = RS_RACE;
|
||||
/* Select a role, if necessary;
|
||||
we'll try to be compatible with pre-selected
|
||||
race/gender/alignment, but may not succeed. */
|
||||
if (ROLE < 0) {
|
||||
/* Process the choice */
|
||||
if (pick4u == 'y' || pick4u == 'a' || ROLE == ROLE_RANDOM) {
|
||||
/* Pick a random role */
|
||||
k = pick_role(RACE, GEND, ALGN, PICK_RANDOM);
|
||||
if (k < 0) {
|
||||
tty_putstr(BASE_WINDOW, 0, "Incompatible role!");
|
||||
k = randrole(FALSE);
|
||||
}
|
||||
} else {
|
||||
/* Prompt for a role */
|
||||
tty_clear_nhwindow(BASE_WINDOW);
|
||||
role_selection_prolog(RS_ROLE, BASE_WINDOW);
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
||||
/* populate the menu with role choices */
|
||||
setup_rolemenu(win, TRUE, RACE, GEND, ALGN);
|
||||
/* add miscellaneous menu entries */
|
||||
role_menu_extra(ROLE_RANDOM, win, TRUE);
|
||||
any = cg.zeroany; /* separator, not a choice */
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0,
|
||||
ATR_NONE, clr, "", MENU_ITEMFLAGS_NONE);
|
||||
role_menu_extra(RS_RACE, win, FALSE);
|
||||
role_menu_extra(RS_GENDER, win, FALSE);
|
||||
role_menu_extra(RS_ALGNMNT, win, FALSE);
|
||||
role_menu_extra(RS_filter, win, FALSE);
|
||||
role_menu_extra(ROLE_NONE, win, FALSE); /* quit */
|
||||
Strcpy(pbuf, "Pick a role or profession");
|
||||
end_menu(win, pbuf);
|
||||
n = select_menu(win, PICK_ONE, &selected);
|
||||
/*
|
||||
* PICK_ONE with preselected choice behaves strangely:
|
||||
* n == -1 -- <escape>, so use quit choice;
|
||||
* n == 0 -- explicitly chose preselected entry,
|
||||
* toggling it off, so use it;
|
||||
* n == 1 -- implicitly chose preselected entry
|
||||
* with <space> or <return>;
|
||||
* n == 2 -- explicitly chose a different entry, so
|
||||
* both it and preselected one are in list.
|
||||
*/
|
||||
if (n > 0) {
|
||||
choice = selected[0].item.a_int;
|
||||
if (n > 1 && choice == ROLE_RANDOM)
|
||||
choice = selected[1].item.a_int;
|
||||
} else
|
||||
choice = (n == 0) ? ROLE_RANDOM : ROLE_NONE;
|
||||
if (selected)
|
||||
free((genericptr_t) selected), selected = 0;
|
||||
destroy_nhwindow(win);
|
||||
|
||||
if (choice == ROLE_NONE) {
|
||||
goto give_up; /* Selected quit */
|
||||
} else if (choice == RS_menu_arg(RS_ALGNMNT)) {
|
||||
ALGN = k = ROLE_NONE;
|
||||
nextpick = RS_ALGNMNT;
|
||||
} else if (choice == RS_menu_arg(RS_GENDER)) {
|
||||
GEND = k = ROLE_NONE;
|
||||
nextpick = RS_GENDER;
|
||||
} else if (choice == RS_menu_arg(RS_RACE)) {
|
||||
RACE = k = ROLE_NONE;
|
||||
nextpick = RS_RACE;
|
||||
} else if (choice == RS_menu_arg(RS_filter)) {
|
||||
ROLE = k = ROLE_NONE;
|
||||
(void) reset_role_filtering();
|
||||
nextpick = RS_ROLE;
|
||||
} else if (choice == ROLE_RANDOM) {
|
||||
k = pick_role(RACE, GEND, ALGN, PICK_RANDOM);
|
||||
if (k < 0)
|
||||
k = randrole(FALSE);
|
||||
} else {
|
||||
k = choice - 1;
|
||||
}
|
||||
}
|
||||
ROLE = k;
|
||||
} /* needed role */
|
||||
} /* picking role */
|
||||
|
||||
if (nextpick == RS_RACE) {
|
||||
nextpick = (ROLE < 0) ? RS_ROLE : RS_GENDER;
|
||||
/* Select a race, if necessary;
|
||||
force compatibility with role, try for compatibility
|
||||
with pre-selected gender/alignment. */
|
||||
if (RACE < 0 || !validrace(ROLE, RACE)) {
|
||||
/* no race yet, or pre-selected race not valid */
|
||||
if (pick4u == 'y' || pick4u == 'a' || RACE == ROLE_RANDOM) {
|
||||
k = pick_race(ROLE, GEND, ALGN, PICK_RANDOM);
|
||||
if (k < 0) {
|
||||
tty_putstr(BASE_WINDOW, 0, "Incompatible race!");
|
||||
k = randrace(ROLE);
|
||||
}
|
||||
} 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(ROLE, i, GEND, ALGN)) {
|
||||
n++;
|
||||
k = i;
|
||||
}
|
||||
if (n == 0) {
|
||||
for (i = 0; races[i].noun; i++)
|
||||
if (validrace(ROLE, i)) {
|
||||
n++;
|
||||
k = i;
|
||||
}
|
||||
}
|
||||
/* Permit the user to pick, if there is more than one */
|
||||
if (n > 1) {
|
||||
tty_clear_nhwindow(BASE_WINDOW);
|
||||
role_selection_prolog(RS_RACE, BASE_WINDOW);
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
||||
any = cg.zeroany; /* zero out all bits */
|
||||
/* populate the menu with role choices */
|
||||
setup_racemenu(win, TRUE, ROLE, GEND, ALGN);
|
||||
/* add miscellaneous menu entries */
|
||||
role_menu_extra(ROLE_RANDOM, win, TRUE);
|
||||
any.a_int = 0; /* separator, not a choice */
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0,
|
||||
ATR_NONE, clr, "", MENU_ITEMFLAGS_NONE);
|
||||
role_menu_extra(RS_ROLE, win, FALSE);
|
||||
role_menu_extra(RS_GENDER, win, FALSE);
|
||||
role_menu_extra(RS_ALGNMNT, win, FALSE);
|
||||
role_menu_extra(RS_filter, win, FALSE);
|
||||
role_menu_extra(ROLE_NONE, win, FALSE); /* quit */
|
||||
Strcpy(pbuf, "Pick a race or species");
|
||||
end_menu(win, pbuf);
|
||||
n = select_menu(win, PICK_ONE, &selected);
|
||||
if (n > 0) {
|
||||
choice = selected[0].item.a_int;
|
||||
if (n > 1 && choice == ROLE_RANDOM)
|
||||
choice = selected[1].item.a_int;
|
||||
} else
|
||||
choice = (n == 0) ? ROLE_RANDOM : ROLE_NONE;
|
||||
if (selected)
|
||||
free((genericptr_t) selected), selected = 0;
|
||||
destroy_nhwindow(win);
|
||||
|
||||
if (choice == ROLE_NONE) {
|
||||
goto give_up; /* Selected quit */
|
||||
} else if (choice == RS_menu_arg(RS_ALGNMNT)) {
|
||||
ALGN = k = ROLE_NONE;
|
||||
nextpick = RS_ALGNMNT;
|
||||
} else if (choice == RS_menu_arg(RS_GENDER)) {
|
||||
GEND = k = ROLE_NONE;
|
||||
nextpick = RS_GENDER;
|
||||
} else if (choice == RS_menu_arg(RS_ROLE)) {
|
||||
ROLE = k = ROLE_NONE;
|
||||
nextpick = RS_ROLE;
|
||||
} else if (choice == RS_menu_arg(RS_filter)) {
|
||||
RACE = k = ROLE_NONE;
|
||||
if (reset_role_filtering())
|
||||
nextpick = RS_ROLE;
|
||||
else
|
||||
nextpick = RS_RACE;
|
||||
} else if (choice == ROLE_RANDOM) {
|
||||
k = pick_race(ROLE, GEND, ALGN, PICK_RANDOM);
|
||||
if (k < 0)
|
||||
k = randrace(ROLE);
|
||||
} else {
|
||||
k = choice - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
RACE = k;
|
||||
} /* needed race */
|
||||
} /* picking race */
|
||||
|
||||
if (nextpick == RS_GENDER) {
|
||||
nextpick = (ROLE < 0) ? RS_ROLE : (RACE < 0) ? RS_RACE
|
||||
: RS_ALGNMNT;
|
||||
/* Select a gender, if necessary;
|
||||
force compatibility with role/race, try for compatibility
|
||||
with pre-selected alignment. */
|
||||
if (GEND < 0 || !validgend(ROLE, RACE, GEND)) {
|
||||
/* no gender yet, or pre-selected gender not valid */
|
||||
if (pick4u == 'y' || pick4u == 'a' || GEND == ROLE_RANDOM) {
|
||||
k = pick_gend(ROLE, RACE, ALGN, PICK_RANDOM);
|
||||
if (k < 0) {
|
||||
tty_putstr(BASE_WINDOW, 0, "Incompatible gender!");
|
||||
k = randgend(ROLE, RACE);
|
||||
}
|
||||
} 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(ROLE, RACE, i, ALGN)) {
|
||||
n++;
|
||||
k = i;
|
||||
}
|
||||
if (n == 0) {
|
||||
for (i = 0; i < ROLE_GENDERS; i++)
|
||||
if (validgend(ROLE, RACE, i)) {
|
||||
n++;
|
||||
k = i;
|
||||
}
|
||||
}
|
||||
/* Permit the user to pick, if there is more than one */
|
||||
if (n > 1) {
|
||||
tty_clear_nhwindow(BASE_WINDOW);
|
||||
role_selection_prolog(RS_GENDER, BASE_WINDOW);
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
||||
any = cg.zeroany; /* zero out all bits */
|
||||
/* populate the menu with gender choices */
|
||||
setup_gendmenu(win, TRUE, ROLE, RACE, ALGN);
|
||||
/* add miscellaneous menu entries */
|
||||
role_menu_extra(ROLE_RANDOM, win, TRUE);
|
||||
any.a_int = 0; /* separator, not a choice */
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0,
|
||||
ATR_NONE, clr, "", MENU_ITEMFLAGS_NONE);
|
||||
role_menu_extra(RS_ROLE, win, FALSE);
|
||||
role_menu_extra(RS_RACE, win, FALSE);
|
||||
role_menu_extra(RS_ALGNMNT, win, FALSE);
|
||||
role_menu_extra(RS_filter, win, FALSE);
|
||||
role_menu_extra(ROLE_NONE, win, FALSE); /* quit */
|
||||
Strcpy(pbuf, "Pick a gender or sex");
|
||||
end_menu(win, pbuf);
|
||||
n = select_menu(win, PICK_ONE, &selected);
|
||||
if (n > 0) {
|
||||
choice = selected[0].item.a_int;
|
||||
if (n > 1 && choice == ROLE_RANDOM)
|
||||
choice = selected[1].item.a_int;
|
||||
} else
|
||||
choice = (n == 0) ? ROLE_RANDOM : ROLE_NONE;
|
||||
if (selected)
|
||||
free((genericptr_t) selected), selected = 0;
|
||||
destroy_nhwindow(win);
|
||||
|
||||
if (choice == ROLE_NONE) {
|
||||
goto give_up; /* Selected quit */
|
||||
} else if (choice == RS_menu_arg(RS_ALGNMNT)) {
|
||||
ALGN = k = ROLE_NONE;
|
||||
nextpick = RS_ALGNMNT;
|
||||
} else if (choice == RS_menu_arg(RS_RACE)) {
|
||||
RACE = k = ROLE_NONE;
|
||||
nextpick = RS_RACE;
|
||||
} else if (choice == RS_menu_arg(RS_ROLE)) {
|
||||
ROLE = k = ROLE_NONE;
|
||||
nextpick = RS_ROLE;
|
||||
} else if (choice == RS_menu_arg(RS_filter)) {
|
||||
GEND = k = ROLE_NONE;
|
||||
if (reset_role_filtering())
|
||||
nextpick = RS_ROLE;
|
||||
else
|
||||
nextpick = RS_GENDER;
|
||||
} else if (choice == ROLE_RANDOM) {
|
||||
k = pick_gend(ROLE, RACE, ALGN, PICK_RANDOM);
|
||||
if (k < 0)
|
||||
k = randgend(ROLE, RACE);
|
||||
} else {
|
||||
k = choice - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
GEND = k;
|
||||
} /* needed gender */
|
||||
} /* picking gender */
|
||||
|
||||
if (nextpick == RS_ALGNMNT) {
|
||||
nextpick = (ROLE < 0) ? RS_ROLE : (RACE < 0) ? RS_RACE : RS_GENDER;
|
||||
/* Select an alignment, if necessary;
|
||||
force compatibility with role/race/gender. */
|
||||
if (ALGN < 0 || !validalign(ROLE, RACE, ALGN)) {
|
||||
/* no alignment yet, or pre-selected alignment not valid */
|
||||
if (pick4u == 'y' || pick4u == 'a' || ALGN == ROLE_RANDOM) {
|
||||
k = pick_align(ROLE, RACE, GEND, PICK_RANDOM);
|
||||
if (k < 0) {
|
||||
tty_putstr(BASE_WINDOW, 0, "Incompatible alignment!");
|
||||
k = randalign(ROLE, RACE);
|
||||
}
|
||||
} 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(ROLE, RACE, GEND, i)) {
|
||||
n++;
|
||||
k = i;
|
||||
}
|
||||
if (n == 0) {
|
||||
for (i = 0; i < ROLE_ALIGNS; i++)
|
||||
if (validalign(ROLE, RACE, i)) {
|
||||
n++;
|
||||
k = i;
|
||||
}
|
||||
}
|
||||
/* Permit the user to pick, if there is more than one */
|
||||
if (n > 1) {
|
||||
tty_clear_nhwindow(BASE_WINDOW);
|
||||
role_selection_prolog(RS_ALGNMNT, BASE_WINDOW);
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
||||
any = cg.zeroany; /* zero out all bits */
|
||||
setup_algnmenu(win, TRUE, ROLE, RACE, GEND);
|
||||
role_menu_extra(ROLE_RANDOM, win, TRUE);
|
||||
any.a_int = 0; /* separator, not a choice */
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0,
|
||||
ATR_NONE, clr, "", MENU_ITEMFLAGS_NONE);
|
||||
role_menu_extra(RS_ROLE, win, FALSE);
|
||||
role_menu_extra(RS_RACE, win, FALSE);
|
||||
role_menu_extra(RS_GENDER, win, FALSE);
|
||||
role_menu_extra(RS_filter, win, FALSE);
|
||||
role_menu_extra(ROLE_NONE, win, FALSE); /* quit */
|
||||
Strcpy(pbuf, "Pick an alignment or creed");
|
||||
end_menu(win, pbuf);
|
||||
n = select_menu(win, PICK_ONE, &selected);
|
||||
if (n > 0) {
|
||||
choice = selected[0].item.a_int;
|
||||
if (n > 1 && choice == ROLE_RANDOM)
|
||||
choice = selected[1].item.a_int;
|
||||
} else
|
||||
choice = (n == 0) ? ROLE_RANDOM : ROLE_NONE;
|
||||
if (selected)
|
||||
free((genericptr_t) selected), selected = 0;
|
||||
destroy_nhwindow(win);
|
||||
|
||||
if (choice == ROLE_NONE) {
|
||||
goto give_up; /* Selected quit */
|
||||
} else if (choice == RS_menu_arg(RS_GENDER)) {
|
||||
GEND = k = ROLE_NONE;
|
||||
nextpick = RS_GENDER;
|
||||
} else if (choice == RS_menu_arg(RS_RACE)) {
|
||||
RACE = k = ROLE_NONE;
|
||||
nextpick = RS_RACE;
|
||||
} else if (choice == RS_menu_arg(RS_ROLE)) {
|
||||
ROLE = k = ROLE_NONE;
|
||||
nextpick = RS_ROLE;
|
||||
} else if (choice == RS_menu_arg(RS_filter)) {
|
||||
ALGN = k = ROLE_NONE;
|
||||
if (reset_role_filtering())
|
||||
nextpick = RS_ROLE;
|
||||
else
|
||||
nextpick = RS_ALGNMNT;
|
||||
} else if (choice == ROLE_RANDOM) {
|
||||
k = pick_align(ROLE, RACE, GEND, PICK_RANDOM);
|
||||
if (k < 0)
|
||||
k = randalign(ROLE, RACE);
|
||||
} else {
|
||||
k = choice - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
ALGN = k;
|
||||
} /* needed alignment */
|
||||
} /* picking alignment */
|
||||
|
||||
} while (ROLE < 0 || RACE < 0 || GEND < 0 || ALGN < 0);
|
||||
|
||||
/*
|
||||
* Role, race, &c have now been determined;
|
||||
* ask for confirmation and maybe go back to choose all over again.
|
||||
*
|
||||
* Uses ynaq for familiarity, although 'a' is usually a
|
||||
* superset of 'y' but here is an alternate form of 'n'.
|
||||
* Menu layout:
|
||||
* title: Is this ok? [ynaq]
|
||||
* blank:
|
||||
* text: $name, $alignment $gender $race $role
|
||||
* blank:
|
||||
* menu: y + yes; play
|
||||
* n - no; pick again
|
||||
* maybe: a - no; rename hero
|
||||
* q - quit
|
||||
* (end)
|
||||
*/
|
||||
getconfirmation = (picksomething && pick4u != 'a' && !flags.randomall);
|
||||
while (getconfirmation) {
|
||||
tty_clear_nhwindow(BASE_WINDOW);
|
||||
role_selection_prolog(ROLE_NONE, BASE_WINDOW);
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
||||
any = cg.zeroany; /* zero out all bits */
|
||||
any.a_int = 0;
|
||||
if (!roles[ROLE].name.f
|
||||
&& (roles[ROLE].allow & ROLE_GENDMASK)
|
||||
== (ROLE_MALE | ROLE_FEMALE))
|
||||
Sprintf(plbuf, " %s", genders[GEND].adj);
|
||||
else
|
||||
*plbuf = '\0'; /* omit redundant gender */
|
||||
Snprintf(pbuf, sizeof(pbuf), "%s, %s%s %s %s", gp.plname,
|
||||
aligns[ALGN].adj, plbuf, races[RACE].adj,
|
||||
(GEND == 1 && roles[ROLE].name.f) ? roles[ROLE].name.f
|
||||
: roles[ROLE].name.m);
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE, clr, pbuf,
|
||||
MENU_ITEMFLAGS_NONE);
|
||||
/* blank separator */
|
||||
any.a_int = 0;
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0,
|
||||
ATR_NONE, clr, "", MENU_ITEMFLAGS_NONE);
|
||||
/* [ynaq] menu choices */
|
||||
any.a_int = 1;
|
||||
add_menu(win, &nul_glyphinfo, &any, 'y', 0,
|
||||
ATR_NONE, clr, "Yes; start game", MENU_ITEMFLAGS_SELECTED);
|
||||
any.a_int = 2;
|
||||
add_menu(win, &nul_glyphinfo, &any, 'n', 0,
|
||||
ATR_NONE, clr, "No; choose role again", MENU_ITEMFLAGS_NONE);
|
||||
if (iflags.renameallowed) {
|
||||
any.a_int = 3;
|
||||
add_menu(win, &nul_glyphinfo, &any, 'a', 0, ATR_NONE,
|
||||
clr, "Not yet; choose another name", MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
any.a_int = -1;
|
||||
add_menu(win, &nul_glyphinfo, &any, 'q', 0,
|
||||
ATR_NONE, clr, "Quit", MENU_ITEMFLAGS_NONE);
|
||||
Sprintf(pbuf, "Is this ok? [yn%sq]", iflags.renameallowed ? "a" : "");
|
||||
end_menu(win, pbuf);
|
||||
n = select_menu(win, PICK_ONE, &selected);
|
||||
/* [pick-one menus with a preselected entry behave oddly...] */
|
||||
choice = (n > 0) ? selected[n - 1].item.a_int : (n == 0) ? 1 : -1;
|
||||
if (selected)
|
||||
free((genericptr_t) selected), selected = 0;
|
||||
destroy_nhwindow(win);
|
||||
|
||||
switch (choice) {
|
||||
default: /* 'q' or ESC */
|
||||
goto give_up; /* quit */
|
||||
break;
|
||||
case 3: { /* 'a' */
|
||||
/*
|
||||
* TODO: what, if anything, should be done if the name is
|
||||
* changed to or from "wizard" after port-specific startup
|
||||
* code has set flags.debug based on the original name?
|
||||
*/
|
||||
int saveROLE, saveRACE, saveGEND, saveALGN;
|
||||
|
||||
iflags.renameinprogress = TRUE;
|
||||
/* plnamesuffix() can change any or all of ROLE, RACE,
|
||||
GEND, ALGN; we'll override that and honor only the name */
|
||||
saveROLE = ROLE, saveRACE = RACE, saveGEND = GEND,
|
||||
saveALGN = ALGN;
|
||||
*gp.plname = '\0';
|
||||
plnamesuffix(); /* calls askname() when gp.plname[] is empty */
|
||||
ROLE = saveROLE, RACE = saveRACE, GEND = saveGEND,
|
||||
ALGN = saveALGN;
|
||||
break; /* getconfirmation is still True */
|
||||
}
|
||||
case 2: /* 'n' */
|
||||
/* start fresh, but bypass "shall I pick everything for you?"
|
||||
step; any partial role selection via config file, command
|
||||
line, or name suffix is discarded this time */
|
||||
pick4u = 'n';
|
||||
ROLE = RACE = GEND = ALGN = ROLE_NONE;
|
||||
goto makepicks;
|
||||
break;
|
||||
case 1: /* 'y' or Space or Return/Enter */
|
||||
/* success; drop out through end of function */
|
||||
getconfirmation = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Success! */
|
||||
tty_display_nhwindow(BASE_WINDOW, FALSE);
|
||||
return;
|
||||
|
||||
give_up:
|
||||
/* Quit */
|
||||
if (selected)
|
||||
free((genericptr_t) selected); /* [obsolete] */
|
||||
bail((char *) 0);
|
||||
/*NOTREACHED*/
|
||||
return;
|
||||
}
|
||||
|
||||
static boolean
|
||||
reset_role_filtering(void)
|
||||
{
|
||||
winid win;
|
||||
anything any;
|
||||
int i, n, clr = 0;
|
||||
char filterprompt[QBUFSZ];
|
||||
menu_item *selected = 0;
|
||||
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
||||
any = cg.zeroany;
|
||||
|
||||
/* no extra blank line preceding this entry; end_menu supplies one */
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE, clr,
|
||||
"Unacceptable roles", MENU_ITEMFLAGS_NONE);
|
||||
setup_rolemenu(win, FALSE, ROLE_NONE, ROLE_NONE, ROLE_NONE);
|
||||
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
|
||||
clr, "", MENU_ITEMFLAGS_NONE);
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
|
||||
clr, "Unacceptable races", MENU_ITEMFLAGS_NONE);
|
||||
setup_racemenu(win, FALSE, ROLE_NONE, ROLE_NONE, ROLE_NONE);
|
||||
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
|
||||
clr, "", MENU_ITEMFLAGS_NONE);
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
|
||||
clr, "Unacceptable genders", MENU_ITEMFLAGS_NONE);
|
||||
setup_gendmenu(win, FALSE, ROLE_NONE, ROLE_NONE, ROLE_NONE);
|
||||
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
|
||||
clr, "", MENU_ITEMFLAGS_NONE);
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
|
||||
clr, "Unacceptable alignments", MENU_ITEMFLAGS_NONE);
|
||||
setup_algnmenu(win, FALSE, ROLE_NONE, ROLE_NONE, ROLE_NONE);
|
||||
|
||||
Sprintf(filterprompt, "Pick all that apply%s",
|
||||
gotrolefilter() ? " and/or unpick any that no longer apply" : "");
|
||||
end_menu(win, filterprompt);
|
||||
n = select_menu(win, PICK_ANY, &selected);
|
||||
|
||||
if (n >= 0) { /* n==0: clear current filters and don't set new ones */
|
||||
clearrolefilter();
|
||||
for (i = 0; i < n; i++)
|
||||
setrolefilter(selected[i].item.a_string);
|
||||
|
||||
ROLE = RACE = GEND = ALGN = ROLE_NONE;
|
||||
}
|
||||
if (selected)
|
||||
free((genericptr_t) selected), selected = 0;
|
||||
destroy_nhwindow(win);
|
||||
return (n > 0) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
#undef ROLE
|
||||
#undef RACE
|
||||
#undef GEND
|
||||
#undef ALGN
|
||||
|
||||
/* add entries a-Archeologist, b-Barbarian, &c to menu being built in 'win' */
|
||||
static void
|
||||
setup_rolemenu(
|
||||
winid win,
|
||||
boolean filtering, /* True => exclude filtered roles;
|
||||
* False => filter reset */
|
||||
int race, int gend, int algn) /* all ROLE_NONE for !filtering case */
|
||||
{
|
||||
anything any;
|
||||
int i;
|
||||
boolean role_ok;
|
||||
char thisch, lastch = '\0', rolenamebuf[50];
|
||||
int clr = 0;
|
||||
|
||||
any = cg.zeroany; /* zero out all bits */
|
||||
for (i = 0; roles[i].name.m; i++) {
|
||||
/* role can be constrained by any of race, gender, or alignment */
|
||||
role_ok = (ok_role(i, race, gend, algn)
|
||||
&& ok_race(i, race, gend, algn)
|
||||
&& ok_gend(i, race, gend, algn)
|
||||
&& ok_align(i, race, gend, algn));
|
||||
if (filtering && !role_ok)
|
||||
continue;
|
||||
if (filtering)
|
||||
any.a_int = i + 1;
|
||||
else
|
||||
any.a_string = roles[i].name.m;
|
||||
thisch = lowc(*roles[i].name.m);
|
||||
if (thisch == lastch)
|
||||
thisch = highc(thisch);
|
||||
Strcpy(rolenamebuf, roles[i].name.m);
|
||||
if (roles[i].name.f) {
|
||||
/* role has distinct name for female (C,P) */
|
||||
if (gend == 1) {
|
||||
/* female already chosen; replace male name */
|
||||
Strcpy(rolenamebuf, roles[i].name.f);
|
||||
} else if (gend < 0) {
|
||||
/* not chosen yet; append slash+female name */
|
||||
Strcat(rolenamebuf, "/");
|
||||
Strcat(rolenamebuf, roles[i].name.f);
|
||||
}
|
||||
}
|
||||
/* !filtering implies reset_role_filtering() where we want to
|
||||
mark this role as preseleted if current filter excludes it */
|
||||
add_menu(win, &nul_glyphinfo, &any, thisch, 0,
|
||||
ATR_NONE, clr, an(rolenamebuf),
|
||||
(!filtering && !role_ok)
|
||||
? MENU_ITEMFLAGS_SELECTED : MENU_ITEMFLAGS_NONE);
|
||||
lastch = thisch;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_racemenu(winid win, boolean filtering, int role, int gend, int algn)
|
||||
{
|
||||
anything any;
|
||||
boolean race_ok;
|
||||
int i;
|
||||
char this_ch;
|
||||
int clr = 0;
|
||||
|
||||
any = cg.zeroany;
|
||||
for (i = 0; races[i].noun; i++) {
|
||||
/* no ok_gend(); race isn't constrained by gender */
|
||||
race_ok = (ok_race(role, i, gend, algn)
|
||||
&& ok_role(role, i, gend, algn)
|
||||
&& ok_align(role, i, gend, algn));
|
||||
if (filtering && !race_ok)
|
||||
continue;
|
||||
if (filtering)
|
||||
any.a_int = i + 1;
|
||||
else
|
||||
any.a_string = races[i].noun;
|
||||
this_ch = *races[i].noun;
|
||||
/* filtering: picking race, so choose by first letter, with
|
||||
capital letter as unseen accelerator;
|
||||
!filtering: resetting filter rather than picking, choose by
|
||||
capital letter since lowercase role letters will be present */
|
||||
add_menu(win, &nul_glyphinfo, &any,
|
||||
filtering ? this_ch : highc(this_ch),
|
||||
filtering ? highc(this_ch) : 0,
|
||||
ATR_NONE, clr, races[i].noun,
|
||||
(!filtering && !race_ok)
|
||||
? MENU_ITEMFLAGS_SELECTED : MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_gendmenu(winid win, boolean filtering, int role, int race, int algn)
|
||||
{
|
||||
anything any;
|
||||
boolean gend_ok;
|
||||
int i;
|
||||
char this_ch;
|
||||
int clr = 0;
|
||||
|
||||
any = cg.zeroany;
|
||||
for (i = 0; i < ROLE_GENDERS; i++) {
|
||||
/* no ok_align(); gender isn't constrained by alignment */
|
||||
gend_ok = (ok_gend(role, race, i, algn)
|
||||
&& ok_role(role, race, i, algn)
|
||||
&& ok_race(role, race, i, algn));
|
||||
if (filtering && !gend_ok)
|
||||
continue;
|
||||
if (filtering)
|
||||
any.a_int = i + 1;
|
||||
else
|
||||
any.a_string = genders[i].adj;
|
||||
this_ch = *genders[i].adj;
|
||||
/* (see setup_racemenu for explanation of selector letters
|
||||
and setup_rolemenu for preselection) */
|
||||
add_menu(win, &nul_glyphinfo, &any,
|
||||
filtering ? this_ch : highc(this_ch),
|
||||
filtering ? highc(this_ch) : 0,
|
||||
ATR_NONE, clr, genders[i].adj,
|
||||
(!filtering && !gend_ok)
|
||||
? MENU_ITEMFLAGS_SELECTED : MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_algnmenu(winid win, boolean filtering, int role, int race, int gend)
|
||||
{
|
||||
anything any;
|
||||
boolean algn_ok;
|
||||
int i;
|
||||
char this_ch;
|
||||
int clr = 0;
|
||||
|
||||
any = cg.zeroany;
|
||||
for (i = 0; i < ROLE_ALIGNS; i++) {
|
||||
/* no ok_gend(); alignment isn't constrained by gender */
|
||||
algn_ok = (ok_align(role, race, gend, i)
|
||||
&& ok_role(role, race, gend, i)
|
||||
&& ok_race(role, race, gend, i));
|
||||
if (filtering && !algn_ok)
|
||||
continue;
|
||||
if (filtering)
|
||||
any.a_int = i + 1;
|
||||
else
|
||||
any.a_string = aligns[i].adj;
|
||||
this_ch = *aligns[i].adj;
|
||||
/* (see setup_racemenu for explanation of selector letters
|
||||
and setup_rolemenu for preselection) */
|
||||
add_menu(win, &nul_glyphinfo, &any,
|
||||
filtering ? this_ch : highc(this_ch),
|
||||
filtering ? highc(this_ch) : 0,
|
||||
ATR_NONE, clr, aligns[i].adj,
|
||||
(!filtering && !algn_ok)
|
||||
? MENU_ITEMFLAGS_SELECTED : MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2783,6 +2022,7 @@ tty_curs(winid window,
|
||||
ttyDisplay->cury = y;
|
||||
}
|
||||
|
||||
#ifndef STATUS_HILITES
|
||||
static void
|
||||
tty_putsym(winid window, int x, int y, char ch)
|
||||
{
|
||||
@@ -2815,6 +2055,7 @@ tty_putsym(winid window, int x, int y, char ch)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char *
|
||||
compress_str(const char *str)
|
||||
|
||||
Reference in New Issue
Block a user