Merge branch 'master' into status_hilite

Conflicts:
	include/extern.h
	win/tty/wintty.c
This commit is contained in:
nhmall
2015-06-01 22:13:41 -04:00
5 changed files with 396 additions and 150 deletions
+6 -4
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 extern.h $NHDT-Date: 1433105379 2015/05/31 20:49:39 $ $NHDT-Branch: status_hilite $:$NHDT-Revision: 1.500 $ */ /* NetHack 3.6 extern.h $NHDT-Date: 1433207912 2015/06/02 01:18:32 $ $NHDT-Branch: master $:$NHDT-Revision: 1.500 $ */
/* Copyright (c) Steve Creps, 1988. */ /* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1977,8 +1977,8 @@ E int FDECL(randgend, (int, int));
E int FDECL(randalign, (int, int)); E int FDECL(randalign, (int, int));
E int FDECL(str2role, (const char *)); E int FDECL(str2role, (const char *));
E int FDECL(str2race, (const char *)); E int FDECL(str2race, (const char *));
E int FDECL(str2gend, (char *)); E int FDECL(str2gend, (const char *));
E int FDECL(str2align, (char *)); E int FDECL(str2align, (const char *));
E boolean FDECL(ok_role, (int, int, int, int)); E boolean FDECL(ok_role, (int, int, int, int));
E int FDECL(pick_role, (int, int, int, int)); E int FDECL(pick_role, (int, int, int, int));
E boolean FDECL(ok_race, (int, int, int, int)); E boolean FDECL(ok_race, (int, int, int, int));
@@ -1988,7 +1988,9 @@ E int FDECL(pick_gend, (int, int, int, int));
E boolean FDECL(ok_align, (int, int, int, int)); E boolean FDECL(ok_align, (int, int, int, int));
E int FDECL(pick_align, (int, int, int, int)); E int FDECL(pick_align, (int, int, int, int));
E void NDECL(rigid_role_checks); E void NDECL(rigid_role_checks);
E boolean FDECL(setrolefilter, (char *)); E boolean FDECL(setrolefilter, (const char *));
E boolean NDECL(gotrolefilter);
E void NDECL(clearrolefilter);
E char *FDECL(build_plselection_prompt, (char *, int, int, int, int, int)); E char *FDECL(build_plselection_prompt, (char *, int, int, int, int, int));
E char *FDECL(root_plselection_prompt, (char *, int, int, int, int, int)); E char *FDECL(root_plselection_prompt, (char *, int, int, int, int, int));
E void NDECL(plnamesuffix); E void NDECL(plnamesuffix);
+3 -2
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 winprocs.h $NHDT-Date: 1432512776 2015/05/25 00:12:56 $ $NHDT-Branch: master $:$NHDT-Revision: 1.34 $ */ /* NetHack 3.6 winprocs.h $NHDT-Date: 1433207914 2015/06/02 01:18:34 $ $NHDT-Branch: master $:$NHDT-Revision: 1.35 $ */
/* Copyright (c) David Cohrs, 1992 */ /* Copyright (c) David Cohrs, 1992 */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -289,7 +289,8 @@ struct wc_Opt {
#define RS_RACE 2 #define RS_RACE 2
#define RS_GENDER 3 #define RS_GENDER 3
#define RS_ALGNMNT 4 #define RS_ALGNMNT 4
#define RS_menu_arg(x) (ROLE_RANDOM - ((x) + 1)) /* 0..4 -> -3..-7 */ #define RS_filter 5
#define RS_menu_arg(x) (ROLE_RANDOM - ((x) + 1)) /* 0..5 -> -3..-8 */
/* Choose_windows() may be called multiple times; these constants tell the /* Choose_windows() may be called multiple times; these constants tell the
* init function whether the window system is coming or going. */ * init function whether the window system is coming or going. */
+2 -1
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 wintype.h $NHDT-Date: 1432512782 2015/05/25 00:13:02 $ $NHDT-Branch: master $:$NHDT-Revision: 1.14 $ */ /* NetHack 3.6 wintype.h $NHDT-Date: 1433207914 2015/06/02 01:18:34 $ $NHDT-Branch: master $:$NHDT-Revision: 1.15 $ */
/* Copyright (c) David Cohrs, 1991 */ /* Copyright (c) David Cohrs, 1991 */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -22,6 +22,7 @@ typedef union any {
long *a_lptr; long *a_lptr;
unsigned long *a_ulptr; unsigned long *a_ulptr;
unsigned *a_uptr; unsigned *a_uptr;
const char *a_string;
/* add types as needed */ /* add types as needed */
} anything; } anything;
#define ANY_P union any /* avoid typedef in prototypes */ #define ANY_P union any /* avoid typedef in prototypes */
+122 -61
View File
@@ -1,4 +1,4 @@
/* 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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -614,34 +614,14 @@ const struct Role roles[] = {
/* The player's role, created at runtime from initial /* The player's role, created at runtime from initial
* choices. This may be munged in role_init(). * choices. This may be munged in role_init().
*/ */
struct Role urole = { { "Undefined", 0 }, struct Role urole = {
{ { 0, 0 }, { "Undefined", 0 },
{ 0, 0 }, { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
{ 0, 0 }, "L", "N", "C",
{ 0, 0 }, "Xxx", "home", "locate",
{ 0, 0 }, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM,
{ 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 */ /* Str Int Wis Dex Con Cha */
{ 7, 7, 7, 7, 7, 7 }, { 7, 7, 7, 7, 7, 7 },
{ 20, 15, 15, 20, 20, 10 }, { 20, 15, 15, 20, 20, 10 },
@@ -656,7 +636,8 @@ struct Role urole = { { "Undefined", 0 },
4, 4,
A_INT, A_INT,
0, 0,
-3 }; -3
};
/* Table of all races */ /* Table of all races */
const struct Race races[] = { const struct Race races[] = {
@@ -816,6 +797,7 @@ static struct {
short mask; short mask;
} filter; } filter;
STATIC_DCL int NDECL(randrole_filtered);
STATIC_DCL char *FDECL(promptsep, (char *, int)); STATIC_DCL char *FDECL(promptsep, (char *, int));
STATIC_DCL int FDECL(role_gendercount, (int)); STATIC_DCL int FDECL(role_gendercount, (int));
STATIC_DCL int FDECL(race_alignmentcount, (int)); STATIC_DCL int FDECL(race_alignmentcount, (int));
@@ -836,6 +818,22 @@ randrole()
return (rn2(SIZE(roles) - 1)); 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 int
str2role(str) str2role(str)
const char *str; const char *str;
@@ -973,7 +971,7 @@ int rolenum, racenum;
int int
str2gend(str) str2gend(str)
char *str; const char *str;
{ {
int i, len; int i, len;
@@ -1039,7 +1037,7 @@ int rolenum, racenum;
int int
str2align(str) str2align(str)
char *str; const char *str;
{ {
int i, len; int i, len;
@@ -1074,6 +1072,8 @@ int rolenum, racenum, gendnum, alignnum;
short allow; short allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1) { if (rolenum >= 0 && rolenum < SIZE(roles) - 1) {
if (filter.roles[rolenum])
return FALSE;
allow = roles[rolenum].allow; allow = roles[rolenum].allow;
if (racenum >= 0 && racenum < SIZE(races) - 1 if (racenum >= 0 && racenum < SIZE(races) - 1
&& !(allow & races[racenum].allow & ROLE_RACEMASK)) && !(allow & races[racenum].allow & ROLE_RACEMASK))
@@ -1084,11 +1084,12 @@ int rolenum, racenum, gendnum, alignnum;
if (alignnum >= 0 && alignnum < ROLE_ALIGNS if (alignnum >= 0 && alignnum < ROLE_ALIGNS
&& !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK)) && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
return FALSE; return FALSE;
if (filter.roles[rolenum])
return FALSE;
return TRUE; return TRUE;
} else { } else {
/* random; check whether any selection is possible */
for (i = 0; i < SIZE(roles) - 1; i++) { for (i = 0; i < SIZE(roles) - 1; i++) {
if (filter.roles[i])
continue;
allow = roles[i].allow; allow = roles[i].allow;
if (racenum >= 0 && racenum < SIZE(races) - 1 if (racenum >= 0 && racenum < SIZE(races) - 1
&& !(allow & races[racenum].allow & ROLE_RACEMASK)) && !(allow & races[racenum].allow & ROLE_RACEMASK))
@@ -1113,24 +1114,21 @@ pick_role(racenum, gendnum, alignnum, pickhow)
int racenum, gendnum, alignnum, pickhow; int racenum, gendnum, alignnum, pickhow;
{ {
int i; int i;
int roles_ok = 0; int roles_ok = 0, set[SIZE(roles)];
for (i = 0; i < SIZE(roles) - 1; i++) { for (i = 0; i < SIZE(roles) - 1; i++) {
if (ok_role(i, racenum, gendnum, alignnum)) if (ok_role(i, racenum, gendnum, alignnum)
roles_ok++; && 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)) if (roles_ok == 0 || (roles_ok > 1 && pickhow == PICK_RIGID))
return ROLE_NONE; return ROLE_NONE;
roles_ok = rn2(roles_ok); return set[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;
} }
/* is racenum compatible with any rolenum/gendnum/alignnum constraints? */ /* is racenum compatible with any rolenum/gendnum/alignnum constraints? */
@@ -1142,6 +1140,8 @@ int rolenum, racenum, gendnum, alignnum;
short allow; short allow;
if (racenum >= 0 && racenum < SIZE(races) - 1) { if (racenum >= 0 && racenum < SIZE(races) - 1) {
if (filter.mask & races[racenum].selfmask)
return FALSE;
allow = races[racenum].allow; allow = races[racenum].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1 if (rolenum >= 0 && rolenum < SIZE(roles) - 1
&& !(allow & roles[rolenum].allow & ROLE_RACEMASK)) && !(allow & roles[rolenum].allow & ROLE_RACEMASK))
@@ -1152,11 +1152,12 @@ int rolenum, racenum, gendnum, alignnum;
if (alignnum >= 0 && alignnum < ROLE_ALIGNS if (alignnum >= 0 && alignnum < ROLE_ALIGNS
&& !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK)) && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
return FALSE; return FALSE;
if (filter.mask & races[racenum].selfmask)
return FALSE;
return TRUE; return TRUE;
} else { } else {
/* random; check whether any selection is possible */
for (i = 0; i < SIZE(races) - 1; i++) { for (i = 0; i < SIZE(races) - 1; i++) {
if (filter.mask & races[i].selfmask)
continue;
allow = races[i].allow; allow = races[i].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1 if (rolenum >= 0 && rolenum < SIZE(roles) - 1
&& !(allow & roles[rolenum].allow & ROLE_RACEMASK)) && !(allow & roles[rolenum].allow & ROLE_RACEMASK))
@@ -1212,6 +1213,8 @@ int alignnum UNUSED;
short allow; short allow;
if (gendnum >= 0 && gendnum < ROLE_GENDERS) { if (gendnum >= 0 && gendnum < ROLE_GENDERS) {
if (filter.mask & genders[gendnum].allow)
return FALSE;
allow = genders[gendnum].allow; allow = genders[gendnum].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1 if (rolenum >= 0 && rolenum < SIZE(roles) - 1
&& !(allow & roles[rolenum].allow & ROLE_GENDMASK)) && !(allow & roles[rolenum].allow & ROLE_GENDMASK))
@@ -1219,11 +1222,12 @@ int alignnum UNUSED;
if (racenum >= 0 && racenum < SIZE(races) - 1 if (racenum >= 0 && racenum < SIZE(races) - 1
&& !(allow & races[racenum].allow & ROLE_GENDMASK)) && !(allow & races[racenum].allow & ROLE_GENDMASK))
return FALSE; return FALSE;
if (filter.mask & genders[gendnum].allow)
return FALSE;
return TRUE; return TRUE;
} else { } else {
/* random; check whether any selection is possible */
for (i = 0; i < ROLE_GENDERS; i++) { for (i = 0; i < ROLE_GENDERS; i++) {
if (filter.mask & genders[i].allow)
continue;
allow = genders[i].allow; allow = genders[i].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1 if (rolenum >= 0 && rolenum < SIZE(roles) - 1
&& !(allow & roles[rolenum].allow & ROLE_GENDMASK)) && !(allow & roles[rolenum].allow & ROLE_GENDMASK))
@@ -1278,6 +1282,8 @@ int alignnum;
short allow; short allow;
if (alignnum >= 0 && alignnum < ROLE_ALIGNS) { if (alignnum >= 0 && alignnum < ROLE_ALIGNS) {
if (filter.mask & aligns[alignnum].allow)
return FALSE;
allow = aligns[alignnum].allow; allow = aligns[alignnum].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1 if (rolenum >= 0 && rolenum < SIZE(roles) - 1
&& !(allow & roles[rolenum].allow & ROLE_ALIGNMASK)) && !(allow & roles[rolenum].allow & ROLE_ALIGNMASK))
@@ -1285,11 +1291,12 @@ int alignnum;
if (racenum >= 0 && racenum < SIZE(races) - 1 if (racenum >= 0 && racenum < SIZE(races) - 1
&& !(allow & races[racenum].allow & ROLE_ALIGNMASK)) && !(allow & races[racenum].allow & ROLE_ALIGNMASK))
return FALSE; return FALSE;
if (filter.mask & aligns[alignnum].allow)
return FALSE;
return TRUE; return TRUE;
} else { } else {
/* random; check whether any selection is possible */
for (i = 0; i < ROLE_ALIGNS; i++) { for (i = 0; i < ROLE_ALIGNS; i++) {
if (filter.mask & aligns[i].allow)
return FALSE;
allow = aligns[i].allow; allow = aligns[i].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1 if (rolenum >= 0 && rolenum < SIZE(roles) - 1
&& !(allow & roles[rolenum].allow & ROLE_ALIGNMASK)) && !(allow & roles[rolenum].allow & ROLE_ALIGNMASK))
@@ -1352,7 +1359,7 @@ rigid_role_checks()
flags.initrole = pick_role(flags.initrace, flags.initgend, flags.initrole = pick_role(flags.initrace, flags.initgend,
flags.initalign, PICK_RANDOM); flags.initalign, PICK_RANDOM);
if (flags.initrole < 0) if (flags.initrole < 0)
flags.initrole = randrole(); flags.initrole = randrole_filtered();
} }
if (flags.initrole != ROLE_NONE) { if (flags.initrole != ROLE_NONE) {
if (flags.initrace == ROLE_NONE) if (flags.initrace == ROLE_NONE)
@@ -1369,7 +1376,7 @@ rigid_role_checks()
boolean boolean
setrolefilter(bufp) setrolefilter(bufp)
char *bufp; const char *bufp;
{ {
int i; int i;
boolean reslt = TRUE; boolean reslt = TRUE;
@@ -1387,6 +1394,29 @@ char *bufp;
return reslt; 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_ALIGN 0
#define BP_GEND 1 #define BP_GEND 1
#define BP_RACE 2 #define BP_RACE 2
@@ -1401,6 +1431,7 @@ char *buf;
int num_post_attribs; int num_post_attribs;
{ {
const char *conjuct = "and "; const char *conjuct = "and ";
if (num_post_attribs > 1 && post_attribs < num_post_attribs if (num_post_attribs > 1 && post_attribs < num_post_attribs
&& post_attribs > 1) && post_attribs > 1)
Strcat(buf, ","); Strcat(buf, ",");
@@ -1416,6 +1447,7 @@ role_gendercount(rolenum)
int rolenum; int rolenum;
{ {
int gendcount = 0; int gendcount = 0;
if (validrole(rolenum)) { if (validrole(rolenum)) {
if (roles[rolenum].allow & ROLE_MALE) if (roles[rolenum].allow & ROLE_MALE)
++gendcount; ++gendcount;
@@ -1432,6 +1464,7 @@ race_alignmentcount(racenum)
int racenum; int racenum;
{ {
int aligncount = 0; int aligncount = 0;
if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) { if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) {
if (races[racenum].allow & ROLE_CHAOTIC) if (races[racenum].allow & ROLE_CHAOTIC)
++aligncount; ++aligncount;
@@ -1619,13 +1652,12 @@ int buflen, rolenum, racenum, gendnum, alignnum;
Sprintf(buf, "%s", s_suffix(tmpbuf)); Sprintf(buf, "%s", s_suffix(tmpbuf));
/* buf should now be: /* buf should now be:
* < your lawful female gnomish cavewoman's> || <your lawful female * <your lawful female gnomish cavewoman's>
* gnome's> * || <your lawful female gnome's>
* || <your lawful female character's> * || <your lawful female character's>
* *
* Now append the post attributes to it * Now append the post attributes to it
*/ */
num_post_attribs = post_attribs; num_post_attribs = post_attribs;
if (post_attribs) { if (post_attribs) {
if (pa[BP_RACE]) { if (pa[BP_RACE]) {
@@ -1811,7 +1843,7 @@ winid where;
anything any; anything any;
char buf[BUFSZ]; char buf[BUFSZ];
const char *what = 0, *constrainer = 0, *forcedvalue = 0; 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; r = flags.initrole;
c = flags.initrace; c = flags.initrace;
@@ -1822,7 +1854,13 @@ winid where;
case RS_ROLE: case RS_ROLE:
what = "role"; what = "role";
f = r; 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; break;
case RS_RACE: case RS_RACE:
what = "race"; what = "race";
@@ -1835,6 +1873,12 @@ winid where;
if (c >= 0) { if (c >= 0) {
constrainer = "role"; constrainer = "role";
forcedvalue = races[c].noun; 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; break;
@@ -1851,6 +1895,12 @@ winid where;
if (g >= 0) { if (g >= 0) {
constrainer = "role"; constrainer = "role";
forcedvalue = genders[g].adj; 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; break;
@@ -1880,6 +1930,13 @@ winid where;
if (a >= 0) if (a >= 0)
constrainer = "race"; 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) if (a >= 0)
forcedvalue = aligns[a].adj; forcedvalue = aligns[a].adj;
break; break;
@@ -1897,6 +1954,10 @@ winid where;
Sprintf(buf, "Pick%s %s first", (f >= 0) ? " another" : "", what); Sprintf(buf, "Pick%s %s first", (f >= 0) ? " another" : "", what);
add_menu(where, NO_GLYPH, &any, RS_menu_let[which], 0, ATR_NONE, buf, add_menu(where, NO_GLYPH, &any, RS_menu_let[which], 0, ATR_NONE, buf,
MENU_UNSELECTED); 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) { } else if (which == ROLE_RANDOM) {
any.a_int = ROLE_RANDOM; any.a_int = ROLE_RANDOM;
add_menu(where, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", add_menu(where, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
@@ -1942,7 +2003,7 @@ role_init()
/* Try the player letter second */ /* Try the player letter second */
if ((flags.initrole = str2role(pl_character)) < 0) if ((flags.initrole = str2role(pl_character)) < 0)
/* None specified; pick a random role */ /* 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. */ /* We now have a valid role index. Copy the role name back. */
+244 -63
View File
@@ -159,6 +159,11 @@ STATIC_DCL const char *FDECL(compress_str, (const char *));
STATIC_DCL void FDECL(tty_putsym, (winid, int, int, CHAR_P)); STATIC_DCL void FDECL(tty_putsym, (winid, int, int, CHAR_P));
STATIC_DCL char *FDECL(copy_of, (const char *)); STATIC_DCL char *FDECL(copy_of, (const char *));
STATIC_DCL void FDECL(bail, (const char *)); /* __attribute__((noreturn)) */ 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 * A string containing all the default commands -- to add to a list
@@ -328,7 +333,7 @@ tty_player_selection()
{ {
int i, k, n, choice, nextpick; int i, k, n, choice, nextpick;
boolean getconfirmation; boolean getconfirmation;
char pick4u = 'n', thisch, lastch = 0; char pick4u = 'n';
char pbuf[QBUFSZ], plbuf[QBUFSZ]; char pbuf[QBUFSZ], plbuf[QBUFSZ];
winid win; winid win;
anything any; anything any;
@@ -352,8 +357,8 @@ tty_player_selection()
if (ROLE == ROLE_NONE || RACE == ROLE_NONE || GEND == ROLE_NONE if (ROLE == ROLE_NONE || RACE == ROLE_NONE || GEND == ROLE_NONE
|| ALGN == ROLE_NONE) { || ALGN == ROLE_NONE) {
int echoline; int echoline;
char *prompt = char *prompt = build_plselection_prompt(pbuf, QBUFSZ,
build_plselection_prompt(pbuf, QBUFSZ, ROLE, RACE, GEND, ALGN); ROLE, RACE, GEND, ALGN);
/* this prompt string ends in "[ynaq]?": /* this prompt string ends in "[ynaq]?":
y - game picks role,&c then asks player to confirm; y - game picks role,&c then asks player to confirm;
@@ -405,36 +410,13 @@ makepicks:
} }
} else { } else {
/* Prompt for a role */ /* Prompt for a role */
char rolenamebuf[QBUFSZ];
tty_clear_nhwindow(BASE_WINDOW); tty_clear_nhwindow(BASE_WINDOW);
role_selection_prolog(RS_ROLE, BASE_WINDOW); role_selection_prolog(RS_ROLE, BASE_WINDOW);
win = create_nhwindow(NHW_MENU); win = create_nhwindow(NHW_MENU);
start_menu(win); start_menu(win);
any = zeroany; /* zero out all bits */ /* populate the menu with role choices */
for (i = 0; roles[i].name.m; i++) { setup_rolemenu(win, TRUE, RACE, GEND, ALGN);
if (!ok_role(i, RACE, GEND, ALGN)) /* add miscellaneous menu entries */
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;
}
role_menu_extra(ROLE_RANDOM, win); role_menu_extra(ROLE_RANDOM, win);
any.a_int = 0; /* separator, not a choice */ any.a_int = 0; /* separator, not a choice */
add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "", add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "",
@@ -442,6 +424,8 @@ makepicks:
role_menu_extra(RS_RACE, win); role_menu_extra(RS_RACE, win);
role_menu_extra(RS_GENDER, win); role_menu_extra(RS_GENDER, win);
role_menu_extra(RS_ALGNMNT, win); role_menu_extra(RS_ALGNMNT, win);
if (gotrolefilter())
role_menu_extra(RS_filter, win);
role_menu_extra(ROLE_NONE, win); /* quit */ role_menu_extra(ROLE_NONE, win); /* quit */
Strcpy(pbuf, "Pick a role or profession"); Strcpy(pbuf, "Pick a role or profession");
end_menu(win, pbuf); end_menu(win, pbuf);
@@ -462,6 +446,10 @@ makepicks:
} else if (choice == RS_menu_arg(RS_RACE)) { } else if (choice == RS_menu_arg(RS_RACE)) {
RACE = k = ROLE_NONE; RACE = k = ROLE_NONE;
nextpick = RS_RACE; 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) { } else if (choice == ROLE_RANDOM) {
k = pick_role(RACE, GEND, ALGN, PICK_RANDOM); k = pick_role(RACE, GEND, ALGN, PICK_RANDOM);
if (k < 0) if (k < 0)
@@ -510,14 +498,9 @@ makepicks:
win = create_nhwindow(NHW_MENU); win = create_nhwindow(NHW_MENU);
start_menu(win); start_menu(win);
any = zeroany; /* zero out all bits */ any = zeroany; /* zero out all bits */
for (i = 0; races[i].noun; i++) { /* populate the menu with role choices */
if (!ok_race(ROLE, i, GEND, ALGN)) setup_racemenu(win, TRUE, ROLE, GEND, ALGN);
continue; /* add miscellaneous menu entries */
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);
}
role_menu_extra(ROLE_RANDOM, win); role_menu_extra(ROLE_RANDOM, win);
any.a_int = 0; /* separator, not a choice */ any.a_int = 0; /* separator, not a choice */
add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "", add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "",
@@ -525,12 +508,14 @@ makepicks:
role_menu_extra(RS_ROLE, win); role_menu_extra(RS_ROLE, win);
role_menu_extra(RS_GENDER, win); role_menu_extra(RS_GENDER, win);
role_menu_extra(RS_ALGNMNT, win); role_menu_extra(RS_ALGNMNT, win);
if (gotrolefilter())
role_menu_extra(RS_filter, win);
role_menu_extra(ROLE_NONE, win); /* quit */ role_menu_extra(ROLE_NONE, win); /* quit */
Strcpy(pbuf, "Pick a race or species"); Strcpy(pbuf, "Pick a race or species");
end_menu(win, pbuf); end_menu(win, pbuf);
n = select_menu(win, PICK_ONE, &selected); n = select_menu(win, PICK_ONE, &selected);
choice = choice = (n == 1) ? selected[0].item.a_int
(n == 1) ? selected[0].item.a_int : ROLE_NONE; : ROLE_NONE;
if (selected) if (selected)
free((genericptr_t) selected), selected = 0; free((genericptr_t) selected), selected = 0;
destroy_nhwindow(win); destroy_nhwindow(win);
@@ -546,6 +531,12 @@ makepicks:
} else if (choice == RS_menu_arg(RS_ROLE)) { } else if (choice == RS_menu_arg(RS_ROLE)) {
ROLE = k = ROLE_NONE; ROLE = k = ROLE_NONE;
nextpick = RS_ROLE; 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) { } else if (choice == ROLE_RANDOM) {
k = pick_race(ROLE, GEND, ALGN, PICK_RANDOM); k = pick_race(ROLE, GEND, ALGN, PICK_RANDOM);
if (k < 0) if (k < 0)
@@ -560,8 +551,8 @@ makepicks:
} /* picking race */ } /* picking race */
if (nextpick == RS_GENDER) { if (nextpick == RS_GENDER) {
nextpick = nextpick = (ROLE < 0) ? RS_ROLE : (RACE < 0) ? RS_RACE
(ROLE < 0) ? RS_ROLE : (RACE < 0) ? RS_RACE : RS_ALGNMNT; : RS_ALGNMNT;
/* Select a gender, if necessary; /* Select a gender, if necessary;
force compatibility with role/race, try for compatibility force compatibility with role/race, try for compatibility
with pre-selected alignment. */ with pre-selected alignment. */
@@ -596,14 +587,9 @@ makepicks:
win = create_nhwindow(NHW_MENU); win = create_nhwindow(NHW_MENU);
start_menu(win); start_menu(win);
any = zeroany; /* zero out all bits */ any = zeroany; /* zero out all bits */
for (i = 0; i < ROLE_GENDERS; i++) { /* populate the menu with gender choices */
if (!ok_gend(ROLE, RACE, i, ALGN)) setup_gendmenu(win, TRUE, ROLE, RACE, ALGN);
continue; /* add miscellaneous menu entries */
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);
}
role_menu_extra(ROLE_RANDOM, win); role_menu_extra(ROLE_RANDOM, win);
any.a_int = 0; /* separator, not a choice */ any.a_int = 0; /* separator, not a choice */
add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "", add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "",
@@ -611,12 +597,14 @@ makepicks:
role_menu_extra(RS_ROLE, win); role_menu_extra(RS_ROLE, win);
role_menu_extra(RS_RACE, win); role_menu_extra(RS_RACE, win);
role_menu_extra(RS_ALGNMNT, win); role_menu_extra(RS_ALGNMNT, win);
if (gotrolefilter())
role_menu_extra(RS_filter, win);
role_menu_extra(ROLE_NONE, win); /* quit */ role_menu_extra(ROLE_NONE, win); /* quit */
Strcpy(pbuf, "Pick a gender or sex"); Strcpy(pbuf, "Pick a gender or sex");
end_menu(win, pbuf); end_menu(win, pbuf);
n = select_menu(win, PICK_ONE, &selected); n = select_menu(win, PICK_ONE, &selected);
choice = choice = (n == 1) ? selected[0].item.a_int
(n == 1) ? selected[0].item.a_int : ROLE_NONE; : ROLE_NONE;
if (selected) if (selected)
free((genericptr_t) selected), selected = 0; free((genericptr_t) selected), selected = 0;
destroy_nhwindow(win); destroy_nhwindow(win);
@@ -632,6 +620,12 @@ makepicks:
} else if (choice == RS_menu_arg(RS_ROLE)) { } else if (choice == RS_menu_arg(RS_ROLE)) {
ROLE = k = ROLE_NONE; ROLE = k = ROLE_NONE;
nextpick = RS_ROLE; 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) { } else if (choice == ROLE_RANDOM) {
k = pick_gend(ROLE, RACE, ALGN, PICK_RANDOM); k = pick_gend(ROLE, RACE, ALGN, PICK_RANDOM);
if (k < 0) if (k < 0)
@@ -646,8 +640,7 @@ makepicks:
} /* picking gender */ } /* picking gender */
if (nextpick == RS_ALGNMNT) { if (nextpick == RS_ALGNMNT) {
nextpick = nextpick = (ROLE < 0) ? RS_ROLE : (RACE < 0) ? RS_RACE : RS_GENDER;
(ROLE < 0) ? RS_ROLE : (RACE < 0) ? RS_RACE : RS_GENDER;
/* Select an alignment, if necessary; /* Select an alignment, if necessary;
force compatibility with role/race/gender. */ force compatibility with role/race/gender. */
if (ALGN < 0 || !validalign(ROLE, RACE, ALGN)) { if (ALGN < 0 || !validalign(ROLE, RACE, ALGN)) {
@@ -681,14 +674,7 @@ makepicks:
win = create_nhwindow(NHW_MENU); win = create_nhwindow(NHW_MENU);
start_menu(win); start_menu(win);
any = zeroany; /* zero out all bits */ any = zeroany; /* zero out all bits */
for (i = 0; i < ROLE_ALIGNS; i++) { setup_algnmenu(win, TRUE, ROLE, RACE, GEND);
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);
}
role_menu_extra(ROLE_RANDOM, win); role_menu_extra(ROLE_RANDOM, win);
any.a_int = 0; /* separator, not a choice */ any.a_int = 0; /* separator, not a choice */
add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "", add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "",
@@ -696,12 +682,14 @@ makepicks:
role_menu_extra(RS_ROLE, win); role_menu_extra(RS_ROLE, win);
role_menu_extra(RS_RACE, win); role_menu_extra(RS_RACE, win);
role_menu_extra(RS_GENDER, win); role_menu_extra(RS_GENDER, win);
if (gotrolefilter())
role_menu_extra(RS_filter, win);
role_menu_extra(ROLE_NONE, win); /* quit */ role_menu_extra(ROLE_NONE, win); /* quit */
Strcpy(pbuf, "Pick an alignment or creed"); Strcpy(pbuf, "Pick an alignment or creed");
end_menu(win, pbuf); end_menu(win, pbuf);
n = select_menu(win, PICK_ONE, &selected); n = select_menu(win, PICK_ONE, &selected);
choice = choice = (n == 1) ? selected[0].item.a_int
(n == 1) ? selected[0].item.a_int : ROLE_NONE; : ROLE_NONE;
if (selected) if (selected)
free((genericptr_t) selected), selected = 0; free((genericptr_t) selected), selected = 0;
destroy_nhwindow(win); destroy_nhwindow(win);
@@ -717,6 +705,12 @@ makepicks:
} else if (choice == RS_menu_arg(RS_ROLE)) { } else if (choice == RS_menu_arg(RS_ROLE)) {
ROLE = k = ROLE_NONE; ROLE = k = ROLE_NONE;
nextpick = RS_ROLE; 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) { } else if (choice == ROLE_RANDOM) {
k = pick_align(ROLE, RACE, GEND, PICK_RANDOM); k = pick_align(ROLE, RACE, GEND, PICK_RANDOM);
if (k < 0) if (k < 0)
@@ -847,11 +841,198 @@ give_up:
return; 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 ROLE
#undef RACE #undef RACE
#undef GEND #undef GEND
#undef ALGN #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 * plname is filled either by an option (-u Player or -uPlayer) or
* explicitly (by being the wizard) or by askname. * explicitly (by being the wizard) or by askname.