home *** CD-ROM | disk | FTP | other *** search
- /* SCCS Id: @(#)options.c 3.1 92/11/14 */
- /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
- /* NetHack may be freely redistributed. See license for details. */
-
- #include "hack.h"
- #include "termcap.h"
- #include <ctype.h>
-
- /*
- * NOTE: If you add (or delete) an option, please update the short
- * options help (option_help()), the long options help (dat/opthelp),
- * and the current options setting display function (doset()).
- */
-
- #if defined(TOS) && defined(TEXTCOLOR)
- extern boolean colors_changed; /* in tos.c */
- #endif
-
- extern const char *roles[]; /* from u_init.c */
- extern char inv_order[]; /* from invent.c */
-
- static boolean initial, from_file;
- static boolean NEARDATA set_order;
-
- static void FDECL(nmcpy, (char *, const char *, int));
- static void FDECL(escapes, (const char *, char *));
- static void FDECL(rejectoption, (const char *));
- static void FDECL(badoption, (const char *));
- static char *FDECL(string_for_env_opt, (const char *, char *));
- static int FDECL(change_inv_order, (char *, int));
- static void FDECL(oc_to_str, (char *, char *));
-
- static struct Bool_Opt
- {
- const char *name;
- boolean *addr, initvalue;
- } boolopt[] = {
- #if defined(MICRO) && !defined(AMIGA)
- {"BIOS", &flags.BIOS, FALSE},
- #endif
- #ifdef INSURANCE
- {"checkpoint", &flags.ins_chkpt, TRUE},
- #endif
- #ifdef TEXTCOLOR
- # ifdef MICRO
- {"color", &flags.use_color, TRUE},
- # else /* systems that support multiple terminals, many monochrome */
- {"color", &flags.use_color, FALSE},
- # endif
- #endif
- {"confirm",&flags.confirm, TRUE},
- #ifdef TERMLIB
- {"DECgraphics", &flags.DECgraphics, FALSE},
- #endif
- {"disclose", &flags.end_disclose, TRUE},
- {"female", &flags.female, FALSE},
- {"fixinv", &flags.invlet_constant, TRUE},
- #ifdef AMIFLUSH
- {"flush", &flags.amiflush, FALSE},
- #endif
- {"help", &flags.help, TRUE},
- #ifdef TEXTCOLOR
- {"hilite_pet", &flags.hilite_pet, FALSE},
- #endif
- #ifdef ASCIIGRAPH
- {"IBMgraphics", &flags.IBMgraphics, FALSE},
- #endif
- {"ignintr", &flags.ignintr, FALSE},
- #ifdef MAC_GRAPHICS_ENV
- {"large_font", &flags.large_font, FALSE},
- #endif
- {"legacy",&flags.legacy, TRUE},
- {"lit_corridor", &flags.lit_corridor, FALSE},
- #ifdef MAC_GRAPHICS_ENV
- {"MACgraphics", &flags.MACgraphics, TRUE},
- #endif
- #ifdef NEWS
- {"news", &flags.news, TRUE},
- #endif
- {"null", &flags.null, TRUE},
- {"number_pad", &flags.num_pad, FALSE},
- {"pickup", &flags.pickup, TRUE},
- #ifdef MAC
- {"popup_dialog", &flags.popup_dialog, FALSE},
- #endif
- #if defined(MICRO) && !defined(AMIGA)
- {"rawio", &flags.rawio, FALSE},
- #endif
- {"rest_on_space", &flags.rest_on_space, FALSE},
- {"safepet", &flags.safe_dog, TRUE},
- #ifdef EXP_ON_BOTL
- {"showexp", &flags.showexp, FALSE},
- #endif
- #ifdef SCORE_ON_BOTL
- {"showscore", &flags.showscore, FALSE},
- #endif
- {"silent", &flags.silent, TRUE},
- {"sortpack", &flags.sortpack, TRUE},
- {"sound", &flags.soundok, TRUE},
- {"standout", &flags.standout, FALSE},
- {"time", &flags.time, FALSE},
- {"tombstone",&flags.tombstone, TRUE},
- {"verbose", &flags.verbose, TRUE},
- {NULL, (boolean *)0, FALSE}
- };
-
- static boolean need_redraw; /* for doset() */
-
- void
- initoptions()
- {
- register char *opts;
- int i;
-
- for (i = 0; boolopt[i].name; i++) {
- if (boolopt[i].addr)
- *(boolopt[i].addr) = boolopt[i].initvalue;
- }
- flags.end_own = FALSE;
- flags.end_top = 3;
- flags.end_around = 2;
- flags.msg_history = 20;
-
- /* Set the default monster and object class symbols. Don't use */
- /* memcpy() --- sizeof char != sizeof uchar on some machines. */
- for (i = 0; i < MAXOCLASSES; i++)
- oc_syms[i] = (uchar) def_oc_syms[i];
- for (i = 0; i < MAXMCLASSES; i++)
- monsyms[i] = (uchar) def_monsyms[i];
-
- switch_graphics(ASCII_GRAPHICS); /* set default characters */
- #ifdef UNIX
- /*
- * Set defaults for some options depending on what we can
- * detect about the environment's capabilities.
- * This has to be done after the global initialization above
- * and before reading user-specific initialization via
- * config file/environment variable below.
- */
- /* this detects the IBM-compatible console on most 386 boxes */
- if (!strncmp(getenv("TERM"), "AT", 2)) {
- switch_graphics(IBM_GRAPHICS);
- # ifdef TEXTCOLOR
- flags.use_color = TRUE;
- # endif
- }
- #endif /* UNIX */
- #if defined(UNIX) || defined(VMS)
- /* detect whether a "vt" terminal can handle alternate charsets */
- if (!strncmpi(getenv("TERM"), "vt", 2) && (AS && AE) &&
- !strcmp(AS, "\016") && !strcmp(AE, "\017")) {
- switch_graphics(DEC_GRAPHICS);
- }
- #endif /* UNIX || VMS */
-
- #ifdef MAC_GRAPHICS_ENV
- switch_graphics(MAC_GRAPHICS);
- #endif /* MAC_GRAPHICS_ENV */
-
- #ifdef TUTTI_FRUTTI
- /* since this is done before init_objects(), do partial init here */
- objects[SLIME_MOLD].oc_name_idx = SLIME_MOLD;
- nmcpy(pl_fruit, OBJ_NAME(objects[SLIME_MOLD]), PL_FSIZ);
- #endif
- opts = getenv("NETHACKOPTIONS");
- if (!opts) opts = getenv("HACKOPTIONS");
- if (opts)
- if (*opts == '/' || *opts == '\\' || *opts == '@') {
- if (*opts == '@') opts++; /* @filename */
- /* looks like a filename */
- read_config_file(opts);
- } else {
- read_config_file(NULL);
- parseoptions(opts, TRUE, FALSE);
- }
- else
- read_config_file(NULL);
- #ifdef AMIGA
- ami_wbench_init(); /* must be here or can't set fruit */
- #endif
- #ifdef TUTTI_FRUTTI
- (void)fruitadd(pl_fruit);
- /* Remove "slime mold" from list of object names; this will */
- /* prevent it from being wished unless it's actually present */
- /* as a named (or default) fruit. Wishing for "fruit" will */
- /* result in the player's preferred fruit [better than "\033"]. */
- obj_descr[SLIME_MOLD].oc_name = "fruit";
- #endif
- if(flags.female) { /* should have been set in NETHACKOPTIONS */
- roles[2] = "Cavewoman";
- roles[6] = "Priestess";
- }
- }
-
- static void
- nmcpy(dest, src, maxlen)
- char *dest;
- const char *src;
- int maxlen;
- {
- int count;
-
- for(count = 1; count < maxlen; count++) {
- if(*src == ',' || *src == '\0') break; /*exit on \0 terminator*/
- *dest++ = *src++;
- }
- *dest = 0;
- }
-
- /*
- * escapes: escape expansion for showsyms. C-style escapes understood include
- * \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal). The ^-prefix
- * for control characters is also understood, and \[mM] followed by any of the
- * previous forms or by a character has the effect of 'meta'-ing the value (so
- * that the alternate character set will be enabled).
- */
- static void
- escapes(cp, tp)
- const char *cp;
- char *tp;
- {
- while (*cp)
- {
- int cval = 0, meta = 0;
-
- if (*cp == '\\' && index("mM", cp[1])) {
- meta = 1;
- cp += 2;
- }
- if (*cp == '\\' && index("0123456789xXoO", cp[1]))
- {
- const char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
- int dcount = 0;
-
- cp++;
- if (*cp == 'x' || *cp == 'X')
- for (++cp; (dp = index(hex, *cp)) && (dcount++ < 2); cp++)
- cval = (cval * 16) + (dp - hex) / 2;
- else if (*cp == 'o' || *cp == 'O')
- for (++cp; (index("01234567",*cp)) && (dcount++ < 3); cp++)
- cval = (cval * 8) + (*cp - '0');
- else
- for (; (index("0123456789",*cp)) && (dcount++ < 3); cp++)
- cval = (cval * 10) + (*cp - '0');
- }
- else if (*cp == '\\') /* C-style character escapes */
- {
- switch (*++cp)
- {
- case '\\': cval = '\\'; break;
- case 'n': cval = '\n'; break;
- case 't': cval = '\t'; break;
- case 'b': cval = '\b'; break;
- case 'r': cval = '\r'; break;
- default: cval = *cp;
- }
- cp++;
- }
- else if (*cp == '^') /* expand control-character syntax */
- {
- cval = (*++cp & 0x1f);
- cp++;
- }
- else
- cval = *cp++;
- if (meta)
- cval |= 0x80;
- *tp++ = cval;
- }
- *tp = '\0';
- }
-
- static void
- rejectoption(optname)
- const char *optname;
- {
- #ifdef MICRO
- # ifdef AMIGA
- if(FromWBench){
- pline("\"%s\" settable only from %s or in icon.",
- optname, configfile);
- } else
- # endif
- pline("\"%s\" settable only from %s.", optname, configfile);
- #else
- pline("%s can be set only from NETHACKOPTIONS or %s.", optname,
- configfile);
- #endif
- }
-
- static void
- badoption(opts)
- const char *opts;
- {
- if(!initial) {
- if(!strncmp(opts, "h", 1) || !strncmp(opts, "?", 1))
- option_help();
- else
- pline("Unknown option: %s. Enter \"?g\" for help.", opts);
- return;
- }
- # ifdef AMIGA
- if(ami_wbench_badopt(opts)) {
- # endif
- if(from_file)
- raw_printf("Bad syntax in OPTIONS in %s: %s.", configfile, opts);
- else
- raw_printf("Bad syntax in NETHACKOPTIONS: %s.", opts);
- # ifdef AMIGA
- }
- # endif
- wait_synch();
- }
-
- static char *
- string_for_env_opt(optname, opts)
- const char *optname;
- char *opts;
- {
- register char *colon;
-
- if(!initial) {
- rejectoption(optname);
- return NULL;
- }
- colon = index(opts,':');
- if(!colon) {
- badoption(opts);
- return NULL;
- }
- return ++colon;
- }
-
- /*
- * Change the inventory order, using the given string as the new order.
- * Missing characters in the new order are filled in at the end from
- * the current inv_order.
- *
- * This routine always returns 1 unless the parameter 'fail' is true
- * and there is a duplicate or bad char in the string.
- */
- static int
- change_inv_order(op, fail)
- char *op;
- int fail; /* If TRUE, return 0 if any duplicates or bad chars. */
- {
- int oc_sym, num;
- char *sp, *tmp, buf[BUFSZ];
-
- for (sp = op; *sp; sp++) {
- oc_sym = def_char_to_objclass(*sp);
-
- /* Remove bad or duplicate entries. */
- if (oc_sym == MAXOCLASSES ||
- (!index(inv_order, oc_sym)) || (index(sp+1, *sp))) {
-
- if (fail) return 0;
- for(tmp = sp; *tmp; tmp++)
- tmp[0] = tmp[1];
- sp--;
- } else
- *sp = (char) oc_sym;
- }
- Strcpy(buf, op);
- for (sp = inv_order, num = strlen(buf); *sp; sp++)
- if (!index(buf, *sp))
- buf[num++] = *sp;
-
- buf[num] = 0;
- Strcpy(inv_order, buf);
- return 1;
- }
-
- void
- parseoptions(opts, tinitial, tfrom_file)
- register char *opts;
- boolean tinitial, tfrom_file;
- {
- register char *op;
- unsigned num;
- boolean negated;
- int i;
-
- initial = tinitial;
- from_file = tfrom_file;
- if ((op = index(opts, ',')) != 0) {
- *op++ = 0;
- parseoptions(op, initial, from_file);
- }
-
- /* strip leading and trailing white space */
- while (isspace(*opts)) opts++;
- op = eos(opts);
- while (--op >= opts && isspace(*op)) *op = '\0';
-
- if(!*opts) return;
- negated = FALSE;
- while((*opts == '!') || !strncmpi(opts, "no", 2)) {
- if(*opts == '!') opts++; else opts += 2;
- negated = !negated;
- }
-
- #if defined(MICRO) && !defined(AMIGA)
- /* included for compatibility with old NetHack.cnf files */
- if (!strncmp(opts, "IBM_", 4)) {
- flags.BIOS = !negated;
- return;
- }
-
- /* put here cause it has to come from the config file */
- if (!strncmpi(opts, "raw", 3)) {
- if (initial)
- flags.rawio = !negated;
- else
- rejectoption("rawio");
- return;
- }
- #endif /* MICRO */
-
- #if defined(TOS) && defined(TEXTCOLOR)
- if (!strncmpi(opts, "col", 3)) {
- flags.use_color = !negated;
- if (flags.BIOS && !initial) {
- if (colors_changed)
- restore_colors();
- else
- set_colors();
- }
- }
- #endif
- /* other special-case boolean options */
- #ifdef TERMLIB
- if (!strncmpi(opts, "DEC", 3)) {
- #ifdef REINCARNATION
- if (!initial && Is_rogue_level(&u.uz))
- assign_rogue_graphics(FALSE);
- #endif
- flags.DECgraphics = !negated;
- need_redraw = TRUE;
- switch_graphics(flags.DECgraphics ?
- DEC_GRAPHICS : ASCII_GRAPHICS);
- #ifdef REINCARNATION
- if (!initial && Is_rogue_level(&u.uz))
- assign_rogue_graphics(TRUE);
- #endif
- return;
- }
- #endif /* TERMLIB */
- #ifdef ASCIIGRAPH
- if (!strncmpi(opts, "IBMg", 4)) {
- #ifdef REINCARNATION
- if (!initial && Is_rogue_level(&u.uz))
- assign_rogue_graphics(FALSE);
- #endif
- flags.IBMgraphics = !negated;
- need_redraw = TRUE;
- switch_graphics(flags.IBMgraphics ?
- IBM_GRAPHICS : ASCII_GRAPHICS);
- #ifdef REINCARNATION
- if (!initial && Is_rogue_level(&u.uz))
- assign_rogue_graphics(TRUE);
- #endif
- return;
- }
- #endif /* ASCIIGRAPH */
- #ifdef MAC_GRAPHICS_ENV
- if (!strncmpi(opts, "MACg", 4)) {
- #ifdef REINCARNATION
- if (!initial && Is_rogue_level(&u.uz))
- assign_rogue_graphics(FALSE);
- #endif
- flags.MACgraphics = !negated;
- need_redraw = TRUE;
- switch_graphics(flags.MACgraphics ?
- MAC_GRAPHICS : ASCII_GRAPHICS);
- #ifdef REINCARNATION
- if (!initial && Is_rogue_level(&u.uz))
- assign_rogue_graphics(TRUE);
- #endif
- return;
- }
- #endif /* MAC_GRAPHICS_ENV */
-
- /* common boolean options */
-
- if (!strncmpi(opts, "fem", 3)) {
- if(!initial && flags.female == negated)
- pline("That is not anatomically possible.");
- else
- flags.female = !negated;
- return;
- }
-
- if (!strncmpi(opts, "fix", 3)) {
- flags.invlet_constant = !negated;
- if (!initial && flags.invlet_constant) reassign();
- return;
- }
-
- if (!strncmpi(opts, "male", 4)) {
- if(!initial && flags.female != negated)
- pline("That is not anatomically possible.");
- else
- flags.female = negated;
- return;
- }
-
- if (!strncmpi(opts, "num", 3)) {
- flags.num_pad = !negated;
- if (!initial) number_pad(flags.num_pad ? 1 : 0);
- return;
- }
- #ifdef EXP_ON_BOTL
- if (!strncmpi(opts, "showexp", 7)) {
- flags.showexp = !negated;
- flags.botl = 1;
- return;
- }
- #endif
- #ifdef SCORE_ON_BOTL
- if (!strncmpi(opts, "showscore", 9)) {
- flags.showscore = !negated;
- flags.botl = 1;
- return;
- }
- #endif
- if (!strncmpi(opts, "time", 4)) {
- flags.time = !negated;
- flags.botl = 1;
- return;
- }
-
- if (!strncmpi(opts, "legacy", 6)) {
- if(!initial) rejectoption("legacy");
- else flags.legacy = !negated;
- return;
- }
-
- /* compound options */
-
- if (!strncmpi(opts, "pet", 3)) {
- if ((op = string_for_env_opt("pettype", opts)) != 0)
- switch (*op) {
- case 'd': /* dog */
- case 'D':
- preferred_pet = 'd';
- break;
- case 'c': /* cat */
- case 'C':
- case 'f': /* feline */
- case 'F':
- preferred_pet = 'c';
- break;
- default:
- pline("Unrecognized pettype '%s'", op);
- break;
- }
- return;
- }
-
- if (!strncmpi(opts, "cat", 3)) {
- if ((op = string_for_env_opt("catname", opts)) != 0)
- nmcpy(catname, op, 62);
- return;
- }
-
- if (!strncmpi(opts, "dog", 3)) {
- if ((op = string_for_env_opt("dogname", opts)) != 0)
- nmcpy(dogname, op, 62);
- return;
- }
-
- if (!strncmpi(opts, "msg", 3)) {
- if ((op = string_for_env_opt("msghistory", opts)) != 0) {
- flags.msg_history = atoi(op);
- }
- return;
- }
- #ifdef TUTTI_FRUTTI
- if (!strncmpi(opts, "fr", 2)) {
- op = index(opts, ':');
- if (!op) {
- badoption(opts);
- return;
- }
- op++;
- if (!initial) {
- struct fruit *f;
- int numfruits = 0;
-
- for(f=ffruit; f; f=f->nextf) {
- if (!strcmp(op, f->fname)) goto goodfruit;
- numfruits++;
- }
- if (numfruits >= 100) {
- pline("Doing that so many times isn't very fruitful.");
- return;
- }
- }
- goodfruit:
- nmcpy(pl_fruit, op, PL_FSIZ);
- if (!*pl_fruit)
- nmcpy(pl_fruit, OBJ_NAME(objects[SLIME_MOLD]), PL_FSIZ);
- if (!initial)
- (void)fruitadd(pl_fruit);
- /* If initial, then initoptions is allowed to do it instead
- * of here (initoptions always has to do it even if there's
- * no fruit option at all. Also, we don't want people
- * setting multiple fruits in their options.)
- */
- return;
- }
- #endif
- /* graphics:string */
- if (!strncmpi(opts, "gr", 2)) {
- uchar translate[MAXPCHARS+1];
- int lth;
-
- if (!(opts = string_for_env_opt("graphics", opts)))
- return;
- escapes(opts, opts);
-
- lth = strlen(opts);
- if (lth > MAXPCHARS) lth = MAXPCHARS;
- /* match the form obtained from PC configuration files */
- for (i = 0; i < lth; i++)
- translate[i] = (uchar) opts[i];
- assign_graphics(translate, lth);
- return;
- }
-
- /* objects:string */
- if (!strncmpi(opts, "objects", 7)) {
- int k, length;
-
- if (!(opts = string_for_env_opt("objects", opts)))
- return;
- escapes(opts, opts);
-
- /*
- * Override the default object class symbols. The first
- * object in the object class is the "random object". I
- * don't want to use 0 as an object class, so the "random
- * object" is basically a place holder.
- *
- * The object class symbols have already been initialized in
- * initoptions().
- */
- length = strlen(opts);
- if (length >= MAXOCLASSES)
- length = MAXOCLASSES-1; /* don't count RANDOM_OBJECT */
-
- for (k = 0; k < length; k++)
- oc_syms[k+1] = (uchar) opts[k];
- return;
- }
-
- /* monsters:string */
- if (!strncmpi(opts, "monsters", 8)) {
- int k, length;
-
- if (!(opts = string_for_env_opt("monsters", opts)))
- return;
- escapes(opts, opts);
-
- /* Override default mon class symbols set in initoptions(). */
- length = strlen(opts);
- if (length >= MAXMCLASSES)
- length = MAXMCLASSES-1; /* mon class 0 unused */
-
- for (k = 0; k < length; k++)
- monsyms[k+1] = (uchar) opts[k];
- return;
- }
-
- /* name:string */
- if (!strncmpi(opts, "name", 4)) {
- if ((op = string_for_env_opt("name", opts)) != 0)
- nmcpy(plname, op, (int)sizeof(plname)-1);
- return;
- }
-
- /* the order to list the pack */
- if (!strncmpi(opts, "pack", 4)) {
- op = index(opts,':');
- if(!op) {
- badoption(opts);
- return;
- }
- op++; /* skip : */
-
- if (!change_inv_order(op, 1))
- set_order = TRUE;
- else
- badoption(opts);
- return;
- }
-
- /* scores:5t[op] 5a[round] o[wn] */
- if (!strncmpi(opts, "scores", 6)) {
- op = index(opts,':');
- if(!op) {
- badoption(opts);
- return;
- }
- op++;
- while(*op) {
- num = 1;
- if(digit(*op)) {
- num = atoi(op);
- while(digit(*op)) op++;
- } else if(*op == '!') {
- negated = !negated;
- op++;
- }
- while(*op == ' ') op++;
-
- switch(*op) {
- case 't':
- case 'T':
- flags.end_top = num;
- break;
- case 'a':
- case 'A':
- flags.end_around = num;
- break;
- case 'o':
- case 'O':
- flags.end_own = !negated;
- break;
- default:
- badoption(opts);
- return;
- }
- while(letter(*++op) || *op == ' ') ;
- if(*op == '/') op++;
- }
- return;
- }
- if (!strncmpi(opts, "win", 3)) {
- if ((op = string_for_env_opt("windowtype", opts)) != 0) {
- char buf[16];
- nmcpy(buf, op, 15);
- choose_windows(buf);
- }
- return;
- }
-
- /* OK, if we still haven't recognized the option, check the boolean
- * options list
- */
- for (i = 0; boolopt[i].name; i++) {
- if (boolopt[i].addr && !strncmpi(boolopt[i].name, opts, 3)) {
- *(boolopt[i].addr) = !negated;
- #ifdef TEXTCOLOR
- if((boolopt[i].addr) == &flags.use_color)
- need_redraw = TRUE;
-
- if((boolopt[i].addr) == &flags.hilite_pet)
- need_redraw = TRUE;
- #endif
- if (!initial && boolopt[i].addr==&flags.lit_corridor) {
- /*
- * All corridor squares seen via night vision or
- * candles & lamps change. Update them by calling
- * newsym() on them. Don't do this if we are
- * initializing the options --- the vision system
- * isn't set up yet.
- */
- vision_recalc(2); /* shut down vision */
- vision_full_recalc = 1; /* delayed recalc */
- }
- return;
- }
- }
-
- /* out of valid options */
- badoption(opts);
- }
-
- /*
- * Convert the given string of object classes to a string of default object
- * symbols.
- */
- static void
- oc_to_str(src,dest)
- char *src, *dest;
- {
- int i;
-
- while ((i = (int) *src++) != 0) {
- if (i < 0 || i >= MAXOCLASSES)
- impossible("oc_to_str: illegal object class %d", i);
- else
- *dest++ = def_oc_syms[i];
- }
- *dest = '\0';
- }
-
- #ifdef MICRO
- # define OPTIONS_HEADING "OPTIONS"
- #else
- # define OPTIONS_HEADING "NETHACKOPTIONS"
- #endif
-
- int
- doset()
- {
- char buf[BUFSZ], pack_order[MAXOCLASSES+1], on_off;
- const char *opt_name;
- int i;
- winid tmpwin;
-
- switch (yn_function("Show the current settings [c], or set options [s]?",
- "csq", 'q')) {
- default:
- case 'q':
- clear_nhwindow(WIN_MESSAGE);
- return 0;
- case 'c':
- tmpwin = create_nhwindow(NHW_MENU);
- putstr(tmpwin, 0, OPTIONS_HEADING);
- putstr(tmpwin, 0, "");
- /* print the booleans */
- for (i = 0; boolopt[i].name; i++) {
- if (!boolopt[i].addr) continue;
- opt_name = boolopt[i].name;
- if (*(boolopt[i].addr)) {
- on_off = ' '; /* on */
- } else {
- if (!strcmp(opt_name, "female"))
- opt_name = "male", on_off = ' ';
- else
- on_off = '!'; /* off */
- }
- Sprintf(buf, "%c%s", on_off, opt_name);
- putstr(tmpwin, 0, buf);
- }
- /* print the compounds */
- Sprintf(buf, " catname: %s",
- (catname[0] != 0) ? catname : "(null)");
- putstr(tmpwin, 0, buf);
- Sprintf(buf, " dogname: %s",
- (dogname[0] != 0) ? dogname : "(null)");
- putstr(tmpwin, 0, buf);
- #ifdef TUTTI_FRUTTI
- Sprintf(buf, " fruit: %s", pl_fruit);
- putstr(tmpwin, 0, buf);
- #endif
- Sprintf(buf, " msghistory: %u", flags.msg_history);
- putstr(tmpwin, 0, buf);
- Sprintf(buf, " name: %s", plname);
- putstr(tmpwin, 0, buf);
- oc_to_str(inv_order, pack_order);
- Sprintf(buf, " packorder: %s", pack_order);
- putstr(tmpwin, 0, buf);
- Sprintf(buf, " pettype: %s", preferred_pet == 'c' ? "cat" :
- preferred_pet == 'd' ? "dog" : "random");
- putstr(tmpwin, 0, buf);
- Sprintf(buf, " scores: %utop/%uaround%s",
- flags.end_top, flags.end_around,
- (flags.end_own ? "/own" : ""));
- putstr(tmpwin, 0, buf);
- Sprintf(buf, " windowtype: %s", windowprocs.name);
- putstr(tmpwin, 0, buf);
- display_nhwindow(tmpwin, TRUE);
- destroy_nhwindow(tmpwin);
- break;
- case 's':
- clear_nhwindow(WIN_MESSAGE);
- getlin("What options do you want to set?", buf);
- clear_nhwindow(WIN_MESSAGE);
- if(buf[0] == '\033') return 0;
- need_redraw = FALSE;
- parseoptions(buf, FALSE, FALSE);
- if(need_redraw)
- (void) doredraw();
- break;
- }
-
- return 0;
- }
-
- int
- dotogglepickup() {
- flags.pickup = !flags.pickup;
- pline("Pickup: %s.", flags.pickup ? "ON" : "OFF");
- return 0;
- }
-
- /* data for option_help() */
- static const char *opt_intro[] = {
- "",
- " NetHack Options Help:",
- "",
- #define CONFIG_SLOT 3 /* fill in next value at run-time */
- NULL,
- #ifndef MICRO
- "or use `NETHACKOPTIONS=\"<options>\"' in your environment;",
- # ifdef VMS
- "-- for example, $ DEFINE NETHACKOPTIONS \"nopickup,fruit:kumquat\"",
- # endif
- #endif
- "or press \"O\" while playing, and type your <options> at the prompt.",
- "In either case, <options> is a list of options separated by commas.",
- "",
- "Boolean options (which can be negated by prefixing them with '!' or \"no\"):",
- NULL
- };
- static const char *opt_compound[] = {
- "Compound options:",
- "`catname' - the name of your (first) cat (e.g., catname:Tabby),",
- "`dogname' - the name of your (first) dog (e.g., dogname:Fang),",
- #ifdef TUTTI_FRUTTI
- "`fruit' - the name of a fruit you enjoy eating,",
- # define FRUIT_OFFSET 1
- #else
- # define FRUIT_OFFSET 0
- #endif
- "`graphics' - defines the symbols to use in drawing the dungeon map,",
- "`monsters' - defines the symbols to use for monsters,",
- "`msghistory'- number of top line messages to save,",
- "`name' - your character's name (e.g., name:Merlin-W),",
- "`objects' - defines the symbols to use for objects,",
- "`packorder' - the inventory order of the items in your pack",
- #define PCKORD_SLOT 9+FRUIT_OFFSET
- NULL,
- "`pettype' - your preferred initial pet type,",
- "`scores' - the parts of the score list you wish to see,",
- "`windowtype'- windowing system to use.",
- "",
- "Some of the options can be set only before the game is started. You will",
- "be so informed, if you attempt to set them while in the game.",
- NULL
- };
-
- void
- option_help()
- {
- char buf[BUFSZ], pack_order[MAXOCLASSES+1];
- register int i;
- winid datawin;
-
- datawin = create_nhwindow(NHW_TEXT);
- #ifdef AMIGA
- if(FromWBench){
- Sprintf(buf,"Set options as OPTIONS= in %s or in icon;",configfile);
- } else
- #endif
- Sprintf(buf, "Set options as OPTIONS=<options> in %s;", configfile);
- opt_intro[CONFIG_SLOT] = (const char *) buf;
- for (i = 0; opt_intro[i]; i++)
- putstr(datawin, 0, opt_intro[i]);
-
- /* Boolean options */
- for (i = 0; boolopt[i].name; i++) {
- if (boolopt[i].addr)
- next_opt(datawin, boolopt[i].name);
- }
- next_opt(datawin, "");
-
- /* Compound options */
- oc_to_str(inv_order, pack_order);
- Sprintf(buf, " (currently, packorder:%s ),", pack_order);
- #if 0
- assert( opt_compound[PCKORD_SLOT] == NULL );
- #endif
- opt_compound[PCKORD_SLOT] = (const char *) buf;
- for (i = 0; opt_compound[i]; i++)
- putstr(datawin, 0, opt_compound[i]);
-
- display_nhwindow(datawin, FALSE);
- destroy_nhwindow(datawin);
- return;
- }
-
- /*
- * prints the next boolean option, on the same line if possible, on a new
- * line if not. End with next_opt("").
- */
- void
- next_opt(datawin, str)
- winid datawin;
- const char *str;
- {
- static char buf[121];
- int i;
- char *s;
-
- if (!*str) {
- for (s = buf; *s; s++); /* find end of string */
- if (s > &buf[1] && s[-2] == ',')
- s[-2] = 0; /* strip last ", " */
- i = 121;
- }
- else
- i = strlen(buf) + strlen(str) + 2;
-
- if (i > COLNO - 2) { /* rule of thumb */
- putstr(datawin, 0, buf);
- buf[0] = 0;
- }
- if (*str) {
- Strcat(buf, str);
- Strcat(buf, ", ");
- }
- else
- putstr(datawin, 0, str);
- return;
- }
-
- #ifdef TUTTI_FRUTTI
- /* Returns the fid of the fruit type; if that type already exists, it
- * returns the fid of that one; if it does not exist, it adds a new fruit
- * type to the chain and returns the new one.
- */
- int
- fruitadd(str)
- char *str;
- {
- register int i,j;
- register struct fruit *f;
- #ifdef GCC_WARN
- struct fruit *lastf = (struct fruit *)0;
- #else
- struct fruit *lastf;
- #endif
- int highest_fruit_id = 0;
- char buf[PL_FSIZ];
- boolean user_specified = (str == pl_fruit);
- /* if not user-specified, then it's a fruit name for a fruit on
- * a bones level...
- */
-
- /* Note: every fruit has an id (spe for fruit objects) of at least
- * 1; 0 is an error.
- */
- if (user_specified) {
- /* disallow naming after other foods (since it'd be impossible
- * to tell the difference)
- */
-
- boolean found = FALSE;
-
- for(i = bases[j=letindex(FOOD_CLASS)]; i < bases[j+1]; i++) {
- if (!strcmp(OBJ_NAME(objects[i]), pl_fruit)) {
- found = TRUE;
- break;
- }
- }
- if (found ||
- (!strncmp(str, "tin of ", 7) && name_to_mon(str+7) > -1) ||
- !strcmp(str, "empty tin") ||
- !strcmp(str, "tin of spinach") ||
- ((!strncmp(eos(str)-6," corpse",7) ||
- !strncmp(eos(str)-3, " egg",4))
- && name_to_mon(str) > -1))
- {
- Strcpy(buf, pl_fruit);
- Strcpy(pl_fruit, "candied ");
- nmcpy(pl_fruit+8, buf, PL_FSIZ-8);
- }
- }
- for(f=ffruit; f; f = f->nextf) {
- lastf = f;
- if(f->fid > highest_fruit_id) highest_fruit_id = f->fid;
- if(!strncmp(str, f->fname, PL_FSIZ))
- goto nonew;
- }
- /* if adding another fruit would overflow spe, use a random
- fruit instead... we've got a lot to choose from. */
- if (highest_fruit_id >= 127) return rnd(127);
- highest_fruit_id++;
- f = newfruit();
- if (ffruit) lastf->nextf = f;
- else ffruit = f;
- Strcpy(f->fname, str);
- f->fid = highest_fruit_id;
- f->nextf = 0;
- nonew:
- if (user_specified) current_fruit = highest_fruit_id;
- return f->fid;
- }
- #endif
-
- /*options.c*/
-