-/* NetHack 3.6 role.c $NHDT-Date: 1432512766 2015/05/25 00:12:46 $ $NHDT-Branch: master $:$NHDT-Revision: 1.30 $ */
+/* NetHack 3.6 role.c $NHDT-Date: 1433207910 2015/06/02 01:18:30 $ $NHDT-Branch: master $:$NHDT-Revision: 1.31 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */
/* NetHack may be freely redistributed. See license for details. */
/* The player's role, created at runtime from initial
* choices. This may be munged in role_init().
*/
-struct Role urole = { { "Undefined", 0 },
- { { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 } },
- "L",
- "N",
- "C",
- "Xxx",
- "home",
- "locate",
- NON_PM,
- NON_PM,
- NON_PM,
- NON_PM,
- NON_PM,
- NON_PM,
- NON_PM,
- NON_PM,
- 0,
- 0,
- 0,
- 0,
- /* Str Int Wis Dex Con Cha */
- { 7, 7, 7, 7, 7, 7 },
- { 20, 15, 15, 20, 20, 10 },
- /* Init Lower Higher */
- { 10, 0, 0, 8, 1, 0 }, /* Hit points */
- { 2, 0, 0, 2, 0, 3 },
- 14, /* Energy */
- 0,
- 10,
- 0,
- 0,
- 4,
- A_INT,
- 0,
- -3 };
+struct Role urole = {
+ { "Undefined", 0 },
+ { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
+ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
+ "L", "N", "C",
+ "Xxx", "home", "locate",
+ NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM,
+ 0, 0, 0, 0,
+ /* Str Int Wis Dex Con Cha */
+ { 7, 7, 7, 7, 7, 7 },
+ { 20, 15, 15, 20, 20, 10 },
+ /* Init Lower Higher */
+ { 10, 0, 0, 8, 1, 0 }, /* Hit points */
+ { 2, 0, 0, 2, 0, 3 },
+ 14, /* Energy */
+ 0,
+ 10,
+ 0,
+ 0,
+ 4,
+ A_INT,
+ 0,
+ -3
+};
/* Table of all races */
const struct Race races[] = {
short mask;
} filter;
+STATIC_DCL int NDECL(randrole_filtered);
STATIC_DCL char *FDECL(promptsep, (char *, int));
STATIC_DCL int FDECL(role_gendercount, (int));
STATIC_DCL int FDECL(race_alignmentcount, (int));
return (rn2(SIZE(roles) - 1));
}
+STATIC_OVL int
+randrole_filtered()
+{
+ int i, n = 0, set[SIZE(roles)];
+
+ /* this doesn't rule out impossible combinations but attempts to
+ honor all the filter masks */
+ for (i = 0; i < SIZE(roles); ++i)
+ if (ok_role(i, ROLE_NONE, ROLE_NONE, ROLE_NONE)
+ && ok_race(i, ROLE_RANDOM, ROLE_NONE, ROLE_NONE)
+ && ok_gend(i, ROLE_NONE, ROLE_RANDOM, ROLE_NONE)
+ && ok_align(i, ROLE_NONE, ROLE_NONE, ROLE_RANDOM))
+ set[n++] = i;
+ return n ? set[rn2(n)] : randrole();
+}
+
int
str2role(str)
const char *str;
int
str2gend(str)
-char *str;
+const char *str;
{
int i, len;
int
str2align(str)
-char *str;
+const char *str;
{
int i, len;
short allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1) {
+ if (filter.roles[rolenum])
+ return FALSE;
allow = roles[rolenum].allow;
if (racenum >= 0 && racenum < SIZE(races) - 1
&& !(allow & races[racenum].allow & ROLE_RACEMASK))
if (alignnum >= 0 && alignnum < ROLE_ALIGNS
&& !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
return FALSE;
- if (filter.roles[rolenum])
- return FALSE;
return TRUE;
} else {
+ /* random; check whether any selection is possible */
for (i = 0; i < SIZE(roles) - 1; i++) {
+ if (filter.roles[i])
+ continue;
allow = roles[i].allow;
if (racenum >= 0 && racenum < SIZE(races) - 1
&& !(allow & races[racenum].allow & ROLE_RACEMASK))
int racenum, gendnum, alignnum, pickhow;
{
int i;
- int roles_ok = 0;
+ int roles_ok = 0, set[SIZE(roles)];
for (i = 0; i < SIZE(roles) - 1; i++) {
- if (ok_role(i, racenum, gendnum, alignnum))
- roles_ok++;
+ if (ok_role(i, racenum, gendnum, alignnum)
+ && ok_race(i, (racenum >= 0) ? racenum : ROLE_RANDOM,
+ gendnum, alignnum)
+ && ok_gend(i, racenum,
+ (gendnum >= 0) ? gendnum : ROLE_RANDOM, alignnum)
+ && ok_race(i, racenum,
+ gendnum, (alignnum >= 0) ? alignnum : ROLE_RANDOM))
+ set[roles_ok++] = i;
}
if (roles_ok == 0 || (roles_ok > 1 && pickhow == PICK_RIGID))
return ROLE_NONE;
- roles_ok = rn2(roles_ok);
- for (i = 0; i < SIZE(roles) - 1; i++) {
- if (ok_role(i, racenum, gendnum, alignnum)) {
- if (roles_ok == 0)
- return i;
- else
- roles_ok--;
- }
- }
- return ROLE_NONE;
+ return set[rn2(roles_ok)];
}
/* is racenum compatible with any rolenum/gendnum/alignnum constraints? */
short allow;
if (racenum >= 0 && racenum < SIZE(races) - 1) {
+ if (filter.mask & races[racenum].selfmask)
+ return FALSE;
allow = races[racenum].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1
&& !(allow & roles[rolenum].allow & ROLE_RACEMASK))
if (alignnum >= 0 && alignnum < ROLE_ALIGNS
&& !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
return FALSE;
- if (filter.mask & races[racenum].selfmask)
- return FALSE;
return TRUE;
} else {
+ /* random; check whether any selection is possible */
for (i = 0; i < SIZE(races) - 1; i++) {
+ if (filter.mask & races[i].selfmask)
+ continue;
allow = races[i].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1
&& !(allow & roles[rolenum].allow & ROLE_RACEMASK))
short allow;
if (gendnum >= 0 && gendnum < ROLE_GENDERS) {
+ if (filter.mask & genders[gendnum].allow)
+ return FALSE;
allow = genders[gendnum].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1
&& !(allow & roles[rolenum].allow & ROLE_GENDMASK))
if (racenum >= 0 && racenum < SIZE(races) - 1
&& !(allow & races[racenum].allow & ROLE_GENDMASK))
return FALSE;
- if (filter.mask & genders[gendnum].allow)
- return FALSE;
return TRUE;
} else {
+ /* random; check whether any selection is possible */
for (i = 0; i < ROLE_GENDERS; i++) {
+ if (filter.mask & genders[i].allow)
+ continue;
allow = genders[i].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1
&& !(allow & roles[rolenum].allow & ROLE_GENDMASK))
short allow;
if (alignnum >= 0 && alignnum < ROLE_ALIGNS) {
+ if (filter.mask & aligns[alignnum].allow)
+ return FALSE;
allow = aligns[alignnum].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1
&& !(allow & roles[rolenum].allow & ROLE_ALIGNMASK))
if (racenum >= 0 && racenum < SIZE(races) - 1
&& !(allow & races[racenum].allow & ROLE_ALIGNMASK))
return FALSE;
- if (filter.mask & aligns[alignnum].allow)
- return FALSE;
return TRUE;
} else {
+ /* random; check whether any selection is possible */
for (i = 0; i < ROLE_ALIGNS; i++) {
+ if (filter.mask & aligns[i].allow)
+ return FALSE;
allow = aligns[i].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1
&& !(allow & roles[rolenum].allow & ROLE_ALIGNMASK))
flags.initrole = pick_role(flags.initrace, flags.initgend,
flags.initalign, PICK_RANDOM);
if (flags.initrole < 0)
- flags.initrole = randrole();
+ flags.initrole = randrole_filtered();
}
if (flags.initrole != ROLE_NONE) {
if (flags.initrace == ROLE_NONE)
boolean
setrolefilter(bufp)
-char *bufp;
+const char *bufp;
{
int i;
boolean reslt = TRUE;
return reslt;
}
+boolean
+gotrolefilter()
+{
+ int i;
+
+ if (filter.mask)
+ return TRUE;
+ for (i = 0; i < SIZE(roles); ++i)
+ if (filter.roles[i])
+ return TRUE;
+ return FALSE;
+}
+
+void
+clearrolefilter()
+{
+ int i;
+
+ for (i = 0; i < SIZE(roles); ++i)
+ filter.roles[i] = FALSE;
+ filter.mask = 0;
+}
+
#define BP_ALIGN 0
#define BP_GEND 1
#define BP_RACE 2
int num_post_attribs;
{
const char *conjuct = "and ";
+
if (num_post_attribs > 1 && post_attribs < num_post_attribs
&& post_attribs > 1)
Strcat(buf, ",");
int rolenum;
{
int gendcount = 0;
+
if (validrole(rolenum)) {
if (roles[rolenum].allow & ROLE_MALE)
++gendcount;
int racenum;
{
int aligncount = 0;
+
if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) {
if (races[racenum].allow & ROLE_CHAOTIC)
++aligncount;
if (alignnum != ROLE_RANDOM)
alignnum = ROLE_NONE;
/* if alignment not specified, but race is specified
- and only one choice of alignment for that race then
- don't include it in the later list */
+ and only one choice of alignment for that race then
+ don't include it in the later list */
if ((((racenum != ROLE_NONE && racenum != ROLE_RANDOM)
&& ok_race(rolenum, racenum, gendnum, alignnum))
&& (aligncount > 1))
Sprintf(buf, "%s", s_suffix(tmpbuf));
/* buf should now be:
- * < your lawful female gnomish cavewoman's> || <your lawful female
- * gnome's>
- * || <your lawful female character's>
+ * <your lawful female gnomish cavewoman's>
+ * || <your lawful female gnome's>
+ * || <your lawful female character's>
*
* Now append the post attributes to it
*/
-
num_post_attribs = post_attribs;
if (post_attribs) {
if (pa[BP_RACE]) {
anything any;
char buf[BUFSZ];
const char *what = 0, *constrainer = 0, *forcedvalue = 0;
- int f = 0, r, c, g, a, allowmask;
+ int f = 0, r, c, g, a, i, allowmask;
r = flags.initrole;
c = flags.initrace;
case RS_ROLE:
what = "role";
f = r;
- /* nothing contrains role to a single choice */
+ for (i = 0; i < SIZE(roles); ++i)
+ if (i != f && !filter.roles[i])
+ break;
+ if (i == SIZE(roles)) {
+ constrainer = "filter";
+ forcedvalue = "role";
+ }
break;
case RS_RACE:
what = "race";
if (c >= 0) {
constrainer = "role";
forcedvalue = races[c].noun;
+ } else if (f >= 0
+ && (allowmask & ~filter.mask) == races[f].selfmask) {
+ /* if there is only one race choice available due to user
+ options disallowing others, race menu entry is disabled */
+ constrainer = "filter";
+ forcedvalue = "race";
}
}
break;
if (g >= 0) {
constrainer = "role";
forcedvalue = genders[g].adj;
+ } else if (f >= 0
+ && (allowmask & ~filter.mask) == genders[f].allow) {
+ /* if there is only one gender choice available due to user
+ options disallowing other, gender menu entry is disabled */
+ constrainer = "filter";
+ forcedvalue = "gender";
}
}
break;
if (a >= 0)
constrainer = "race";
}
+ if (f >= 0 && !constrainer
+ && (ROLE_ALIGNMASK & ~filter.mask) == aligns[f].allow) {
+ /* if there is only one alignment choice available due to user
+ options disallowing others, algn menu entry is disabled */
+ constrainer = "filter";
+ forcedvalue = "alignment";
+ }
if (a >= 0)
forcedvalue = aligns[a].adj;
break;
Sprintf(buf, "Pick%s %s first", (f >= 0) ? " another" : "", what);
add_menu(where, NO_GLYPH, &any, RS_menu_let[which], 0, ATR_NONE, buf,
MENU_UNSELECTED);
+ } else if (which == RS_filter) {
+ any.a_int = RS_menu_arg(RS_filter);
+ add_menu(where, NO_GLYPH, &any, '~', 0, ATR_NONE,
+ "Reset role/race/&c filtering", MENU_UNSELECTED);
} else if (which == ROLE_RANDOM) {
any.a_int = ROLE_RANDOM;
add_menu(where, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
/* Try the player letter second */
if ((flags.initrole = str2role(pl_character)) < 0)
/* None specified; pick a random role */
- flags.initrole = randrole();
+ flags.initrole = randrole_filtered();
}
/* We now have a valid role index. Copy the role name back. */
-/* NetHack 3.6 wintty.c $NHDT-Date: 1432536533 2015/05/25 06:48:53 $ $NHDT-Branch: master $:$NHDT-Revision: 1.94 $ */
+/* NetHack 3.6 wintty.c $NHDT-Date: 1433207911 2015/06/02 01:18:31 $ $NHDT-Branch: master $:$NHDT-Revision: 1.95 $ */
/* Copyright (c) David Cohrs, 1991 */
/* NetHack may be freely redistributed. See license for details. */
STATIC_DCL void FDECL(tty_putsym, (winid, int, int, CHAR_P));
STATIC_DCL char *FDECL(copy_of, (const char *));
STATIC_DCL void FDECL(bail, (const char *)); /* __attribute__((noreturn)) */
+STATIC_DCL void FDECL(setup_rolemenu, (winid, BOOLEAN_P, int, int, int));
+STATIC_DCL void FDECL(setup_racemenu, (winid, BOOLEAN_P, int, int, int));
+STATIC_DCL void FDECL(setup_gendmenu, (winid, BOOLEAN_P, int, int, int));
+STATIC_DCL void FDECL(setup_algnmenu, (winid, BOOLEAN_P, int, int, int));
+STATIC_DCL boolean NDECL(reset_role_filtering);
/*
* A string containing all the default commands -- to add to a list
{
int i, k, n, choice, nextpick;
boolean getconfirmation;
- char pick4u = 'n', thisch, lastch = 0;
+ char pick4u = 'n';
char pbuf[QBUFSZ], plbuf[QBUFSZ];
winid win;
anything any;
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);
+ 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;
}
} else {
/* Prompt for a role */
- char rolenamebuf[QBUFSZ];
-
tty_clear_nhwindow(BASE_WINDOW);
role_selection_prolog(RS_ROLE, BASE_WINDOW);
win = create_nhwindow(NHW_MENU);
start_menu(win);
- any = zeroany; /* zero out all bits */
- for (i = 0; roles[i].name.m; i++) {
- if (!ok_role(i, RACE, GEND, ALGN))
- continue;
- any.a_int = i + 1; /* must be non-zero */
- thisch = lowc(roles[i].name.m[0]);
- 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);
- }
- }
- add_menu(win, NO_GLYPH, &any, thisch, 0, ATR_NONE,
- an(rolenamebuf), MENU_UNSELECTED);
- lastch = thisch;
- }
+ /* populate the menu with role choices */
+ setup_rolemenu(win, TRUE, RACE, GEND, ALGN);
+ /* add miscellaneous menu entries */
role_menu_extra(ROLE_RANDOM, win);
any.a_int = 0; /* separator, not a choice */
add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "",
role_menu_extra(RS_RACE, win);
role_menu_extra(RS_GENDER, win);
role_menu_extra(RS_ALGNMNT, win);
+ if (gotrolefilter())
+ role_menu_extra(RS_filter, win);
role_menu_extra(ROLE_NONE, win); /* quit */
Strcpy(pbuf, "Pick a role or profession");
end_menu(win, pbuf);
} 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)
win = create_nhwindow(NHW_MENU);
start_menu(win);
any = zeroany; /* zero out all bits */
- for (i = 0; races[i].noun; i++) {
- if (!ok_race(ROLE, i, GEND, ALGN))
- continue;
- 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);
- }
+ /* populate the menu with role choices */
+ setup_racemenu(win, TRUE, ROLE, GEND, ALGN);
+ /* add miscellaneous menu entries */
role_menu_extra(ROLE_RANDOM, win);
any.a_int = 0; /* separator, not a choice */
add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "",
role_menu_extra(RS_ROLE, win);
role_menu_extra(RS_GENDER, win);
role_menu_extra(RS_ALGNMNT, win);
+ if (gotrolefilter())
+ role_menu_extra(RS_filter, win);
role_menu_extra(ROLE_NONE, win); /* quit */
Strcpy(pbuf, "Pick a race or species");
end_menu(win, pbuf);
n = select_menu(win, PICK_ONE, &selected);
- choice =
- (n == 1) ? selected[0].item.a_int : ROLE_NONE;
+ choice = (n == 1) ? selected[0].item.a_int
+ : ROLE_NONE;
if (selected)
free((genericptr_t) selected), selected = 0;
destroy_nhwindow(win);
} 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)
} /* picking race */
if (nextpick == RS_GENDER) {
- nextpick =
- (ROLE < 0) ? RS_ROLE : (RACE < 0) ? RS_RACE : RS_ALGNMNT;
+ 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. */
win = create_nhwindow(NHW_MENU);
start_menu(win);
any = zeroany; /* zero out all bits */
- for (i = 0; i < ROLE_GENDERS; i++) {
- if (!ok_gend(ROLE, RACE, i, ALGN))
- continue;
- any.a_int = i + 1; /* non-zero */
- add_menu(win, NO_GLYPH, &any, genders[i].adj[0],
- 0, ATR_NONE, genders[i].adj,
- MENU_UNSELECTED);
- }
+ /* populate the menu with gender choices */
+ setup_gendmenu(win, TRUE, ROLE, RACE, ALGN);
+ /* add miscellaneous menu entries */
role_menu_extra(ROLE_RANDOM, win);
any.a_int = 0; /* separator, not a choice */
add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "",
role_menu_extra(RS_ROLE, win);
role_menu_extra(RS_RACE, win);
role_menu_extra(RS_ALGNMNT, win);
+ if (gotrolefilter())
+ role_menu_extra(RS_filter, win);
role_menu_extra(ROLE_NONE, win); /* quit */
Strcpy(pbuf, "Pick a gender or sex");
end_menu(win, pbuf);
n = select_menu(win, PICK_ONE, &selected);
- choice =
- (n == 1) ? selected[0].item.a_int : ROLE_NONE;
+ choice = (n == 1) ? selected[0].item.a_int
+ : ROLE_NONE;
if (selected)
free((genericptr_t) selected), selected = 0;
destroy_nhwindow(win);
} 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)
} /* picking gender */
if (nextpick == RS_ALGNMNT) {
- nextpick =
- (ROLE < 0) ? RS_ROLE : (RACE < 0) ? RS_RACE : RS_GENDER;
+ 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)) {
win = create_nhwindow(NHW_MENU);
start_menu(win);
any = zeroany; /* zero out all bits */
- for (i = 0; i < ROLE_ALIGNS; i++) {
- if (!ok_align(ROLE, RACE, GEND, i))
- continue;
- any.a_int = i + 1; /* non-zero */
- add_menu(win, NO_GLYPH, &any, aligns[i].adj[0], 0,
- ATR_NONE, aligns[i].adj,
- MENU_UNSELECTED);
- }
+ setup_algnmenu(win, TRUE, ROLE, RACE, GEND);
role_menu_extra(ROLE_RANDOM, win);
any.a_int = 0; /* separator, not a choice */
add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "",
role_menu_extra(RS_ROLE, win);
role_menu_extra(RS_RACE, win);
role_menu_extra(RS_GENDER, win);
+ if (gotrolefilter())
+ role_menu_extra(RS_filter, win);
role_menu_extra(ROLE_NONE, win); /* quit */
Strcpy(pbuf, "Pick an alignment or creed");
end_menu(win, pbuf);
n = select_menu(win, PICK_ONE, &selected);
- choice =
- (n == 1) ? selected[0].item.a_int : ROLE_NONE;
+ choice = (n == 1) ? selected[0].item.a_int
+ : ROLE_NONE;
if (selected)
free((genericptr_t) selected), selected = 0;
destroy_nhwindow(win);
} 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)
/* 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;
+ saveALGN = ALGN;
*plname = '\0';
plnamesuffix(); /* calls askname() when plname[] is empty */
ROLE = saveROLE, RACE = saveRACE, GEND = saveGEND,
- ALGN = saveALGN;
+ ALGN = saveALGN;
}
break; /* getconfirmation is still True */
case 2: /* 'n' */
return;
}
+STATIC_OVL boolean
+reset_role_filtering()
+{
+ winid win;
+ anything any;
+ int i, n;
+ menu_item *selected = 0;
+
+ win = create_nhwindow(NHW_MENU);
+ start_menu(win);
+ any = zeroany;
+
+ /* no extra blank line preceding this entry; end_menu supplies one */
+ add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
+ "Unacceptable roles", MENU_UNSELECTED);
+ setup_rolemenu(win, FALSE, ROLE_NONE, ROLE_NONE, ROLE_NONE);
+
+ add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
+ add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
+ "Unacceptable races", MENU_UNSELECTED);
+ setup_racemenu(win, FALSE, ROLE_NONE, ROLE_NONE, ROLE_NONE);
+
+ add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
+ add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
+ "Unacceptable genders", MENU_UNSELECTED);
+ setup_gendmenu(win, FALSE, ROLE_NONE, ROLE_NONE, ROLE_NONE);
+
+ add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
+ add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
+ "Uncceptable alignments", MENU_UNSELECTED);
+ setup_algnmenu(win, FALSE, ROLE_NONE, ROLE_NONE, ROLE_NONE);
+
+ end_menu(win, "Pick all that apply");
+ n = select_menu(win, PICK_ANY, &selected);
+
+ if (n > 0) {
+ 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_OVL void
+setup_rolemenu(win, filtering, race, gend, algn)
+winid win;
+boolean filtering; /* True => exclude filtered roles; False => filter reset */
+int race, gend, algn; /* all ROLE_NONE for !filtering case */
+{
+ anything any;
+ int i;
+ boolean role_ok;
+ char thisch, lastch = '\0', rolenamebuf[50];
+
+ any = zeroany; /* zero out all bits */
+ for (i = 0; roles[i].name.m; i++) {
+ role_ok = ok_role(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, NO_GLYPH, &any, thisch, 0, ATR_NONE, an(rolenamebuf),
+ (!filtering && !role_ok) ? MENU_SELECTED : MENU_UNSELECTED);
+ lastch = thisch;
+ }
+}
+
+STATIC_OVL void
+setup_racemenu(win, filtering, role, gend, algn)
+winid win;
+boolean filtering;
+int role, gend, algn;
+{
+ anything any;
+ boolean race_ok;
+ int i;
+ char this_ch;
+
+ any = zeroany;
+ for (i = 0; races[i].noun; i++) {
+ race_ok = ok_race(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, NO_GLYPH, &any,
+ filtering ? this_ch : highc(this_ch),
+ filtering ? highc(this_ch) : 0,
+ ATR_NONE, races[i].noun,
+ (!filtering && !race_ok) ? MENU_SELECTED : MENU_UNSELECTED);
+ }
+}
+
+STATIC_DCL void
+setup_gendmenu(win, filtering, role, race, algn)
+winid win;
+boolean filtering;
+int role, race, algn;
+{
+ anything any;
+ boolean gend_ok;
+ int i;
+ char this_ch;
+
+ any = zeroany;
+ for (i = 0; i < ROLE_GENDERS; i++) {
+ gend_ok = ok_gend(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, NO_GLYPH, &any,
+ filtering ? this_ch : highc(this_ch),
+ filtering ? highc(this_ch) : 0,
+ ATR_NONE, genders[i].adj,
+ (!filtering && !gend_ok) ? MENU_SELECTED : MENU_UNSELECTED);
+ }
+}
+
+STATIC_DCL void
+setup_algnmenu(win, filtering, role, race, gend)
+winid win;
+boolean filtering;
+int role, race, gend;
+{
+ anything any;
+ boolean algn_ok;
+ int i;
+ char this_ch;
+
+ any = zeroany;
+ for (i = 0; i < ROLE_ALIGNS; i++) {
+ algn_ok = ok_align(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, NO_GLYPH, &any,
+ filtering ? this_ch : highc(this_ch),
+ filtering ? highc(this_ch) : 0,
+ ATR_NONE, aligns[i].adj,
+ (!filtering && !algn_ok) ? MENU_SELECTED : MENU_UNSELECTED);
+ }
+}
+
/*
* plname is filled either by an option (-u Player or -uPlayer) or
* explicitly (by being the wizard) or by askname.