Add optional config file sections, selected with CHOOSE

Allows the user to define arbitrarily named optional sections
in the config file, and select which of those sections are used.

For example:

  OPTIONS=color
  CHOOSE=char A,char B

  [char A]
  OPTIONS=role:arc,race:dwa,align:law,gender:fem

  [char B]
  OPTIONS=role:wiz,race:elf,align:cha,gender:mal
This commit is contained in:
Pasi Kallinen
2017-09-02 12:04:27 +03:00
parent a2f886c665
commit bfad877fba
4 changed files with 150 additions and 0 deletions

View File

@@ -2203,6 +2203,12 @@ can be created with any text editor.
Any line in the configuration file starting with `#' is treated as a comment.
Empty lines are ignored.
.pg
Any line beginning with `[' and ending in `]' is considered a section
marker. The text between the square brackets is the section name.
Lines after a section marker belong to that section, and are
ignored unless a CHOOSE -statement was used to select that section.
Section names are case insensitive.
.pg
You can use different configuration statements in the file, some
of which can be used multiple times. In general, the statements are
written in capital letters, followed by an equals sign, followed by
@@ -2267,6 +2273,19 @@ Example:
.sd
\fBBIND=^X:getpos.autodescribe\fP
.ed
.lp CHOOSE
Chooses at random one of the comma-separated parameters as an active
section name. Lines in other sections are ignored.
.pg
Example:
.sd
\fBOPTIONS=color\fP
\fBCHOOSE=char A,char B\fP
\fB[char A]\fP
\fBOPTIONS=role:arc,race:dwa,align:law,gender:fem\fP
\fB[char B]\fP
\fBOPTIONS=role:wiz,race:elf,align:cha,gender:mal\fP
.ed
.lp MSGTYPE
Change the way messages are shown in the top status line.
See the ``Configuring Message Types`` section.

View File

@@ -2688,6 +2688,13 @@ can be created with any text editor.
Any line in the configuration file starting with `{\tt \#}' is treated as a comment.
Empty lines are ignored.
%.pg
Any line beginning with `{\tt [}' and ending in `{\tt ]}' is considered a section
marker. The text between the square brackets is the section name.
Lines after a section marker belong to that section, and are
ignored unless a CHOOSE -statement was used to select that section.
Section names are case insensitive.
%.pg
You can use different configuration statements in the file, some
of which can be used multiple times. In general, the statements are
@@ -2776,6 +2783,24 @@ Example:
\end{verbatim}
%.ed
%.lp
\item[\bb{CHOOSE}]
Chooses at random one of the comma-separated parameters as an active
section name. Lines in other sections are ignored.
%.pg
Example:
%.sd
\begin{verbatim}
OPTIONS=color
CHOOSE=char A,char B
[char A]
OPTIONS=role:arc,race:dwa,align:law,gender:fem
[char B]
OPTIONS=role:wiz,race:elf,align:cha,gender:mal
\end{verbatim}
%.ed
%.lp
\item[\bb{MSGTYPE}]
Change the way messages are shown in the top status line.

View File

@@ -627,6 +627,7 @@ blinded hero or monster who breathes vapor from broken potion of healing,
potion: full == always; extra == if not-cursed; plain == if blessed)
sysconf definition BONES_POOLS to allow more bones files per level
blessed scroll of fire lets you choose explosion location like stinking cloud
optional sections in the config file, selected with CHOOSE
Platform- and/or Interface-Specific New Features

View File

@@ -198,6 +198,10 @@ STATIC_DCL void FDECL(set_symhandling, (char *, int));
#ifdef NOCWD_ASSUMPTIONS
STATIC_DCL void FDECL(adjust_prefix, (char *, int));
#endif
STATIC_DCL void NDECL(free_config_sections);
STATIC_DCL char *FDECL(choose_random_part, (char *, char));
STATIC_DCL boolean FDECL(is_config_section, (const char *));
STATIC_DCL boolean FDECL(handle_config_section, (char *));
#ifdef SELF_RECOVER
STATIC_DCL boolean FDECL(copy_bytes, (int, int));
#endif
@@ -205,6 +209,10 @@ STATIC_DCL boolean FDECL(copy_bytes, (int, int));
STATIC_DCL int FDECL(open_levelfile_exclusively, (const char *, int, int));
#endif
static char *config_section_chosen = (char *) 0;
static char *config_section_current = (char *) 0;
/*
* fname_encode()
*
@@ -2130,6 +2138,91 @@ int prefixid;
}
#endif
/* Choose at random one of the sep separated parts from str. Mangles str. */
STATIC_OVL char *
choose_random_part(str,sep)
char *str;
char sep;
{
int nsep = 1;
int csep;
int len = 0;
char *begin = str;
if (!str)
return (char *) 0;
while (*str) {
if (*str == sep) nsep++;
str++;
}
csep = rn2(nsep);
str = begin;
while ((csep > 0) && *str) {
str++;
if (*str == sep) csep--;
}
if (*str) {
if (*str == sep) str++;
begin = str;
while (*str && *str != sep) {
str++;
len++;
}
*str = '\0';
if (len)
return begin;
}
return (char *) 0;
}
STATIC_OVL void
free_config_sections()
{
if (config_section_chosen) {
free(config_section_chosen);
config_section_chosen = NULL;
}
if (config_section_current) {
free(config_section_current);
config_section_current = NULL;
}
}
STATIC_OVL boolean
is_config_section(str)
const char *str;
{
const char *a = rindex(str, ']');
return (a && *str == '[' && *(a+1) == '\0' && (int)(a - str) > 0);
}
STATIC_OVL boolean
handle_config_section(buf)
char *buf;
{
if (is_config_section(buf)) {
char *send;
if (config_section_current) {
free(config_section_current);
}
config_section_current = dupstr(&buf[1]);
send = rindex(config_section_current, ']');
*send = '\0';
debugpline1("set config section: '%s'", config_section_current);
return TRUE;
}
if (config_section_current) {
if (!config_section_chosen)
return TRUE;
if (strcmp(config_section_current, config_section_chosen))
return TRUE;
}
return FALSE;
}
#define match_varname(INP, NAM, LEN) match_optname(INP, NAM, LEN, TRUE)
int
@@ -2156,6 +2249,9 @@ int src;
if (!*buf || *buf == '#' || !strcmp(buf, " "))
return 1;
if (src != SET_IN_SYS && handle_config_section(buf))
return 1;
/* find the '=' or ':' */
bufp = index(buf, '=');
altp = index(buf, ':');
@@ -2183,6 +2279,13 @@ int src;
++bufp; /* skip '='; parseoptions() handles spaces */
parseoptions(bufp, TRUE, TRUE);
} else if (match_varname(buf, "CHOOSE", 6)) {
char *section;
if (config_section_chosen)
free(config_section_chosen);
section = choose_random_part(bufp, ',');
if (section)
config_section_chosen = dupstr(section);
} else if (match_varname(buf, "AUTOPICKUP_EXCEPTION", 5)) {
add_autopickup_exception(bufp);
} else if (match_varname(buf, "BINDINGS", 4)) {
@@ -2642,6 +2745,7 @@ int src;
/* begin detection of duplicate configfile options */
set_duplicate_opt_detection(1);
free_config_sections();
while (fgets(buf, sizeof buf, fp)) {
#ifdef notyet
@@ -2665,6 +2769,7 @@ OR: Forbid multiline stuff for alternate config sources.
}
(void) fclose(fp);
free_config_sections();
/* turn off detection of duplicate configfile options */
set_duplicate_opt_detection(0);
return rv;