Source:NetHack 3.6.0/src/options.c

From NetHackWiki
(Redirected from Source:Options.c)
Jump to: navigation, search

Below is the full text to options.c from the source code of NetHack 3.6.0. To link to a particular line, write [[Source:NetHack 3.6.0/src/options.c#line123]], for example.

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

Contents

Top of file

  1.  /* NetHack 3.6	options.c	$NHDT-Date: 1448241657 2015/11/23 01:20:57 $  $NHDT-Branch: master $:$NHDT-Revision: 1.243 $ */
  2.  /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5.  #ifdef OPTION_LISTS_ONLY /* (AMIGA) external program for opt lists */
  6.  #include "config.h"
  7.  #include "objclass.h"
  8.  #include "flag.h"
  9.  NEARDATA struct flag flags; /* provide linkage */
  10.  #ifdef SYSFLAGS
  11.  NEARDATA struct sysflag sysflags; /* provide linkage */
  12.  #endif
  13.  NEARDATA struct instance_flags iflags; /* provide linkage */
  14.  #define static
  15.  #else
  16.  #include "hack.h"
  17.  #include "tcap.h"
  18.  #include <ctype.h>
  19.  #endif
  20.  
  21.  #define BACKWARD_COMPAT
  22.  #define WINTYPELEN 16
  23.  
  24.  #ifdef DEFAULT_WC_TILED_MAP
  25.  #define PREFER_TILED TRUE
  26.  #else
  27.  #define PREFER_TILED FALSE
  28.  #endif
  29.  
  30.  #define MESSAGE_OPTION 1
  31.  #define STATUS_OPTION 2
  32.  #define MAP_OPTION 3
  33.  #define MENU_OPTION 4
  34.  #define TEXT_OPTION 5
  35.  
  36.  #define PILE_LIMIT_DFLT 5
  37.  

Boolean options

  1.  /*
  2.   *  NOTE:  If you add (or delete) an option, please update the short
  3.   *  options help (option_help()), the long options help (dat/opthelp),
  4.   *  and the current options setting display function (doset()),
  5.   *  and also the Guidebooks.
  6.   *
  7.   *  The order matters.  If an option is a an initial substring of another
  8.   *  option (e.g. time and timed_delay) the shorter one must come first.
  9.   */
  10.  
  11.  static struct Bool_Opt {
  12.      const char *name;
  13.      boolean *addr, initvalue;
  14.      int optflags;
  15.  } boolopt[] = {
  16.      { "acoustics", &flags.acoustics, TRUE, SET_IN_GAME },
  17.  #if defined(SYSFLAGS) && defined(AMIGA)
  18.      /* Amiga altmeta causes Alt+key to be converted into Meta+key by
  19.         low level nethack code; on by default, can be toggled off if
  20.         Alt+key is needed for some ASCII chars on non-ASCII keyboard */
  21.      { "altmeta", &sysflags.altmeta, TRUE, DISP_IN_GAME },
  22.  #else
  23.  #ifdef ALTMETA
  24.      /* non-Amiga altmeta causes nethack's top level command loop to treat
  25.         two character sequence "ESC c" as M-c, for terminals or emulators
  26.         which send "ESC c" when Alt+c is pressed; off by default, enabling
  27.         this can potentially make trouble if user types ESC when nethack
  28.         is honoring this conversion request (primarily after starting a
  29.         count prefix prior to a command and then deciding to cancel it) */
  30.      { "altmeta", &iflags.altmeta, FALSE, SET_IN_GAME },
  31.  #else
  32.      { "altmeta", (boolean *) 0, TRUE, DISP_IN_GAME },
  33.  #endif
  34.  #endif
  35.      { "ascii_map", &iflags.wc_ascii_map, !PREFER_TILED, SET_IN_GAME }, /*WC*/
  36.  #if defined(SYSFLAGS) && defined(MFLOPPY)
  37.      { "asksavedisk", &sysflags.asksavedisk, FALSE, SET_IN_GAME },
  38.  #else
  39.      { "asksavedisk", (boolean *) 0, FALSE, SET_IN_FILE },
  40.  #endif
  41.      { "autodig", &flags.autodig, FALSE, SET_IN_GAME },
  42.      { "autoopen", &flags.autoopen, TRUE, SET_IN_GAME },
  43.      { "autopickup", &flags.pickup, TRUE, SET_IN_GAME },
  44.      { "autoquiver", &flags.autoquiver, FALSE, SET_IN_GAME },
  45.  #if defined(MICRO) && !defined(AMIGA)
  46.      { "BIOS", &iflags.BIOS, FALSE, SET_IN_FILE },
  47.  #else
  48.      { "BIOS", (boolean *) 0, FALSE, SET_IN_FILE },
  49.  #endif
  50.      { "blind", &u.uroleplay.blind, FALSE, DISP_IN_GAME },
  51.      { "bones", &flags.bones, TRUE, SET_IN_FILE },
  52.  #ifdef INSURANCE
  53.      { "checkpoint", &flags.ins_chkpt, TRUE, SET_IN_GAME },
  54.  #else
  55.      { "checkpoint", (boolean *) 0, FALSE, SET_IN_FILE },
  56.  #endif
  57.  #ifdef MFLOPPY
  58.      { "checkspace", &iflags.checkspace, TRUE, SET_IN_GAME },
  59.  #else
  60.      { "checkspace", (boolean *) 0, FALSE, SET_IN_FILE },
  61.  #endif
  62.      { "clicklook", &iflags.clicklook, FALSE, SET_IN_GAME },
  63.      { "cmdassist", &iflags.cmdassist, TRUE, SET_IN_GAME },
  64.  #if defined(MICRO) || defined(WIN32)
  65.      { "color", &iflags.wc_color, TRUE, SET_IN_GAME }, /*WC*/
  66.  #else /* systems that support multiple terminals, many monochrome */
  67.      { "color", &iflags.wc_color, FALSE, SET_IN_GAME }, /*WC*/
  68.  #endif
  69.      { "confirm", &flags.confirm, TRUE, SET_IN_GAME },
  70.      { "dark_room", &flags.dark_room, TRUE, SET_IN_GAME },
  71.      { "eight_bit_tty", &iflags.wc_eight_bit_input, FALSE,
  72.        SET_IN_GAME }, /*WC*/
  73.  #ifdef TTY_GRAPHICS
  74.      { "extmenu", &iflags.extmenu, FALSE, SET_IN_GAME },
  75.  #else
  76.      { "extmenu", (boolean *) 0, FALSE, SET_IN_FILE },
  77.  #endif
  78.  #ifdef OPT_DISPMAP
  79.      { "fast_map", &flags.fast_map, TRUE, SET_IN_GAME },
  80.  #else
  81.      { "fast_map", (boolean *) 0, TRUE, SET_IN_FILE },
  82.  #endif
  83.      { "female", &flags.female, FALSE, DISP_IN_GAME },
  84.      { "fixinv", &flags.invlet_constant, TRUE, SET_IN_GAME },
  85.  #if defined(SYSFLAGS) && defined(AMIFLUSH)
  86.      { "flush", &sysflags.amiflush, FALSE, SET_IN_GAME },
  87.  #else
  88.      { "flush", (boolean *) 0, FALSE, SET_IN_FILE },
  89.  #endif
  90.      { "fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE },
  91.      { "help", &flags.help, TRUE, SET_IN_GAME },
  92.      { "hilite_pet", &iflags.wc_hilite_pet, FALSE, SET_IN_GAME }, /*WC*/
  93.      { "hilite_pile", &iflags.hilite_pile, FALSE, SET_IN_GAME },
  94.  #ifndef MAC
  95.      { "ignintr", &flags.ignintr, FALSE, SET_IN_GAME },
  96.  #else
  97.      { "ignintr", (boolean *) 0, FALSE, SET_IN_FILE },
  98.  #endif
  99.      { "implicit_uncursed", &iflags.implicit_uncursed, TRUE, SET_IN_GAME },
  100.      { "large_font", &iflags.obsolete, FALSE, SET_IN_FILE }, /* OBSOLETE */
  101.      { "legacy", &flags.legacy, TRUE, DISP_IN_GAME },
  102.      { "lit_corridor", &flags.lit_corridor, FALSE, SET_IN_GAME },
  103.      { "lootabc", &flags.lootabc, FALSE, SET_IN_GAME },
  104.  #ifdef MAIL
  105.      { "mail", &flags.biff, TRUE, SET_IN_GAME },
  106.  #else
  107.      { "mail", (boolean *) 0, TRUE, SET_IN_FILE },
  108.  #endif
  109.      { "mention_walls", &iflags.mention_walls, FALSE, SET_IN_GAME },
  110.      { "menucolors", &iflags.use_menu_color, FALSE, SET_IN_GAME },
  111.      /* for menu debugging only*/
  112.      { "menu_tab_sep", &iflags.menu_tab_sep, FALSE, SET_IN_GAME },
  113.      { "menu_objsyms", &iflags.menu_head_objsym, FALSE, SET_IN_GAME },
  114.      { "mouse_support", &iflags.wc_mouse_support, TRUE, DISP_IN_GAME }, /*WC*/
  115.  #ifdef NEWS
  116.      { "news", &iflags.news, TRUE, DISP_IN_GAME },
  117.  #else
  118.      { "news", (boolean *) 0, FALSE, SET_IN_FILE },
  119.  #endif
  120.      { "nudist", &u.uroleplay.nudist, FALSE, DISP_IN_GAME },
  121.      { "null", &flags.null, TRUE, SET_IN_GAME },
  122.  #if defined(SYSFLAGS) && defined(MAC)
  123.      { "page_wait", &sysflags.page_wait, TRUE, SET_IN_GAME },
  124.  #else
  125.      { "page_wait", (boolean *) 0, FALSE, SET_IN_FILE },
  126.  #endif
  127.      { "perm_invent", &flags.perm_invent, FALSE, SET_IN_GAME },
  128.      { "pickup_thrown", &flags.pickup_thrown, TRUE, SET_IN_GAME },
  129.      { "popup_dialog", &iflags.wc_popup_dialog, FALSE, SET_IN_GAME },   /*WC*/
  130.      { "preload_tiles", &iflags.wc_preload_tiles, TRUE, DISP_IN_GAME }, /*WC*/
  131.      { "pushweapon", &flags.pushweapon, FALSE, SET_IN_GAME },
  132.  #if defined(MICRO) && !defined(AMIGA)
  133.      { "rawio", &iflags.rawio, FALSE, DISP_IN_GAME },
  134.  #else
  135.      { "rawio", (boolean *) 0, FALSE, SET_IN_FILE },
  136.  #endif
  137.      { "rest_on_space", &flags.rest_on_space, FALSE, SET_IN_GAME },
  138.  #ifdef RLECOMP
  139.      { "rlecomp", &iflags.rlecomp,
  140.  #if defined(COMPRESS) || defined(ZLIB_COMP)
  141.        FALSE,
  142.  #else
  143.        TRUE,
  144.  #endif
  145.        DISP_IN_GAME },
  146.  #endif
  147.      { "safe_pet", &flags.safe_dog, TRUE, SET_IN_GAME },
  148.      { "sanity_check", &iflags.sanity_check, FALSE, SET_IN_GAME },
  149.      { "selectsaved", &iflags.wc2_selectsaved, TRUE, DISP_IN_GAME }, /*WC*/
  150.      { "showexp", &flags.showexp, FALSE, SET_IN_GAME },
  151.      { "showrace", &flags.showrace, FALSE, SET_IN_GAME },
  152.  #ifdef SCORE_ON_BOTL
  153.      { "showscore", &flags.showscore, FALSE, SET_IN_GAME },
  154.  #else
  155.      { "showscore", (boolean *) 0, FALSE, SET_IN_FILE },
  156.  #endif
  157.      { "silent", &flags.silent, TRUE, SET_IN_GAME },
  158.      { "softkeyboard", &iflags.wc2_softkeyboard, FALSE, SET_IN_FILE },
  159.      { "sortpack", &flags.sortpack, TRUE, SET_IN_GAME },
  160.      { "sparkle", &flags.sparkle, TRUE, SET_IN_GAME },
  161.      { "splash_screen", &iflags.wc_splash_screen, TRUE, DISP_IN_GAME }, /*WC*/
  162.      { "standout", &flags.standout, FALSE, SET_IN_GAME },
  163.  #if defined(STATUS_VIA_WINDOWPORT) && defined(STATUS_HILITES)
  164.      { "statushilites", &iflags.use_status_hilites, TRUE, SET_IN_GAME },
  165.  #else
  166.      { "statushilites", &iflags.use_status_hilites, FALSE, DISP_IN_GAME },
  167.  #endif
  168.      { "tiled_map", &iflags.wc_tiled_map, PREFER_TILED, DISP_IN_GAME }, /*WC*/
  169.      { "time", &flags.time, FALSE, SET_IN_GAME },
  170.  #ifdef TIMED_DELAY
  171.      { "timed_delay", &flags.nap, TRUE, SET_IN_GAME },
  172.  #else
  173.      { "timed_delay", (boolean *) 0, FALSE, SET_IN_GAME },
  174.  #endif
  175.      { "tombstone", &flags.tombstone, TRUE, SET_IN_GAME },
  176.      { "toptenwin", &iflags.toptenwin, FALSE, SET_IN_GAME },
  177.      { "travel", &flags.travelcmd, TRUE, SET_IN_GAME },
  178.      { "use_darkgray", &iflags.wc2_darkgray, TRUE, SET_IN_FILE },
  179.  #ifdef WIN32
  180.      { "use_inverse", &iflags.wc_inverse, TRUE, SET_IN_GAME }, /*WC*/
  181.  #else
  182.      { "use_inverse", &iflags.wc_inverse, FALSE, SET_IN_GAME }, /*WC*/
  183.  #endif
  184.      { "verbose", &flags.verbose, TRUE, SET_IN_GAME },
  185.      { "wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME },
  186.  #ifdef ZEROCOMP
  187.      { "zerocomp", &iflags.zerocomp,
  188.  #if defined(COMPRESS) || defined(ZLIB_COMP)
  189.        FALSE,
  190.  #else
  191.        TRUE,
  192.  #endif
  193.        DISP_IN_GAME },
  194.  #endif
  195.      { (char *) 0, (boolean *) 0, FALSE, 0 }
  196.  };
  197.  

Compound options

  1.  /* compound options, for option_help() and external programs like Amiga
  2.   * frontend */
  3.  static struct Comp_Opt {
  4.      const char *name, *descr;
  5.      int size; /* for frontends and such allocating space --
  6.                 * usually allowed size of data in game, but
  7.                 * occasionally maximum reasonable size for
  8.                 * typing when game maintains information in
  9.                 * a different format */
  10.      int optflags;
  11.  } compopt[] = {
  12.      { "align", "your starting alignment (lawful, neutral, or chaotic)", 8,
  13.        DISP_IN_GAME },
  14.      { "align_message", "message window alignment", 20, DISP_IN_GAME }, /*WC*/
  15.      { "align_status", "status window alignment", 20, DISP_IN_GAME },   /*WC*/
  16.      { "altkeyhandler", "alternate key handler", 20, DISP_IN_GAME },
  17.  #ifdef BACKWARD_COMPAT
  18.      { "boulder", "deprecated (use S_boulder in sym file instead)", 1,
  19.        SET_IN_FILE },
  20.  #endif
  21.      { "catname", "the name of your (first) cat (e.g., catname:Tabby)",
  22.        PL_PSIZ, DISP_IN_GAME },
  23.      { "disclose", "the kinds of information to disclose at end of game",
  24.        sizeof(flags.end_disclose) * 2, SET_IN_GAME },
  25.      { "dogname", "the name of your (first) dog (e.g., dogname:Fang)", PL_PSIZ,
  26.        DISP_IN_GAME },
  27.      { "dungeon", "the symbols to use in drawing the dungeon map",
  28.        MAXDCHARS + 1, SET_IN_FILE },
  29.      { "effects", "the symbols to use in drawing special effects",
  30.        MAXECHARS + 1, SET_IN_FILE },
  31.      { "font_map", "the font to use in the map window", 40,
  32.        DISP_IN_GAME },                                              /*WC*/
  33.      { "font_menu", "the font to use in menus", 40, DISP_IN_GAME }, /*WC*/
  34.      { "font_message", "the font to use in the message window", 40,
  35.        DISP_IN_GAME },                                                  /*WC*/
  36.      { "font_size_map", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/
  37.      { "font_size_menu", "the size of the menu font", 20,
  38.        DISP_IN_GAME }, /*WC*/
  39.      { "font_size_message", "the size of the message font", 20,
  40.        DISP_IN_GAME }, /*WC*/
  41.      { "font_size_status", "the size of the status font", 20,
  42.        DISP_IN_GAME }, /*WC*/
  43.      { "font_size_text", "the size of the text font", 20,
  44.        DISP_IN_GAME }, /*WC*/
  45.      { "font_status", "the font to use in status window", 40,
  46.        DISP_IN_GAME }, /*WC*/
  47.      { "font_text", "the font to use in text windows", 40,
  48.        DISP_IN_GAME }, /*WC*/
  49.      { "fruit", "the name of a fruit you enjoy eating", PL_FSIZ, SET_IN_GAME },
  50.      { "gender", "your starting gender (male or female)", 8, DISP_IN_GAME },
  51.      { "horsename", "the name of your (first) horse (e.g., horsename:Silver)",
  52.        PL_PSIZ, DISP_IN_GAME },
  53.      { "map_mode", "map display mode under Windows", 20, DISP_IN_GAME }, /*WC*/
  54.      { "menustyle", "user interface for object selection", MENUTYPELEN,
  55.        SET_IN_GAME },
  56.      { "menu_deselect_all", "deselect all items in a menu", 4, SET_IN_FILE },
  57.      { "menu_deselect_page", "deselect all items on this page of a menu", 4,
  58.        SET_IN_FILE },
  59.      { "menu_first_page", "jump to the first page in a menu", 4, SET_IN_FILE },
  60.      { "menu_headings", "text attribute for menu headings", 9, SET_IN_GAME },
  61.      { "menu_invert_all", "invert all items in a menu", 4, SET_IN_FILE },
  62.      { "menu_invert_page", "invert all items on this page of a menu", 4,
  63.        SET_IN_FILE },
  64.      { "menu_last_page", "jump to the last page in a menu", 4, SET_IN_FILE },
  65.      { "menu_next_page", "goto the next menu page", 4, SET_IN_FILE },
  66.      { "menu_previous_page", "goto the previous menu page", 4, SET_IN_FILE },
  67.      { "menu_search", "search for a menu item", 4, SET_IN_FILE },
  68.      { "menu_select_all", "select all items in a menu", 4, SET_IN_FILE },
  69.      { "menu_select_page", "select all items on this page of a menu", 4,
  70.        SET_IN_FILE },
  71.      { "monsters", "the symbols to use for monsters", MAXMCLASSES,
  72.        SET_IN_FILE },
  73.      { "msghistory", "number of top line messages to save", 5, DISP_IN_GAME },
  74.  #ifdef TTY_GRAPHICS
  75.      { "msg_window", "the type of message window required", 1, SET_IN_GAME },
  76.  #else
  77.      { "msg_window", "the type of message window required", 1, SET_IN_FILE },
  78.  #endif
  79.      { "name", "your character's name (e.g., name:Merlin-W)", PL_NSIZ,
  80.        DISP_IN_GAME },
  81.      { "number_pad", "use the number pad for movement", 1, SET_IN_GAME },
  82.      { "objects", "the symbols to use for objects", MAXOCLASSES, SET_IN_FILE },
  83.      { "packorder", "the inventory order of the items in your pack",
  84.        MAXOCLASSES, SET_IN_GAME },
  85.  #ifdef CHANGE_COLOR
  86.      { "palette",
  87.  #ifndef WIN32
  88.        "palette (00c/880/-fff is blue/yellow/reverse white)", 15,
  89.        SET_IN_GAME },
  90.  #else
  91.        "palette (adjust an RGB color in palette (color-R-G-B)", 15,
  92.        SET_IN_FILE },
  93.  #endif
  94.  #if defined(MAC)
  95.      { "hicolor", "same as palette, only order is reversed", 15, SET_IN_FILE },
  96.  #endif
  97.  #endif
  98.      { "paranoid_confirmation", "extra prompting in certain situations", 28,
  99.        SET_IN_GAME },
  100.      { "pettype", "your preferred initial pet type", 4, DISP_IN_GAME },
  101.      { "pickup_burden", "maximum burden picked up before prompt", 20,
  102.        SET_IN_GAME },
  103.      { "pickup_types", "types of objects to pick up automatically",
  104.        MAXOCLASSES, SET_IN_GAME },
  105.      { "pile_limit", "threshold for \"there are many objects here\"", 24,
  106.        SET_IN_GAME },
  107.      { "playmode", "normal play, non-scoring explore mode, or debug mode", 8,
  108.        DISP_IN_GAME },
  109.      { "player_selection", "choose character via dialog or prompts", 12,
  110.        DISP_IN_GAME },
  111.      { "race", "your starting race (e.g., Human, Elf)", PL_CSIZ,
  112.        DISP_IN_GAME },
  113.      { "role", "your starting role (e.g., Barbarian, Valkyrie)", PL_CSIZ,
  114.        DISP_IN_GAME },
  115.      { "runmode", "display frequency when `running' or `travelling'",
  116.        sizeof "teleport", SET_IN_GAME },
  117.      { "scores", "the parts of the score list you wish to see", 32,
  118.        SET_IN_GAME },
  119.      { "scroll_amount", "amount to scroll map when scroll_margin is reached",
  120.        20, DISP_IN_GAME }, /*WC*/
  121.      { "scroll_margin", "scroll map when this far from the edge", 20,
  122.        DISP_IN_GAME }, /*WC*/
  123.      { "sortloot", "sort object selection lists by description", 4,
  124.        SET_IN_GAME },
  125.  #ifdef MSDOS
  126.      { "soundcard", "type of sound card to use", 20, SET_IN_FILE },
  127.  #endif
  128.      { "symset", "load a set of display symbols from the symbols file", 70,
  129.        SET_IN_GAME },
  130.      { "roguesymset",
  131.        "load a set of rogue display symbols from the symbols file", 70,
  132.        SET_IN_GAME },
  133.      { "suppress_alert", "suppress alerts about version-specific features", 8,
  134.        SET_IN_GAME },
  135.      { "tile_width", "width of tiles", 20, DISP_IN_GAME },   /*WC*/
  136.      { "tile_height", "height of tiles", 20, DISP_IN_GAME }, /*WC*/
  137.      { "tile_file", "name of tile file", 70, DISP_IN_GAME }, /*WC*/
  138.      { "traps", "the symbols to use in drawing traps", MAXTCHARS + 1,
  139.        SET_IN_FILE },
  140.      { "vary_msgcount", "show more old messages at a time", 20,
  141.        DISP_IN_GAME }, /*WC*/
  142.  #ifdef MSDOS
  143.      { "video", "method of video updating", 20, SET_IN_FILE },
  144.  #endif
  145.  #ifdef VIDEOSHADES
  146.      { "videocolors", "color mappings for internal screen routines", 40,
  147.        DISP_IN_GAME },
  148.      { "videoshades", "gray shades to map to black/gray/white", 32,
  149.        DISP_IN_GAME },
  150.  #endif
  151.  #ifdef WIN32
  152.      { "subkeyvalue", "override keystroke value", 7, SET_IN_FILE },
  153.  #endif
  154.      { "windowcolors", "the foreground/background colors of windows", /*WC*/
  155.        80, DISP_IN_GAME },
  156.      { "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME },
  157.  #ifdef WINCHAIN
  158.      { "windowchain", "window processor to use", WINTYPELEN, SET_IN_SYS },
  159.  #endif
  160.  #ifdef BACKWARD_COMPAT
  161.      { "DECgraphics", "load DECGraphics display symbols", 70, SET_IN_FILE },
  162.      { "IBMgraphics", "load IBMGraphics display symbols", 70, SET_IN_FILE },
  163.  #ifdef MAC_GRAPHICS_ENV
  164.      { "Macgraphics", "load MACGraphics display symbols", 70, SET_IN_FILE },
  165.  #endif
  166.  #endif
  167.      { (char *) 0, (char *) 0, 0, 0 }
  168.  };
  169.  

Options system handling

  1.  #ifdef OPTION_LISTS_ONLY
  2.  #undef static
  3.  
  4.  #else /* use rest of file */
  5.  
  6.  extern struct symparse loadsyms[];
  7.  static boolean need_redraw; /* for doset() */
  8.  
  9.  #if defined(TOS) && defined(TEXTCOLOR)
  10.  extern boolean colors_changed;  /* in tos.c */
  11.  #endif
  12.  
  13.  #ifdef VIDEOSHADES
  14.  extern char *shade[3];          /* in sys/msdos/video.c */
  15.  extern char ttycolors[CLR_MAX]; /* in sys/msdos/video.c */
  16.  #endif
  17.  
  18.  static char def_inv_order[MAXOCLASSES] = {
  19.      COIN_CLASS, AMULET_CLASS, WEAPON_CLASS, ARMOR_CLASS, FOOD_CLASS,
  20.      SCROLL_CLASS, SPBOOK_CLASS, POTION_CLASS, RING_CLASS, WAND_CLASS,
  21.      TOOL_CLASS, GEM_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, 0,
  22.  };
  23.  
  24.  /*
  25.   * Default menu manipulation command accelerators.  These may _not_ be:
  26.   *
  27.   *      + a number - reserved for counts
  28.   *      + an upper or lower case US ASCII letter - used for accelerators
  29.   *      + ESC - reserved for escaping the menu
  30.   *      + NULL, CR or LF - reserved for commiting the selection(s).  NULL
  31.   *        is kind of odd, but the tty's xwaitforspace() will return it if
  32.   *        someone hits a <ret>.
  33.   *      + a default object class symbol - used for object class accelerators
  34.   *
  35.   * Standard letters (for now) are:
  36.   *
  37.   *              <  back 1 page
  38.   *              >  forward 1 page
  39.   *              ^  first page
  40.   *              |  last page
  41.   *              :  search
  42.   *
  43.   *              page            all
  44.   *               ,    select     .
  45.   *               \    deselect   -
  46.   *               ~    invert     @
  47.   *
  48.   * The command name list is duplicated in the compopt array.
  49.   */
  50.  typedef struct {
  51.      const char *name;
  52.      char cmd;
  53.  } menu_cmd_t;
  54.  
  55.  #define NUM_MENU_CMDS 11
  56.  static const menu_cmd_t default_menu_cmd_info[NUM_MENU_CMDS] = {
  57.  /* 0*/  { "menu_first_page", MENU_FIRST_PAGE },
  58.          { "menu_last_page", MENU_LAST_PAGE },
  59.          { "menu_next_page", MENU_NEXT_PAGE },
  60.          { "menu_previous_page", MENU_PREVIOUS_PAGE },
  61.          { "menu_select_all", MENU_SELECT_ALL },
  62.  /* 5*/  { "menu_deselect_all", MENU_UNSELECT_ALL },
  63.          { "menu_invert_all", MENU_INVERT_ALL },
  64.          { "menu_select_page", MENU_SELECT_PAGE },
  65.          { "menu_deselect_page", MENU_UNSELECT_PAGE },
  66.          { "menu_invert_page", MENU_INVERT_PAGE },
  67.  /*10*/  { "menu_search", MENU_SEARCH },
  68.  };
  69.  
  70.  /*
  71.   * Allow the user to map incoming characters to various menu commands.
  72.   * The accelerator list must be a valid C string.
  73.   */
  74.  #define MAX_MENU_MAPPED_CMDS 32 /* some number */
  75.  char mapped_menu_cmds[MAX_MENU_MAPPED_CMDS + 1]; /* exported */
  76.  static char mapped_menu_op[MAX_MENU_MAPPED_CMDS + 1];
  77.  static short n_menu_mapped = 0;
  78.  
  79.  static boolean initial, from_file;
  80.  
  81.  STATIC_DCL void FDECL(doset_add_menu, (winid, const char *, int));
  82.  STATIC_DCL void FDECL(nmcpy, (char *, const char *, int));
  83.  STATIC_DCL void FDECL(escapes, (const char *, char *));
  84.  STATIC_DCL void FDECL(rejectoption, (const char *));
  85.  STATIC_DCL void FDECL(badoption, (const char *));
  86.  STATIC_DCL char *FDECL(string_for_opt, (char *, BOOLEAN_P));
  87.  STATIC_DCL char *FDECL(string_for_env_opt, (const char *, char *, BOOLEAN_P));
  88.  STATIC_DCL void FDECL(bad_negation, (const char *, BOOLEAN_P));
  89.  STATIC_DCL int FDECL(change_inv_order, (char *));
  90.  STATIC_DCL void FDECL(oc_to_str, (char *, char *));
  91.  STATIC_DCL int FDECL(feature_alert_opts, (char *, const char *));
  92.  STATIC_DCL const char *FDECL(get_compopt_value, (const char *, char *));
  93.  STATIC_DCL boolean FDECL(special_handling, (const char *,
  94.                                              BOOLEAN_P, BOOLEAN_P));
  95.  STATIC_DCL void FDECL(warning_opts, (char *, const char *));
  96.  STATIC_DCL boolean FDECL(duplicate_opt_detection, (const char *, int));
  97.  STATIC_DCL void FDECL(complain_about_duplicate, (const char *, int));
  98.  
  99.  STATIC_OVL void FDECL(wc_set_font_name, (int, char *));
  100.  STATIC_OVL int FDECL(wc_set_window_colors, (char *));
  101.  STATIC_OVL boolean FDECL(is_wc_option, (const char *));
  102.  STATIC_OVL boolean FDECL(wc_supported, (const char *));
  103.  STATIC_OVL boolean FDECL(is_wc2_option, (const char *));
  104.  STATIC_OVL boolean FDECL(wc2_supported, (const char *));
  105.  STATIC_DCL void FDECL(remove_autopickup_exception,
  106.                        (struct autopickup_exception *));
  107.  STATIC_OVL int FDECL(count_ape_maps, (int *, int *));
  108.  STATIC_DCL const char *FDECL(attr2attrname, (int));
  109.  STATIC_DCL int NDECL(query_color);
  110.  STATIC_DCL int NDECL(query_msgtype);
  111.  STATIC_DCL int FDECL(query_attr, (const char *));
  112.  STATIC_DCL const char * FDECL(msgtype2name, (int));
  113.  STATIC_DCL boolean FDECL(msgtype_add, (int, char *));
  114.  STATIC_DCL void FDECL(free_one_msgtype, (int));
  115.  STATIC_DCL int NDECL(msgtype_count);
  116.  STATIC_DCL boolean FDECL(add_menu_coloring_parsed, (char *, int, int));
  117.  STATIC_DCL void FDECL(free_one_menu_coloring, (int));
  118.  STATIC_DCL int NDECL(count_menucolors);
  119.  STATIC_DCL int FDECL(handle_add_list_remove, (const char *, int));
  120.  

reglyph_darkroom

  1.  void
  2.  reglyph_darkroom()
  3.  {
  4.      xchar x, y;
  5.  
  6.      for (x = 0; x < COLNO; x++)
  7.          for (y = 0; y < ROWNO; y++) {
  8.              struct rm *lev = &levl[x][y];
  9.  
  10.              if (!flags.dark_room || !iflags.use_color
  11.                  || Is_rogue_level(&u.uz)) {
  12.                  if (lev->glyph == cmap_to_glyph(S_darkroom))
  13.                      lev->glyph = lev->waslit ? cmap_to_glyph(S_room)
  14.                                               : cmap_to_glyph(S_stone);
  15.              } else {
  16.                  if (lev->glyph == cmap_to_glyph(S_room) && lev->seenv
  17.                      && lev->waslit && !cansee(x, y))
  18.                      lev->glyph = cmap_to_glyph(S_darkroom);
  19.                  else if (lev->glyph == cmap_to_glyph(S_stone)
  20.                           && lev->typ == ROOM && lev->seenv && !cansee(x, y))
  21.                      lev->glyph = cmap_to_glyph(S_darkroom);
  22.              }
  23.          }
  24.      if (flags.dark_room && iflags.use_color)
  25.          showsyms[S_darkroom] = showsyms[S_room];
  26.      else
  27.          showsyms[S_darkroom] = showsyms[S_stone];
  28.  }
  29.  

match_optname

  1.  /* check whether a user-supplied option string is a proper leading
  2.     substring of a particular option name; option string might have
  3.     a colon or equals sign and arbitrary value appended to it */
  4.  boolean
  5.  match_optname(user_string, opt_name, min_length, val_allowed)
  6.  const char *user_string, *opt_name;
  7.  int min_length;
  8.  boolean val_allowed;
  9.  {
  10.      int len = (int) strlen(user_string);
  11.  
  12.      if (val_allowed) {
  13.          const char *p = index(user_string, ':'),
  14.                     *q = index(user_string, '=');
  15.  
  16.          if (!p || (q && q < p))
  17.              p = q;
  18.          while (p && p > user_string && isspace((uchar) * (p - 1)))
  19.              p--;
  20.          if (p)
  21.              len = (int) (p - user_string);
  22.      }
  23.  
  24.      return (boolean) (len >= min_length
  25.                        && !strncmpi(opt_name, user_string, len));
  26.  }
  27.  

nh_getenv

  1.  /* most environment variables will eventually be printed in an error
  2.   * message if they don't work, and most error message paths go through
  3.   * BUFSZ buffers, which could be overflowed by a maliciously long
  4.   * environment variable.  If a variable can legitimately be long, or
  5.   * if it's put in a smaller buffer, the responsible code will have to
  6.   * bounds-check itself.
  7.   */
  8.  char *
  9.  nh_getenv(ev)
  10.  const char *ev;
  11.  {
  12.      char *getev = getenv(ev);
  13.  
  14.      if (getev && strlen(getev) <= (BUFSZ / 2))
  15.          return getev;
  16.      else
  17.          return (char *) 0;
  18.  }
  19.  

initoptions

  1.  /* process options, possibly including SYSCF */
  2.  void
  3.  initoptions()
  4.  {
  5.      initoptions_init();
  6.  #ifdef SYSCF
  7.  /* someday there may be other SYSCF alternatives besides text file */
  8.  #ifdef SYSCF_FILE
  9.      /* If SYSCF_FILE is specified, it _must_ exist... */
  10.      assure_syscf_file();
  11.      /* ... and _must_ parse correctly. */
  12.      if (!read_config_file(SYSCF_FILE, SET_IN_SYS)) {
  13.          raw_printf("Error(s) found in SYSCF_FILE, quitting.");
  14.          terminate(EXIT_FAILURE);
  15.      }
  16.      /*
  17.       * TODO [maybe]: parse the sysopt entries which are space-separated
  18.       * lists of usernames into arrays with one name per element.
  19.       */
  20.  #endif
  21.  #endif
  22.      initoptions_finish();
  23.  }
  24.  

initoptions_init

  1.  void
  2.  initoptions_init()
  3.  {
  4.  #if defined(UNIX) || defined(VMS)
  5.      char *opts;
  6.  #endif
  7.      int i;
  8.  
  9.      /* set up the command parsing */
  10.      reset_commands(TRUE); /* init */
  11.  
  12.      /* initialize the random number generator */
  13.      setrandom();
  14.  
  15.      /* for detection of configfile options specified multiple times */
  16.      iflags.opt_booldup = iflags.opt_compdup = (int *) 0;
  17.  
  18.      for (i = 0; boolopt[i].name; i++) {
  19.          if (boolopt[i].addr)
  20.              *(boolopt[i].addr) = boolopt[i].initvalue;
  21.      }
  22.  #if defined(COMPRESS) || defined(ZLIB_COMP)
  23.      set_savepref("externalcomp");
  24.      set_restpref("externalcomp");
  25.  #ifdef RLECOMP
  26.      set_savepref("!rlecomp");
  27.      set_restpref("!rlecomp");
  28.  #endif
  29.  #else
  30.  #ifdef ZEROCOMP
  31.      set_savepref("zerocomp");
  32.      set_restpref("zerocomp");
  33.  #endif
  34.  #ifdef RLECOMP
  35.      set_savepref("rlecomp");
  36.      set_restpref("rlecomp");
  37.  #endif
  38.  #endif
  39.  #ifdef SYSFLAGS
  40.      Strcpy(sysflags.sysflagsid, "sysflags");
  41.      sysflags.sysflagsid[9] = (char) sizeof(struct sysflag);
  42.  #endif
  43.      flags.end_own = FALSE;
  44.      flags.end_top = 3;
  45.      flags.end_around = 2;
  46.      flags.paranoia_bits = PARANOID_PRAY; /* old prayconfirm=TRUE */
  47.      flags.pile_limit = PILE_LIMIT_DFLT;  /* 5 */
  48.      flags.runmode = RUN_LEAP;
  49.      iflags.msg_history = 20;
  50.  #ifdef TTY_GRAPHICS
  51.      iflags.prevmsg_window = 's';
  52.  #endif
  53.      iflags.menu_headings = ATR_INVERSE;
  54.  
  55.      /* hero's role, race, &c haven't been chosen yet */
  56.      flags.initrole = flags.initrace = flags.initgend = flags.initalign =
  57.          ROLE_NONE;
  58.  
  59.      /* Set the default monster and object class symbols. */
  60.      init_symbols();
  61.      for (i = 0; i < WARNCOUNT; i++)
  62.          warnsyms[i] = def_warnsyms[i].sym;
  63.      iflags.bouldersym = 0;
  64.  
  65.      iflags.travelcc.x = iflags.travelcc.y = -1;
  66.  
  67.      /* assert( sizeof flags.inv_order == sizeof def_inv_order ); */
  68.      (void) memcpy((genericptr_t) flags.inv_order,
  69.                    (genericptr_t) def_inv_order, sizeof flags.inv_order);
  70.      flags.pickup_types[0] = '\0';
  71.      flags.pickup_burden = MOD_ENCUMBER;
  72.      flags.sortloot = 'l'; /* sort only loot by default */
  73.  
  74.      for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++)
  75.          flags.end_disclose[i] = DISCLOSE_PROMPT_DEFAULT_NO;
  76.      switch_symbols(FALSE); /* set default characters */
  77.  #if defined(UNIX) && defined(TTY_GRAPHICS)
  78.      /*
  79.       * Set defaults for some options depending on what we can
  80.       * detect about the environment's capabilities.
  81.       * This has to be done after the global initialization above
  82.       * and before reading user-specific initialization via
  83.       * config file/environment variable below.
  84.       */
  85.      /* this detects the IBM-compatible console on most 386 boxes */
  86.      if ((opts = nh_getenv("TERM")) && !strncmp(opts, "AT", 2)) {
  87.          if (!symset[PRIMARY].name)
  88.              load_symset("IBMGraphics", PRIMARY);
  89.          if (!symset[ROGUESET].name)
  90.              load_symset("RogueIBM", ROGUESET);
  91.          switch_symbols(TRUE);
  92.  #ifdef TEXTCOLOR
  93.          iflags.use_color = TRUE;
  94.  #endif
  95.      }
  96.  #endif /* UNIX && TTY_GRAPHICS */
  97.  #if defined(UNIX) || defined(VMS)
  98.  #ifdef TTY_GRAPHICS
  99.      /* detect whether a "vt" terminal can handle alternate charsets */
  100.      if ((opts = nh_getenv("TERM"))
  101.          /* [could also check "xterm" which emulates vtXXX by default] */
  102.          && !strncmpi(opts, "vt", 2)
  103.          && AS && AE && index(AS, '\016') && index(AE, '\017')) {
  104.          if (!symset[PRIMARY].name)
  105.              load_symset("DECGraphics", PRIMARY);
  106.          switch_symbols(TRUE);
  107.      }
  108.  #endif
  109.  #endif /* UNIX || VMS */
  110.  
  111.  #ifdef MAC_GRAPHICS_ENV
  112.      if (!symset[PRIMARY].name)
  113.          load_symset("MACGraphics", PRIMARY);
  114.      switch_symbols(TRUE);
  115.  #endif /* MAC_GRAPHICS_ENV */
  116.      flags.menu_style = MENU_FULL;
  117.  
  118.      /* since this is done before init_objects(), do partial init here */
  119.      objects[SLIME_MOLD].oc_name_idx = SLIME_MOLD;
  120.      nmcpy(pl_fruit, OBJ_NAME(objects[SLIME_MOLD]), PL_FSIZ);
  121.  }
  122.  

initoptions_finish

  1.  void
  2.  initoptions_finish()
  3.  {
  4.  #ifndef MAC
  5.      char *opts = getenv("NETHACKOPTIONS");
  6.  
  7.      if (!opts)
  8.          opts = getenv("HACKOPTIONS");
  9.      if (opts) {
  10.          if (*opts == '/' || *opts == '\\' || *opts == '@') {
  11.              if (*opts == '@')
  12.                  opts++; /* @filename */
  13.              /* looks like a filename */
  14.              if (strlen(opts) < BUFSZ / 2)
  15.                  read_config_file(opts, SET_IN_FILE);
  16.          } else {
  17.              read_config_file((char *) 0, SET_IN_FILE);
  18.              /* let the total length of options be long;
  19.               * parseoptions() will check each individually
  20.               */
  21.              parseoptions(opts, TRUE, FALSE);
  22.          }
  23.      } else
  24.  #endif
  25.          read_config_file((char *) 0, SET_IN_FILE);
  26.  
  27.      (void) fruitadd(pl_fruit, (struct fruit *) 0);
  28.      /*
  29.       * Remove "slime mold" from list of object names.  This will
  30.       * prevent it from being wished unless it's actually present
  31.       * as a named (or default) fruit.  Wishing for "fruit" will
  32.       * result in the player's preferred fruit [better than "\033"].
  33.       */
  34.      obj_descr[SLIME_MOLD].oc_name = "fruit";
  35.  
  36.      if (iflags.bouldersym)
  37.          update_bouldersym();
  38.      reglyph_darkroom();
  39.      return;
  40.  }
  41.  

nmcpy

  1.  STATIC_OVL void
  2.  nmcpy(dest, src, maxlen)
  3.  char *dest;
  4.  const char *src;
  5.  int maxlen;
  6.  {
  7.      int count;
  8.  
  9.      for (count = 1; count < maxlen; count++) {
  10.          if (*src == ',' || *src == '\0')
  11.              break; /*exit on \0 terminator*/
  12.          *dest++ = *src++;
  13.      }
  14.      *dest = 0;
  15.  }
  16.  

escapes

  1.  /*
  2.   * escapes(): escape expansion for showsyms.  C-style escapes understood
  3.   * include \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal).
  4.   * The ^-prefix for control characters is also understood, and \[mM]
  5.   * has the effect of 'meta'-ing the value which follows (so that the
  6.   * alternate character set will be enabled).
  7.   *
  8.   * For 3.4.3 and earlier, input ending with "\M", backslash, or caret
  9.   * prior to terminating '\0' would pull that '\0' into the output and then
  10.   * keep processing past it, potentially overflowing the output buffer.
  11.   * Now, trailing \ or ^ will act like \\ or \^ and add '\\' or '^' to the
  12.   * output and stop there; trailing \M will fall through to \<other> and
  13.   * yield 'M', then stop.  Any \X or \O followed by something other than
  14.   * an appropriate digit will also fall through to \<other> and yield 'X'
  15.   * or 'O', plus stop if the non-digit is end-of-string.
  16.   */
  17.  STATIC_OVL void
  18.  escapes(cp, tp)
  19.  const char *cp;
  20.  char *tp;
  21.  {
  22.      static NEARDATA const char oct[] = "01234567", dec[] = "0123456789",
  23.                                 hex[] = "00112233445566778899aAbBcCdDeEfF";
  24.      const char *dp;
  25.      int cval, meta, dcount;
  26.  
  27.      while (*cp) {
  28.          /* \M has to be followed by something to do meta conversion,
  29.             otherwise it will just be \M which ultimately yields 'M' */
  30.          meta = (*cp == '\\' && (cp[1] == 'm' || cp[1] == 'M') && cp[2]);
  31.          if (meta)
  32.              cp += 2;
  33.  
  34.          cval = dcount = 0; /* for decimal, octal, hexadecimal cases */
  35.          if ((*cp != '\\' && *cp != '^') || !cp[1]) {
  36.              /* simple character, or nothing left for \ or ^ to escape */
  37.              cval = *cp++;
  38.          } else if (*cp == '^') { /* expand control-character syntax */
  39.              cval = (*++cp & 0x1f);
  40.              ++cp;
  41.              /* remaining cases are all for backslash and we know cp[1] is not
  42.               * \0 */
  43.          } else if (index(dec, cp[1])) {
  44.              ++cp; /* move past backslash to first digit */
  45.              do {
  46.                  cval = (cval * 10) + (*cp - '0');
  47.              } while (*++cp && index(dec, *cp) && ++dcount < 3);
  48.          } else if ((cp[1] == 'o' || cp[1] == 'O') && cp[2]
  49.                     && index(oct, cp[2])) {
  50.              cp += 2; /* move past backslash and 'O' */
  51.              do {
  52.                  cval = (cval * 8) + (*cp - '0');
  53.              } while (*++cp && index(oct, *cp) && ++dcount < 3);
  54.          } else if ((cp[1] == 'x' || cp[1] == 'X') && cp[2]
  55.                     && (dp = index(hex, cp[2])) != 0) {
  56.              cp += 2; /* move past backslash and 'X' */
  57.              do {
  58.                  cval = (cval * 16) + ((int) (dp - hex) / 2);
  59.              } while (*++cp && (dp = index(hex, *cp)) != 0 && ++dcount < 2);
  60.          } else { /* C-style character escapes */
  61.              switch (*++cp) {
  62.              case '\\':
  63.                  cval = '\\';
  64.                  break;
  65.              case 'n':
  66.                  cval = '\n';
  67.                  break;
  68.              case 't':
  69.                  cval = '\t';
  70.                  break;
  71.              case 'b':
  72.                  cval = '\b';
  73.                  break;
  74.              case 'r':
  75.                  cval = '\r';
  76.                  break;
  77.              default:
  78.                  cval = *cp;
  79.              }
  80.              ++cp;
  81.          }
  82.  
  83.          if (meta)
  84.              cval |= 0x80;
  85.          *tp++ = (char) cval;
  86.      }
  87.      *tp = '\0';
  88.  }
  89.  

rejectoption

  1.  STATIC_OVL void
  2.  rejectoption(optname)
  3.  const char *optname;
  4.  {
  5.  #ifdef MICRO
  6.      pline("\"%s\" settable only from %s.", optname, lastconfigfile);
  7.  #else
  8.      pline("%s can be set only from NETHACKOPTIONS or %s.", optname,
  9.            lastconfigfile);
  10.  #endif
  11.  }
  12.  

badoption

  1.  STATIC_OVL void
  2.  badoption(opts)
  3.  const char *opts;
  4.  {
  5.      if (!initial) {
  6.          if (!strncmp(opts, "h", 1) || !strncmp(opts, "?", 1))
  7.              option_help();
  8.          else
  9.              pline("Bad syntax: %s.  Enter \"?g\" for help.", opts);
  10.          return;
  11.      }
  12.  #ifdef MAC
  13.      else
  14.          return;
  15.  #endif
  16.  
  17.      if (from_file)
  18.          raw_printf("Bad syntax in OPTIONS in %s: %s%s.\n", lastconfigfile,
  19.  #ifdef WIN32
  20.                      "\n",
  21.  #else
  22.                      "",
  23.  #endif
  24.                      opts);
  25.      else
  26.          raw_printf("Bad syntax in NETHACKOPTIONS: %s%s.\n",
  27.  #ifdef WIN32
  28.                      "\n",
  29.  #else
  30.                      "",
  31.  #endif
  32.                      opts);
  33.      wait_synch();
  34.  }
  35.  

string_for_opt

  1.  STATIC_OVL char *
  2.  string_for_opt(opts, val_optional)
  3.  char *opts;
  4.  boolean val_optional;
  5.  {
  6.      char *colon, *equals;
  7.  
  8.      colon = index(opts, ':');
  9.      equals = index(opts, '=');
  10.      if (!colon || (equals && equals < colon))
  11.          colon = equals;
  12.  
  13.      if (!colon || !*++colon) {
  14.          if (!val_optional)
  15.              badoption(opts);
  16.          return (char *) 0;
  17.      }
  18.      return colon;
  19.  }
  20.  

string_for_env_opt

  1.  STATIC_OVL char *
  2.  string_for_env_opt(optname, opts, val_optional)
  3.  const char *optname;
  4.  char *opts;
  5.  boolean val_optional;
  6.  {
  7.      if (!initial) {
  8.          rejectoption(optname);
  9.          return (char *) 0;
  10.      }
  11.      return string_for_opt(opts, val_optional);
  12.  }
  13.  

bad_negation

  1.  STATIC_OVL void
  2.  bad_negation(optname, with_parameter)
  3.  const char *optname;
  4.  boolean with_parameter;
  5.  {
  6.      pline_The("%s option may not %sbe negated.", optname,
  7.                with_parameter ? "both have a value and " : "");
  8.  }
  9.  

change_inv_order

  1.  /*
  2.   * Change the inventory order, using the given string as the new order.
  3.   * Missing characters in the new order are filled in at the end from
  4.   * the current inv_order, except for gold, which is forced to be first
  5.   * if not explicitly present.
  6.   *
  7.   * This routine returns 1 unless there is a duplicate or bad char in
  8.   * the string.
  9.   */
  10.  STATIC_OVL int
  11.  change_inv_order(op)
  12.  char *op;
  13.  {
  14.      int oc_sym, num;
  15.      char *sp, buf[BUFSZ];
  16.  
  17.      num = 0;
  18.      /*  !!!! probably unnecessary with gold as normal inventory */
  19.  
  20.      for (sp = op; *sp; sp++) {
  21.          oc_sym = def_char_to_objclass(*sp);
  22.          /* reject bad or duplicate entries */
  23.          if (oc_sym == MAXOCLASSES || oc_sym == RANDOM_CLASS
  24.              || oc_sym == ILLOBJ_CLASS || !index(flags.inv_order, oc_sym)
  25.              || index(sp + 1, *sp))
  26.              return 0;
  27.          /* retain good ones */
  28.          buf[num++] = (char) oc_sym;
  29.      }
  30.      buf[num] = '\0';
  31.  
  32.      /* fill in any omitted classes, using previous ordering */
  33.      for (sp = flags.inv_order; *sp; sp++)
  34.          if (!index(buf, *sp)) {
  35.              buf[num++] = *sp;
  36.              buf[num] = '\0'; /* explicitly terminate for next index() */
  37.          }
  38.  
  39.      Strcpy(flags.inv_order, buf);
  40.      return 1;
  41.  }
  42.  

warning_opts

  1.  STATIC_OVL void
  2.  warning_opts(opts, optype)
  3.  register char *opts;
  4.  const char *optype;
  5.  {
  6.      uchar translate[WARNCOUNT];
  7.      int length, i;
  8.  
  9.      if (!(opts = string_for_env_opt(optype, opts, FALSE)))
  10.          return;
  11.      escapes(opts, opts);
  12.  
  13.      length = (int) strlen(opts);
  14.      /* match the form obtained from PC configuration files */
  15.      for (i = 0; i < WARNCOUNT; i++)
  16.          translate[i] = (i >= length) ? 0
  17.                                       : opts[i] ? (uchar) opts[i]
  18.                                                 : def_warnsyms[i].sym;
  19.      assign_warnings(translate);
  20.  }
  21.  

assign_warnings

  1.  void
  2.  assign_warnings(graph_chars)
  3.  register uchar *graph_chars;
  4.  {
  5.      int i;
  6.  
  7.      for (i = 0; i < WARNCOUNT; i++)
  8.          if (graph_chars[i])
  9.              warnsyms[i] = graph_chars[i];
  10.  }
  11.  

feature_alert_opts

  1.  STATIC_OVL int
  2.  feature_alert_opts(op, optn)
  3.  char *op;
  4.  const char *optn;
  5.  {
  6.      char buf[BUFSZ];
  7.      boolean rejectver = FALSE;
  8.      unsigned long fnv = get_feature_notice_ver(op); /* version.c */
  9.  
  10.      if (fnv == 0L)
  11.          return 0;
  12.      if (fnv > get_current_feature_ver())
  13.          rejectver = TRUE;
  14.      else
  15.          flags.suppress_alert = fnv;
  16.      if (rejectver) {
  17.          if (!initial) {
  18.              You_cant("disable new feature alerts for future versions.");
  19.          } else {
  20.              Sprintf(buf,
  21.                      "\n%s=%s Invalid reference to a future version ignored",
  22.                      optn, op);
  23.              badoption(buf);
  24.          }
  25.          return 0;
  26.      }
  27.      if (!initial) {
  28.          Sprintf(buf, "%lu.%lu.%lu", FEATURE_NOTICE_VER_MAJ,
  29.                  FEATURE_NOTICE_VER_MIN, FEATURE_NOTICE_VER_PATCH);
  30.          pline(
  31.            "Feature change alerts disabled for NetHack %s features and prior.",
  32.                buf);
  33.      }
  34.      return 1;
  35.  }
  36.  

set_duplicate_opt_detection

  1.  void
  2.  set_duplicate_opt_detection(on_or_off)
  3.  int on_or_off;
  4.  {
  5.      int k, *optptr;
  6.  
  7.      if (on_or_off != 0) {
  8.          /*-- ON --*/
  9.          if (iflags.opt_booldup)
  10.              impossible("iflags.opt_booldup already on (memory leak)");
  11.          iflags.opt_booldup = (int *) alloc(SIZE(boolopt) * sizeof(int));
  12.          optptr = iflags.opt_booldup;
  13.          for (k = 0; k < SIZE(boolopt); ++k)
  14.              *optptr++ = 0;
  15.  
  16.          if (iflags.opt_compdup)
  17.              impossible("iflags.opt_compdup already on (memory leak)");
  18.          iflags.opt_compdup = (int *) alloc(SIZE(compopt) * sizeof(int));
  19.          optptr = iflags.opt_compdup;
  20.          for (k = 0; k < SIZE(compopt); ++k)
  21.              *optptr++ = 0;
  22.      } else {
  23.          /*-- OFF --*/
  24.          if (iflags.opt_booldup)
  25.              free((genericptr_t) iflags.opt_booldup);
  26.          iflags.opt_booldup = (int *) 0;
  27.          if (iflags.opt_compdup)
  28.              free((genericptr_t) iflags.opt_compdup);
  29.          iflags.opt_compdup = (int *) 0;
  30.      }
  31.  }
  32.  

duplicate_opt_detection

  1.  STATIC_OVL boolean
  2.  duplicate_opt_detection(opts, iscompound)
  3.  const char *opts;
  4.  int iscompound; /* 0 == boolean option, 1 == compound */
  5.  {
  6.      int i, *optptr;
  7.  
  8.      if (!iscompound && iflags.opt_booldup && initial && from_file) {
  9.          for (i = 0; boolopt[i].name; i++) {
  10.              if (match_optname(opts, boolopt[i].name, 3, FALSE)) {
  11.                  optptr = iflags.opt_booldup + i;
  12.                  *optptr += 1;
  13.                  if (*optptr > 1)
  14.                      return TRUE;
  15.                  else
  16.                      return FALSE;
  17.              }
  18.          }
  19.      } else if (iscompound && iflags.opt_compdup && initial && from_file) {
  20.          for (i = 0; compopt[i].name; i++) {
  21.              if (match_optname(opts, compopt[i].name, strlen(compopt[i].name),
  22.                                TRUE)) {
  23.                  optptr = iflags.opt_compdup + i;
  24.                  *optptr += 1;
  25.                  if (*optptr > 1)
  26.                      return TRUE;
  27.                  else
  28.                      return FALSE;
  29.              }
  30.          }
  31.      }
  32.      return FALSE;
  33.  }
  34.  

complain_about_duplicate

  1.  STATIC_OVL void
  2.  complain_about_duplicate(opts, iscompound)
  3.  const char *opts;
  4.  int iscompound; /* 0 == boolean option, 1 == compound */
  5.  {
  6.  #ifdef MAC
  7.      /* the Mac has trouble dealing with the output of messages while
  8.       * processing the config file.  That should get fixed one day.
  9.       * For now just return.
  10.       */
  11.  #else /* !MAC */
  12.      raw_printf("\nWarning - %s option specified multiple times: %s.\n",
  13.                 iscompound ? "compound" : "boolean", opts);
  14.      wait_synch();
  15.  #endif /* ?MAC */
  16.      return;
  17.  }
  18.  

Paranoia/menucoloring structures and handlers

  1.  /* paranoia[] - used by parseoptions() and special_handling() */
  2.  STATIC_VAR const struct paranoia_opts {
  3.      int flagmask;        /* which paranoid option */
  4.      const char *argname; /* primary name */
  5.      int argMinLen;       /* minimum number of letters to match */
  6.      const char *synonym; /* alternate name (optional) */
  7.      int synMinLen;
  8.      const char *explain; /* for interactive menu */
  9.  } paranoia[] = {
  10.      /* there are some initial-letter conflicts: "a"ttack vs "a"ll, "attack"
  11.         takes precedence and "all" isn't present in the interactive menu,
  12.         and "d"ie vs "d"eath, synonyms for each other so doesn't matter;
  13.         (also "p"ray vs "P"aranoia, "pray" takes precedence since "Paranoia"
  14.         is just a synonym for "Confirm") */
  15.      { PARANOID_CONFIRM, "Confirm", 1, "Paranoia", 2,
  16.        "for \"yes\" confirmations, require \"no\" to reject" },
  17.      { PARANOID_QUIT, "quit", 1, "explore", 1,
  18.        "yes vs y to quit or to enter explore mode" },
  19.      { PARANOID_DIE, "die", 1, "death", 2,
  20.        "yes vs y to die (explore mode or debug mode)" },
  21.      { PARANOID_BONES, "bones", 1, 0, 0,
  22.        "yes vs y to save bones data when dying in debug mode" },
  23.      { PARANOID_HIT, "attack", 1, "hit", 1,
  24.        "yes vs y to attack a peaceful monster" },
  25.      { PARANOID_PRAY, "pray", 1, 0, 0,
  26.        "y to pray (supersedes old \"prayconfirm\" option)" },
  27.      { PARANOID_REMOVE, "Remove", 1, "Takeoff", 1,
  28.        "always pick from inventory for Remove and Takeoff" },
  29.      { PARANOID_BREAKWAND, "wand", 1, "breakwand", 2,
  30.        "yes vs y to break a wand" },
  31.      /* for config file parsing; interactive menu skips these */
  32.      { 0, "none", 4, 0, 0, 0 }, /* require full word match */
  33.      { ~0, "all", 3, 0, 0, 0 }, /* ditto */
  34.  };
  35.  
  36.  extern struct menucoloring *menu_colorings;
  37.  
  38.  static const struct {
  39.      const char *name;
  40.      const int color;
  41.  } colornames[] = {
  42.      { "black", CLR_BLACK },
  43.      { "red", CLR_RED },
  44.      { "green", CLR_GREEN },
  45.      { "brown", CLR_BROWN },
  46.      { "blue", CLR_BLUE },
  47.      { "magenta", CLR_MAGENTA },
  48.      { "cyan", CLR_CYAN },
  49.      { "gray", CLR_GRAY },
  50.      { "grey", CLR_GRAY },
  51.      { "orange", CLR_ORANGE },
  52.      { "light green", CLR_BRIGHT_GREEN },
  53.      { "yellow", CLR_YELLOW },
  54.      { "light blue", CLR_BRIGHT_BLUE },
  55.      { "light magenta", CLR_BRIGHT_MAGENTA },
  56.      { "light cyan", CLR_BRIGHT_CYAN },
  57.      { "white", CLR_WHITE }
  58.  };
  59.  
  60.  static const struct {
  61.      const char *name;
  62.      const int attr;
  63.  } attrnames[] = {
  64.      { "none", ATR_NONE },
  65.      { "bold", ATR_BOLD },
  66.      { "dim", ATR_DIM },
  67.      { "underline", ATR_ULINE },
  68.      { "blink", ATR_BLINK },
  69.      { "inverse", ATR_INVERSE }
  70.  };
  71.  

clr2colorname

  1.  const char *
  2.  clr2colorname(clr)
  3.  int clr;
  4.  {
  5.      int i;
  6.  
  7.      for (i = 0; i < SIZE(colornames); i++)
  8.          if (colornames[i].color == clr)
  9.              return colornames[i].name;
  10.      return (char *) 0;
  11.  }
  12.  

attr2attrname

  1.  const char *
  2.  attr2attrname(attr)
  3.  int attr;
  4.  {
  5.      int i;
  6.  
  7.      for (i = 0; i < SIZE(attrnames); i++)
  8.          if (attrnames[i].attr == attr)
  9.              return attrnames[i].name;
  10.      return (char *) 0;
  11.  }
  12.  

query_color

  1.  int
  2.  query_color()
  3.  {
  4.      winid tmpwin;
  5.      anything any;
  6.      int i, pick_cnt;
  7.      menu_item *picks = (menu_item *) 0;
  8.  
  9.      tmpwin = create_nhwindow(NHW_MENU);
  10.      start_menu(tmpwin);
  11.      any = zeroany;
  12.      for (i = 0; i < SIZE(colornames); i++) {
  13.          if (!strcmp(colornames[i].name, "grey"))
  14.              continue;
  15.          any.a_int = i + 1;
  16.          add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, colornames[i].name,
  17.                   MENU_UNSELECTED);
  18.      }
  19.      end_menu(tmpwin, "Pick a color");
  20.      pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
  21.      destroy_nhwindow(tmpwin);
  22.      if (pick_cnt > 0) {
  23.          i = colornames[picks->item.a_int - 1].color;
  24.          free((genericptr_t) picks);
  25.          return i;
  26.      }
  27.      return -1;
  28.  }
  29.  

query_attr

  1.  int
  2.  query_attr(prompt)
  3.  const char *prompt;
  4.  {
  5.      winid tmpwin;
  6.      anything any;
  7.      int i, pick_cnt;
  8.      menu_item *picks = (menu_item *) 0;
  9.  
  10.      tmpwin = create_nhwindow(NHW_MENU);
  11.      start_menu(tmpwin);
  12.      any = zeroany;
  13.      for (i = 0; i < SIZE(attrnames); i++) {
  14.          any.a_int = i + 1;
  15.          add_menu(tmpwin, NO_GLYPH, &any, 0, 0, attrnames[i].attr,
  16.                   attrnames[i].name, MENU_UNSELECTED);
  17.      }
  18.      end_menu(tmpwin, prompt ? prompt : "Pick an attribute");
  19.      pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
  20.      destroy_nhwindow(tmpwin);
  21.      if (pick_cnt > 0) {
  22.          i = attrnames[picks->item.a_int - 1].attr;
  23.          free((genericptr_t) picks);
  24.          return i;
  25.      }
  26.      return -1;
  27.  }
  28.  

MSGTYPE

msgtype2name

  1.  static const struct {
  2.      const char *name;
  3.      const xchar msgtyp;
  4.      const char *descr;
  5.  } msgtype_names[] = {
  6.      { "show", MSGTYP_NORMAL, "Show message normally" },
  7.      { "hide", MSGTYP_NOSHOW, "Hide message" },
  8.      { "noshow", MSGTYP_NOSHOW, NULL },
  9.      { "stop", MSGTYP_STOP, "Prompt for more after the message" },
  10.      { "more", MSGTYP_STOP, NULL },
  11.      { "norep", MSGTYP_NOREP, "Do not repeat the message" }
  12.  };
  13.  
  14.  const char *
  15.  msgtype2name(typ)
  16.  int typ;
  17.  {
  18.      int i;
  19.  
  20.      for (i = 0; i < SIZE(msgtype_names); i++)
  21.          if (msgtype_names[i].descr && msgtype_names[i].msgtyp == typ)
  22.              return msgtype_names[i].name;
  23.      return (char *) 0;
  24.  }
  25.  

query_msgtype

  1.  int
  2.  query_msgtype()
  3.  {
  4.      winid tmpwin;
  5.      anything any;
  6.      int i, pick_cnt;
  7.      menu_item *picks = (menu_item *) 0;
  8.  
  9.      tmpwin = create_nhwindow(NHW_MENU);
  10.      start_menu(tmpwin);
  11.      any = zeroany;
  12.      for (i = 0; i < SIZE(msgtype_names); i++)
  13.          if (msgtype_names[i].descr) {
  14.              any.a_int = msgtype_names[i].msgtyp + 1;
  15.              add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
  16.                   msgtype_names[i].descr, MENU_UNSELECTED);
  17.          }
  18.      end_menu(tmpwin, "How to show the message");
  19.      pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
  20.      destroy_nhwindow(tmpwin);
  21.      if (pick_cnt > 0) {
  22.          i = picks->item.a_int - 1;
  23.          free((genericptr_t) picks);
  24.          return i;
  25.      }
  26.      return -1;
  27.  }
  28.  

msgtype_add

  1.  boolean
  2.  msgtype_add(typ, pattern)
  3.  int typ;
  4.  char *pattern;
  5.  {
  6.      struct plinemsg_type *tmp
  7.                = (struct plinemsg_type *) alloc(sizeof (struct plinemsg_type));
  8.  
  9.      if (!tmp)
  10.          return FALSE;
  11.      tmp->msgtype = typ;
  12.      tmp->regex = regex_init();
  13.      if (!regex_compile(pattern, tmp->regex)) {
  14.          static const char *re_error = "MSGTYPE regex error";
  15.  
  16.          if (!iflags.window_inited)
  17.              raw_printf("\n%s: %s\n", re_error, regex_error_desc(tmp->regex));
  18.          else
  19.              pline("%s: %s", re_error, regex_error_desc(tmp->regex));
  20.          wait_synch();
  21.          regex_free(tmp->regex);
  22.          free((genericptr_t) tmp);
  23.          return FALSE;
  24.      }
  25.      tmp->pattern = dupstr(pattern);
  26.      tmp->next = plinemsg_types;
  27.      plinemsg_types = tmp;
  28.      return TRUE;
  29.  }
  30.  

msgtype_free

  1.  void
  2.  msgtype_free()
  3.  {
  4.      struct plinemsg_type *tmp, *tmp2 = 0;
  5.  
  6.      for (tmp = plinemsg_types; tmp; tmp = tmp2) {
  7.          tmp2 = tmp->next;
  8.          free((genericptr_t) tmp->pattern);
  9.          regex_free(tmp->regex);
  10.          free((genericptr_t) tmp);
  11.      }
  12.      plinemsg_types = (struct plinemsg_type *) 0;
  13.  }
  14.  

free_one_msgtype

  1.  void
  2.  free_one_msgtype(idx)
  3.  int idx; /* 0 .. */
  4.  {
  5.      struct plinemsg_type *tmp = plinemsg_types;
  6.      struct plinemsg_type *prev = NULL;
  7.  
  8.      while (tmp) {
  9.          if (idx == 0) {
  10.              struct plinemsg_type *next = tmp->next;
  11.  
  12.              regex_free(tmp->regex);
  13.              free((genericptr_t) tmp->pattern);
  14.              free((genericptr_t) tmp);
  15.              if (prev)
  16.                  prev->next = next;
  17.              else
  18.                  plinemsg_types = next;
  19.              return;
  20.          }
  21.          idx--;
  22.          prev = tmp;
  23.          tmp = tmp->next;
  24.      }
  25.  }
  26.  

msgtype_type

  1.  int
  2.  msgtype_type(msg)
  3.  const char *msg;
  4.  {
  5.      struct plinemsg_type *tmp = plinemsg_types;
  6.  
  7.      while (tmp) {
  8.          if (regex_match(msg, tmp->regex))
  9.              return tmp->msgtype;
  10.          tmp = tmp->next;
  11.      }
  12.      return MSGTYP_NORMAL;
  13.  }
  14.  

msgtype_count

  1.  int
  2.  msgtype_count()
  3.  {
  4.      int c = 0;
  5.      struct plinemsg_type *tmp = plinemsg_types;
  6.  
  7.      while (tmp) {
  8.          c++;
  9.          tmp = tmp->next;
  10.      }
  11.      return c;
  12.  }
  13.  

msgtype_parse_add

  1.  boolean
  2.  msgtype_parse_add(str)
  3.  char *str;
  4.  {
  5.      char pattern[256];
  6.      char msgtype[11];
  7.  
  8.      if (sscanf(str, "%10s \"%255[^\"]\"", msgtype, pattern) == 2) {
  9.          int typ = -1;
  10.          int i;
  11.  
  12.          for (i = 0; i < SIZE(msgtype_names); i++)
  13.              if (!strncmpi(msgtype_names[i].name, msgtype, strlen(msgtype))) {
  14.                  typ = msgtype_names[i].msgtyp;
  15.                  break;
  16.              }
  17.          if (typ != -1)
  18.              return msgtype_add(typ, pattern);
  19.      }
  20.      return FALSE;
  21.  }
  22.  

Menucolors

add_menu_coloring_parsed

  1.  boolean
  2.  add_menu_coloring_parsed(str, c, a)
  3.  char *str;
  4.  int c, a;
  5.  {
  6.      static const char re_error[] = "Menucolor regex error";
  7.      struct menucoloring *tmp;
  8.  
  9.      if (!str)
  10.          return FALSE;
  11.      tmp = (struct menucoloring *) alloc(sizeof (struct menucoloring));
  12.      tmp->match = regex_init();
  13.      if (!regex_compile(str, tmp->match)) {
  14.          if (!iflags.window_inited)
  15.              raw_printf("\n%s: %s\n", re_error, regex_error_desc(tmp->match));
  16.          else
  17.              pline("%s: %s", re_error, regex_error_desc(tmp->match));
  18.          wait_synch();
  19.          regex_free(tmp->match);
  20.          free(tmp);
  21.          return FALSE;
  22.      } else {
  23.          tmp->next = menu_colorings;
  24.          tmp->origstr = dupstr(str);
  25.          tmp->color = c;
  26.          tmp->attr = a;
  27.          menu_colorings = tmp;
  28.          return TRUE;
  29.      }
  30.  }
  31.  

add_menu_coloring

  1.  /* parse '"regex_string"=color&attr' and add it to menucoloring */
  2.  boolean
  3.  add_menu_coloring(str)
  4.  char *str;
  5.  {
  6.      int i, c = NO_COLOR, a = ATR_NONE;
  7.      char *tmps, *cs, *amp;
  8.  
  9.      if (!str || (cs = index(str, '=')) == 0)
  10.          return FALSE;
  11.  
  12.      tmps = cs + 1; /* advance past '=' */
  13.      mungspaces(tmps);
  14.      if ((amp = index(tmps, '&')) != 0)
  15.          *amp = '\0';
  16.  
  17.      /* allow "lightblue", "light blue", and "light-blue" to match "light blue"
  18.         (also junk like "_l i-gh_t---b l u e" but we won't worry about that);
  19.         also copes with trailing space; mungspaces removed any leading space */
  20.      for (i = 0; i < SIZE(colornames); i++)
  21.          if (fuzzymatch(tmps, colornames[i].name, " -_", TRUE)) {
  22.              c = colornames[i].color;
  23.              break;
  24.          }
  25.      if (i == SIZE(colornames) && (*tmps >= '0' && *tmps <= '9'))
  26.          c = atoi(tmps);
  27.  
  28.      if (c > 15)
  29.          return FALSE;
  30.  
  31.      if (amp) {
  32.          tmps = amp + 1; /* advance past '&' */
  33.          /* unlike colors, none of he attribute names has any embedded spaces,
  34.             but use of fuzzymatch() allows us ignore the presence of leading
  35.             and/or trailing (and also embedded) spaces in the user's string;
  36.             dash and underscore skipping could be omitted but does no harm */
  37.          for (i = 0; i < SIZE(attrnames); i++)
  38.              if (fuzzymatch(tmps, attrnames[i].name, " -_", TRUE)) {
  39.                  a = attrnames[i].attr;
  40.                  break;
  41.              }
  42.          if (i == SIZE(attrnames) && (*tmps >= '0' && *tmps <= '9'))
  43.              a = atoi(tmps);
  44.      }
  45.  
  46.      /* the regexp portion here has not been condensed by mungspaces() */
  47.      *cs = '\0';
  48.      tmps = str;
  49.      if (*tmps == '"' || *tmps == '\'') {
  50.          cs--;
  51.          while (isspace((uchar) *cs))
  52.              cs--;
  53.          if (*cs == *tmps) {
  54.              *cs = '\0';
  55.              tmps++;
  56.          }
  57.      }
  58.  
  59.      return add_menu_coloring_parsed(tmps, c, a);
  60.  }
  61.  

get_menu_coloring

  1.  boolean
  2.  get_menu_coloring(str, color, attr)
  3.  char *str;
  4.  int *color, *attr;
  5.  {
  6.      struct menucoloring *tmpmc;
  7.  
  8.      if (iflags.use_menu_color)
  9.          for (tmpmc = menu_colorings; tmpmc; tmpmc = tmpmc->next)
  10.              if (regex_match(str, tmpmc->match)) {
  11.                  *color = tmpmc->color;
  12.                  *attr = tmpmc->attr;
  13.                  return TRUE;
  14.              }
  15.      return FALSE;
  16.  }
  17.  

free_menu_coloring

  1.  void
  2.  free_menu_coloring()
  3.  {
  4.      struct menucoloring *tmp = menu_colorings;
  5.  
  6.      while (tmp) {
  7.          struct menucoloring *tmp2 = tmp->next;
  8.  
  9.          regex_free(tmp->match);
  10.          free((genericptr_t) tmp->origstr);
  11.          free((genericptr_t) tmp);
  12.          tmp = tmp2;
  13.      }
  14.  }
  15.  

free_one_menu_coloring

  1.  void
  2.  free_one_menu_coloring(idx)
  3.  int idx; /* 0 .. */
  4.  {
  5.      struct menucoloring *tmp = menu_colorings;
  6.      struct menucoloring *prev = NULL;
  7.  
  8.      while (tmp) {
  9.          if (idx == 0) {
  10.              struct menucoloring *next = tmp->next;
  11.  
  12.              regex_free(tmp->match);
  13.              free((genericptr_t) tmp->origstr);
  14.              free((genericptr_t) tmp);
  15.              if (prev)
  16.                  prev->next = next;
  17.              else
  18.                  menu_colorings = next;
  19.              return;
  20.          }
  21.          idx--;
  22.          prev = tmp;
  23.          tmp = tmp->next;
  24.      }
  25.  }
  26.  

count_menucolors

  1.  int
  2.  count_menucolors()
  3.  {
  4.      int count = 0;
  5.      struct menucoloring *tmp = menu_colorings;
  6.  
  7.      while (tmp) {
  8.          count++;
  9.          tmp = tmp->next;
  10.      }
  11.      return count;
  12.  }
  13.  

Option parsing and miscellaneous handling

parseoptions

  1.  void
  2.  parseoptions(opts, tinitial, tfrom_file)
  3.  register char *opts;
  4.  boolean tinitial, tfrom_file;
  5.  {
  6.      register char *op;
  7.      unsigned num;
  8.      boolean negated, val_negated, duplicate;
  9.      int i;
  10.      const char *fullname;
  11.  
  12.      initial = tinitial;
  13.      from_file = tfrom_file;
  14.      if ((op = index(opts, ',')) != 0) {
  15.          *op++ = 0;
  16.          parseoptions(op, initial, from_file);
  17.      }
  18.      if (strlen(opts) > BUFSZ / 2) {
  19.          badoption("option too long");
  20.          return;
  21.      }
  22.  
  23.      /* strip leading and trailing white space */
  24.      while (isspace((uchar) *opts))
  25.          opts++;
  26.      op = eos(opts);
  27.      while (--op >= opts && isspace((uchar) *op))
  28.          *op = '\0';
  29.  
  30.      if (!*opts)
  31.          return;
  32.      negated = FALSE;
  33.      while ((*opts == '!') || !strncmpi(opts, "no", 2)) {
  34.          if (*opts == '!')
  35.              opts++;
  36.          else
  37.              opts += 2;
  38.          negated = !negated;
  39.      }
  40.  
  41.      /* variant spelling */
  42.  
  43.      if (match_optname(opts, "colour", 5, FALSE))
  44.          Strcpy(opts, "color"); /* fortunately this isn't longer */
  45.  
  46.      /* special boolean options */
  47.  
  48.      if (match_optname(opts, "female", 3, FALSE)) {
  49.          if (duplicate_opt_detection(opts, 0))
  50.              complain_about_duplicate(opts, 0);
  51.          if (!initial && flags.female == negated)
  52.              pline("That is not anatomically possible.");
  53.          else
  54.              flags.initgend = flags.female = !negated;
  55.          return;
  56.      }
  57.  
  58.      if (match_optname(opts, "male", 4, FALSE)) {
  59.          if (duplicate_opt_detection(opts, 0))
  60.              complain_about_duplicate(opts, 0);
  61.          if (!initial && flags.female != negated)
  62.              pline("That is not anatomically possible.");
  63.          else
  64.              flags.initgend = flags.female = negated;
  65.          return;
  66.      }
  67.  
  68.  #if defined(MICRO) && !defined(AMIGA)
  69.      /* included for compatibility with old NetHack.cnf files */
  70.      if (match_optname(opts, "IBM_", 4, FALSE)) {
  71.          iflags.BIOS = !negated;
  72.          return;
  73.      }
  74.  #endif /* MICRO */
  75.  
  76.      /* compound options */
  77.  
  78.      /* This first batch can be duplicated if their values are negated */
  79.  
  80.      /* align:string */
  81.      fullname = "align";
  82.      if (match_optname(opts, fullname, sizeof("align") - 1, TRUE)) {
  83.          if (negated) {
  84.              bad_negation(fullname, FALSE);
  85.          } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
  86.              val_negated = FALSE;
  87.              while ((*op == '!') || !strncmpi(op, "no", 2)) {
  88.                  if (*op == '!')
  89.                      op++;
  90.                  else
  91.                      op += 2;
  92.                  val_negated = !val_negated;
  93.              }
  94.              if (val_negated) {
  95.                  if (!setrolefilter(op))
  96.                      badoption(opts);
  97.              } else {
  98.                  if (duplicate_opt_detection(opts, 1))
  99.                      complain_about_duplicate(opts, 1);
  100.                  if ((flags.initalign = str2align(op)) == ROLE_NONE)
  101.                      badoption(opts);
  102.              }
  103.          }
  104.          return;
  105.      }
  106.  
  107.      /* role:string or character:string */
  108.      fullname = "role";
  109.      if (match_optname(opts, fullname, 4, TRUE)
  110.          || match_optname(opts, (fullname = "character"), 4, TRUE)) {
  111.          if (negated) {
  112.              bad_negation(fullname, FALSE);
  113.          } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
  114.              val_negated = FALSE;
  115.              while ((*op == '!') || !strncmpi(op, "no", 2)) {
  116.                  if (*op == '!')
  117.                      op++;
  118.                  else
  119.                      op += 2;
  120.                  val_negated = !val_negated;
  121.              }
  122.              if (val_negated) {
  123.                  if (!setrolefilter(op))
  124.                      badoption(opts);
  125.              } else {
  126.                  if (duplicate_opt_detection(opts, 1))
  127.                      complain_about_duplicate(opts, 1);
  128.                  if ((flags.initrole = str2role(op)) == ROLE_NONE)
  129.                      badoption(opts);
  130.                  else /* Backwards compatibility */
  131.                      nmcpy(pl_character, op, PL_NSIZ);
  132.              }
  133.          }
  134.          return;
  135.      }
  136.  
  137.      /* race:string */
  138.      fullname = "race";
  139.      if (match_optname(opts, fullname, 4, TRUE)) {
  140.          if (negated) {
  141.              bad_negation(fullname, FALSE);
  142.          } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
  143.              val_negated = FALSE;
  144.              while ((*op == '!') || !strncmpi(op, "no", 2)) {
  145.                  if (*op == '!')
  146.                      op++;
  147.                  else
  148.                      op += 2;
  149.                  val_negated = !val_negated;
  150.              }
  151.              if (val_negated) {
  152.                  if (!setrolefilter(op))
  153.                      badoption(opts);
  154.              } else {
  155.                  if (duplicate_opt_detection(opts, 1))
  156.                      complain_about_duplicate(opts, 1);
  157.                  if ((flags.initrace = str2race(op)) == ROLE_NONE)
  158.                      badoption(opts);
  159.                  else /* Backwards compatibility */
  160.                      pl_race = *op;
  161.              }
  162.          }
  163.          return;
  164.      }
  165.  
  166.      /* gender:string */
  167.      fullname = "gender";
  168.      if (match_optname(opts, fullname, 4, TRUE)) {
  169.          if (negated) {
  170.              bad_negation(fullname, FALSE);
  171.          } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
  172.              val_negated = FALSE;
  173.              while ((*op == '!') || !strncmpi(op, "no", 2)) {
  174.                  if (*op == '!')
  175.                      op++;
  176.                  else
  177.                      op += 2;
  178.                  val_negated = !val_negated;
  179.              }
  180.              if (val_negated) {
  181.                  if (!setrolefilter(op))
  182.                      badoption(opts);
  183.              } else {
  184.                  if (duplicate_opt_detection(opts, 1))
  185.                      complain_about_duplicate(opts, 1);
  186.                  if ((flags.initgend = str2gend(op)) == ROLE_NONE)
  187.                      badoption(opts);
  188.                  else
  189.                      flags.female = flags.initgend;
  190.              }
  191.          }
  192.          return;
  193.      }
  194.  
  195.      /* We always check for duplicates on the remaining compound options,
  196.         although individual option processing can choose to complain or not */
  197.  
  198.      duplicate =
  199.          duplicate_opt_detection(opts, 1); /* 1 means check compounds */
  200.  
  201.      fullname = "pettype";
  202.      if (match_optname(opts, fullname, 3, TRUE)) {
  203.          if (duplicate)
  204.              complain_about_duplicate(opts, 1);
  205.          if ((op = string_for_env_opt(fullname, opts, negated)) != 0) {
  206.              if (negated)
  207.                  bad_negation(fullname, TRUE);
  208.              else
  209.                  switch (lowc(*op)) {
  210.                  case 'd': /* dog */
  211.                      preferred_pet = 'd';
  212.                      break;
  213.                  case 'c': /* cat */
  214.                  case 'f': /* feline */
  215.                      preferred_pet = 'c';
  216.                      break;
  217.                  case 'h': /* horse */
  218.                  case 'q': /* quadruped */
  219.                      /* avoids giving "unrecognized type of pet" but
  220.                         pet_type(dog.c) won't actually honor this */
  221.                      preferred_pet = 'h';
  222.                      break;
  223.                  case 'n': /* no pet */
  224.                      preferred_pet = 'n';
  225.                      break;
  226.                  case '*': /* random */
  227.                      preferred_pet = '\0';
  228.                      break;
  229.                  default:
  230.                      pline("Unrecognized pet type '%s'.", op);
  231.                      break;
  232.                  }
  233.          } else if (negated)
  234.              preferred_pet = 'n';
  235.          return;
  236.      }
  237.  
  238.      fullname = "catname";
  239.      if (match_optname(opts, fullname, 3, TRUE)) {
  240.          if (duplicate)
  241.              complain_about_duplicate(opts, 1);
  242.          if (negated)
  243.              bad_negation(fullname, FALSE);
  244.          else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
  245.              nmcpy(catname, op, PL_PSIZ);
  246.          sanitize_name(catname);
  247.          return;
  248.      }
  249.  
  250.      fullname = "dogname";
  251.      if (match_optname(opts, fullname, 3, TRUE)) {
  252.          if (duplicate)
  253.              complain_about_duplicate(opts, 1);
  254.          if (negated)
  255.              bad_negation(fullname, FALSE);
  256.          else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
  257.              nmcpy(dogname, op, PL_PSIZ);
  258.          sanitize_name(dogname);
  259.          return;
  260.      }
  261.  
  262.      fullname = "horsename";
  263.      if (match_optname(opts, fullname, 5, TRUE)) {
  264.          if (duplicate)
  265.              complain_about_duplicate(opts, 1);
  266.          if (negated)
  267.              bad_negation(fullname, FALSE);
  268.          else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
  269.              nmcpy(horsename, op, PL_PSIZ);
  270.          sanitize_name(horsename);
  271.          return;
  272.      }
  273.  
  274.      fullname = "number_pad";
  275.      if (match_optname(opts, fullname, 10, TRUE)) {
  276.          boolean compat = (strlen(opts) <= 10);
  277.  
  278.          if (duplicate)
  279.              complain_about_duplicate(opts, 1);
  280.          op = string_for_opt(opts, (compat || !initial));
  281.          if (!op) {
  282.              if (compat || negated || initial) {
  283.                  /* for backwards compatibility, "number_pad" without a
  284.                     value is a synonym for number_pad:1 */
  285.                  iflags.num_pad = !negated;
  286.                  iflags.num_pad_mode = 0;
  287.              }
  288.          } else if (negated) {
  289.              bad_negation("number_pad", TRUE);
  290.              return;
  291.          } else {
  292.              int mode = atoi(op);
  293.  
  294.              if (mode < -1 || mode > 4 || (mode == 0 && *op != '0')) {
  295.                  badoption(opts);
  296.                  return;
  297.              } else if (mode <= 0) {
  298.                  iflags.num_pad = FALSE;
  299.                  /* German keyboard; y and z keys swapped */
  300.                  iflags.num_pad_mode = (mode < 0); /* 0 or 1 */
  301.              } else {                              /* mode > 0 */
  302.                  iflags.num_pad = TRUE;
  303.                  iflags.num_pad_mode = 0;
  304.                  /* PC Hack / MSDOS compatibility */
  305.                  if (mode == 2 || mode == 4)
  306.                      iflags.num_pad_mode |= 1;
  307.                  /* phone keypad layout */
  308.                  if (mode == 3 || mode == 4)
  309.                      iflags.num_pad_mode |= 2;
  310.              }
  311.          }
  312.          reset_commands(FALSE);
  313.          number_pad(iflags.num_pad ? 1 : 0);
  314.          return;
  315.      }
  316.  
  317.      fullname = "roguesymset";
  318.      if (match_optname(opts, fullname, 7, TRUE)) {
  319.          if (duplicate)
  320.              complain_about_duplicate(opts, 1);
  321.          if (negated) {
  322.              bad_negation(fullname, FALSE);
  323.          } else if ((op = string_for_opt(opts, FALSE)) != 0) {
  324.              symset[ROGUESET].name = dupstr(op);
  325.              if (!read_sym_file(ROGUESET)) {
  326.                  clear_symsetentry(ROGUESET, TRUE);
  327.                  raw_printf("Unable to load symbol set \"%s\" from \"%s\".",
  328.                             op, SYMBOLS);
  329.                  wait_synch();
  330.              } else {
  331.                  if (!initial && Is_rogue_level(&u.uz))
  332.                      assign_graphics(ROGUESET);
  333.                  need_redraw = TRUE;
  334.              }
  335.          }
  336.          return;
  337.      }
  338.  
  339.      fullname = "symset";
  340.      if (match_optname(opts, fullname, 6, TRUE)) {
  341.          if (duplicate)
  342.              complain_about_duplicate(opts, 1);
  343.          if (negated) {
  344.              bad_negation(fullname, FALSE);
  345.          } else if ((op = string_for_opt(opts, FALSE)) != 0) {
  346.              symset[PRIMARY].name = dupstr(op);
  347.              if (!read_sym_file(PRIMARY)) {
  348.                  clear_symsetentry(PRIMARY, TRUE);
  349.                  raw_printf("Unable to load symbol set \"%s\" from \"%s\".",
  350.                             op, SYMBOLS);
  351.                  wait_synch();
  352.              } else {
  353.                  switch_symbols(TRUE);
  354.                  need_redraw = TRUE;
  355.              }
  356.          }
  357.          return;
  358.      }
  359.  
  360.      fullname = "runmode";
  361.      if (match_optname(opts, fullname, 4, TRUE)) {
  362.          if (duplicate)
  363.              complain_about_duplicate(opts, 1);
  364.          if (negated) {
  365.              flags.runmode = RUN_TPORT;
  366.          } else if ((op = string_for_opt(opts, FALSE)) != 0) {
  367.              if (!strncmpi(op, "teleport", strlen(op)))
  368.                  flags.runmode = RUN_TPORT;
  369.              else if (!strncmpi(op, "run", strlen(op)))
  370.                  flags.runmode = RUN_LEAP;
  371.              else if (!strncmpi(op, "walk", strlen(op)))
  372.                  flags.runmode = RUN_STEP;
  373.              else if (!strncmpi(op, "crawl", strlen(op)))
  374.                  flags.runmode = RUN_CRAWL;
  375.              else
  376.                  badoption(opts);
  377.          }
  378.          return;
  379.      }
  380.  
  381.      /* menucolor:"regex_string"=color */
  382.      fullname = "menucolor";
  383.      if (match_optname(opts, fullname, 9, TRUE)) {
  384.          if (negated)
  385.              bad_negation(fullname, FALSE);
  386.          else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
  387.              if (!add_menu_coloring(op))
  388.                  badoption(opts);
  389.          return;
  390.      }
  391.  
  392.      fullname = "msghistory";
  393.      if (match_optname(opts, fullname, 3, TRUE)) {
  394.          if (duplicate)
  395.              complain_about_duplicate(opts, 1);
  396.          op = string_for_env_opt(fullname, opts, negated);
  397.          if ((negated && !op) || (!negated && op)) {
  398.              iflags.msg_history = negated ? 0 : atoi(op);
  399.          } else if (negated)
  400.              bad_negation(fullname, TRUE);
  401.          return;
  402.      }
  403.  
  404.      fullname = "msg_window";
  405.      /* msg_window:single, combo, full or reversed */
  406.      if (match_optname(opts, fullname, 4, TRUE)) {
  407.  /* allow option to be silently ignored by non-tty ports */
  408.  #ifdef TTY_GRAPHICS
  409.          int tmp;
  410.  
  411.          if (duplicate)
  412.              complain_about_duplicate(opts, 1);
  413.          if (!(op = string_for_opt(opts, TRUE))) {
  414.              tmp = negated ? 's' : 'f';
  415.          } else {
  416.              if (negated) {
  417.                  bad_negation(fullname, TRUE);
  418.                  return;
  419.              }
  420.              tmp = tolower(*op);
  421.          }
  422.          switch (tmp) {
  423.          case 's': /* single message history cycle (default if negated) */
  424.              iflags.prevmsg_window = 's';
  425.              break;
  426.          case 'c': /* combination: two singles, then full page reversed */
  427.              iflags.prevmsg_window = 'c';
  428.              break;
  429.          case 'f': /* full page (default if no opts) */
  430.              iflags.prevmsg_window = 'f';
  431.              break;
  432.          case 'r': /* full page (reversed) */
  433.              iflags.prevmsg_window = 'r';
  434.              break;
  435.          default:
  436.              badoption(opts);
  437.          }
  438.  #endif
  439.          return;
  440.      }
  441.  
  442.      /* WINCAP
  443.       * setting font options  */
  444.      fullname = "font";
  445.      if (!strncmpi(opts, fullname, 4)) {
  446.          int opttype = -1;
  447.          char *fontopts = opts + 4;
  448.  
  449.          if (!strncmpi(fontopts, "map", 3) || !strncmpi(fontopts, "_map", 4))
  450.              opttype = MAP_OPTION;
  451.          else if (!strncmpi(fontopts, "message", 7)
  452.                   || !strncmpi(fontopts, "_message", 8))
  453.              opttype = MESSAGE_OPTION;
  454.          else if (!strncmpi(fontopts, "text", 4)
  455.                   || !strncmpi(fontopts, "_text", 5))
  456.              opttype = TEXT_OPTION;
  457.          else if (!strncmpi(fontopts, "menu", 4)
  458.                   || !strncmpi(fontopts, "_menu", 5))
  459.              opttype = MENU_OPTION;
  460.          else if (!strncmpi(fontopts, "status", 6)
  461.                   || !strncmpi(fontopts, "_status", 7))
  462.              opttype = STATUS_OPTION;
  463.          else if (!strncmpi(fontopts, "_size", 5)) {
  464.              if (!strncmpi(fontopts, "_size_map", 8))
  465.                  opttype = MAP_OPTION;
  466.              else if (!strncmpi(fontopts, "_size_message", 12))
  467.                  opttype = MESSAGE_OPTION;
  468.              else if (!strncmpi(fontopts, "_size_text", 9))
  469.                  opttype = TEXT_OPTION;
  470.              else if (!strncmpi(fontopts, "_size_menu", 9))
  471.                  opttype = MENU_OPTION;
  472.              else if (!strncmpi(fontopts, "_size_status", 11))
  473.                  opttype = STATUS_OPTION;
  474.              else {
  475.                  badoption(opts);
  476.                  return;
  477.              }
  478.              if (duplicate)
  479.                  complain_about_duplicate(opts, 1);
  480.              if (opttype > 0 && !negated
  481.                  && (op = string_for_opt(opts, FALSE)) != 0) {
  482.                  switch (opttype) {
  483.                  case MAP_OPTION:
  484.                      iflags.wc_fontsiz_map = atoi(op);
  485.                      break;
  486.                  case MESSAGE_OPTION:
  487.                      iflags.wc_fontsiz_message = atoi(op);
  488.                      break;
  489.                  case TEXT_OPTION:
  490.                      iflags.wc_fontsiz_text = atoi(op);
  491.                      break;
  492.                  case MENU_OPTION:
  493.                      iflags.wc_fontsiz_menu = atoi(op);
  494.                      break;
  495.                  case STATUS_OPTION:
  496.                      iflags.wc_fontsiz_status = atoi(op);
  497.                      break;
  498.                  }
  499.              }
  500.              return;
  501.          } else {
  502.              badoption(opts);
  503.          }
  504.          if (opttype > 0 && (op = string_for_opt(opts, FALSE)) != 0) {
  505.              wc_set_font_name(opttype, op);
  506.  #ifdef MAC
  507.              set_font_name(opttype, op);
  508.  #endif
  509.              return;
  510.          } else if (negated)
  511.              bad_negation(fullname, TRUE);
  512.          return;
  513.      }
  514.  #ifdef CHANGE_COLOR
  515.      if (match_optname(opts, "palette", 3, TRUE)
  516.  #ifdef MAC
  517.          || match_optname(opts, "hicolor", 3, TRUE)
  518.  #endif
  519.              ) {
  520.          int color_number, color_incr;
  521.  
  522.  #ifndef WIN32
  523.          if (duplicate)
  524.              complain_about_duplicate(opts, 1);
  525.  #endif
  526.  #ifdef MAC
  527.          if (match_optname(opts, "hicolor", 3, TRUE)) {
  528.              if (negated) {
  529.                  bad_negation("hicolor", FALSE);
  530.                  return;
  531.              }
  532.              color_number = CLR_MAX + 4; /* HARDCODED inverse number */
  533.              color_incr = -1;
  534.          } else {
  535.  #endif
  536.              if (negated) {
  537.                  bad_negation("palette", FALSE);
  538.                  return;
  539.              }
  540.              color_number = 0;
  541.              color_incr = 1;
  542.  #ifdef MAC
  543.          }
  544.  #endif
  545.  #ifdef WIN32
  546.          op = string_for_opt(opts, TRUE);
  547.          if (!alternative_palette(op))
  548.              badoption(opts);
  549.  #else
  550.          if ((op = string_for_opt(opts, FALSE)) != (char *) 0) {
  551.              char *pt = op;
  552.              int cnt, tmp, reverse;
  553.              long rgb;
  554.  
  555.              while (*pt && color_number >= 0) {
  556.                  cnt = 3;
  557.                  rgb = 0L;
  558.                  if (*pt == '-') {
  559.                      reverse = 1;
  560.                      pt++;
  561.                  } else {
  562.                      reverse = 0;
  563.                  }
  564.                  while (cnt-- > 0) {
  565.                      if (*pt && *pt != '/') {
  566.  #ifdef AMIGA
  567.                          rgb <<= 4;
  568.  #else
  569.                          rgb <<= 8;
  570.  #endif
  571.                          tmp = *(pt++);
  572.                          if (isalpha(tmp)) {
  573.                              tmp = (tmp + 9) & 0xf; /* Assumes ASCII... */
  574.                          } else {
  575.                              tmp &= 0xf; /* Digits in ASCII too... */
  576.                          }
  577.  #ifndef AMIGA
  578.                          /* Add an extra so we fill f -> ff and 0 -> 00 */
  579.                          rgb += tmp << 4;
  580.  #endif
  581.                          rgb += tmp;
  582.                      }
  583.                  }
  584.                  if (*pt == '/') {
  585.                      pt++;
  586.                  }
  587.                  change_color(color_number, rgb, reverse);
  588.                  color_number += color_incr;
  589.              }
  590.          }
  591.  #endif /* !WIN32 */
  592.          if (!initial) {
  593.              need_redraw = TRUE;
  594.          }
  595.          return;
  596.      }
  597.  #endif /* CHANGE_COLOR */
  598.  
  599.      if (match_optname(opts, "fruit", 2, TRUE)) {
  600.          struct fruit *forig = 0;
  601.          char empty_str = '\0';
  602.  
  603.          if (duplicate)
  604.              complain_about_duplicate(opts, 1);
  605.          op = string_for_opt(opts, negated);
  606.          if (negated) {
  607.              if (op) {
  608.                  bad_negation("fruit", TRUE);
  609.                  return;
  610.              }
  611.              op = &empty_str;
  612.              goto goodfruit;
  613.          }
  614.          if (!op)
  615.              return;
  616.          if (!initial) {
  617.              struct fruit *f;
  618.  
  619.              num = 0;
  620.              for (f = ffruit; f; f = f->nextf) {
  621.                  if (!strcmp(op, f->fname))
  622.                      break;
  623.                  num++;
  624.              }
  625.              if (!flags.made_fruit) {
  626.                  for (forig = ffruit; forig; forig = forig->nextf) {
  627.                      if (!strcmp(pl_fruit, forig->fname)) {
  628.                          break;
  629.                      }
  630.                  }
  631.              }
  632.              if (!forig && num >= 100) {
  633.                  pline("Doing that so many times isn't very fruitful.");
  634.                  return;
  635.              }
  636.          }
  637.      goodfruit:
  638.          nmcpy(pl_fruit, op, PL_FSIZ);
  639.          sanitize_name(pl_fruit);
  640.          /* OBJ_NAME(objects[SLIME_MOLD]) won't work after initialization */
  641.          if (!*pl_fruit)
  642.              nmcpy(pl_fruit, "slime mold", PL_FSIZ);
  643.          if (!initial) {
  644.              (void) fruitadd(pl_fruit, forig);
  645.              pline("Fruit is now \"%s\".", pl_fruit);
  646.          }
  647.          /* If initial, then initoptions is allowed to do it instead
  648.           * of here (initoptions always has to do it even if there's
  649.           * no fruit option at all.  Also, we don't want people
  650.           * setting multiple fruits in their options.)
  651.           */
  652.          return;
  653.      }
  654.  
  655.      fullname = "warnings";
  656.      if (match_optname(opts, fullname, 5, TRUE)) {
  657.          if (duplicate)
  658.              complain_about_duplicate(opts, 1);
  659.          if (negated)
  660.              bad_negation(fullname, FALSE);
  661.          else
  662.              warning_opts(opts, fullname);
  663.          return;
  664.      }
  665.  
  666.  #ifdef BACKWARD_COMPAT
  667.      /* boulder:symbol */
  668.      fullname = "boulder";
  669.      if (match_optname(opts, fullname, 7, TRUE)) {
  670.          int clash = 0;
  671.          if (duplicate)
  672.              complain_about_duplicate(opts, 1);
  673.          if (negated) {
  674.              bad_negation(fullname, FALSE);
  675.              return;
  676.          }
  677.          /* if (!(opts = string_for_env_opt(fullname, opts, FALSE)))
  678.           */
  679.          if (!(opts = string_for_opt(opts, FALSE)))
  680.              return;
  681.          escapes(opts, opts);
  682.          if (def_char_to_monclass(opts[0]) != MAXMCLASSES)
  683.              clash = 1;
  684.          else if (opts[0] >= '1' && opts[0] <= '5')
  685.              clash = 2;
  686.          if (clash) {
  687.              /* symbol chosen matches a used monster or warning
  688.                 symbol which is not good - reject it*/
  689.              pline(
  690.                  "Badoption - boulder symbol '%c' conflicts with a %s symbol.",
  691.                  opts[0], (clash == 1) ? "monster" : "warning");
  692.          } else {
  693.              /*
  694.               * Override the default boulder symbol.
  695.               */
  696.              iflags.bouldersym = (uchar) opts[0];
  697.          }
  698.          if (!initial)
  699.              need_redraw = TRUE;
  700.          return;
  701.      }
  702.  #endif
  703.  
  704.      /* name:string */
  705.      fullname = "name";
  706.      if (match_optname(opts, fullname, 4, TRUE)) {
  707.          if (duplicate)
  708.              complain_about_duplicate(opts, 1);
  709.          if (negated)
  710.              bad_negation(fullname, FALSE);
  711.          else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
  712.              nmcpy(plname, op, PL_NSIZ);
  713.          return;
  714.      }
  715.  
  716.      /* altkeyhandler:string */
  717.      fullname = "altkeyhandler";
  718.      if (match_optname(opts, fullname, 4, TRUE)) {
  719.          if (duplicate)
  720.              complain_about_duplicate(opts, 1);
  721.          if (negated) {
  722.              bad_negation(fullname, FALSE);
  723.          } else if ((op = string_for_opt(opts, negated)) != 0) {
  724.  #ifdef WIN32
  725.              (void) strncpy(iflags.altkeyhandler, op, MAX_ALTKEYHANDLER - 5);
  726.              load_keyboard_handler();
  727.  #endif
  728.          }
  729.          return;
  730.      }
  731.  
  732.      /* WINCAP
  733.       * align_status:[left|top|right|bottom] */
  734.      fullname = "align_status";
  735.      if (match_optname(opts, fullname, sizeof("align_status") - 1, TRUE)) {
  736.          op = string_for_opt(opts, negated);
  737.          if (op && !negated) {
  738.              if (!strncmpi(op, "left", sizeof("left") - 1))
  739.                  iflags.wc_align_status = ALIGN_LEFT;
  740.              else if (!strncmpi(op, "top", sizeof("top") - 1))
  741.                  iflags.wc_align_status = ALIGN_TOP;
  742.              else if (!strncmpi(op, "right", sizeof("right") - 1))
  743.                  iflags.wc_align_status = ALIGN_RIGHT;
  744.              else if (!strncmpi(op, "bottom", sizeof("bottom") - 1))
  745.                  iflags.wc_align_status = ALIGN_BOTTOM;
  746.              else
  747.                  badoption(opts);
  748.          } else if (negated)
  749.              bad_negation(fullname, TRUE);
  750.          return;
  751.      }
  752.      /* WINCAP
  753.       * align_message:[left|top|right|bottom] */
  754.      fullname = "align_message";
  755.      if (match_optname(opts, fullname, sizeof("align_message") - 1, TRUE)) {
  756.          if (duplicate)
  757.              complain_about_duplicate(opts, 1);
  758.          op = string_for_opt(opts, negated);
  759.          if (op && !negated) {
  760.              if (!strncmpi(op, "left", sizeof("left") - 1))
  761.                  iflags.wc_align_message = ALIGN_LEFT;
  762.              else if (!strncmpi(op, "top", sizeof("top") - 1))
  763.                  iflags.wc_align_message = ALIGN_TOP;
  764.              else if (!strncmpi(op, "right", sizeof("right") - 1))
  765.                  iflags.wc_align_message = ALIGN_RIGHT;
  766.              else if (!strncmpi(op, "bottom", sizeof("bottom") - 1))
  767.                  iflags.wc_align_message = ALIGN_BOTTOM;
  768.              else
  769.                  badoption(opts);
  770.          } else if (negated)
  771.              bad_negation(fullname, TRUE);
  772.          return;
  773.      }
  774.      /* the order to list the pack */
  775.      fullname = "packorder";
  776.      if (match_optname(opts, fullname, 4, TRUE)) {
  777.          if (duplicate)
  778.              complain_about_duplicate(opts, 1);
  779.          if (negated) {
  780.              bad_negation(fullname, FALSE);
  781.              return;
  782.          } else if (!(op = string_for_opt(opts, FALSE)))
  783.              return;
  784.  
  785.          if (!change_inv_order(op))
  786.              badoption(opts);
  787.          return;
  788.      }
  789.  
  790.      /* user can change required response for some prompts (quit, die, hit),
  791.         or add an extra prompt (pray, Remove) that isn't ordinarily there */
  792.      fullname = "paranoid_confirmation";
  793.      if (match_optname(opts, fullname, 8, TRUE)) {
  794.          /* at present we don't complain about duplicates for this
  795.             option, but we do throw away the old settings whenever
  796.             we process a new one [clearing old flags is essential
  797.             for handling default paranoid_confirm:pray sanely] */
  798.          flags.paranoia_bits = 0; /* clear all */
  799.          if (negated) {
  800.              flags.paranoia_bits = 0; /* [now redundant...] */
  801.          } else if ((op = string_for_opt(opts, TRUE)) != 0) {
  802.              char *pp, buf[BUFSZ];
  803.  
  804.              op = mungspaces(strcpy(buf, op));
  805.              for (;;) {
  806.                  /* We're looking to parse
  807.                     "paranoid_confirm:whichone wheretwo whothree"
  808.                     and "paranoid_confirm:" prefix has already
  809.                     been stripped off by the time we get here */
  810.                  pp = index(op, ' ');
  811.                  if (pp)
  812.                      *pp = '\0';
  813.                  /* we aren't matching option names but match_optname
  814.                     does what we want once we've broken the space
  815.                     delimited aggregate into separate tokens */
  816.                  for (i = 0; i < SIZE(paranoia); ++i) {
  817.                      if (match_optname(op, paranoia[i].argname,
  818.                                        paranoia[i].argMinLen, FALSE)
  819.                          || (paranoia[i].synonym
  820.                              && match_optname(op, paranoia[i].synonym,
  821.                                               paranoia[i].synMinLen, FALSE))) {
  822.                          if (paranoia[i].flagmask)
  823.                              flags.paranoia_bits |= paranoia[i].flagmask;
  824.                          else /* 0 == "none", so clear all */
  825.                              flags.paranoia_bits = 0;
  826.                          break;
  827.                      }
  828.                  }
  829.                  if (i == SIZE(paranoia)) {
  830.                      /* didn't match anything, so arg is bad;
  831.                         any flags already set will stay set */
  832.                      badoption(opts);
  833.                      break;
  834.                  }
  835.                  /* move on to next token */
  836.                  if (pp)
  837.                      op = pp + 1;
  838.                  else
  839.                      break; /* no next token */
  840.              }              /* for(;;) */
  841.          }
  842.          return;
  843.      }
  844.  
  845.      /* accept deprecated boolean; superseded by paranoid_confirm:pray */
  846.      fullname = "prayconfirm";
  847.      if (match_optname(opts, fullname, 4, FALSE)) {
  848.          if (negated)
  849.              flags.paranoia_bits &= ~PARANOID_PRAY;
  850.          else
  851.              flags.paranoia_bits |= PARANOID_PRAY;
  852.          return;
  853.      }
  854.  
  855.      /* maximum burden picked up before prompt (Warren Cheung) */
  856.      fullname = "pickup_burden";
  857.      if (match_optname(opts, fullname, 8, TRUE)) {
  858.          if (duplicate)
  859.              complain_about_duplicate(opts, 1);
  860.          if (negated) {
  861.              bad_negation(fullname, FALSE);
  862.              return;
  863.          } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
  864.              switch (tolower(*op)) {
  865.              /* Unencumbered */
  866.              case 'u':
  867.                  flags.pickup_burden = UNENCUMBERED;
  868.                  break;
  869.              /* Burdened (slight encumbrance) */
  870.              case 'b':
  871.                  flags.pickup_burden = SLT_ENCUMBER;
  872.                  break;
  873.              /* streSsed (moderate encumbrance) */
  874.              case 's':
  875.                  flags.pickup_burden = MOD_ENCUMBER;
  876.                  break;
  877.              /* straiNed (heavy encumbrance) */
  878.              case 'n':
  879.                  flags.pickup_burden = HVY_ENCUMBER;
  880.                  break;
  881.              /* OverTaxed (extreme encumbrance) */
  882.              case 'o':
  883.              case 't':
  884.                  flags.pickup_burden = EXT_ENCUMBER;
  885.                  break;
  886.              /* overLoaded */
  887.              case 'l':
  888.                  flags.pickup_burden = OVERLOADED;
  889.                  break;
  890.              default:
  891.                  badoption(opts);
  892.              }
  893.          }
  894.          return;
  895.      }
  896.  
  897.      /* types of objects to pick up automatically */
  898.      if (match_optname(opts, "pickup_types", 8, TRUE)) {
  899.          char ocl[MAXOCLASSES + 1], tbuf[MAXOCLASSES + 1], qbuf[QBUFSZ],
  900.              abuf[BUFSZ];
  901.          int oc_sym;
  902.          boolean badopt = FALSE, compat = (strlen(opts) <= 6), use_menu;
  903.  
  904.          if (duplicate)
  905.              complain_about_duplicate(opts, 1);
  906.          oc_to_str(flags.pickup_types, tbuf);
  907.          flags.pickup_types[0] = '\0'; /* all */
  908.          op = string_for_opt(opts, (compat || !initial));
  909.          if (!op) {
  910.              if (compat || negated || initial) {
  911.                  /* for backwards compatibility, "pickup" without a
  912.                     value is a synonym for autopickup of all types
  913.                     (and during initialization, we can't prompt yet) */
  914.                  flags.pickup = !negated;
  915.                  return;
  916.              }
  917.              oc_to_str(flags.inv_order, ocl);
  918.              use_menu = TRUE;
  919.              if (flags.menu_style == MENU_TRADITIONAL
  920.                  || flags.menu_style == MENU_COMBINATION) {
  921.                  use_menu = FALSE;
  922.                  Sprintf(qbuf, "New pickup_types: [%s am] (%s)", ocl,
  923.                          *tbuf ? tbuf : "all");
  924.                  getlin(qbuf, abuf);
  925.                  op = mungspaces(abuf);
  926.                  if (abuf[0] == '\0' || abuf[0] == '\033')
  927.                      op = tbuf; /* restore */
  928.                  else if (abuf[0] == 'm')
  929.                      use_menu = TRUE;
  930.              }
  931.              if (use_menu) {
  932.                  (void) choose_classes_menu("Auto-Pickup what?", 1, TRUE, ocl,
  933.                                             tbuf);
  934.                  op = tbuf;
  935.              }
  936.          }
  937.          if (negated) {
  938.              bad_negation("pickup_types", TRUE);
  939.              return;
  940.          }
  941.          while (*op == ' ')
  942.              op++;
  943.          if (*op != 'a' && *op != 'A') {
  944.              num = 0;
  945.              while (*op) {
  946.                  oc_sym = def_char_to_objclass(*op);
  947.                  /* make sure all are valid obj symbols occurring once */
  948.                  if (oc_sym != MAXOCLASSES
  949.                      && !index(flags.pickup_types, oc_sym)) {
  950.                      flags.pickup_types[num] = (char) oc_sym;
  951.                      flags.pickup_types[++num] = '\0';
  952.                  } else
  953.                      badopt = TRUE;
  954.                  op++;
  955.              }
  956.              if (badopt)
  957.                  badoption(opts);
  958.          }
  959.          return;
  960.      }
  961.  
  962.      /* pile limit: when walking over objects, number which triggers
  963.         "there are several/many objects here" instead of listing them */
  964.      fullname = "pile_limit";
  965.      if (match_optname(opts, fullname, 4, TRUE)) {
  966.          if (duplicate)
  967.              complain_about_duplicate(opts, 1);
  968.          op = string_for_opt(opts, negated);
  969.          if ((negated && !op) || (!negated && op))
  970.              flags.pile_limit = negated ? 0 : atoi(op);
  971.          else if (negated)
  972.              bad_negation(fullname, TRUE);
  973.          else /* !op */
  974.              flags.pile_limit = PILE_LIMIT_DFLT;
  975.          /* sanity check */
  976.          if (flags.pile_limit < 0)
  977.              flags.pile_limit = PILE_LIMIT_DFLT;
  978.          return;
  979.      }
  980.  
  981.      /* play mode: normal, explore/discovery, or debug/wizard */
  982.      fullname = "playmode";
  983.      if (match_optname(opts, fullname, 4, TRUE)) {
  984.          if (duplicate)
  985.              complain_about_duplicate(opts, 1);
  986.          if (negated)
  987.              bad_negation(fullname, FALSE);
  988.          if (duplicate || negated)
  989.              return;
  990.          op = string_for_opt(opts, TRUE);
  991.          if (!strncmpi(op, "normal", 6) || !strcmpi(op, "play")) {
  992.              wizard = discover = FALSE;
  993.          } else if (!strncmpi(op, "explore", 6)
  994.                     || !strncmpi(op, "discovery", 6)) {
  995.              wizard = FALSE, discover = TRUE;
  996.          } else if (!strncmpi(op, "debug", 5) || !strncmpi(op, "wizard", 6)) {
  997.              wizard = TRUE, discover = FALSE;
  998.          } else {
  999.              raw_printf("Invalid value for \"%s\":%s.", fullname, op);
  1000.          }
  1001.          return;
  1002.      }
  1003.  
  1004.      /* WINCAP
  1005.       * player_selection: dialog | prompts */
  1006.      fullname = "player_selection";
  1007.      if (match_optname(opts, fullname, sizeof("player_selection") - 1, TRUE)) {
  1008.          if (duplicate)
  1009.              complain_about_duplicate(opts, 1);
  1010.          op = string_for_opt(opts, negated);
  1011.          if (op && !negated) {
  1012.              if (!strncmpi(op, "dialog", sizeof("dialog") - 1))
  1013.                  iflags.wc_player_selection = VIA_DIALOG;
  1014.              else if (!strncmpi(op, "prompt", sizeof("prompt") - 1))
  1015.                  iflags.wc_player_selection = VIA_PROMPTS;
  1016.              else
  1017.                  badoption(opts);
  1018.          } else if (negated)
  1019.              bad_negation(fullname, TRUE);
  1020.          return;
  1021.      }
  1022.  
  1023.      /* things to disclose at end of game */
  1024.      if (match_optname(opts, "disclose", 7, TRUE)) {
  1025.          /*
  1026.           * The order that the end_disclose options are stored:
  1027.           *      inventory, attribs, vanquished, genocided,
  1028.           *      conduct, overview.
  1029.           * There is an array in flags:
  1030.           *      end_disclose[NUM_DISCLOSURE_OPT];
  1031.           * with option settings for the each of the following:
  1032.           * iagvc [see disclosure_options in decl.c]:
  1033.           * Legal setting values in that array are:
  1034.           *      DISCLOSE_PROMPT_DEFAULT_YES  ask with default answer yes
  1035.           *      DISCLOSE_PROMPT_DEFAULT_NO   ask with default answer no
  1036.           *      DISCLOSE_YES_WITHOUT_PROMPT  always disclose and don't ask
  1037.           *      DISCLOSE_NO_WITHOUT_PROMPT   never disclose and don't ask
  1038.           *
  1039.           * Those setting values can be used in the option
  1040.           * string as a prefix to get the desired behaviour.
  1041.           *
  1042.           * For backward compatibility, no prefix is required,
  1043.           * and the presence of a i,a,g,v, or c without a prefix
  1044.           * sets the corresponding value to DISCLOSE_YES_WITHOUT_PROMPT.
  1045.           */
  1046.          boolean badopt = FALSE;
  1047.          int idx, prefix_val;
  1048.  
  1049.          if (duplicate)
  1050.              complain_about_duplicate(opts, 1);
  1051.          op = string_for_opt(opts, TRUE);
  1052.          if (op && negated) {
  1053.              bad_negation("disclose", TRUE);
  1054.              return;
  1055.          }
  1056.          /* "disclose" without a value means "all with prompting"
  1057.             and negated means "none without prompting" */
  1058.          if (!op || !strcmpi(op, "all") || !strcmpi(op, "none")) {
  1059.              if (op && !strcmpi(op, "none"))
  1060.                  negated = TRUE;
  1061.              for (num = 0; num < NUM_DISCLOSURE_OPTIONS; num++)
  1062.                  flags.end_disclose[num] = negated
  1063.                                                ? DISCLOSE_NO_WITHOUT_PROMPT
  1064.                                                : DISCLOSE_PROMPT_DEFAULT_YES;
  1065.              return;
  1066.          }
  1067.  
  1068.          num = 0;
  1069.          prefix_val = -1;
  1070.          while (*op && num < sizeof flags.end_disclose - 1) {
  1071.              static char valid_settings[] = {
  1072.                  DISCLOSE_PROMPT_DEFAULT_YES, DISCLOSE_PROMPT_DEFAULT_NO,
  1073.                  DISCLOSE_YES_WITHOUT_PROMPT, DISCLOSE_NO_WITHOUT_PROMPT, '\0'
  1074.              };
  1075.              register char c, *dop;
  1076.  
  1077.              c = lowc(*op);
  1078.              if (c == 'k')
  1079.                  c = 'v'; /* killed -> vanquished */
  1080.              if (c == 'd')
  1081.                  c = 'o'; /* dungeon -> overview */
  1082.              dop = index(disclosure_options, c);
  1083.              if (dop) {
  1084.                  idx = (int) (dop - disclosure_options);
  1085.                  if (idx < 0 || idx > NUM_DISCLOSURE_OPTIONS - 1) {
  1086.                      impossible("bad disclosure index %d %c", idx, c);
  1087.                      continue;
  1088.                  }
  1089.                  if (prefix_val != -1) {
  1090.                      flags.end_disclose[idx] = prefix_val;
  1091.                      prefix_val = -1;
  1092.                  } else
  1093.                      flags.end_disclose[idx] = DISCLOSE_YES_WITHOUT_PROMPT;
  1094.              } else if (index(valid_settings, c)) {
  1095.                  prefix_val = c;
  1096.              } else if (c == ' ') {
  1097.                  ; /* do nothing */
  1098.              } else
  1099.                  badopt = TRUE;
  1100.              op++;
  1101.          }
  1102.          if (badopt)
  1103.              badoption(opts);
  1104.          return;
  1105.      }
  1106.  
  1107.      /* scores:5t[op] 5a[round] o[wn] */
  1108.      if (match_optname(opts, "scores", 4, TRUE)) {
  1109.          if (duplicate)
  1110.              complain_about_duplicate(opts, 1);
  1111.          if (negated) {
  1112.              bad_negation("scores", FALSE);
  1113.              return;
  1114.          }
  1115.          if (!(op = string_for_opt(opts, FALSE)))
  1116.              return;
  1117.  
  1118.          while (*op) {
  1119.              int inum = 1;
  1120.  
  1121.              if (digit(*op)) {
  1122.                  inum = atoi(op);
  1123.                  while (digit(*op))
  1124.                      op++;
  1125.              } else if (*op == '!') {
  1126.                  negated = !negated;
  1127.                  op++;
  1128.              }
  1129.              while (*op == ' ')
  1130.                  op++;
  1131.  
  1132.              switch (*op) {
  1133.              case 't':
  1134.              case 'T':
  1135.                  flags.end_top = inum;
  1136.                  break;
  1137.              case 'a':
  1138.              case 'A':
  1139.                  flags.end_around = inum;
  1140.                  break;
  1141.              case 'o':
  1142.              case 'O':
  1143.                  flags.end_own = !negated;
  1144.                  break;
  1145.              default:
  1146.                  badoption(opts);
  1147.                  return;
  1148.              }
  1149.              while (letter(*++op) || *op == ' ')
  1150.                  continue;
  1151.              if (*op == '/')
  1152.                  op++;
  1153.          }
  1154.          return;
  1155.      }
  1156.  
  1157.      fullname = "sortloot";
  1158.      if (match_optname(opts, fullname, 4, TRUE)) {
  1159.          op = string_for_env_opt(fullname, opts, FALSE);
  1160.          if (op) {
  1161.              switch (tolower(*op)) {
  1162.              case 'n':
  1163.              case 'l':
  1164.              case 'f':
  1165.                  flags.sortloot = tolower(*op);
  1166.                  break;
  1167.              default:
  1168.                  badoption(opts);
  1169.                  return;
  1170.              }
  1171.          }
  1172.          return;
  1173.      }
  1174.  
  1175.      fullname = "suppress_alert";
  1176.      if (match_optname(opts, fullname, 4, TRUE)) {
  1177.          if (duplicate)
  1178.              complain_about_duplicate(opts, 1);
  1179.          op = string_for_opt(opts, negated);
  1180.          if (negated)
  1181.              bad_negation(fullname, FALSE);
  1182.          else if (op)
  1183.              (void) feature_alert_opts(op, fullname);
  1184.          return;
  1185.      }
  1186.  
  1187.  #ifdef VIDEOSHADES
  1188.      /* videocolors:string */
  1189.      fullname = "videocolors";
  1190.      if (match_optname(opts, fullname, 6, TRUE)
  1191.          || match_optname(opts, "videocolours", 10, TRUE)) {
  1192.          if (duplicate)
  1193.              complain_about_duplicate(opts, 1);
  1194.          if (negated) {
  1195.              bad_negation(fullname, FALSE);
  1196.              return;
  1197.          } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
  1198.              return;
  1199.          }
  1200.          if (!assign_videocolors(opts))
  1201.              badoption(opts);
  1202.          return;
  1203.      }
  1204.      /* videoshades:string */
  1205.      fullname = "videoshades";
  1206.      if (match_optname(opts, fullname, 6, TRUE)) {
  1207.          if (duplicate)
  1208.              complain_about_duplicate(opts, 1);
  1209.          if (negated) {
  1210.              bad_negation(fullname, FALSE);
  1211.              return;
  1212.          } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
  1213.              return;
  1214.          }
  1215.          if (!assign_videoshades(opts))
  1216.              badoption(opts);
  1217.          return;
  1218.      }
  1219.  #endif /* VIDEOSHADES */
  1220.  #ifdef MSDOS
  1221.  #ifdef NO_TERMS
  1222.      /* video:string -- must be after longer tests */
  1223.      fullname = "video";
  1224.      if (match_optname(opts, fullname, 5, TRUE)) {
  1225.          if (duplicate)
  1226.              complain_about_duplicate(opts, 1);
  1227.          if (negated) {
  1228.              bad_negation(fullname, FALSE);
  1229.              return;
  1230.          } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
  1231.              return;
  1232.          }
  1233.          if (!assign_video(opts))
  1234.              badoption(opts);
  1235.          return;
  1236.      }
  1237.  #endif /* NO_TERMS */
  1238.      /* soundcard:string -- careful not to match boolean 'sound' */
  1239.      fullname = "soundcard";
  1240.      if (match_optname(opts, fullname, 6, TRUE)) {
  1241.          if (duplicate)
  1242.              complain_about_duplicate(opts, 1);
  1243.          if (negated) {
  1244.              bad_negation(fullname, FALSE);
  1245.              return;
  1246.          } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
  1247.              return;
  1248.          }
  1249.          if (!assign_soundcard(opts))
  1250.              badoption(opts);
  1251.          return;
  1252.      }
  1253.  #endif /* MSDOS */
  1254.  
  1255.      /* WINCAP
  1256.       *
  1257.       *  map_mode:[tiles|ascii4x6|ascii6x8|ascii8x8|ascii16x8|ascii7x12|
  1258.       *            ascii8x12|ascii16x12|ascii12x16|ascii10x18|fit_to_screen]
  1259.       */
  1260.      fullname = "map_mode";
  1261.      if (match_optname(opts, fullname, sizeof("map_mode") - 1, TRUE)) {
  1262.          if (duplicate)
  1263.              complain_about_duplicate(opts, 1);
  1264.          op = string_for_opt(opts, negated);
  1265.          if (op && !negated) {
  1266.              if (!strncmpi(op, "tiles", sizeof("tiles") - 1))
  1267.                  iflags.wc_map_mode = MAP_MODE_TILES;
  1268.              else if (!strncmpi(op, "ascii4x6", sizeof("ascii4x6") - 1))
  1269.                  iflags.wc_map_mode = MAP_MODE_ASCII4x6;
  1270.              else if (!strncmpi(op, "ascii6x8", sizeof("ascii6x8") - 1))
  1271.                  iflags.wc_map_mode = MAP_MODE_ASCII6x8;
  1272.              else if (!strncmpi(op, "ascii8x8", sizeof("ascii8x8") - 1))
  1273.                  iflags.wc_map_mode = MAP_MODE_ASCII8x8;
  1274.              else if (!strncmpi(op, "ascii16x8", sizeof("ascii16x8") - 1))
  1275.                  iflags.wc_map_mode = MAP_MODE_ASCII16x8;
  1276.              else if (!strncmpi(op, "ascii7x12", sizeof("ascii7x12") - 1))
  1277.                  iflags.wc_map_mode = MAP_MODE_ASCII7x12;
  1278.              else if (!strncmpi(op, "ascii8x12", sizeof("ascii8x12") - 1))
  1279.                  iflags.wc_map_mode = MAP_MODE_ASCII8x12;
  1280.              else if (!strncmpi(op, "ascii16x12", sizeof("ascii16x12") - 1))
  1281.                  iflags.wc_map_mode = MAP_MODE_ASCII16x12;
  1282.              else if (!strncmpi(op, "ascii12x16", sizeof("ascii12x16") - 1))
  1283.                  iflags.wc_map_mode = MAP_MODE_ASCII12x16;
  1284.              else if (!strncmpi(op, "ascii10x18", sizeof("ascii10x18") - 1))
  1285.                  iflags.wc_map_mode = MAP_MODE_ASCII10x18;
  1286.              else if (!strncmpi(op, "fit_to_screen",
  1287.                                 sizeof("fit_to_screen") - 1))
  1288.                  iflags.wc_map_mode = MAP_MODE_ASCII_FIT_TO_SCREEN;
  1289.              else
  1290.                  badoption(opts);
  1291.          } else if (negated)
  1292.              bad_negation(fullname, TRUE);
  1293.          return;
  1294.      }
  1295.      /* WINCAP
  1296.       * scroll_amount:nn */
  1297.      fullname = "scroll_amount";
  1298.      if (match_optname(opts, fullname, sizeof("scroll_amount") - 1, TRUE)) {
  1299.          if (duplicate)
  1300.              complain_about_duplicate(opts, 1);
  1301.          op = string_for_opt(opts, negated);
  1302.          if ((negated && !op) || (!negated && op)) {
  1303.              iflags.wc_scroll_amount = negated ? 1 : atoi(op);
  1304.          } else if (negated)
  1305.              bad_negation(fullname, TRUE);
  1306.          return;
  1307.      }
  1308.      /* WINCAP
  1309.       * scroll_margin:nn */
  1310.      fullname = "scroll_margin";
  1311.      if (match_optname(opts, fullname, sizeof("scroll_margin") - 1, TRUE)) {
  1312.          if (duplicate)
  1313.              complain_about_duplicate(opts, 1);
  1314.          op = string_for_opt(opts, negated);
  1315.          if ((negated && !op) || (!negated && op)) {
  1316.              iflags.wc_scroll_margin = negated ? 5 : atoi(op);
  1317.          } else if (negated)
  1318.              bad_negation(fullname, TRUE);
  1319.          return;
  1320.      }
  1321.      fullname = "subkeyvalue";
  1322.      if (match_optname(opts, fullname, 5, TRUE)) {
  1323.          /* no duplicate complaint here */
  1324.          if (negated) {
  1325.              bad_negation(fullname, FALSE);
  1326.          } else {
  1327.  #if defined(WIN32)
  1328.              op = string_for_opt(opts, 0);
  1329.              map_subkeyvalue(op);
  1330.  #endif
  1331.          }
  1332.          return;
  1333.      }
  1334.      /* WINCAP
  1335.       * tile_width:nn */
  1336.      fullname = "tile_width";
  1337.      if (match_optname(opts, fullname, sizeof("tile_width") - 1, TRUE)) {
  1338.          if (duplicate)
  1339.              complain_about_duplicate(opts, 1);
  1340.          op = string_for_opt(opts, negated);
  1341.          if ((negated && !op) || (!negated && op)) {
  1342.              iflags.wc_tile_width = negated ? 0 : atoi(op);
  1343.          } else if (negated)
  1344.              bad_negation(fullname, TRUE);
  1345.          return;
  1346.      }
  1347.      /* WINCAP
  1348.       * tile_file:name */
  1349.      fullname = "tile_file";
  1350.      if (match_optname(opts, fullname, sizeof("tile_file") - 1, TRUE)) {
  1351.          if (duplicate)
  1352.              complain_about_duplicate(opts, 1);
  1353.          if ((op = string_for_opt(opts, FALSE)) != 0) {
  1354.              if (iflags.wc_tile_file)
  1355.                  free(iflags.wc_tile_file);
  1356.              iflags.wc_tile_file = (char *) alloc(strlen(op) + 1);
  1357.              Strcpy(iflags.wc_tile_file, op);
  1358.          }
  1359.          return;
  1360.      }
  1361.      /* WINCAP
  1362.       * tile_height:nn */
  1363.      fullname = "tile_height";
  1364.      if (match_optname(opts, fullname, sizeof("tile_height") - 1, TRUE)) {
  1365.          if (duplicate)
  1366.              complain_about_duplicate(opts, 1);
  1367.          op = string_for_opt(opts, negated);
  1368.          if ((negated && !op) || (!negated && op)) {
  1369.              iflags.wc_tile_height = negated ? 0 : atoi(op);
  1370.          } else if (negated)
  1371.              bad_negation(fullname, TRUE);
  1372.          return;
  1373.      }
  1374.      /* WINCAP
  1375.       * vary_msgcount:nn */
  1376.      fullname = "vary_msgcount";
  1377.      if (match_optname(opts, fullname, sizeof("vary_msgcount") - 1, TRUE)) {
  1378.          if (duplicate)
  1379.              complain_about_duplicate(opts, 1);
  1380.          op = string_for_opt(opts, negated);
  1381.          if ((negated && !op) || (!negated && op)) {
  1382.              iflags.wc_vary_msgcount = negated ? 0 : atoi(op);
  1383.          } else if (negated)
  1384.              bad_negation(fullname, TRUE);
  1385.          return;
  1386.      }
  1387.      fullname = "windowtype";
  1388.      if (match_optname(opts, fullname, 3, TRUE)) {
  1389.          if (duplicate)
  1390.              complain_about_duplicate(opts, 1);
  1391.          if (negated) {
  1392.              bad_negation(fullname, FALSE);
  1393.              return;
  1394.          } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
  1395.              char buf[WINTYPELEN];
  1396.              nmcpy(buf, op, WINTYPELEN);
  1397.              choose_windows(buf);
  1398.          }
  1399.          return;
  1400.      }
  1401.  #ifdef WINCHAIN
  1402.      fullname = "windowchain";
  1403.      if (match_optname(opts, fullname, 3, TRUE)) {
  1404.          if (negated) {
  1405.              bad_negation(fullname, FALSE);
  1406.              return;
  1407.          } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
  1408.              char buf[WINTYPELEN];
  1409.              nmcpy(buf, op, WINTYPELEN);
  1410.              addto_windowchain(buf);
  1411.          }
  1412.          return;
  1413.      }
  1414.  #endif
  1415.  
  1416.      /* WINCAP
  1417.       * setting window colors
  1418.       * syntax: windowcolors=menu foregrnd/backgrnd text foregrnd/backgrnd
  1419.       */
  1420.      fullname = "windowcolors";
  1421.      if (match_optname(opts, fullname, 7, TRUE)) {
  1422.          if (duplicate)
  1423.              complain_about_duplicate(opts, 1);
  1424.          if ((op = string_for_opt(opts, FALSE)) != 0) {
  1425.              if (!wc_set_window_colors(op))
  1426.                  badoption(opts);
  1427.          } else if (negated)
  1428.              bad_negation(fullname, TRUE);
  1429.          return;
  1430.      }
  1431.  
  1432.      /* menustyle:traditional or combination or full or partial */
  1433.      if (match_optname(opts, "menustyle", 4, TRUE)) {
  1434.          int tmp;
  1435.          boolean val_required = (strlen(opts) > 5 && !negated);
  1436.  
  1437.          if (duplicate)
  1438.              complain_about_duplicate(opts, 1);
  1439.          if (!(op = string_for_opt(opts, !val_required))) {
  1440.              if (val_required)
  1441.                  return; /* string_for_opt gave feedback */
  1442.              tmp = negated ? 'n' : 'f';
  1443.          } else {
  1444.              tmp = tolower(*op);
  1445.          }
  1446.          switch (tmp) {
  1447.          case 'n': /* none */
  1448.          case 't': /* traditional */
  1449.              flags.menu_style = MENU_TRADITIONAL;
  1450.              break;
  1451.          case 'c': /* combo: trad.class sel+menu */
  1452.              flags.menu_style = MENU_COMBINATION;
  1453.              break;
  1454.          case 'p': /* partial: no class menu */
  1455.              flags.menu_style = MENU_PARTIAL;
  1456.              break;
  1457.          case 'f': /* full: class menu + menu */
  1458.              flags.menu_style = MENU_FULL;
  1459.              break;
  1460.          default:
  1461.              badoption(opts);
  1462.          }
  1463.          return;
  1464.      }
  1465.  
  1466.      fullname = "menu_headings";
  1467.      if (match_optname(opts, fullname, 12, TRUE)) {
  1468.          if (duplicate)
  1469.              complain_about_duplicate(opts, 1);
  1470.          if (negated) {
  1471.              bad_negation(fullname, FALSE);
  1472.              return;
  1473.          } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
  1474.              return;
  1475.          }
  1476.          for (i = 0; i < SIZE(attrnames); i++)
  1477.              if (!strcmpi(opts, attrnames[i].name)) {
  1478.                  iflags.menu_headings = attrnames[i].attr;
  1479.                  return;
  1480.              }
  1481.          badoption(opts);
  1482.          return;
  1483.      }
  1484.  
  1485.      /* check for menu command mapping */
  1486.      for (i = 0; i < NUM_MENU_CMDS; i++) {
  1487.          fullname = default_menu_cmd_info[i].name;
  1488.          if (duplicate)
  1489.              complain_about_duplicate(opts, 1);
  1490.          if (match_optname(opts, fullname, (int) strlen(fullname), TRUE)) {
  1491.              if (negated) {
  1492.                  bad_negation(fullname, FALSE);
  1493.              } else if ((op = string_for_opt(opts, FALSE)) != 0) {
  1494.                  int j;
  1495.                  char c, op_buf[BUFSZ];
  1496.                  boolean isbad = FALSE;
  1497.  
  1498.                  escapes(op, op_buf);
  1499.                  c = *op_buf;
  1500.  
  1501.                  if (c == 0 || c == '\r' || c == '\n' || c == '\033'
  1502.                      || c == ' ' || digit(c) || (letter(c) && c != '@'))
  1503.                      isbad = TRUE;
  1504.                  else /* reject default object class symbols */
  1505.                      for (j = 1; j < MAXOCLASSES; j++)
  1506.                          if (c == def_oc_syms[i].sym) {
  1507.                              isbad = TRUE;
  1508.                              break;
  1509.                          }
  1510.  
  1511.                  if (isbad)
  1512.                      badoption(opts);
  1513.                  else
  1514.                      add_menu_cmd_alias(c, default_menu_cmd_info[i].cmd);
  1515.              }
  1516.              return;
  1517.          }
  1518.      }
  1519.  #if defined(STATUS_VIA_WINDOWPORT) && defined(STATUS_HILITES)
  1520.      /* hilite fields in status prompt */
  1521.      if (match_optname(opts, "hilite_status", 13, TRUE)) {
  1522.          if (duplicate)
  1523.              complain_about_duplicate(opts, 1);
  1524.          op = string_for_opt(opts, TRUE);
  1525.          if (op && negated) {
  1526.              clear_status_hilites(tfrom_file);
  1527.              return;
  1528.          } else if (!op) {
  1529.              /* a value is mandatory */
  1530.              badoption(opts);
  1531.              return;
  1532.          }
  1533.          if (!set_status_hilites(op, tfrom_file))
  1534.              badoption(opts);
  1535.          return;
  1536.      }
  1537.  #endif
  1538.  
  1539.  #if defined(BACKWARD_COMPAT)
  1540.      fullname = "DECgraphics";
  1541.      if (match_optname(opts, fullname, 3, TRUE)) {
  1542.          boolean badflag = FALSE;
  1543.  
  1544.          if (duplicate)
  1545.              complain_about_duplicate(opts, 1);
  1546.          if (!negated) {
  1547.              /* There is no rogue level DECgraphics-specific set */
  1548.              if (symset[PRIMARY].name) {
  1549.                  badflag = TRUE;
  1550.              } else {
  1551.                  symset[PRIMARY].name = dupstr(fullname);
  1552.                  if (!read_sym_file(PRIMARY)) {
  1553.                      badflag = TRUE;
  1554.                      clear_symsetentry(PRIMARY, TRUE);
  1555.                  } else
  1556.                      switch_symbols(TRUE);
  1557.              }
  1558.              if (badflag) {
  1559.                  pline("Failure to load symbol set %s.", fullname);
  1560.                  wait_synch();
  1561.              }
  1562.          }
  1563.          return;
  1564.      }
  1565.      fullname = "IBMgraphics";
  1566.      if (match_optname(opts, fullname, 3, TRUE)) {
  1567.          const char *sym_name = fullname;
  1568.          boolean badflag = FALSE;
  1569.  
  1570.          if (duplicate)
  1571.              complain_about_duplicate(opts, 1);
  1572.          if (!negated) {
  1573.              for (i = 0; i < NUM_GRAPHICS; ++i) {
  1574.                  if (symset[i].name) {
  1575.                      badflag = TRUE;
  1576.                  } else {
  1577.                      if (i == ROGUESET)
  1578.                          sym_name = "RogueIBM";
  1579.                      symset[i].name = dupstr(sym_name);
  1580.                      if (!read_sym_file(i)) {
  1581.                          badflag = TRUE;
  1582.                          clear_symsetentry(i, TRUE);
  1583.                          break;
  1584.                      }
  1585.                  }
  1586.              }
  1587.              if (badflag) {
  1588.                  pline("Failure to load symbol set %s.", sym_name);
  1589.                  wait_synch();
  1590.              } else {
  1591.                  switch_symbols(TRUE);
  1592.                  if (!initial && Is_rogue_level(&u.uz))
  1593.                      assign_graphics(ROGUESET);
  1594.              }
  1595.          }
  1596.          return;
  1597.      }
  1598.  #endif
  1599.  #ifdef MAC_GRAPHICS_ENV
  1600.      fullname = "MACgraphics";
  1601.      if (match_optname(opts, fullname, 3, TRUE)) {
  1602.          boolean badflag = FALSE;
  1603.  
  1604.          if (duplicate)
  1605.              complain_about_duplicate(opts, 1);
  1606.          if (!negated) {
  1607.              if (symset[PRIMARY].name) {
  1608.                  badflag = TRUE;
  1609.              } else {
  1610.                  symset[PRIMARY].name = dupstr(fullname);
  1611.                  if (!read_sym_file(PRIMARY)) {
  1612.                      badflag = TRUE;
  1613.                      clear_symsetentry(PRIMARY, TRUE);
  1614.                  }
  1615.              }
  1616.              if (badflag) {
  1617.                  pline("Failure to load symbol set %s.", fullname);
  1618.                  wait_synch();
  1619.              } else {
  1620.                  switch_symbols(TRUE);
  1621.                  if (!initial && Is_rogue_level(&u.uz))
  1622.                      assign_graphics(ROGUESET);
  1623.              }
  1624.          }
  1625.          return;
  1626.      }
  1627.  #endif
  1628.  
  1629.      /* OK, if we still haven't recognized the option, check the boolean
  1630.       * options list
  1631.       */
  1632.      for (i = 0; boolopt[i].name; i++) {
  1633.          if (match_optname(opts, boolopt[i].name, 3, FALSE)) {
  1634.              /* options that don't exist */
  1635.              if (!boolopt[i].addr) {
  1636.                  if (!initial && !negated)
  1637.                      pline_The("\"%s\" option is not available.",
  1638.                                boolopt[i].name);
  1639.                  return;
  1640.              }
  1641.              /* options that must come from config file */
  1642.              if (!initial && (boolopt[i].optflags == SET_IN_FILE)) {
  1643.                  rejectoption(boolopt[i].name);
  1644.                  return;
  1645.              }
  1646.  
  1647.              *(boolopt[i].addr) = !negated;
  1648.  
  1649.              /* 0 means boolean opts */
  1650.              if (duplicate_opt_detection(boolopt[i].name, 0))
  1651.                  complain_about_duplicate(boolopt[i].name, 0);
  1652.  
  1653.  #ifdef RLECOMP
  1654.              if ((boolopt[i].addr) == &iflags.rlecomp) {
  1655.                  if (*boolopt[i].addr)
  1656.                      set_savepref("rlecomp");
  1657.                  else
  1658.                      set_savepref("!rlecomp");
  1659.              }
  1660.  #endif
  1661.  #ifdef ZEROCOMP
  1662.              if ((boolopt[i].addr) == &iflags.zerocomp) {
  1663.                  if (*boolopt[i].addr)
  1664.                      set_savepref("zerocomp");
  1665.                  else
  1666.                      set_savepref("externalcomp");
  1667.              }
  1668.  #endif
  1669.              /* only do processing below if setting with doset() */
  1670.              if (initial)
  1671.                  return;
  1672.  
  1673.              if ((boolopt[i].addr) == &flags.time
  1674.                  || (boolopt[i].addr) == &flags.showexp
  1675.  #ifdef SCORE_ON_BOTL
  1676.                  || (boolopt[i].addr) == &flags.showscore
  1677.  #endif
  1678.                  ) {
  1679.  #ifdef STATUS_VIA_WINDOWPORT
  1680.                  status_initialize(REASSESS_ONLY);
  1681.  #endif
  1682.                  context.botl = TRUE;
  1683.              } else if ((boolopt[i].addr) == &flags.invlet_constant) {
  1684.                  if (flags.invlet_constant)
  1685.                      reassign();
  1686.              } else if (((boolopt[i].addr) == &flags.lit_corridor)
  1687.                         || ((boolopt[i].addr) == &flags.dark_room)) {
  1688.                  /*
  1689.                   * All corridor squares seen via night vision or
  1690.                   * candles & lamps change.  Update them by calling
  1691.                   * newsym() on them.  Don't do this if we are
  1692.                   * initializing the options --- the vision system
  1693.                   * isn't set up yet.
  1694.                   */
  1695.                  vision_recalc(2);       /* shut down vision */
  1696.                  vision_full_recalc = 1; /* delayed recalc */
  1697.                  if (iflags.use_color)
  1698.                      need_redraw = TRUE; /* darkroom refresh */
  1699.              } else if ((boolopt[i].addr) == &iflags.use_inverse
  1700.                         || (boolopt[i].addr) == &flags.showrace
  1701.                         || (boolopt[i].addr) == &iflags.hilite_pet) {
  1702.                  need_redraw = TRUE;
  1703.  #ifdef TEXTCOLOR
  1704.              } else if ((boolopt[i].addr) == &iflags.use_color) {
  1705.                  need_redraw = TRUE;
  1706.  #ifdef TOS
  1707.                  if ((boolopt[i].addr) == &iflags.use_color && iflags.BIOS) {
  1708.                      if (colors_changed)
  1709.                          restore_colors();
  1710.                      else
  1711.                          set_colors();
  1712.                  }
  1713.  #endif
  1714.  #endif /* TEXTCOLOR */
  1715.              }
  1716.              return;
  1717.          }
  1718.      }
  1719.  
  1720.      /* out of valid options */
  1721.      badoption(opts);
  1722.  }
  1723.  
  1724.  static NEARDATA const char *menutype[] = { "traditional", "combination",
  1725.                                             "full", "partial" };
  1726.  
  1727.  static NEARDATA const char *burdentype[] = { "unencumbered", "burdened",
  1728.                                               "stressed",     "strained",
  1729.                                               "overtaxed",    "overloaded" };
  1730.  
  1731.  static NEARDATA const char *runmodes[] = { "teleport", "run", "walk",
  1732.                                             "crawl" };
  1733.  
  1734.  static NEARDATA const char *sortltype[] = { "none", "loot", "full" };
  1735.  

