From 37763d030e0b0f73e3b2fcca750128c5f2ee59ee Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 29 May 2015 17:42:15 -0700 Subject: [PATCH 1/2] add warning glow for Orcrist & Grimtooth Make Orcrist glow light blue when orcs are present, just like Sting. (Sting supposedly glowed because it was made by the elves of Gondolin rather than any particular attribute built into it, and Orcrist was made there too. I think it also glowed in the Hobbit; that was how Bilbo recognized what the situation was when he first saw Sting glow. Maybe it was the other sword rather than Orcrist, but they were treated as being functionally equivalent.) Also make Grimtooth glow red when elves are present. That's from thin air, to give it some novelty. Unlike Sting, whose double-damage bonus is restricted to orc targets, Grimtooth's weak 1d6 bonus still applies to all targets. --- include/artilist.h | 25 ++++++++++++++----------- src/artifact.c | 16 +++++++++++++--- src/display.c | 5 ++--- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/include/artilist.h b/include/artilist.h index 50ec60636..bde9d5b52 100644 --- a/include/artilist.h +++ b/include/artilist.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 artilist.h $NHDT-Date: 1432512781 2015/05/25 00:13:01 $ $NHDT-Branch: master $:$NHDT-Revision: 1.14 $ */ +/* NetHack 3.6 artilist.h $NHDT-Date: 1432946531 2015/05/30 00:42:11 $ $NHDT-Branch: master $:$NHDT-Revision: 1.15 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -65,21 +65,24 @@ STATIC_OVL NEARDATA struct artifact artilist[] = { A("Cleaver", BATTLE_AXE, SPFX_RESTR, 0, 0, PHYS(3, 6), NO_DFNS, NO_CARY, 0, A_NEUTRAL, PM_BARBARIAN, NON_PM, 1500L), - A("Grimtooth", ORCISH_DAGGER, SPFX_RESTR, 0, 0, PHYS(2, 6), NO_DFNS, + /* + * Grimtooth glows in warning when elves are present, but its + * damage bonus applies to all targets rather than just elves + * (handled as special case in spec_dbon()). + */ + A("Grimtooth", ORCISH_DAGGER, (SPFX_RESTR | SPFX_WARN | SPFX_DFLAG2), + 0, M2_ELF, PHYS(2, 6), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ORC, 300L), /* * Orcrist and Sting have same alignment as elves. + * + * The combination of SPFX_WARN+SPFX_DFLAG2+M2_value will trigger + * EWarn_of_mon for all monsters that have the M2_value flag. + * Sting and Orcrist will warn of M2_ORC monsters. */ - A("Orcrist", ELVEN_BROADSWORD, SPFX_DFLAG2, 0, M2_ORC, PHYS(5, 0), - NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ELF, 2000L), + A("Orcrist", ELVEN_BROADSWORD, (SPFX_WARN | SPFX_DFLAG2), 0, M2_ORC, + PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ELF, 2000L), - /* - * The combination of SPFX_WARN and M2_something on an artifact - * will trigger EWarn_of_mon for all monsters that have the - * appropriate - * M2_something flags. In Sting's case it will trigger EWarn_of_mon - * for M2_ORC monsters. - */ A("Sting", ELVEN_DAGGER, (SPFX_WARN | SPFX_DFLAG2), 0, M2_ORC, PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ELF, 800L), /* diff --git a/src/artifact.c b/src/artifact.c index 2a5873f79..89ca6109a 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 artifact.c $NHDT-Date: 1432863398 2015/05/29 01:36:38 $ $NHDT-Branch: master $:$NHDT-Revision: 1.87 $ */ +/* NetHack 3.6 artifact.c $NHDT-Date: 1432946531 2015/05/30 00:42:11 $ $NHDT-Branch: master $:$NHDT-Revision: 1.89 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -842,6 +842,10 @@ int tmp; if (!weap || (weap->attk.adtyp == AD_PHYS && /* check for `NO_ATTK' */ weap->attk.damn == 0 && weap->attk.damd == 0)) spec_dbon_applies = FALSE; + else if (otmp->oartifact == ART_GRIMTOOTH) + /* Grimtooth has SPFX settings to warn against elves but we want its + damage bonus to apply to all targets, so bypass spec_applies() */ + spec_dbon_applies = TRUE; else spec_dbon_applies = spec_applies(weap, mon); @@ -1808,11 +1812,15 @@ long *abil; return (struct obj *) 0; } +/* use for warning "glow" for Sting, Orcrist, and Grimtooth */ void Sting_effects(orc_count) int orc_count; { - if (uwep && uwep->oartifact == ART_STING) { + if (uwep + && (uwep->oartifact == ART_STING + || uwep->oartifact == ART_ORCRIST + || uwep->oartifact == ART_GRIMTOOTH)) { /* * Toggling blindness in between warning messages can result in * Sting glows light blue! [...] Sting stops quivering. @@ -1824,7 +1832,9 @@ int orc_count; if (!Blind) pline("%s %s %s!", bare_artifactname(uwep), otense(uwep, "glow"), - hcolor(NH_LIGHT_BLUE)); + hcolor((uwep->oartifact == ART_GRIMTOOTH) + ? NH_RED + : NH_LIGHT_BLUE)); else pline("%s quivers slightly.", bare_artifactname(uwep)); } else if (orc_count == 0 && warn_obj_cnt > 0) { diff --git a/src/display.c b/src/display.c index 3bb62436c..70d88ef82 100644 --- a/src/display.c +++ b/src/display.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 display.c $NHDT-Date: 1432863399 2015/05/29 01:36:39 $ $NHDT-Branch: master $:$NHDT-Revision: 1.55 $ */ +/* NetHack 3.6 display.c $NHDT-Date: 1432946532 2015/05/30 00:42:12 $ $NHDT-Branch: master $:$NHDT-Revision: 1.56 $ */ /* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */ /* and Dave Cohrs, 1990. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1147,8 +1147,7 @@ see_monsters() /* * Make Sting glow blue or stop glowing if required. */ - if (new_warn_obj_cnt != warn_obj_cnt && uwep - && uwep->oartifact == ART_STING) { + if (new_warn_obj_cnt != warn_obj_cnt) { Sting_effects(new_warn_obj_cnt); warn_obj_cnt = new_warn_obj_cnt; } From bd968776a9da36ac69ebe7ef7751ab7904ba73f8 Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 30 May 2015 01:25:46 -0700 Subject: [PATCH 2/2] menucolors parsing Revise the menucolor parsing (color and attribute portion, not the regexp part) to switch to the string matching used for wishing in order to allow space in the "light " entries instead of forcing the two words to be run together. Having them be run together still works, as does use of dash or underscore to separate the two words. So the canonical form for light blue is now "light blue" instead of "lightblue", but all of "light blue", "lightblue", "light-blue", and "light_blue" match it. (So do weird things like "--li-gh_-_tbl ue _" but I won't lose any sleep over that.) Almost all of this if formatting; mostly blank line after declarations but also there was new stuff that didn't match the recent reformat. --- src/options.c | 169 +++++++++++++++++++++++++++++--------------------- 1 file changed, 98 insertions(+), 71 deletions(-) diff --git a/src/options.c b/src/options.c index af1302e6b..e418add02 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 options.c $NHDT-Date: 1432805756 2015/05/28 09:35:56 $ $NHDT-Branch: master $:$NHDT-Revision: 1.206 $ */ +/* NetHack 3.6 options.c $NHDT-Date: 1432974335 2015/05/30 08:25:35 $ $NHDT-Branch: master $:$NHDT-Revision: 1.207 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -100,7 +100,7 @@ static struct Bool_Opt { { "cmdassist", &iflags.cmdassist, TRUE, SET_IN_GAME }, #if defined(MICRO) || defined(WIN32) { "color", &iflags.wc_color, TRUE, SET_IN_GAME }, /*WC*/ -#else /* systems that support multiple terminals, many monochrome */ +#else /* systems that support multiple terminals, many monochrome */ { "color", &iflags.wc_color, FALSE, SET_IN_GAME }, /*WC*/ #endif { "confirm", &flags.confirm, TRUE, SET_IN_GAME }, @@ -451,17 +451,17 @@ typedef struct { #define NUM_MENU_CMDS 11 static const menu_cmd_t default_menu_cmd_info[NUM_MENU_CMDS] = { - /* 0*/ { "menu_first_page", MENU_FIRST_PAGE }, - { "menu_last_page", MENU_LAST_PAGE }, - { "menu_next_page", MENU_NEXT_PAGE }, - { "menu_previous_page", MENU_PREVIOUS_PAGE }, - { "menu_select_all", MENU_SELECT_ALL }, - /* 5*/ { "menu_deselect_all", MENU_UNSELECT_ALL }, - { "menu_invert_all", MENU_INVERT_ALL }, - { "menu_select_page", MENU_SELECT_PAGE }, - { "menu_deselect_page", MENU_UNSELECT_PAGE }, - { "menu_invert_page", MENU_INVERT_PAGE }, - /*10*/ { "menu_search", MENU_SEARCH }, +/* 0*/ { "menu_first_page", MENU_FIRST_PAGE }, + { "menu_last_page", MENU_LAST_PAGE }, + { "menu_next_page", MENU_NEXT_PAGE }, + { "menu_previous_page", MENU_PREVIOUS_PAGE }, + { "menu_select_all", MENU_SELECT_ALL }, +/* 5*/ { "menu_deselect_all", MENU_UNSELECT_ALL }, + { "menu_invert_all", MENU_INVERT_ALL }, + { "menu_select_page", MENU_SELECT_PAGE }, + { "menu_deselect_page", MENU_UNSELECT_PAGE }, + { "menu_invert_page", MENU_INVERT_PAGE }, +/*10*/ { "menu_search", MENU_SEARCH }, }; /* @@ -515,9 +515,11 @@ void reglyph_darkroom() { xchar x, y; + for (x = 0; x < COLNO; x++) for (y = 0; y < ROWNO; y++) { struct rm *lev = &levl[x][y]; + if (!flags.dark_room) { if (lev->glyph == cmap_to_glyph(S_darkroom)) lev->glyph = lev->waslit ? cmap_to_glyph(S_room) @@ -678,13 +680,13 @@ initoptions_init() flags.end_disclose[i] = DISCLOSE_PROMPT_DEFAULT_NO; switch_symbols(FALSE); /* set default characters */ #if defined(UNIX) && defined(TTY_GRAPHICS) - /* - * Set defaults for some options depending on what we can - * detect about the environment's capabilities. - * This has to be done after the global initialization above - * and before reading user-specific initialization via - * config file/environment variable below. - */ + /* + * Set defaults for some options depending on what we can + * detect about the environment's capabilities. + * This has to be done after the global initialization above + * and before reading user-specific initialization via + * config file/environment variable below. + */ /* this detects the IBM-compatible console on most 386 boxes */ if ((opts = nh_getenv("TERM")) && !strncmp(opts, "AT", 2)) { if (!symset[PRIMARY].name) @@ -726,6 +728,7 @@ initoptions_finish() { #ifndef MAC char *opts = getenv("NETHACKOPTIONS"); + if (!opts) opts = getenv("HACKOPTIONS"); if (opts) { @@ -747,17 +750,17 @@ initoptions_finish() read_config_file((char *) 0, SET_IN_FILE); (void) fruitadd(pl_fruit, (struct fruit *) 0); - /* Remove "slime mold" from list of object names; this will */ - /* prevent it from being wished unless it's actually present */ - /* as a named (or default) fruit. Wishing for "fruit" will */ - /* result in the player's preferred fruit [better than "\033"]. */ + /* + * Remove "slime mold" from list of object names. This will + * prevent it from being wished unless it's actually present + * as a named (or default) fruit. Wishing for "fruit" will + * result in the player's preferred fruit [better than "\033"]. + */ obj_descr[SLIME_MOLD].oc_name = "fruit"; if (iflags.bouldersym) update_bouldersym(); - reglyph_darkroom(); - return; } @@ -1013,6 +1016,7 @@ assign_warnings(graph_chars) register uchar *graph_chars; { int i; + for (i = 0; i < WARNCOUNT; i++) if (graph_chars[i]) warnsyms[i] = graph_chars[i]; @@ -1026,6 +1030,7 @@ const char *optn; char buf[BUFSZ]; boolean rejectver = FALSE; unsigned long fnv = get_feature_notice_ver(op); /* version.c */ + if (fnv == 0L) return 0; if (fnv > get_current_feature_ver()) @@ -1058,6 +1063,7 @@ set_duplicate_opt_detection(on_or_off) int on_or_off; { int k, *optptr; + if (on_or_off != 0) { /*-- ON --*/ if (iflags.opt_booldup) @@ -1090,6 +1096,7 @@ const char *opts; int iscompound; /* 0 == boolean option, 1 == compound */ { int i, *optptr; + if (!iscompound && iflags.opt_booldup && initial && from_file) { for (i = 0; boolopt[i].name; i++) { if (match_optname(opts, boolopt[i].name, 3, FALSE)) { @@ -1122,17 +1129,16 @@ complain_about_duplicate(opts, iscompound) const char *opts; int iscompound; /* 0 == boolean option, 1 == compound */ { -#if defined(MAC) +#ifdef MAC /* the Mac has trouble dealing with the output of messages while * processing the config file. That should get fixed one day. * For now just return. */ - return; -#endif - +#else /* !MAC */ raw_printf("\nWarning - %s option specified multiple times: %s.\n", iscompound ? "compound" : "boolean", opts); wait_synch(); +#endif /* ?MAC */ return; } @@ -1174,38 +1180,43 @@ extern struct menucoloring *menu_colorings; static const struct { const char *name; const int color; -} colornames[] = { { "black", CLR_BLACK }, - { "red", CLR_RED }, - { "green", CLR_GREEN }, - { "brown", CLR_BROWN }, - { "blue", CLR_BLUE }, - { "magenta", CLR_MAGENTA }, - { "cyan", CLR_CYAN }, - { "gray", CLR_GRAY }, - { "grey", CLR_GRAY }, - { "orange", CLR_ORANGE }, - { "lightgreen", CLR_BRIGHT_GREEN }, - { "yellow", CLR_YELLOW }, - { "lightblue", CLR_BRIGHT_BLUE }, - { "lightmagenta", CLR_BRIGHT_MAGENTA }, - { "lightcyan", CLR_BRIGHT_CYAN }, - { "white", CLR_WHITE } }; +} colornames[] = { + { "black", CLR_BLACK }, + { "red", CLR_RED }, + { "green", CLR_GREEN }, + { "brown", CLR_BROWN }, + { "blue", CLR_BLUE }, + { "magenta", CLR_MAGENTA }, + { "cyan", CLR_CYAN }, + { "gray", CLR_GRAY }, + { "grey", CLR_GRAY }, + { "orange", CLR_ORANGE }, + { "light green", CLR_BRIGHT_GREEN }, + { "yellow", CLR_YELLOW }, + { "light blue", CLR_BRIGHT_BLUE }, + { "light magenta", CLR_BRIGHT_MAGENTA }, + { "light cyan", CLR_BRIGHT_CYAN }, + { "white", CLR_WHITE } +}; static const struct { const char *name; const int attr; -} attrnames[] = { { "none", ATR_NONE }, - { "bold", ATR_BOLD }, - { "dim", ATR_DIM }, - { "underline", ATR_ULINE }, - { "blink", ATR_BLINK }, - { "inverse", ATR_INVERSE } }; +} attrnames[] = { + { "none", ATR_NONE }, + { "bold", ATR_BOLD }, + { "dim", ATR_DIM }, + { "underline", ATR_ULINE }, + { "blink", ATR_BLINK }, + { "inverse", ATR_INVERSE } +}; const char * clr2colorname(clr) int clr; { int i; + for (i = 0; i < SIZE(colornames); i++) if (colornames[i].color == clr) return colornames[i].name; @@ -1217,6 +1228,7 @@ attr2attrname(attr) int attr; { int i; + for (i = 0; i < SIZE(attrnames); i++) if (attrnames[i].attr == attr) return attrnames[i].name; @@ -1298,6 +1310,7 @@ msgtype2name(typ) int typ; { int i; + for (i = 0; i < SIZE(msgtype_names); i++) if (msgtype_names[i].descr && msgtype_names[i].msgtyp == typ) return msgtype_names[i].name; @@ -1337,8 +1350,11 @@ msgtype_add(typ, pattern) int typ; char *pattern; { - struct plinemsg_type *tmp = (struct plinemsg_type *) alloc(sizeof(struct plinemsg_type)); - if (!tmp) return FALSE; + struct plinemsg_type *tmp + = (struct plinemsg_type *) alloc(sizeof (struct plinemsg_type)); + + if (!tmp) + return FALSE; tmp->msgtype = typ; tmp->regex = regex_init(); if (!regex_compile(pattern, tmp->regex)) { @@ -1362,6 +1378,7 @@ msgtype_free() { struct plinemsg_type *tmp = plinemsg_types; struct plinemsg_type *tmp2; + while (tmp) { free(tmp->pattern); regex_free(tmp->regex); @@ -1402,6 +1419,7 @@ msgtype_type(msg) const char *msg; { struct plinemsg_type *tmp = plinemsg_types; + while (tmp) { if (regex_match(msg, tmp->regex)) return tmp->msgtype; tmp = tmp->next; @@ -1414,6 +1432,7 @@ msgtype_count() { int c = 0; struct plinemsg_type *tmp = plinemsg_types; + while (tmp) { c++; tmp = tmp->next; @@ -1427,6 +1446,7 @@ char *str; { char pattern[256]; char msgtype[11]; + if (sscanf(str, "%10s \"%255[^\"]\"", msgtype, pattern) == 2) { int typ = -1; int i; @@ -1446,13 +1466,14 @@ add_menu_coloring_parsed(str, c, a) char *str; int c, a; { + static const char re_error[] = "Menucolor regex error"; struct menucoloring *tmp; + if (!str) return FALSE; tmp = (struct menucoloring *) alloc(sizeof(struct menucoloring)); tmp->match = regex_init(); if (!regex_compile(str, tmp->match)) { - static const char *re_error = "Menucolor regex error"; if (!iflags.window_inited) raw_printf("\n%s: %s\n", re_error, regex_error_desc(tmp->match)); else @@ -1476,44 +1497,49 @@ add_menu_coloring(str) char *str; { int i, c = NO_COLOR, a = ATR_NONE; - char *tmps, *cs = strchr(str, '='); + char *tmps, *cs, *amp; - if (!cs || !str) + if (!str || (cs = index(str, '=')) == 0) return FALSE; - tmps = cs; - tmps++; - while (*tmps && isspace((uchar) *tmps)) - tmps++; + tmps = cs + 1; /* advance past '=' */ + mungspaces(tmps); + if ((amp = index(tmps, '&')) != 0) + *amp = '\0'; + /* allow "lightblue", "light blue", and "light-blue" to match "light blue" + (also junk like "_l i-gh_t---b l u e" but we won't worry about that); + also copes with trailing space; mungspaces removed any leading space */ for (i = 0; i < SIZE(colornames); i++) - if (strstri(tmps, colornames[i].name) == tmps) { + if (fuzzymatch(tmps, colornames[i].name, " -_", TRUE)) { c = colornames[i].color; break; } - if ((i == SIZE(colornames)) && (*tmps >= '0' && *tmps <= '9')) + if (i == SIZE(colornames) && (*tmps >= '0' && *tmps <= '9')) c = atoi(tmps); if (c > 15) return FALSE; - tmps = strchr(str, '&'); - if (tmps) { - tmps++; - while (*tmps && isspace((uchar) *tmps)) - tmps++; + if (amp) { + tmps = amp + 1; /* advance past '&' */ + /* unlike colors, none of he attribute names has any embedded spaces, + but use of fuzzymatch() allows us ignore the presence of leading + and/or trailing (and also embedded) spaces in the user's string; + dash and underscore skipping could be omitted but does no harm */ for (i = 0; i < SIZE(attrnames); i++) - if (strstri(tmps, attrnames[i].name) == tmps) { + if (fuzzymatch(tmps, attrnames[i].name, " -_", TRUE)) { a = attrnames[i].attr; break; } - if ((i == SIZE(attrnames)) && (*tmps >= '0' && *tmps <= '9')) + if (i == SIZE(attrnames) && (*tmps >= '0' && *tmps <= '9')) a = atoi(tmps); } + /* the regexp portion here has not been condensed by mungspaces() */ *cs = '\0'; tmps = str; - if ((*tmps == '"') || (*tmps == '\'')) { + if (*tmps == '"' || *tmps == '\'') { cs--; while (isspace((uchar) *cs)) cs--; @@ -1532,6 +1558,7 @@ char *str; int *color, *attr; { struct menucoloring *tmpmc; + if (iflags.use_menu_color) for (tmpmc = menu_colorings; tmpmc; tmpmc = tmpmc->next) if (regex_match(str, tmpmc->match)) {