oc_to_str

  1.  /*
  2.   * Convert the given string of object classes to a string of default object
  3.   * symbols.
  4.   */
  5.  STATIC_OVL void
  6.  oc_to_str(src, dest)
  7.  char *src, *dest;
  8.  {
  9.      int i;
  10.  
  11.      while ((i = (int) *src++) != 0) {
  12.          if (i < 0 || i >= MAXOCLASSES)
  13.              impossible("oc_to_str:  illegal object class %d", i);
  14.          else
  15.              *dest++ = def_oc_syms[i].sym;
  16.      }
  17.      *dest = '\0';
  18.  }
  19.  

add_menu_cmd_alias

  1.  /*
  2.   * Add the given mapping to the menu command map list.  Always keep the
  3.   * maps valid C strings.
  4.   */
  5.  void
  6.  add_menu_cmd_alias(from_ch, to_ch)
  7.  char from_ch, to_ch;
  8.  {
  9.      if (n_menu_mapped >= MAX_MENU_MAPPED_CMDS) {
  10.          pline("out of menu map space.");
  11.      } else {
  12.          mapped_menu_cmds[n_menu_mapped] = from_ch;
  13.          mapped_menu_op[n_menu_mapped] = to_ch;
  14.          n_menu_mapped++;
  15.          mapped_menu_cmds[n_menu_mapped] = 0;
  16.          mapped_menu_op[n_menu_mapped] = 0;
  17.      }
  18.  }
  19.  

map_menu_cmd

  1.  /*
  2.   * Map the given character to its corresponding menu command.  If it
  3.   * doesn't match anything, just return the original.
  4.   */
  5.  char
  6.  map_menu_cmd(ch)
  7.  char ch;
  8.  {
  9.      char *found = index(mapped_menu_cmds, ch);
  10.      if (found) {
  11.          int idx = (int) (found - mapped_menu_cmds);
  12.          ch = mapped_menu_op[idx];
  13.      }
  14.      return ch;
  15.  }
  16.  

doset_add_menu

  1.  #if defined(MICRO) || defined(MAC) || defined(WIN32)
  2.  #define OPTIONS_HEADING "OPTIONS"
  3.  #else
  4.  #define OPTIONS_HEADING "NETHACKOPTIONS"
  5.  #endif
  6.  
  7.  static char fmtstr_doset_add_menu[] = "%s%-15s [%s]   ";
  8.  static char fmtstr_doset_add_menu_tab[] = "%s\t[%s]";
  9.  
  10.  STATIC_OVL void
  11.  doset_add_menu(win, option, indexoffset)
  12.  winid win;          /* window to add to */
  13.  const char *option; /* option name */
  14.  int indexoffset;    /* value to add to index in compopt[], or zero
  15.                         if option cannot be changed */
  16.  {
  17.      const char *value = "unknown"; /* current value */
  18.      char buf[BUFSZ], buf2[BUFSZ];
  19.      anything any;
  20.      int i;
  21.  
  22.      any = zeroany;
  23.      if (indexoffset == 0) {
  24.          any.a_int = 0;
  25.          value = get_compopt_value(option, buf2);
  26.      } else {
  27.          for (i = 0; compopt[i].name; i++)
  28.              if (strcmp(option, compopt[i].name) == 0)
  29.                  break;
  30.  
  31.          if (compopt[i].name) {
  32.              any.a_int = i + 1 + indexoffset;
  33.              value = get_compopt_value(option, buf2);
  34.          } else {
  35.              /* We are trying to add an option not found in compopt[].
  36.                 This is almost certainly bad, but we'll let it through anyway
  37.                 (with a zero value, so it can't be selected). */
  38.              any.a_int = 0;
  39.          }
  40.      }
  41.      /* "    " replaces "a - " -- assumes menus follow that style */
  42.      if (!iflags.menu_tab_sep)
  43.          Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ", option,
  44.                  value);
  45.      else
  46.          Sprintf(buf, fmtstr_doset_add_menu_tab, option, value);
  47.      add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
  48.  }
  49.  

doset

  1.  /* Changing options via menu by Per Liboriussen */
  2.  int
  3.  doset()
  4.  {
  5.      char buf[BUFSZ], buf2[BUFSZ];
  6.      int i = 0, pass, boolcount, pick_cnt, pick_idx, opt_indx;
  7.      boolean *bool_p;
  8.      winid tmpwin;
  9.      anything any;
  10.      menu_item *pick_list;
  11.      int indexoffset, startpass, endpass;
  12.      boolean setinitial = FALSE, fromfile = FALSE;
  13.      int biggest_name = 0;
  14.      const char *n_currently_set = "(%d currently set)";
  15.  
  16.      tmpwin = create_nhwindow(NHW_MENU);
  17.      start_menu(tmpwin);
  18.  
  19.      any = zeroany;
  20.      add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
  21.               "Booleans (selecting will toggle value):", MENU_UNSELECTED);
  22.      any.a_int = 0;
  23.      /* first list any other non-modifiable booleans, then modifiable ones */
  24.      for (pass = 0; pass <= 1; pass++)
  25.          for (i = 0; boolopt[i].name; i++)
  26.              if ((bool_p = boolopt[i].addr) != 0
  27.                  && ((boolopt[i].optflags == DISP_IN_GAME && pass == 0)
  28.                      || (boolopt[i].optflags == SET_IN_GAME && pass == 1))) {
  29.                  if (bool_p == &flags.female)
  30.                      continue; /* obsolete */
  31.                  if (bool_p == &iflags.sanity_check && !wizard)
  32.                      continue;
  33.                  if (bool_p == &iflags.menu_tab_sep && !wizard)
  34.                      continue;
  35.                  if (is_wc_option(boolopt[i].name)
  36.                      && !wc_supported(boolopt[i].name))
  37.                      continue;
  38.                  if (is_wc2_option(boolopt[i].name)
  39.                      && !wc2_supported(boolopt[i].name))
  40.                      continue;
  41.                  any.a_int = (pass == 0) ? 0 : i + 1;
  42.                  if (!iflags.menu_tab_sep)
  43.                      Sprintf(buf, "%s%-17s [%s]", pass == 0 ? "    " : "",
  44.                              boolopt[i].name, *bool_p ? "true" : "false");
  45.                  else
  46.                      Sprintf(buf, "%s\t[%s]", boolopt[i].name,
  47.                              *bool_p ? "true" : "false");
  48.                  add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
  49.                           MENU_UNSELECTED);
  50.              }
  51.  
  52.      boolcount = i;
  53.      indexoffset = boolcount;
  54.      any = zeroany;
  55.      add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
  56.      add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
  57.               "Compounds (selecting will prompt for new value):",
  58.               MENU_UNSELECTED);
  59.  
  60.  #ifdef notyet /* SYSCF */
  61.      /* XXX I think this is still fragile.  Fixing initial/from_file and/or
  62.       changing
  63.       the SET_* etc to bitmaps will let me make this better. */
  64.      if (wizard)
  65.          startpass = SET_IN_SYS;
  66.      else
  67.  #endif
  68.          startpass = DISP_IN_GAME;
  69.      endpass = SET_IN_GAME;
  70.  
  71.      /* spin through the options to find the biggest name
  72.         and adjust the format string accordingly if needed */
  73.      biggest_name = 0;
  74.      for (i = 0; compopt[i].name; i++)
  75.          if (compopt[i].optflags >= startpass && compopt[i].optflags <= endpass
  76.              && strlen(compopt[i].name) > (unsigned) biggest_name)
  77.              biggest_name = (int) strlen(compopt[i].name);
  78.      if (biggest_name > 30)
  79.          biggest_name = 30;
  80.      if (!iflags.menu_tab_sep)
  81.          Sprintf(fmtstr_doset_add_menu, "%%s%%-%ds [%%s]", biggest_name);
  82.  
  83.      /* deliberately put `playmode', `name', `role', `race', `gender' first
  84.         (also alignment if anything ever comes before it in compopt[]) */
  85.      doset_add_menu(tmpwin, "playmode", 0);
  86.      doset_add_menu(tmpwin, "name", 0);
  87.      doset_add_menu(tmpwin, "role", 0);
  88.      doset_add_menu(tmpwin, "race", 0);
  89.      doset_add_menu(tmpwin, "gender", 0);
  90.  
  91.      for (pass = startpass; pass <= endpass; pass++)
  92.          for (i = 0; compopt[i].name; i++)
  93.              if (compopt[i].optflags == pass) {
  94.                  if (!strcmp(compopt[i].name, "playmode")
  95.                      || !strcmp(compopt[i].name, "name")
  96.                      || !strcmp(compopt[i].name, "role")
  97.                      || !strcmp(compopt[i].name, "race")
  98.                      || !strcmp(compopt[i].name, "gender"))
  99.                      continue;
  100.                  else if (is_wc_option(compopt[i].name)
  101.                           && !wc_supported(compopt[i].name))
  102.                      continue;
  103.                  else if (is_wc2_option(compopt[i].name)
  104.                           && !wc2_supported(compopt[i].name))
  105.                      continue;
  106.                  else
  107.                      doset_add_menu(tmpwin, compopt[i].name,
  108.                                     (pass == DISP_IN_GAME) ? 0 : indexoffset);
  109.              }
  110.      any.a_int = -4;
  111.      Sprintf(buf2, n_currently_set, msgtype_count());
  112.      Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ",
  113.              "message types", buf2);
  114.      add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
  115.      any.a_int = -3;
  116.      Sprintf(buf2, n_currently_set, count_menucolors());
  117.      Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ",
  118.              "menucolors", buf2);
  119.      add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
  120.  #ifdef STATUS_VIA_WINDOWPORT
  121.  #ifdef STATUS_HILITES
  122.      any.a_int = -2;
  123.      get_status_hilites(buf2, 60);
  124.      if (!*buf2)
  125.          Sprintf(buf2, "%s", "(none)");
  126.      if (!iflags.menu_tab_sep)
  127.          Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ",
  128.                  "status_hilites", buf2);
  129.      else
  130.          Sprintf(buf, fmtstr_doset_add_menu_tab, "status_hilites", buf2);
  131.      add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
  132.  #endif
  133.  #endif
  134.      any.a_int = -1;
  135.      Sprintf(buf2, n_currently_set, count_ape_maps((int *) 0, (int *) 0));
  136.      Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ",
  137.              "autopickup exceptions", buf2);
  138.      add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
  139.  #ifdef PREFIXES_IN_USE
  140.      any = zeroany;
  141.      add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
  142.      add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
  143.               "Variable playground locations:", MENU_UNSELECTED);
  144.      for (i = 0; i < PREFIX_COUNT; i++)
  145.          doset_add_menu(tmpwin, fqn_prefix_names[i], 0);
  146.  #endif
  147.      end_menu(tmpwin, "Set what options?");
  148.      need_redraw = FALSE;
  149.      if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &pick_list)) > 0) {
  150.          /*
  151.           * Walk down the selection list and either invert the booleans
  152.           * or prompt for new values. In most cases, call parseoptions()
  153.           * to take care of options that require special attention, like
  154.           * redraws.
  155.           */
  156.          for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
  157.              opt_indx = pick_list[pick_idx].item.a_int - 1;
  158.              if (opt_indx == -2) {
  159.                  /* -2 due to -1 offset for select_menu() */
  160.                  (void) special_handling("autopickup_exception", setinitial,
  161.                                          fromfile);
  162.  #ifdef STATUS_VIA_WINDOWPORT
  163.  #ifdef STATUS_HILITES
  164.              } else if (opt_indx == -3) {
  165.                  /* -3 due to -1 offset for select_menu() */
  166.                  if (!status_hilite_menu()) {
  167.                      pline("Bad status hilite(s) specified.");
  168.                  } else {
  169.                      if (wc2_supported("status_hilites"))
  170.                          preference_update("status_hilites");
  171.                  }
  172.  #endif
  173.  #endif
  174.              } else if (opt_indx == -4) {
  175.                      (void) special_handling("menucolors", setinitial,
  176.                                              fromfile);
  177.              } else if (opt_indx == -5) {
  178.                      (void) special_handling("msgtype", setinitial, fromfile);
  179.              } else if (opt_indx < boolcount) {
  180.                  /* boolean option */
  181.                  Sprintf(buf, "%s%s", *boolopt[opt_indx].addr ? "!" : "",
  182.                          boolopt[opt_indx].name);
  183.                  parseoptions(buf, setinitial, fromfile);
  184.                  if (wc_supported(boolopt[opt_indx].name)
  185.                      || wc2_supported(boolopt[opt_indx].name))
  186.                      preference_update(boolopt[opt_indx].name);
  187.              } else {
  188.                  /* compound option */
  189.                  opt_indx -= boolcount;
  190.  
  191.                  if (!special_handling(compopt[opt_indx].name, setinitial,
  192.                                        fromfile)) {
  193.                      Sprintf(buf, "Set %s to what?", compopt[opt_indx].name);
  194.                      getlin(buf, buf2);
  195.                      if (buf2[0] == '\033')
  196.                          continue;
  197.                      Sprintf(buf, "%s:%s", compopt[opt_indx].name, buf2);
  198.                      /* pass the buck */
  199.                      parseoptions(buf, setinitial, fromfile);
  200.                  }
  201.                  if (wc_supported(compopt[opt_indx].name)
  202.                      || wc2_supported(compopt[opt_indx].name))
  203.                      preference_update(compopt[opt_indx].name);
  204.              }
  205.          }
  206.          free((genericptr_t) pick_list);
  207.          pick_list = (menu_item *) 0;
  208.      }
  209.  
  210.      destroy_nhwindow(tmpwin);
  211.      if (need_redraw) {
  212.          reglyph_darkroom();
  213.          (void) doredraw();
  214.      }
  215.      return 0;
  216.  }
  217.  

handle_add_list_remove

  1.  int
  2.  handle_add_list_remove(optname, numtotal)
  3.  const char *optname;
  4.  int numtotal;
  5.  {
  6.      winid tmpwin;
  7.      anything any;
  8.      int i, pick_cnt, pick_idx, opt_idx;
  9.      menu_item *pick_list = (menu_item *) 0;
  10.      static const struct action {
  11.          char letr;
  12.          const char *desc;
  13.      } action_titles[] = {
  14.          { 'a', "add new %s" },         /* [0] */
  15.          { 'l', "list %s" },            /* [1] */
  16.          { 'r', "remove existing %s" }, /* [2] */
  17.          { 'x', "exit this menu" },     /* [3] */
  18.      };
  19.  
  20.      opt_idx = 0;
  21.      tmpwin = create_nhwindow(NHW_MENU);
  22.      start_menu(tmpwin);
  23.      any = zeroany;
  24.      for (i = 0; i < SIZE(action_titles); i++) {
  25.          char tmpbuf[BUFSZ];
  26.          any.a_int++;
  27.          /* omit list and remove if there aren't any yet */
  28.          if (!numtotal && (i == 1 || i == 2))
  29.              continue;
  30.          Sprintf(tmpbuf, action_titles[i].desc,
  31.                  (i == 1) ? makeplural(optname) : optname);
  32.          add_menu(tmpwin, NO_GLYPH, &any, action_titles[i].letr, 0, ATR_NONE,
  33.                   tmpbuf,
  34.  #if 0 /* this ought to work but doesn't... */
  35.                   (action_titles[i].letr == 'x') ? MENU_SELECTED :
  36.  #endif
  37.                   MENU_UNSELECTED);
  38.      }
  39.      end_menu(tmpwin, "Do what?");
  40.      if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &pick_list)) > 0) {
  41.          for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
  42.              opt_idx = pick_list[pick_idx].item.a_int - 1;
  43.          }
  44.          free((genericptr_t) pick_list);
  45.          pick_list = (menu_item *) 0;
  46.      }
  47.      destroy_nhwindow(tmpwin);
  48.  
  49.      if (pick_cnt < 1)
  50.          opt_idx = 3; /* none selected, exit menu */
  51.      return opt_idx;
  52.  }
  53.  

special_handling

  1.  struct symsetentry *symset_list = 0; /* files.c will populate this with
  2.                                                list of available sets */
  3.  
  4.  STATIC_OVL boolean
  5.  special_handling(optname, setinitial, setfromfile)
  6.  const char *optname;
  7.  boolean setinitial, setfromfile;
  8.  {
  9.      winid tmpwin;
  10.      anything any;
  11.      int i;
  12.      char buf[BUFSZ];
  13.  
  14.      /* Special handling of menustyle, pickup_burden, pickup_types,
  15.       * disclose, runmode, msg_window, menu_headings, sortloot,
  16.       * and number_pad options.
  17.       * Also takes care of interactive autopickup_exception_handling changes.
  18.       */
  19.      if (!strcmp("menustyle", optname)) {
  20.          const char *style_name;
  21.          menu_item *style_pick = (menu_item *) 0;
  22.          tmpwin = create_nhwindow(NHW_MENU);
  23.          start_menu(tmpwin);
  24.          any = zeroany;
  25.          for (i = 0; i < SIZE(menutype); i++) {
  26.              style_name = menutype[i];
  27.              /* note: separate `style_name' variable used
  28.                 to avoid an optimizer bug in VAX C V2.3 */
  29.              any.a_int = i + 1;
  30.              add_menu(tmpwin, NO_GLYPH, &any, *style_name, 0, ATR_NONE,
  31.                       style_name, MENU_UNSELECTED);
  32.          }
  33.          end_menu(tmpwin, "Select menustyle:");
  34.          if (select_menu(tmpwin, PICK_ONE, &style_pick) > 0) {
  35.              flags.menu_style = style_pick->item.a_int - 1;
  36.              free((genericptr_t) style_pick);
  37.          }
  38.          destroy_nhwindow(tmpwin);
  39.      } else if (!strcmp("paranoid_confirmation", optname)) {
  40.          menu_item *paranoia_picks = (menu_item *) 0;
  41.  
  42.          tmpwin = create_nhwindow(NHW_MENU);
  43.          start_menu(tmpwin);
  44.          any = zeroany;
  45.          for (i = 0; paranoia[i].flagmask != 0; ++i) {
  46.              if (paranoia[i].flagmask == PARANOID_BONES && !wizard)
  47.                  continue;
  48.              any.a_int = paranoia[i].flagmask;
  49.              add_menu(tmpwin, NO_GLYPH, &any, *paranoia[i].argname, 0,
  50.                       ATR_NONE, paranoia[i].explain,
  51.                       (flags.paranoia_bits & paranoia[i].flagmask)
  52.                           ? MENU_SELECTED
  53.                           : MENU_UNSELECTED);
  54.          }
  55.          end_menu(tmpwin, "Actions requiring extra confirmation:");
  56.          i = select_menu(tmpwin, PICK_ANY, &paranoia_picks);
  57.          if (i >= 0) {
  58.              /* player didn't cancel; we reset all the paranoia options
  59.                 here even if there were no items picked, since user
  60.                 could have toggled off preselected ones to end up with 0 */
  61.              flags.paranoia_bits = 0;
  62.              if (i > 0) {
  63.                  /* at least 1 item set, either preselected or newly picked */
  64.                  while (--i >= 0)
  65.                      flags.paranoia_bits |= paranoia_picks[i].item.a_int;
  66.                  free((genericptr_t) paranoia_picks);
  67.              }
  68.          }
  69.          destroy_nhwindow(tmpwin);
  70.      } else if (!strcmp("pickup_burden", optname)) {
  71.          const char *burden_name, *burden_letters = "ubsntl";
  72.          menu_item *burden_pick = (menu_item *) 0;
  73.  
  74.          tmpwin = create_nhwindow(NHW_MENU);
  75.          start_menu(tmpwin);
  76.          any = zeroany;
  77.          for (i = 0; i < SIZE(burdentype); i++) {
  78.              burden_name = burdentype[i];
  79.              any.a_int = i + 1;
  80.              add_menu(tmpwin, NO_GLYPH, &any, burden_letters[i], 0, ATR_NONE,
  81.                       burden_name, MENU_UNSELECTED);
  82.          }
  83.          end_menu(tmpwin, "Select encumbrance level:");
  84.          if (select_menu(tmpwin, PICK_ONE, &burden_pick) > 0) {
  85.              flags.pickup_burden = burden_pick->item.a_int - 1;
  86.              free((genericptr_t) burden_pick);
  87.          }
  88.          destroy_nhwindow(tmpwin);
  89.      } else if (!strcmp("pickup_types", optname)) {
  90.          /* parseoptions will prompt for the list of types */
  91.          parseoptions(strcpy(buf, "pickup_types"), setinitial, setfromfile);
  92.      } else if (!strcmp("disclose", optname)) {
  93.          /* order of disclose_names[] must correspond to
  94.             disclosure_options in decl.c */
  95.          static const char *disclosure_names[] = {
  96.              "inventory", "attributes", "vanquished",
  97.              "genocides", "conduct",    "overview",
  98.          };
  99.          int disc_cat[NUM_DISCLOSURE_OPTIONS];
  100.          int pick_cnt, pick_idx, opt_idx;
  101.          menu_item *disclosure_pick = (menu_item *) 0;
  102.  
  103.          tmpwin = create_nhwindow(NHW_MENU);
  104.          start_menu(tmpwin);
  105.          any = zeroany;
  106.          for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
  107.              Sprintf(buf, "%-12s[%c%c]", disclosure_names[i],
  108.                      flags.end_disclose[i], disclosure_options[i]);
  109.              any.a_int = i + 1;
  110.              add_menu(tmpwin, NO_GLYPH, &any, disclosure_options[i], 0,
  111.                       ATR_NONE, buf, MENU_UNSELECTED);
  112.              disc_cat[i] = 0;
  113.          }
  114.          end_menu(tmpwin, "Change which disclosure options categories:");
  115.          pick_cnt = select_menu(tmpwin, PICK_ANY, &disclosure_pick);
  116.          if (pick_cnt > 0) {
  117.              for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
  118.                  opt_idx = disclosure_pick[pick_idx].item.a_int - 1;
  119.                  disc_cat[opt_idx] = 1;
  120.              }
  121.              free((genericptr_t) disclosure_pick);
  122.              disclosure_pick = (menu_item *) 0;
  123.          }
  124.          destroy_nhwindow(tmpwin);
  125.  
  126.          for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
  127.              if (disc_cat[i]) {
  128.                  Sprintf(buf, "Disclosure options for %s:",
  129.                          disclosure_names[i]);
  130.                  tmpwin = create_nhwindow(NHW_MENU);
  131.                  start_menu(tmpwin);
  132.                  any = zeroany;
  133.                  /* 'y','n',and '+' work as alternate selectors; '-' doesn't */
  134.                  any.a_char = DISCLOSE_NO_WITHOUT_PROMPT;
  135.                  add_menu(tmpwin, NO_GLYPH, &any, 'a', any.a_char, ATR_NONE,
  136.                           "Never disclose, without prompting",
  137.                           MENU_UNSELECTED);
  138.                  any.a_char = DISCLOSE_YES_WITHOUT_PROMPT;
  139.                  add_menu(tmpwin, NO_GLYPH, &any, 'b', any.a_char, ATR_NONE,
  140.                           "Always disclose, without prompting",
  141.                           MENU_UNSELECTED);
  142.                  any.a_char = DISCLOSE_PROMPT_DEFAULT_NO;
  143.                  add_menu(tmpwin, NO_GLYPH, &any, 'c', any.a_char, ATR_NONE,
  144.                           "Prompt, with default answer of \"No\"",
  145.                           MENU_UNSELECTED);
  146.                  any.a_char = DISCLOSE_PROMPT_DEFAULT_YES;
  147.                  add_menu(tmpwin, NO_GLYPH, &any, 'd', any.a_char, ATR_NONE,
  148.                           "Prompt, with default answer of \"Yes\"",
  149.                           MENU_UNSELECTED);
  150.                  end_menu(tmpwin, buf);
  151.                  if (select_menu(tmpwin, PICK_ONE, &disclosure_pick) > 0) {
  152.                      flags.end_disclose[i] = disclosure_pick->item.a_char;
  153.                      free((genericptr_t) disclosure_pick);
  154.                  }
  155.                  destroy_nhwindow(tmpwin);
  156.              }
  157.          }
  158.      } else if (!strcmp("runmode", optname)) {
  159.          const char *mode_name;
  160.          menu_item *mode_pick = (menu_item *) 0;
  161.  
  162.          tmpwin = create_nhwindow(NHW_MENU);
  163.          start_menu(tmpwin);
  164.          any = zeroany;
  165.          for (i = 0; i < SIZE(runmodes); i++) {
  166.              mode_name = runmodes[i];
  167.              any.a_int = i + 1;
  168.              add_menu(tmpwin, NO_GLYPH, &any, *mode_name, 0, ATR_NONE,
  169.                       mode_name, MENU_UNSELECTED);
  170.          }
  171.          end_menu(tmpwin, "Select run/travel display mode:");
  172.          if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
  173.              flags.runmode = mode_pick->item.a_int - 1;
  174.              free((genericptr_t) mode_pick);
  175.          }
  176.          destroy_nhwindow(tmpwin);
  177.      } else if (!strcmp("msg_window", optname)) {
  178.  #ifdef TTY_GRAPHICS
  179.          /* by Christian W. Cooper */
  180.          menu_item *window_pick = (menu_item *) 0;
  181.  
  182.          tmpwin = create_nhwindow(NHW_MENU);
  183.          start_menu(tmpwin);
  184.          any = zeroany;
  185.          any.a_char = 's';
  186.          add_menu(tmpwin, NO_GLYPH, &any, 's', 0, ATR_NONE, "single",
  187.                   MENU_UNSELECTED);
  188.          any.a_char = 'c';
  189.          add_menu(tmpwin, NO_GLYPH, &any, 'c', 0, ATR_NONE, "combination",
  190.                   MENU_UNSELECTED);
  191.          any.a_char = 'f';
  192.          add_menu(tmpwin, NO_GLYPH, &any, 'f', 0, ATR_NONE, "full",
  193.                   MENU_UNSELECTED);
  194.          any.a_char = 'r';
  195.          add_menu(tmpwin, NO_GLYPH, &any, 'r', 0, ATR_NONE, "reversed",
  196.                   MENU_UNSELECTED);
  197.          end_menu(tmpwin, "Select message history display type:");
  198.          if (select_menu(tmpwin, PICK_ONE, &window_pick) > 0) {
  199.              iflags.prevmsg_window = window_pick->item.a_char;
  200.              free((genericptr_t) window_pick);
  201.          }
  202.          destroy_nhwindow(tmpwin);
  203.  #endif
  204.      } else if (!strcmp("sortloot", optname)) {
  205.          const char *sortl_name;
  206.          menu_item *sortl_pick = (menu_item *) 0;
  207.  
  208.          tmpwin = create_nhwindow(NHW_MENU);
  209.          start_menu(tmpwin);
  210.          any = zeroany;
  211.          for (i = 0; i < SIZE(sortltype); i++) {
  212.              sortl_name = sortltype[i];
  213.              any.a_char = *sortl_name;
  214.              add_menu(tmpwin, NO_GLYPH, &any, *sortl_name, 0, ATR_NONE,
  215.                       sortl_name, MENU_UNSELECTED);
  216.          }
  217.          end_menu(tmpwin, "Select loot sorting type:");
  218.          if (select_menu(tmpwin, PICK_ONE, &sortl_pick) > 0) {
  219.              flags.sortloot = sortl_pick->item.a_char;
  220.              free((genericptr_t) sortl_pick);
  221.          }
  222.          destroy_nhwindow(tmpwin);
  223.      } else if (!strcmp("align_message", optname)
  224.                 || !strcmp("align_status", optname)) {
  225.          menu_item *window_pick = (menu_item *) 0;
  226.          char abuf[BUFSZ];
  227.          boolean msg = (*(optname + 6) == 'm');
  228.  
  229.          tmpwin = create_nhwindow(NHW_MENU);
  230.          start_menu(tmpwin);
  231.          any = zeroany;
  232.          any.a_int = ALIGN_TOP;
  233.          add_menu(tmpwin, NO_GLYPH, &any, 't', 0, ATR_NONE, "top",
  234.                   MENU_UNSELECTED);
  235.          any.a_int = ALIGN_BOTTOM;
  236.          add_menu(tmpwin, NO_GLYPH, &any, 'b', 0, ATR_NONE, "bottom",
  237.                   MENU_UNSELECTED);
  238.          any.a_int = ALIGN_LEFT;
  239.          add_menu(tmpwin, NO_GLYPH, &any, 'l', 0, ATR_NONE, "left",
  240.                   MENU_UNSELECTED);
  241.          any.a_int = ALIGN_RIGHT;
  242.          add_menu(tmpwin, NO_GLYPH, &any, 'r', 0, ATR_NONE, "right",
  243.                   MENU_UNSELECTED);
  244.          Sprintf(abuf, "Select %s window placement relative to the map:",
  245.                  msg ? "message" : "status");
  246.          end_menu(tmpwin, abuf);
  247.          if (select_menu(tmpwin, PICK_ONE, &window_pick) > 0) {
  248.              if (msg)
  249.                  iflags.wc_align_message = window_pick->item.a_int;
  250.              else
  251.                  iflags.wc_align_status = window_pick->item.a_int;
  252.              free((genericptr_t) window_pick);
  253.          }
  254.          destroy_nhwindow(tmpwin);
  255.      } else if (!strcmp("number_pad", optname)) {
  256.          static const char *npchoices[] = {
  257.              " 0 (off)", " 1 (on)", " 2 (on, MSDOS compatible)",
  258.              " 3 (on, phone-style digit layout)",
  259.              " 4 (on, phone-style layout, MSDOS compatible)",
  260.              "-1 (off, 'z' to move upper-left, 'y' to zap wands)"
  261.          };
  262.          menu_item *mode_pick = (menu_item *) 0;
  263.  
  264.          tmpwin = create_nhwindow(NHW_MENU);
  265.          start_menu(tmpwin);
  266.          any = zeroany;
  267.          for (i = 0; i < SIZE(npchoices); i++) {
  268.              any.a_int = i + 1;
  269.              add_menu(tmpwin, NO_GLYPH, &any, 'a' + i, 0, ATR_NONE,
  270.                       npchoices[i], MENU_UNSELECTED);
  271.          }
  272.          end_menu(tmpwin, "Select number_pad mode:");
  273.          if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
  274.              switch (mode_pick->item.a_int - 1) {
  275.              case 0:
  276.                  iflags.num_pad = FALSE;
  277.                  iflags.num_pad_mode = 0;
  278.                  break;
  279.              case 1:
  280.                  iflags.num_pad = TRUE;
  281.                  iflags.num_pad_mode = 0;
  282.                  break;
  283.              case 2:
  284.                  iflags.num_pad = TRUE;
  285.                  iflags.num_pad_mode = 1;
  286.                  break;
  287.              case 3:
  288.                  iflags.num_pad = TRUE;
  289.                  iflags.num_pad_mode = 2;
  290.                  break;
  291.              case 4:
  292.                  iflags.num_pad = TRUE;
  293.                  iflags.num_pad_mode = 3;
  294.                  break;
  295.              /* last menu choice: number_pad == -1 */
  296.              case 5:
  297.                  iflags.num_pad = FALSE;
  298.                  iflags.num_pad_mode = 1;
  299.                  break;
  300.              }
  301.              reset_commands(FALSE);
  302.              number_pad(iflags.num_pad ? 1 : 0);
  303.              free((genericptr_t) mode_pick);
  304.          }
  305.          destroy_nhwindow(tmpwin);
  306.      } else if (!strcmp("menu_headings", optname)) {
  307.          int mhattr = query_attr("How to highlight menu headings:");
  308.  
  309.          if (mhattr != -1)
  310.              iflags.menu_headings = mhattr;
  311.      } else if (!strcmp("msgtype", optname)) {
  312.          int opt_idx, nmt, mttyp;
  313.          char mtbuf[BUFSZ];
  314.  
  315.      msgtypes_again:
  316.          nmt = msgtype_count();
  317.          opt_idx = handle_add_list_remove("message type", nmt);
  318.          if (opt_idx == 3) {
  319.              ; /* done--fall through to function exit */
  320.          } else if (opt_idx == 0) { /* add new */
  321.              getlin("What new message pattern?", mtbuf);
  322.              if (*mtbuf == '\033' || !*mtbuf)
  323.                  goto msgtypes_again;
  324.              mttyp = query_msgtype();
  325.              if (mttyp == -1)
  326.                  goto msgtypes_again;
  327.              if (!msgtype_add(mttyp, mtbuf)) {
  328.                  pline("Error adding the message type.");
  329.                  wait_synch();
  330.                  goto msgtypes_again;
  331.              }
  332.          } else { /* list or remove */
  333.              int pick_idx, pick_cnt;
  334.              int mt_idx;
  335.              menu_item *pick_list = (menu_item *) 0;
  336.              struct plinemsg_type *tmp = plinemsg_types;
  337.  
  338.              tmpwin = create_nhwindow(NHW_MENU);
  339.              start_menu(tmpwin);
  340.              any = zeroany;
  341.              mt_idx = 0;
  342.              while (tmp) {
  343.                  const char *mtype = msgtype2name(tmp->msgtype);
  344.  
  345.                  any.a_int = ++mt_idx;
  346.                  Sprintf(mtbuf, "%-5s \"%s\"", mtype, tmp->pattern);
  347.                  add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, mtbuf,
  348.                           MENU_UNSELECTED);
  349.                  tmp = tmp->next;
  350.              }
  351.              Sprintf(mtbuf, "%s message types",
  352.                      (opt_idx == 1) ? "List of" : "Remove which");
  353.              end_menu(tmpwin, mtbuf);
  354.              pick_cnt = select_menu(tmpwin,
  355.                                     (opt_idx == 1) ? PICK_NONE : PICK_ANY,
  356.                                     &pick_list);
  357.              if (pick_cnt > 0) {
  358.                  for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
  359.                      free_one_msgtype(pick_list[pick_idx].item.a_int - 1
  360.                                             - pick_idx);
  361.                  free((genericptr_t) pick_list), pick_list = (menu_item *) 0;
  362.              }
  363.              destroy_nhwindow(tmpwin);
  364.              if (pick_cnt >= 0)
  365.                  goto msgtypes_again;
  366.          }
  367.      } else if (!strcmp("menucolors", optname)) {
  368.          int opt_idx, nmc, mcclr, mcattr;
  369.          char mcbuf[BUFSZ];
  370.  
  371.      menucolors_again:
  372.          nmc = count_menucolors();
  373.          opt_idx = handle_add_list_remove("menucolor", nmc);
  374.          if (opt_idx == 3) {
  375.              ;                      /* done--fall through to function exit */
  376.          } else if (opt_idx == 0) { /* add new */
  377.              getlin("What new menucolor pattern?", mcbuf);
  378.              if (*mcbuf == '\033' || !*mcbuf)
  379.                  goto menucolors_again;
  380.              mcclr = query_color();
  381.              if (mcclr == -1)
  382.                  goto menucolors_again;
  383.              mcattr = query_attr(NULL);
  384.              if (mcattr == -1)
  385.                  goto menucolors_again;
  386.              if (!add_menu_coloring_parsed(mcbuf, mcclr, mcattr)) {
  387.                  pline("Error adding the menu color.");
  388.                  wait_synch();
  389.                  goto menucolors_again;
  390.              }
  391.          } else { /* list or remove */
  392.              int pick_idx, pick_cnt;
  393.              int mc_idx;
  394.              menu_item *pick_list = (menu_item *) 0;
  395.              struct menucoloring *tmp = menu_colorings;
  396.  
  397.              tmpwin = create_nhwindow(NHW_MENU);
  398.              start_menu(tmpwin);
  399.              any = zeroany;
  400.              mc_idx = 0;
  401.              while (tmp) {
  402.                  const char *sattr = attr2attrname(tmp->attr);
  403.                  const char *sclr = clr2colorname(tmp->color);
  404.  
  405.                  any.a_int = (++mc_idx);
  406.                  Sprintf(mcbuf, "\"%s\"=%s%s%s", tmp->origstr, sclr,
  407.                          (tmp->attr != ATR_NONE) ? " & " : "",
  408.                          (tmp->attr != ATR_NONE) ? sattr : "");
  409.                  add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, mcbuf,
  410.                           MENU_UNSELECTED);
  411.                  tmp = tmp->next;
  412.              }
  413.              Sprintf(mcbuf, "%s menu colors",
  414.                      (opt_idx == 1) ? "List of" : "Remove which");
  415.              end_menu(tmpwin, mcbuf);
  416.              pick_cnt = select_menu(tmpwin,
  417.                                     (opt_idx == 1) ? PICK_NONE : PICK_ANY,
  418.                                     &pick_list);
  419.              if (pick_cnt > 0) {
  420.                  for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
  421.                      free_one_menu_coloring(pick_list[pick_idx].item.a_int - 1
  422.                                             - pick_idx);
  423.                  free((genericptr_t) pick_list), pick_list = (menu_item *) 0;
  424.              }
  425.              destroy_nhwindow(tmpwin);
  426.              if (pick_cnt >= 0)
  427.                  goto menucolors_again;
  428.          }
  429.      } else if (!strcmp("autopickup_exception", optname)) {
  430.          int opt_idx, pass, totalapes = 0, numapes[2] = { 0, 0 };
  431.          char apebuf[1 + BUFSZ]; /* so &apebuf[1] is BUFSZ long for getlin() */
  432.          struct autopickup_exception *ape;
  433.  
  434.      ape_again:
  435.          totalapes = count_ape_maps(&numapes[AP_LEAVE], &numapes[AP_GRAB]);
  436.          opt_idx = handle_add_list_remove("autopickup exception", totalapes);
  437.          if (opt_idx == 3) {
  438.              ;                      /* done--fall through to function exit */
  439.          } else if (opt_idx == 0) { /* add new */
  440.              getlin("What new autopickup exception pattern?", &apebuf[1]);
  441.              mungspaces(&apebuf[1]); /* regularize whitespace */
  442.              if (apebuf[1] == '\033') {
  443.                  ; /* fall through to function exit */
  444.              } else {
  445.                  if (apebuf[1]) {
  446.                      apebuf[0] = '\"';
  447.                      /* guarantee room for \" prefix and \"\0 suffix;
  448.                         -2 is good enough for apebuf[] but -3 makes
  449.                         sure the whole thing fits within normal BUFSZ */
  450.                      apebuf[sizeof apebuf - 3] = '\0';
  451.                      Strcat(apebuf, "\"");
  452.                      add_autopickup_exception(apebuf);
  453.                  }
  454.                  goto ape_again;
  455.              }
  456.          } else { /* list or remove */
  457.              int pick_idx, pick_cnt;
  458.              menu_item *pick_list = (menu_item *) 0;
  459.  
  460.              tmpwin = create_nhwindow(NHW_MENU);
  461.              start_menu(tmpwin);
  462.              for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
  463.                  if (numapes[pass] == 0)
  464.                      continue;
  465.                  ape = iflags.autopickup_exceptions[pass];
  466.                  any = zeroany;
  467.                  add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
  468.                           (pass == 0) ? "Never pickup" : "Always pickup",
  469.                           MENU_UNSELECTED);
  470.                  for (i = 0; i < numapes[pass] && ape; i++) {
  471.                      any.a_void = (opt_idx == 1) ? 0 : ape;
  472.                      Sprintf(apebuf, "\"%s\"", ape->pattern);
  473.                      add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, apebuf,
  474.                               MENU_UNSELECTED);
  475.                      ape = ape->next;
  476.                  }
  477.              }
  478.              Sprintf(apebuf, "%s autopickup exceptions",
  479.                      (opt_idx == 1) ? "List of" : "Remove which");
  480.              end_menu(tmpwin, apebuf);
  481.              pick_cnt = select_menu(tmpwin,
  482.                                     (opt_idx == 1) ? PICK_NONE : PICK_ANY,
  483.                                     &pick_list);
  484.              if (pick_cnt > 0) {
  485.                  for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
  486.                      remove_autopickup_exception(
  487.                                           (struct autopickup_exception *)
  488.                                               pick_list[pick_idx].item.a_void);
  489.                  free((genericptr_t) pick_list), pick_list = (menu_item *) 0;
  490.              }
  491.              destroy_nhwindow(tmpwin);
  492.              if (pick_cnt >= 0)
  493.                  goto ape_again;
  494.          }
  495.      } else if (!strcmp("symset", optname)
  496.                 || !strcmp("roguesymset", optname)) {
  497.          menu_item *symset_pick = (menu_item *) 0;
  498.          boolean primaryflag = (*optname == 's'),
  499.                  rogueflag = (*optname == 'r'),
  500.                  ready_to_switch = FALSE,
  501.                  nothing_to_do = FALSE;
  502.          char *symset_name, fmtstr[20];
  503.          struct symsetentry *sl;
  504.          int res, which_set, setcount = 0, chosen = -2;
  505.  
  506.          if (rogueflag)
  507.              which_set = ROGUESET;
  508.          else
  509.              which_set = PRIMARY;
  510.  
  511.          /* clear symset[].name as a flag to read_sym_file() to build list */
  512.          symset_name = symset[which_set].name;
  513.          symset[which_set].name = (char *) 0;
  514.          symset_list = (struct symsetentry *) 0;
  515.  
  516.          res = read_sym_file(which_set);
  517.          if (res && symset_list) {
  518.              char symsetchoice[BUFSZ];
  519.              int let = 'a', biggest = 0, thissize = 0;
  520.  
  521.              sl = symset_list;
  522.              while (sl) {
  523.                  /* check restrictions */
  524.                  if ((!rogueflag && sl->rogue)
  525.                      || (!primaryflag && sl->primary)) {
  526.                      sl = sl->next;
  527.                      continue;
  528.                  }
  529.                  setcount++;
  530.                  /* find biggest name */
  531.                  if (sl->name)
  532.                      thissize = strlen(sl->name);
  533.                  if (thissize > biggest)
  534.                      biggest = thissize;
  535.                  sl = sl->next;
  536.              }
  537.              if (!setcount) {
  538.                  pline("There are no appropriate %ssymbol sets available.",
  539.                        (rogueflag) ? "rogue level "
  540.                                    : (primaryflag) ? "primary " : "");
  541.                  return TRUE;
  542.              }
  543.  
  544.              Sprintf(fmtstr, "%%-%ds %%s", biggest + 5);
  545.              tmpwin = create_nhwindow(NHW_MENU);
  546.              start_menu(tmpwin);
  547.              any = zeroany;
  548.              any.a_int = 1;
  549.              add_menu(tmpwin, NO_GLYPH, &any, let++, 0, ATR_NONE,
  550.                       "Default Symbols", MENU_UNSELECTED);
  551.  
  552.              sl = symset_list;
  553.              while (sl) {
  554.                  /* check restrictions */
  555.                  if ((!rogueflag && sl->rogue)
  556.                      || (!primaryflag && sl->primary)) {
  557.                      sl = sl->next;
  558.                      continue;
  559.                  }
  560.                  if (sl->name) {
  561.                      any.a_int = sl->idx + 2;
  562.                      Sprintf(symsetchoice, fmtstr, sl->name,
  563.                              sl->desc ? sl->desc : "");
  564.                      add_menu(tmpwin, NO_GLYPH, &any, let, 0, ATR_NONE,
  565.                               symsetchoice, MENU_UNSELECTED);
  566.                      if (let == 'z')
  567.                          let = 'A';
  568.                      else
  569.                          let++;
  570.                  }
  571.                  sl = sl->next;
  572.              }
  573.              end_menu(tmpwin, "Select symbol set:");
  574.              if (select_menu(tmpwin, PICK_ONE, &symset_pick) > 0) {
  575.                  chosen = symset_pick->item.a_int - 2;
  576.                  free((genericptr_t) symset_pick);
  577.              }
  578.              destroy_nhwindow(tmpwin);
  579.  
  580.              if (chosen > -1) {
  581.                  /* chose an actual symset name from file */
  582.                  sl = symset_list;
  583.                  while (sl) {
  584.                      if (sl->idx == chosen) {
  585.                          if (symset_name) {
  586.                              free((genericptr_t) symset_name);
  587.                              symset_name = (char *) 0;
  588.                          }
  589.                          /* free the now stale attributes */
  590.                          clear_symsetentry(which_set, TRUE);
  591.  
  592.                          /* transfer only the name of the symbol set */
  593.                          symset[which_set].name = dupstr(sl->name);
  594.                          ready_to_switch = TRUE;
  595.                          break;
  596.                      }
  597.                      sl = sl->next;
  598.                  }
  599.              } else if (chosen == -1) {
  600.                  /* explicit selection of defaults */
  601.                  /* free the now stale symset attributes */
  602.                  if (symset_name) {
  603.                      free((genericptr_t) symset_name);
  604.                      symset_name = (char *) 0;
  605.                  }
  606.                  clear_symsetentry(which_set, TRUE);
  607.              } else
  608.                  nothing_to_do = TRUE;
  609.          } else if (!res) {
  610.              /* The symbols file could not be accessed */
  611.              pline("Unable to access \"%s\" file.", SYMBOLS);
  612.              return TRUE;
  613.          } else if (!symset_list) {
  614.              /* The symbols file was empty */
  615.              pline("There were no symbol sets found in \"%s\".", SYMBOLS);
  616.              return TRUE;
  617.          }
  618.  
  619.          /* clean up */
  620.          while (symset_list) {
  621.              sl = symset_list;
  622.              if (sl->name)
  623.                  free((genericptr_t) sl->name);
  624.              sl->name = (char *) 0;
  625.  
  626.              if (sl->desc)
  627.                  free((genericptr_t) sl->desc);
  628.              sl->desc = (char *) 0;
  629.  
  630.              symset_list = sl->next;
  631.              free((genericptr_t) sl);
  632.          }
  633.  
  634.          if (nothing_to_do)
  635.              return TRUE;
  636.  
  637.          if (!symset[which_set].name && symset_name)
  638.              symset[which_set].name = symset_name; /* not dupstr() here */
  639.  
  640.          /* Set default symbols and clear the handling value */
  641.          if (rogueflag)
  642.              init_r_symbols();
  643.          else
  644.              init_l_symbols();
  645.  
  646.          if (symset[which_set].name) {
  647.              if (read_sym_file(which_set)) {
  648.                  ready_to_switch = TRUE;
  649.              } else {
  650.                  clear_symsetentry(which_set, TRUE);
  651.                  return TRUE;
  652.              }
  653.          }
  654.  
  655.          if (ready_to_switch)
  656.              switch_symbols(TRUE);
  657.  
  658.          if (Is_rogue_level(&u.uz)) {
  659.              if (rogueflag)
  660.                  assign_graphics(ROGUESET);
  661.          } else if (!rogueflag)
  662.              assign_graphics(PRIMARY);
  663.          need_redraw = TRUE;
  664.          return TRUE;
  665.  
  666.      } else {
  667.          /* didn't match any of the special options */
  668.          return FALSE;
  669.      }
  670.      return TRUE;
  671.  }
  672.  

get_compopt_value

  1.  #define rolestring(val, array, field) \
  2.      ((val >= 0) ? array[val].field : (val == ROLE_RANDOM) ? randomrole : none)
  3.  
  4.  /* This is ugly. We have all the option names in the compopt[] array,
  5.     but we need to look at each option individually to get the value. */
  6.  STATIC_OVL const char *
  7.  get_compopt_value(optname, buf)
  8.  const char *optname;
  9.  char *buf;
  10.  {
  11.      char ocl[MAXOCLASSES + 1];
  12.      static const char none[] = "(none)", randomrole[] = "random",
  13.                        to_be_done[] = "(to be done)", defopt[] = "default",
  14.                        defbrief[] = "def";
  15.      int i;
  16.  
  17.      buf[0] = '\0';
  18.      if (!strcmp(optname, "align_message"))
  19.          Sprintf(buf, "%s",
  20.                  iflags.wc_align_message == ALIGN_TOP
  21.                      ? "top"
  22.                      : iflags.wc_align_message == ALIGN_LEFT
  23.                            ? "left"
  24.                            : iflags.wc_align_message == ALIGN_BOTTOM
  25.                                  ? "bottom"
  26.                                  : iflags.wc_align_message == ALIGN_RIGHT
  27.                                        ? "right"
  28.                                        : defopt);
  29.      else if (!strcmp(optname, "align_status"))
  30.          Sprintf(buf, "%s",
  31.                  iflags.wc_align_status == ALIGN_TOP
  32.                      ? "top"
  33.                      : iflags.wc_align_status == ALIGN_LEFT
  34.                            ? "left"
  35.                            : iflags.wc_align_status == ALIGN_BOTTOM
  36.                                  ? "bottom"
  37.                                  : iflags.wc_align_status == ALIGN_RIGHT
  38.                                        ? "right"
  39.                                        : defopt);
  40.      else if (!strcmp(optname, "align"))
  41.          Sprintf(buf, "%s", rolestring(flags.initalign, aligns, adj));
  42.  #ifdef WIN32
  43.      else if (!strcmp(optname, "altkeyhandler"))
  44.          Sprintf(buf, "%s",
  45.                  iflags.altkeyhandler[0] ? iflags.altkeyhandler : "default");
  46.  #endif
  47.  #ifdef BACKWARD_COMPAT
  48.      else if (!strcmp(optname, "boulder"))
  49.          Sprintf(buf, "%c",
  50.                  iflags.bouldersym
  51.                      ? iflags.bouldersym
  52.                      : showsyms[(int) objects[BOULDER].oc_class + SYM_OFF_O]);
  53.  #endif
  54.      else if (!strcmp(optname, "catname"))
  55.          Sprintf(buf, "%s", catname[0] ? catname : none);
  56.      else if (!strcmp(optname, "disclose"))
  57.          for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
  58.              if (i)
  59.                  (void) strkitten(buf, ' ');
  60.              (void) strkitten(buf, flags.end_disclose[i]);
  61.              (void) strkitten(buf, disclosure_options[i]);
  62.          }
  63.      else if (!strcmp(optname, "dogname"))
  64.          Sprintf(buf, "%s", dogname[0] ? dogname : none);
  65.      else if (!strcmp(optname, "dungeon"))
  66.          Sprintf(buf, "%s", to_be_done);
  67.      else if (!strcmp(optname, "effects"))
  68.          Sprintf(buf, "%s", to_be_done);
  69.      else if (!strcmp(optname, "font_map"))
  70.          Sprintf(buf, "%s", iflags.wc_font_map ? iflags.wc_font_map : defopt);
  71.      else if (!strcmp(optname, "font_message"))
  72.          Sprintf(buf, "%s",
  73.                  iflags.wc_font_message ? iflags.wc_font_message : defopt);
  74.      else if (!strcmp(optname, "font_status"))
  75.          Sprintf(buf, "%s",
  76.                  iflags.wc_font_status ? iflags.wc_font_status : defopt);
  77.      else if (!strcmp(optname, "font_menu"))
  78.          Sprintf(buf, "%s",
  79.                  iflags.wc_font_menu ? iflags.wc_font_menu : defopt);
  80.      else if (!strcmp(optname, "font_text"))
  81.          Sprintf(buf, "%s",
  82.                  iflags.wc_font_text ? iflags.wc_font_text : defopt);
  83.      else if (!strcmp(optname, "font_size_map")) {
  84.          if (iflags.wc_fontsiz_map)
  85.              Sprintf(buf, "%d", iflags.wc_fontsiz_map);
  86.          else
  87.              Strcpy(buf, defopt);
  88.      } else if (!strcmp(optname, "font_size_message")) {
  89.          if (iflags.wc_fontsiz_message)
  90.              Sprintf(buf, "%d", iflags.wc_fontsiz_message);
  91.          else
  92.              Strcpy(buf, defopt);
  93.      } else if (!strcmp(optname, "font_size_status")) {
  94.          if (iflags.wc_fontsiz_status)
  95.              Sprintf(buf, "%d", iflags.wc_fontsiz_status);
  96.          else
  97.              Strcpy(buf, defopt);
  98.      } else if (!strcmp(optname, "font_size_menu")) {
  99.          if (iflags.wc_fontsiz_menu)
  100.              Sprintf(buf, "%d", iflags.wc_fontsiz_menu);
  101.          else
  102.              Strcpy(buf, defopt);
  103.      } else if (!strcmp(optname, "font_size_text")) {
  104.          if (iflags.wc_fontsiz_text)
  105.              Sprintf(buf, "%d", iflags.wc_fontsiz_text);
  106.          else
  107.              Strcpy(buf, defopt);
  108.      } else if (!strcmp(optname, "fruit"))
  109.          Sprintf(buf, "%s", pl_fruit);
  110.      else if (!strcmp(optname, "gender"))
  111.          Sprintf(buf, "%s", rolestring(flags.initgend, genders, adj));
  112.      else if (!strcmp(optname, "horsename"))
  113.          Sprintf(buf, "%s", horsename[0] ? horsename : none);
  114.      else if (!strcmp(optname, "map_mode"))
  115.          Sprintf(buf, "%s",
  116.                  iflags.wc_map_mode == MAP_MODE_TILES
  117.                    ? "tiles"
  118.                    : iflags.wc_map_mode == MAP_MODE_ASCII4x6
  119.                       ? "ascii4x6"
  120.                       : iflags.wc_map_mode == MAP_MODE_ASCII6x8
  121.                          ? "ascii6x8"
  122.                          : iflags.wc_map_mode == MAP_MODE_ASCII8x8
  123.                             ? "ascii8x8"
  124.                             : iflags.wc_map_mode == MAP_MODE_ASCII16x8
  125.                                ? "ascii16x8"
  126.                                : iflags.wc_map_mode == MAP_MODE_ASCII7x12
  127.                                   ? "ascii7x12"
  128.                                   : iflags.wc_map_mode == MAP_MODE_ASCII8x12
  129.                                      ? "ascii8x12"
  130.                                      : iflags.wc_map_mode
  131.                                        == MAP_MODE_ASCII16x12
  132.                                         ? "ascii16x12"
  133.                                         : iflags.wc_map_mode
  134.                                           == MAP_MODE_ASCII12x16
  135.                                            ? "ascii12x16"
  136.                                            : iflags.wc_map_mode
  137.                                              == MAP_MODE_ASCII10x18
  138.                                               ? "ascii10x18"
  139.                                               : iflags.wc_map_mode
  140.                                                 == MAP_MODE_ASCII_FIT_TO_SCREEN
  141.                                                  ? "fit_to_screen"
  142.                                                  : defopt);
  143.      else if (!strcmp(optname, "menustyle"))
  144.          Sprintf(buf, "%s", menutype[(int) flags.menu_style]);
  145.      else if (!strcmp(optname, "menu_deselect_all"))
  146.          Sprintf(buf, "%s", to_be_done);
  147.      else if (!strcmp(optname, "menu_deselect_page"))
  148.          Sprintf(buf, "%s", to_be_done);
  149.      else if (!strcmp(optname, "menu_first_page"))
  150.          Sprintf(buf, "%s", to_be_done);
  151.      else if (!strcmp(optname, "menu_invert_all"))
  152.          Sprintf(buf, "%s", to_be_done);
  153.      else if (!strcmp(optname, "menu_headings"))
  154.          Sprintf(buf, "%s", attr2attrname(iflags.menu_headings));
  155.      else if (!strcmp(optname, "menu_invert_page"))
  156.          Sprintf(buf, "%s", to_be_done);
  157.      else if (!strcmp(optname, "menu_last_page"))
  158.          Sprintf(buf, "%s", to_be_done);
  159.      else if (!strcmp(optname, "menu_next_page"))
  160.          Sprintf(buf, "%s", to_be_done);
  161.      else if (!strcmp(optname, "menu_previous_page"))
  162.          Sprintf(buf, "%s", to_be_done);
  163.      else if (!strcmp(optname, "menu_search"))
  164.          Sprintf(buf, "%s", to_be_done);
  165.      else if (!strcmp(optname, "menu_select_all"))
  166.          Sprintf(buf, "%s", to_be_done);
  167.      else if (!strcmp(optname, "menu_select_page"))
  168.          Sprintf(buf, "%s", to_be_done);
  169.      else if (!strcmp(optname, "monsters")) {
  170.          Sprintf(buf, "%s", to_be_done);
  171.      } else if (!strcmp(optname, "msghistory")) {
  172.          Sprintf(buf, "%u", iflags.msg_history);
  173.  #ifdef TTY_GRAPHICS
  174.      } else if (!strcmp(optname, "msg_window")) {
  175.          Sprintf(buf, "%s", (iflags.prevmsg_window == 's')
  176.                                 ? "single"
  177.                                 : (iflags.prevmsg_window == 'c')
  178.                                       ? "combination"
  179.                                       : (iflags.prevmsg_window == 'f')
  180.                                             ? "full"
  181.                                             : "reversed");
  182.  #endif
  183.      } else if (!strcmp(optname, "name")) {
  184.          Sprintf(buf, "%s", plname);
  185.      } else if (!strcmp(optname, "number_pad")) {
  186.          static const char *numpadmodes[] = {
  187.              "0=off", "1=on", "2=on, MSDOS compatible",
  188.              "3=on, phone-style layout",
  189.              "4=on, phone layout, MSDOS compatible",
  190.              "-1=off, y & z swapped", /*[5]*/
  191.          };
  192.          int indx = Cmd.num_pad
  193.                         ? (Cmd.phone_layout ? (Cmd.pcHack_compat ? 4 : 3)
  194.                                             : (Cmd.pcHack_compat ? 2 : 1))
  195.                         : Cmd.swap_yz ? 5 : 0;
  196.  
  197.          Strcpy(buf, numpadmodes[indx]);
  198.      } else if (!strcmp(optname, "objects")) {
  199.          Sprintf(buf, "%s", to_be_done);
  200.      } else if (!strcmp(optname, "packorder")) {
  201.          oc_to_str(flags.inv_order, ocl);
  202.          Sprintf(buf, "%s", ocl);
  203.  #ifdef CHANGE_COLOR
  204.      } else if (!strcmp(optname, "palette")) {
  205.          Sprintf(buf, "%s", get_color_string());
  206.  #endif
  207.      } else if (!strcmp(optname, "paranoid_confirmation")) {
  208.          char tmpbuf[QBUFSZ];
  209.  
  210.          tmpbuf[0] = '\0';
  211.          if (ParanoidConfirm)
  212.              Strcat(tmpbuf, " Confirm");
  213.          if (ParanoidQuit)
  214.              Strcat(tmpbuf, " quit");
  215.          if (ParanoidDie)
  216.              Strcat(tmpbuf, " die");
  217.          if (ParanoidBones)
  218.              Strcat(tmpbuf, " bones");
  219.          if (ParanoidHit)
  220.              Strcat(tmpbuf, " attack");
  221.          if (ParanoidPray)
  222.              Strcat(tmpbuf, " pray");
  223.          if (ParanoidRemove)
  224.              Strcat(tmpbuf, " Remove");
  225.          Strcpy(buf, tmpbuf[0] ? &tmpbuf[1] : "none");
  226.      } else if (!strcmp(optname, "pettype")) {
  227.          Sprintf(buf, "%s", (preferred_pet == 'c') ? "cat"
  228.                             : (preferred_pet == 'd') ? "dog"
  229.                               : (preferred_pet == 'h') ? "horse"
  230.                                 : (preferred_pet == 'n') ? "none"
  231.                                   : "random");
  232.      } else if (!strcmp(optname, "pickup_burden")) {
  233.          Sprintf(buf, "%s", burdentype[flags.pickup_burden]);
  234.      } else if (!strcmp(optname, "pickup_types")) {
  235.          oc_to_str(flags.pickup_types, ocl);
  236.          Sprintf(buf, "%s", ocl[0] ? ocl : "all");
  237.      } else if (!strcmp(optname, "pile_limit")) {
  238.          Sprintf(buf, "%d", flags.pile_limit);
  239.      } else if (!strcmp(optname, "playmode")) {
  240.          Strcpy(buf, wizard ? "debug" : discover ? "explore" : "normal");
  241.      } else if (!strcmp(optname, "race")) {
  242.          Sprintf(buf, "%s", rolestring(flags.initrace, races, noun));
  243.      } else if (!strcmp(optname, "roguesymset")) {
  244.          Sprintf(buf, "%s",
  245.                  symset[ROGUESET].name ? symset[ROGUESET].name : "default");
  246.          if (currentgraphics == ROGUESET && symset[ROGUESET].name)
  247.              Strcat(buf, ", active");
  248.      } else if (!strcmp(optname, "role")) {
  249.          Sprintf(buf, "%s", rolestring(flags.initrole, roles, name.m));
  250.      } else if (!strcmp(optname, "runmode")) {
  251.          Sprintf(buf, "%s", runmodes[flags.runmode]);
  252.      } else if (!strcmp(optname, "scores")) {
  253.          Sprintf(buf, "%d top/%d around%s", flags.end_top, flags.end_around,
  254.                  flags.end_own ? "/own" : "");
  255.      } else if (!strcmp(optname, "scroll_amount")) {
  256.          if (iflags.wc_scroll_amount)
  257.              Sprintf(buf, "%d", iflags.wc_scroll_amount);
  258.          else
  259.              Strcpy(buf, defopt);
  260.      } else if (!strcmp(optname, "scroll_margin")) {
  261.          if (iflags.wc_scroll_margin)
  262.              Sprintf(buf, "%d", iflags.wc_scroll_margin);
  263.          else
  264.              Strcpy(buf, defopt);
  265.      } else if (!strcmp(optname, "sortloot")) {
  266.          for (i = 0; i < SIZE(sortltype); i++)
  267.              if (flags.sortloot == sortltype[i][0]) {
  268.                  Strcpy(buf, sortltype[i]);
  269.                  break;
  270.              }
  271.      } else if (!strcmp(optname, "player_selection")) {
  272.          Sprintf(buf, "%s", iflags.wc_player_selection ? "prompts" : "dialog");
  273.  #ifdef MSDOS
  274.      } else if (!strcmp(optname, "soundcard")) {
  275.          Sprintf(buf, "%s", to_be_done);
  276.  #endif
  277.      } else if (!strcmp(o