Merge branch 'master' into win32-x64-working

Conflicts:
	src/mon.c
	src/options.c
	src/pickup.c
	src/zap.c

 Changes to be committed:
	modified:   doc/Guidebook.mn
	modified:   doc/Guidebook.tex
	modified:   doc/fixes35.0
	modified:   include/color.h
	modified:   include/extern.h
	modified:   include/mondata.h
	modified:   src/ball.c
	modified:   src/dbridge.c
	modified:   src/dig.c
	modified:   src/display.c
	modified:   src/dokick.c
	modified:   src/dungeon.c
	modified:   src/fountain.c
	modified:   src/invent.c
	modified:   src/mkmaze.c
	modified:   src/mkobj.c
	modified:   src/mon.c
	modified:   src/monmove.c
	modified:   src/mthrowu.c
	modified:   src/options.c
	modified:   src/pickup.c
	modified:   src/sit.c
This commit is contained in:
nhmall
2015-04-30 06:39:44 -04:00
25 changed files with 434 additions and 193 deletions

View File

@@ -2097,8 +2097,8 @@ Implemented by the Amiga, Gem and tty ports.
Default '^'.
.lp menu_headings
Controls how the headings in a menu are highlighted.
Values are 'bold', 'inverse', or 'underline'.
Not all ports can actually display all three types.
Values are 'none', 'bold', 'dim', 'underline', 'blink', or 'inverse'.
Not all ports can actually display all types.
.lp menu_invert_all
Menu character accelerator to invert all items in a menu.
Implemented by the Amiga, Gem, X11 and tty ports.

View File

@@ -2530,8 +2530,9 @@ Implemented by the Amiga, Gem and tty ports.
Default `\verb+^+'.
\item[\ib{menu\_headings}]
Controls how the headings in a menu are highlighted.
Values are ``{\tt bold}'', ``{\tt inverse}'', or ``{\tt underline}''.
Not all ports can actually display all three types.
Values are ``{\tt none}'', ``{\tt bold}'', ``{\tt dim}'',
``{\tt underline}'', ``{\tt blink}'', or ``{\tt inverse}''.
Not all ports can actually display all types.
\item[\ib{menu\_invert\_all}]
Menu character accelerator to invert all items in a menu.
Implemented by the Amiga, Gem, X11 and tty ports.

View File

@@ -903,6 +903,9 @@ some monsters can eat through iron bars
inaccessible niches occasionally have iron bars in front
sinks may teleport or polymorph
shopkeepers give honorifics to vampires and elves
when commands (D, A, object identify) mix object class filtering with BUCX
filtering, take the intersection rather than the union (so ?B picks
blessed scrolls rather than all scrolls plus blessed everything)
Platform- and/or Interface-Specific Fixes

View File

@@ -53,6 +53,7 @@
struct menucoloring {
struct nhregex *match;
char *origstr;
int color, attr;
struct menucoloring *next;
};

View File

@@ -222,6 +222,7 @@ E boolean FDECL(is_lava, (int,int));
E boolean FDECL(is_pool_or_lava, (int,int));
E boolean FDECL(is_ice, (int,int));
E boolean FDECL(is_moat, (int,int));
E schar FDECL(db_under_typ, (int));
E int FDECL(is_drawbridge_wall, (int,int));
E boolean FDECL(is_db_wall, (int,int));
E boolean FDECL(find_drawbridge, (int *,int*));
@@ -1373,6 +1374,7 @@ E void FDECL(mon_regen, (struct monst *,BOOLEAN_P));
E int FDECL(dochugw, (struct monst *));
E boolean FDECL(onscary, (int,int,struct monst *));
E void FDECL(monflee, (struct monst *, int, BOOLEAN_P, BOOLEAN_P));
E void FDECL(mon_yells, (struct monst *, const char *));
E int FDECL(dochug, (struct monst *));
E int FDECL(m_move, (struct monst *,int));
E void FDECL(dissolve_bars, (int,int));

View File

@@ -134,6 +134,8 @@
#define is_displacer(ptr) (((ptr)->mflags3 & M3_DISPLACES) != 0L)
#define is_mplayer(ptr) (((ptr) >= &mons[PM_ARCHEOLOGIST]) && \
((ptr) <= &mons[PM_WIZARD]))
#define is_watch(ptr) ((ptr) == &mons[PM_WATCHMAN] || \
(ptr) == &mons[PM_WATCH_CAPTAIN])
#define is_rider(ptr) ((ptr) == &mons[PM_DEATH] || \
(ptr) == &mons[PM_FAMINE] || \
(ptr) == &mons[PM_PESTILENCE])

View File

@@ -1,4 +1,4 @@
/* NetHack 3.5 ball.c $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$ */
/* NetHack 3.5 ball.c $NHDT-Date: 1430365884 2015/04/30 03:51:24 $ $NHDT-Branch: master $:$NHDT-Revision: 1.22 $ */
/* NetHack 3.5 ball.c $Date: 2011/08/30 22:13:26 $ $Revision: 1.17 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -102,7 +102,7 @@ ballfall()
* It is assumed that when this is called, the ball and chain are NOT
* attached to the object list.
*
* Should not be called while swallowed.
* Should not be called while swallowed except on waterlevel.
*/
void
placebc()
@@ -133,7 +133,19 @@ placebc()
void
unplacebc()
{
if (u.uswallow) return; /* ball&chain not placed while swallowed */
if (u.uswallow) {
if (Is_waterlevel(&u.uz)) {
/* we need to proceed with the removal from the floor
* so that movebubbles() processing will disregard it as
* intended. Ignore all the vision stuff.
*/
if (!carried(uball))
obj_extract_self(uball);
obj_extract_self(uchain);
}
/* ball&chain not unplaced while swallowed */
return;
}
if (!carried(uball)) {
obj_extract_self(uball);

View File

@@ -102,6 +102,18 @@ int x, y;
return FALSE;
}
schar
db_under_typ(mask)
int mask;
{
switch (mask & DB_UNDER) {
case DB_ICE: return ICE; break;
case DB_LAVA: return LAVAPOOL; break;
case DB_MOAT: return MOAT; break;
default: return STONE; break;
}
}
/*
* We want to know whether a wall (or a door) is the portcullis (passageway)
* of an eventual drawbridge.

View File

@@ -1170,8 +1170,7 @@ watch_dig(mtmp, x, y, zap)
if (!mtmp) {
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) continue;
if ((mtmp->data == &mons[PM_WATCHMAN] ||
mtmp->data == &mons[PM_WATCH_CAPTAIN]) &&
if (is_watch(mtmp->data) &&
mtmp->mcansee && m_canseeu(mtmp) &&
couldsee(mtmp->mx, mtmp->my) && mtmp->mpeaceful)
break;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.5 display.c $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$ */
/* NetHack 3.5 display.c $NHDT-Date: 1430365890 2015/04/30 03:51:30 $ $NHDT-Branch: master $:$NHDT-Revision: 1.49 $ */
/* NetHack 3.5 display.c $Date: 2011/12/05 03:17:36 $ $Revision: 1.34 $ */
/* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */
/* and Dave Cohrs, 1990. */
@@ -1363,11 +1363,16 @@ row_refresh(start,stop,y)
void
cls()
{
static boolean in_cls = 0;
if (in_cls) return;
in_cls = TRUE;
display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */
context.botlx = 1; /* force update of botl window */
clear_nhwindow(WIN_MAP); /* clear physical screen */
clear_glyph_buffer(); /* this is sort of an extra effort, but OK */
in_cls = FALSE;
}
/*

View File

@@ -1198,15 +1198,10 @@ dumb:
if (in_town(x, y))
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) continue;
if((mtmp->data == &mons[PM_WATCHMAN] ||
mtmp->data == &mons[PM_WATCH_CAPTAIN]) &&
if (is_watch(mtmp->data) &&
couldsee(mtmp->mx, mtmp->my) &&
mtmp->mpeaceful) {
if (canspotmon(mtmp))
pline("%s yells:", Amonnam(mtmp));
else
You_hear("someone yell:");
verbalize("Halt, thief! You're under arrest!");
mon_yells(mtmp, "Halt, thief! You're under arrest!");
(void) angry_guards(FALSE);
break;
}
@@ -1218,18 +1213,13 @@ dumb:
if (in_town(x, y))
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) continue;
if ((mtmp->data == &mons[PM_WATCHMAN] ||
mtmp->data == &mons[PM_WATCH_CAPTAIN]) &&
if (is_watch(mtmp->data) &&
mtmp->mpeaceful && couldsee(mtmp->mx, mtmp->my)) {
if (canspotmon(mtmp))
pline("%s yells:", Amonnam(mtmp));
else
You_hear("someone yell:");
if(levl[x][y].looted & D_WARNED) {
verbalize("Halt, vandal! You're under arrest!");
mon_yells(mtmp, "Halt, vandal! You're under arrest!");
(void) angry_guards(FALSE);
} else {
verbalize("Hey, stop damaging that door!");
mon_yells(mtmp, "Hey, stop damaging that door!");
levl[x][y].looted |= D_WARNED;
}
break;

View File

@@ -1867,9 +1867,10 @@ donamelevel()
if (!(mptr = find_mapseen(&u.uz))) return 0;
if (mptr->custom) {
char qbuf[BUFSZ];
Sprintf(qbuf, "Replace annotation \"%s\" with?", mptr->custom);
getlin(qbuf, nbuf);
char tmpbuf[BUFSZ];
Sprintf(tmpbuf, "Replace annotation \"%.30s%s\" with?",
mptr->custom, strlen(mptr->custom) > 30 ? "..." : "");
getlin(tmpbuf, nbuf);
} else
getlin("What do you want to call this dungeon level?", nbuf);
if (index(nbuf, '\033')) return 0;
@@ -2205,12 +2206,7 @@ recalc_mapseen()
if (cansee(x, y) || (x == u.ux && y == u.uy && !Levitation)) {
ltyp = levl[x][y].typ;
if (ltyp == DRAWBRIDGE_UP)
switch (levl[x][y].drawbridgemask & DB_UNDER) {
case DB_ICE: ltyp = ICE; break;
case DB_LAVA: ltyp = LAVAPOOL; break;
case DB_MOAT: ltyp = MOAT; break;
default: ltyp = STONE; break;
}
ltyp = db_under_typ(levl[x][y].drawbridgemask);
if ((mtmp = m_at(x, y)) != 0 &&
mtmp->m_ap_type == M_AP_FURNITURE && canseemon(mtmp))
ltyp = cmap_to_type(mtmp->mappearance);

View File

@@ -168,8 +168,7 @@ boolean isyou;
/* Warn about future fountain use. */
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) continue;
if ((mtmp->data == &mons[PM_WATCHMAN] ||
mtmp->data == &mons[PM_WATCH_CAPTAIN]) &&
if (is_watch(mtmp->data) &&
couldsee(mtmp->mx, mtmp->my) &&
mtmp->mpeaceful) {
pline("%s yells:", Amonnam(mtmp));

View File

@@ -395,6 +395,7 @@ addinv(obj)
struct obj *obj;
{
struct obj *otmp, *prev;
int saved_otyp = (int)obj->otyp; /* for panic */
if (obj->where != OBJ_FREE)
panic("addinv: obj not free");
@@ -411,12 +412,16 @@ struct obj *obj;
extra to quivered stack is more useful than to wielded one */
if (uquiver && merged(&uquiver, &obj)) {
obj = uquiver;
if (!obj)
panic("addinv: null obj after quiver merge otyp=%d", saved_otyp);
goto added;
}
/* merge if possible; find end of chain in the process */
for (prev = 0, otmp = invent; otmp; prev = otmp, otmp = otmp->nobj)
if (merged(&otmp, &obj)) {
obj = otmp;
if (!obj)
panic("addinv: null obj after merge otyp=%d", saved_otyp);
goto added;
}
/* didn't merge, so insert into chain */

View File

@@ -1156,12 +1156,7 @@ xchar x,y;
lev = &levl[x][y];
ltyp = lev->typ;
if (ltyp == DRAWBRIDGE_UP)
switch (lev->drawbridgemask & DB_UNDER) {
case DB_ICE: ltyp = ICE; break;
case DB_LAVA: ltyp = LAVAPOOL; break;
case DB_MOAT: ltyp = MOAT; break;
default: ltyp = STONE; break;
}
ltyp = db_under_typ(lev->drawbridgemask);
if (ltyp == LAVAPOOL)
return "lava";

View File

@@ -2193,7 +2193,7 @@ unsigned oid;
for (fx = ex; abs(fx - ex) < 3; fx += dx) {
for (fy = ey; abs(fy - ey) < 3; fy += dy) {
/* 0, 0 was checked above */
if (fx != x || fy != y) {
if (isok(fx,fy) && (fx != x || fy != y)) {
if ((otmp = sobj_at(otyp, fx, fy)) != 0) {
return otmp;
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.5 mon.c $NHDT-Date: 1429666918 2015/04/22 01:41:58 $ $NHDT-Branch: master $:$NHDT-Revision: 1.165 $ */
/* NetHack 3.5 mon.c $NHDT-Date: 1430365894 2015/04/30 03:51:34 $ $NHDT-Branch: master $:$NHDT-Revision: 1.168 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1849,7 +1849,7 @@ register struct monst *mtmp;
u.uy = mtmp->my;
u.uswallow = 0;
u.uswldtim = 0;
if (Punished) placebc();
if (BALL_IN_MON) placebc();
vision_full_recalc = 1;
docrt();
}
@@ -3116,9 +3116,7 @@ register boolean silent;
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) continue;
if((mtmp->data == &mons[PM_WATCHMAN] ||
mtmp->data == &mons[PM_WATCH_CAPTAIN])
&& mtmp->mpeaceful) {
if (is_watch(mtmp->data) && mtmp->mpeaceful) {
ct++;
if(cansee(mtmp->mx, mtmp->my) && mtmp->mcanmove) {
if (distu(mtmp->mx, mtmp->my) == 2) nct++;
@@ -3156,9 +3154,8 @@ pacify_guards()
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) continue;
if (mtmp->data == &mons[PM_WATCHMAN] ||
mtmp->data == &mons[PM_WATCH_CAPTAIN])
mtmp->mpeaceful = 1;
if (is_watch(mtmp->data))
mtmp->mpeaceful = 1;
}
}

View File

@@ -50,6 +50,18 @@ boolean for_unlocking; /* true => credit card ok, false => not ok */
return m_carrying(mon, SKELETON_KEY) || m_carrying(mon, LOCK_PICK);
}
void
mon_yells(mon, shout)
struct monst *mon;
const char *shout;
{
if (canspotmon(mon))
pline("%s yells:", Amonnam(mon));
else
You_hear("someone yell:");
verbalize(shout);
}
STATIC_OVL void
watch_on_duty(mtmp)
register struct monst *mtmp;
@@ -63,13 +75,11 @@ register struct monst *mtmp;
(levl[x][y].doormask & D_LOCKED)) {
if(couldsee(mtmp->mx, mtmp->my)) {
pline("%s yells:", Amonnam(mtmp));
if(levl[x][y].looted & D_WARNED) {
verbalize("Halt, thief! You're under arrest!");
mon_yells(mtmp, "Halt, thief! You're under arrest!");
(void) angry_guards(!!Deaf);
} else {
verbalize("Hey, stop picking that lock!");
mon_yells(mtmp, "Hey, stop picking that lock!");
levl[x][y].looted |= D_WARNED;
}
stop_occupation();
@@ -400,7 +410,7 @@ register struct monst *mtmp;
}
/* the watch will look around and see if you are up to no good :-) */
if (mdat == &mons[PM_WATCHMAN] || mdat == &mons[PM_WATCH_CAPTAIN])
if (is_watch(mdat))
watch_on_duty(mtmp);
else if (is_mind_flayer(mdat) && !rn2(20)) {
@@ -1295,15 +1305,10 @@ register int x, y;
{
int levtyp = levl[x][y].typ;
if (levtyp == DRAWBRIDGE_UP) {
/* use underlying terrain in front of closed drawbridge */
switch (levl[x][y].drawbridgemask & DB_UNDER) {
case DB_MOAT: levtyp = MOAT; break;
case DB_LAVA: levtyp = LAVAPOOL; break;
case DB_ICE: levtyp = ICE; break;
case DB_FLOOR: levtyp = ROOM; break;
}
}
/* use underlying terrain in front of closed drawbridge */
if (levtyp == DRAWBRIDGE_UP)
levtyp = db_under_typ(levl[x][y].drawbridgemask);
return (boolean)(ACCESSIBLE(levtyp) && !closed_door(x, y));
}

View File

@@ -421,7 +421,8 @@ struct obj *obj; /* missile (or stack providing it) */
(void) drop_throw(singleobj, hitu, u.ux, u.uy);
break;
}
} else if (!range /* reached end of path */
}
if (!range /* reached end of path */
/* missile hits edge of screen */
|| !isok(bhitpos.x+dx,bhitpos.y+dy)
/* missile hits the wall */
@@ -440,7 +441,7 @@ struct obj *obj; /* missile (or stack providing it) */
tmp_at(bhitpos.x, bhitpos.y);
delay_output();
}
if (isok(bhitpos.x, bhitpos.y)) tmp_at(bhitpos.x, bhitpos.y);
tmp_at(bhitpos.x, bhitpos.y);
delay_output();
tmp_at(DISP_END, 0);

View File

@@ -1,4 +1,4 @@
/* NetHack 3.5 options.c $NHDT-Date: 1429953065 2015/04/25 09:11:05 $ $NHDT-Branch: master $:$NHDT-Revision: 1.186 $ */
/* NetHack 3.5 options.c $NHDT-Date: 1430192504 2015/04/28 03:41:44 $ $NHDT-Branch: master $:$NHDT-Revision: 1.189 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -282,7 +282,7 @@ static struct Comp_Opt
4, SET_IN_FILE },
{ "menu_first_page", "jump to the first page in a menu",
4, SET_IN_FILE },
{ "menu_headings", "bold, inverse, or underline headings", 9, SET_IN_GAME },
{ "menu_headings", "text attribute for menu headings", 9, SET_IN_GAME },
{ "menu_invert_all", "invert all items in a menu", 4, SET_IN_FILE },
{ "menu_invert_page", "invert all items on this page of a menu",
4, SET_IN_FILE },
@@ -497,6 +497,13 @@ STATIC_OVL boolean FDECL(is_wc2_option, (const char *));
STATIC_OVL boolean FDECL(wc2_supported, (const char *));
STATIC_DCL void FDECL(remove_autopickup_exception, (struct autopickup_exception *));
STATIC_OVL int FDECL(count_ape_maps, (int *, int *));
STATIC_DCL const char *FDECL(clr2colorname, (int));
STATIC_DCL const char *FDECL(attr2attrname, (int));
STATIC_DCL int NDECL(query_color);
STATIC_DCL int FDECL(query_attr, (char *));
STATIC_DCL boolean FDECL(add_menu_coloring_parsed, (char *, int, int));
STATIC_DCL void FDECL(free_one_menu_coloring, (int));
STATIC_DCL int NDECL(count_menucolors);
void
@@ -1162,13 +1169,116 @@ static const struct {
{"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;
return NULL;
}
const char *
attr2attrname(attr)
int attr;
{
int i;
for (i = 0; i < SIZE(attrnames); i++)
if (attrnames[i].attr == attr)
return attrnames[i].name;
return NULL;
}
int
query_color()
{
winid tmpwin;
anything any;
int i, pick_cnt;
menu_item *picks = (menu_item *)0;
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin);
any = zeroany;
for (i = 0; i < SIZE(colornames); i++) {
if (!strcmp(colornames[i].name, "grey")) continue;
any.a_int = i + 1;
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, colornames[i].name, MENU_UNSELECTED);
}
end_menu(tmpwin, "Pick a color");
pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
destroy_nhwindow(tmpwin);
if (pick_cnt > 0) {
i = colornames[picks->item.a_int - 1].color;
free((genericptr_t)picks);
return i;
}
return -1;
}
int
query_attr(prompt)
char *prompt;
{
winid tmpwin;
anything any;
int i, pick_cnt;
menu_item *picks = (menu_item *)0;
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin);
any = zeroany;
for (i = 0; i < SIZE(attrnames); i++) {
any.a_int = i + 1;
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, attrnames[i].attr, attrnames[i].name, MENU_UNSELECTED);
}
end_menu(tmpwin, prompt ? prompt : "Pick an attribute");
pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
destroy_nhwindow(tmpwin);
if (pick_cnt > 0) {
i = attrnames[picks->item.a_int - 1].attr;
free((genericptr_t)picks);
return i;
}
return -1;
}
boolean
add_menu_coloring_parsed(str, c, a)
char *str;
int c, a;
{
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
pline("%s: %s", re_error, regex_error_desc(tmp->match));
wait_synch();
free(tmp);
return FALSE;
} else {
tmp->next = menu_colorings;
tmp->origstr = dupstr(str);
tmp->color = c;
tmp->attr = a;
menu_colorings = tmp;
return TRUE;
}
}
/* parse '"regex_string"=color&attr' and add it to menucoloring */
boolean
add_menu_coloring(str)
char *str;
{
int i, c = NO_COLOR, a = ATR_NONE;
struct menucoloring *tmp;
char *tmps, *cs = strchr(str, '=');
if (!cs || !str) return FALSE;
@@ -1211,20 +1321,7 @@ char *str;
}
}
tmp = (struct menucoloring *)alloc(sizeof(struct menucoloring));
tmp->match = regex_init();
if (!regex_compile(tmps, tmp->match)) {
raw_printf("\nMenucolor regex error: %s\n", regex_error_desc(tmp->match));
wait_synch();
free(tmp);
return FALSE;
} else {
tmp->next = menu_colorings;
tmp->color = c;
tmp->attr = a;
menu_colorings = tmp;
return TRUE;
}
return add_menu_coloring_parsed(tmps, c, a);
}
boolean
@@ -1251,11 +1348,48 @@ free_menu_coloring()
while (tmp) {
struct menucoloring *tmp2 = tmp->next;
regex_free(tmp->match);
free(tmp->origstr);
free(tmp);
tmp = tmp2;
}
}
void
free_one_menu_coloring(idx)
int idx; /* 0 .. */
{
struct menucoloring *tmp = menu_colorings;
struct menucoloring *prev = NULL;
while (tmp) {
if (idx == 0) {
struct menucoloring *next = tmp->next;
regex_free(tmp->match);
free(tmp->origstr);
free(tmp);
if (prev) prev->next = next;
else menu_colorings = next;
return;
}
idx--;
prev = tmp;
tmp = tmp->next;
}
}
int
count_menucolors()
{
int count = 0;
struct menucoloring *tmp = menu_colorings;
while (tmp) {
count++;
tmp = tmp->next;
}
return count;
}
void
parseoptions(opts, tinitial, tfrom_file)
@@ -2617,14 +2751,12 @@ goodfruit:
else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
return;
}
if (!strcmpi(opts,"bold"))
iflags.menu_headings = ATR_BOLD;
else if (!strcmpi(opts,"inverse"))
iflags.menu_headings = ATR_INVERSE;
else if (!strcmpi(opts,"underline"))
iflags.menu_headings = ATR_ULINE;
else
badoption(opts);
for (i = 0; i < SIZE(attrnames); i++)
if (!strcmpi(opts, attrnames[i].name)) {
iflags.menu_headings = attrnames[i].attr;
return;
}
badoption(opts);
return;
}
@@ -3086,6 +3218,11 @@ doset()
doset_add_menu(tmpwin, compopt[i].name,
(pass == DISP_IN_GAME) ? 0 : indexoffset);
}
any.a_int = -3;
Sprintf(buf2, "(%d currently set)", count_menucolors());
Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : " ",
"menucolors", buf2);
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
#ifdef STATUS_VIA_WINDOWPORT
# ifdef STATUS_HILITES
any.a_int = -2;
@@ -3137,6 +3274,10 @@ doset()
} else
# endif
#endif
if (opt_indx == -4) {
(void)special_handling("menucolors",
setinitial, fromfile);
} else
if (opt_indx < boolcount) {
/* boolean option */
Sprintf(buf, "%s%s", *boolopt[opt_indx].addr ? "!" : "",
@@ -3176,6 +3317,57 @@ doset()
return 0;
}
int
handle_add_list_remove(optname, numtotal)
char *optname;
int numtotal;
{
winid tmpwin;
anything any;
int i, pick_cnt, pick_idx, opt_idx;
menu_item *pick_list = (menu_item *)0;
static const struct action {
char letr;
const char *desc;
} action_titles[] = {
{ 'a', "add new %s" }, /* [0] */
{ 'l', "list %s" }, /* [1] */
{ 'r', "remove existing %s" }, /* [2] */
{ 'x', "exit this menu" }, /* [3] */
};
opt_idx = 0;
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin);
any = zeroany;
for (i = 0; i < SIZE(action_titles); i++) {
char tmpbuf[BUFSZ];
any.a_int++;
/* omit list and remove if there aren't any yet */
if (!numtotal && (i == 1 || i == 2)) continue;
Sprintf(tmpbuf, action_titles[i].desc, (i == 1) ? makeplural(optname) : optname);
add_menu(tmpwin, NO_GLYPH, &any, action_titles[i].letr,
0, ATR_NONE, tmpbuf,
#if 0 /* this ought to work but doesn't... */
(action_titles[i].letr == 'x') ? MENU_SELECTED :
#endif
MENU_UNSELECTED);
}
end_menu(tmpwin, "Do what?");
if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &pick_list)) > 0) {
for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
opt_idx = pick_list[pick_idx].item.a_int - 1;
}
free((genericptr_t)pick_list);
pick_list = (menu_item *)0;
}
destroy_nhwindow(tmpwin);
if (pick_cnt < 1) opt_idx = 3; /* none selected, exit menu */
return opt_idx;
}
struct symsetentry *symset_list = 0; /* files.c will populate this with
list of available sets */
@@ -3453,79 +3645,70 @@ boolean setinitial,setfromfile;
}
destroy_nhwindow(tmpwin);
} else if (!strcmp("menu_headings", optname)) {
static const char *mhchoices[3] = {"bold", "inverse", "underline"};
const char *npletters = "biu";
menu_item *mode_pick = (menu_item *)0;
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin);
any = zeroany;
for (i = 0; i < SIZE(mhchoices); i++) {
any.a_int = i + 1;
add_menu(tmpwin, NO_GLYPH, &any, npletters[i], 0,
ATR_NONE, mhchoices[i], MENU_UNSELECTED);
}
end_menu(tmpwin, "How to highlight menu headings:");
if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
int mode = mode_pick->item.a_int - 1;
switch(mode) {
case 2:
iflags.menu_headings = ATR_ULINE;
break;
case 0:
iflags.menu_headings = ATR_BOLD;
break;
case 1:
default:
iflags.menu_headings = ATR_INVERSE;
int mhattr = query_attr("How to highlight menu headings:");
if (mhattr != -1) iflags.menu_headings = mhattr;
} else if (!strcmp("menucolors", optname)) {
int opt_idx, nmc, mcclr, mcattr;
char mcbuf[BUFSZ];
menucolors_again:
nmc = count_menucolors();
opt_idx = handle_add_list_remove("menucolor", nmc);
if (opt_idx == 3) {
; /* done--fall through to function exit */
} else if (opt_idx == 0) { /* add new */
getlin("What new menucolor pattern?", mcbuf);
if (*mcbuf == '\033' || !*mcbuf) goto menucolors_again;
mcclr = query_color();
if (mcclr == -1) goto menucolors_again;
mcattr = query_attr(NULL);
if (mcattr == -1) goto menucolors_again;
if (!add_menu_coloring_parsed(mcbuf, mcclr, mcattr)) {
pline("Error adding the menu color.");
wait_synch();
goto menucolors_again;
}
free((genericptr_t)mode_pick);
}
destroy_nhwindow(tmpwin);
} else if (!strcmp("autopickup_exception", optname)) {
int pick_cnt, pick_idx, opt_idx, pass;
int totalapes = 0, numapes[2] = {0,0};
menu_item *pick_list = (menu_item *)0;
char apebuf[1+BUFSZ]; /* so &apebuf[1] is BUFSZ long for getlin() */
struct autopickup_exception *ape;
static const struct ape_action {
char letr;
const char *desc;
} action_titles[] = {
{ 'a', "add new autopickup exception" }, /* [0] */
{ 'l', "list autopickup exceptions" }, /* [1] */
{ 'r', "remove existing autopickup exception" }, /* [2] */
{ 'x', "exit this menu" }, /* [3] */
};
ape_again:
opt_idx = 0;
totalapes = count_ape_maps(&numapes[AP_LEAVE], &numapes[AP_GRAB]);
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin);
any = zeroany;
for (i = 0; i < SIZE(action_titles); i++) {
any.a_int++;
/* omit list and remove if there aren't any yet */
if (!totalapes && (i == 1 || i == 2)) continue;
add_menu(tmpwin, NO_GLYPH, &any, action_titles[i].letr,
0, ATR_NONE, action_titles[i].desc,
#if 0 /* this ought to work but doesn't... */
(action_titles[i].letr == 'x') ? MENU_SELECTED :
#endif
MENU_UNSELECTED);
}
end_menu(tmpwin, "Do what?");
if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &pick_list)) > 0) {
for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
opt_idx = pick_list[pick_idx].item.a_int - 1;
} else { /* list or remove */
int pick_idx, pick_cnt;
int mc_idx;
menu_item *pick_list = (menu_item *)0;
struct menucoloring *tmp = menu_colorings;
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin);
any = zeroany;
mc_idx = 0;
while (tmp) {
const char *sattr = attr2attrname(tmp->attr);
const char *sclr = clr2colorname(tmp->color);
any.a_int = (++mc_idx);
Sprintf(mcbuf, "\"%s\"=%s%s%s", tmp->origstr, sclr,
(tmp->attr != ATR_NONE) ? " & " : "",
(tmp->attr != ATR_NONE) ? sattr : "");
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, mcbuf, MENU_UNSELECTED);
tmp = tmp->next;
}
Sprintf(mcbuf, "%s menu colors",
(opt_idx == 1) ? "List of" : "Remove which");
end_menu(tmpwin, mcbuf);
pick_cnt = select_menu(tmpwin,
(opt_idx == 1) ? PICK_NONE : PICK_ANY,
&pick_list);
if (pick_cnt > 0) {
for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
free_one_menu_coloring(pick_list[pick_idx].item.a_int - 1 - pick_idx);
}
free((genericptr_t)pick_list);
pick_list = (menu_item *)0;
destroy_nhwindow(tmpwin);
if (pick_cnt >= 0) goto menucolors_again;
}
destroy_nhwindow(tmpwin);
if (pick_cnt < 1 || opt_idx == 3) {
} else if (!strcmp("autopickup_exception", optname)) {
int opt_idx, pass, totalapes = 0, numapes[2] = {0,0};
char apebuf[1+BUFSZ]; /* so &apebuf[1] is BUFSZ long for getlin() */
struct autopickup_exception *ape;
ape_again:
totalapes = count_ape_maps(&numapes[AP_LEAVE], &numapes[AP_GRAB]);
opt_idx = handle_add_list_remove("autopickup exception", totalapes);
if (opt_idx == 3) {
; /* done--fall through to function exit */
} else if (opt_idx == 0) { /* add new */
getlin("What new autopickup exception pattern?", &apebuf[1]);
@@ -3545,6 +3728,8 @@ boolean setinitial,setfromfile;
goto ape_again;
}
} else { /* list or remove */
int pick_idx, pick_cnt;
menu_item *pick_list = (menu_item *)0;
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin);
for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
@@ -3869,10 +4054,7 @@ char *buf;
else if (!strcmp(optname, "menu_invert_all"))
Sprintf(buf, "%s", to_be_done);
else if (!strcmp(optname, "menu_headings")) {
Sprintf(buf, "%s", (iflags.menu_headings == ATR_BOLD) ?
"bold" : (iflags.menu_headings == ATR_INVERSE) ?
"inverse" : (iflags.menu_headings == ATR_ULINE) ?
"underline" : "unknown");
Sprintf(buf, "%s", attr2attrname(iflags.menu_headings));
}
else if (!strcmp(optname, "menu_invert_page"))
Sprintf(buf, "%s", to_be_done);

View File

@@ -1,4 +1,4 @@
/* NetHack 3.5 pickup.c $NHDT-Date: 1426558927 2015/03/17 02:22:07 $ $NHDT-Branch: master $:$NHDT-Revision: 1.131 $ */
/* NetHack 3.5 pickup.c $NHDT-Date: 1430122768 2015/04/27 08:19:28 $ $NHDT-Branch: master $:$NHDT-Revision: 1.150 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -307,8 +307,10 @@ struct obj *obj;
return (obj->quan >= val_for_n_or_more);
}
/* List of valid menu classes for query_objlist() and allow_category callback */
static char valid_menu_classes[MAXOCLASSES + 2];
/* list of valid menu classes for query_objlist() and allow_category callback
(with room for all object classes, 'u'npaid, BUCX, and terminator) */
static char valid_menu_classes[MAXOCLASSES + 1 + 4 + 1];
static boolean class_filter, bucx_filter, shop_filter;
void
add_valid_menu_class(c)
@@ -316,10 +318,19 @@ int c;
{
static int vmc_count = 0;
if (c == 0) /* reset */
vmc_count = 0;
else
valid_menu_classes[vmc_count++] = (char)c;
if (c == 0) { /* reset */
vmc_count = 0;
class_filter = bucx_filter = shop_filter = FALSE;
} else {
valid_menu_classes[vmc_count++] = (char)c;
/* categorize the new class */
switch (c) {
case 'B': case 'U': case 'C': /*FALLTHRU*/
case 'X': bucx_filter = TRUE; break;
case 'u': shop_filter = TRUE; break;
default: class_filter = TRUE; break;
}
}
valid_menu_classes[vmc_count] = '\0';
}
@@ -344,26 +355,47 @@ boolean
allow_category(obj)
struct obj *obj;
{
if (Role_if(PM_PRIEST)) obj->bknown = TRUE;
/* if obj's class is in the list, then obj is acceptable */
if (index(valid_menu_classes, obj->oclass))
return TRUE;
/* unpaid and BUC checks don't apply to coins */
if (obj->oclass == COIN_CLASS)
return index(valid_menu_classes, COIN_CLASS) ? TRUE : FALSE;
if (Role_if(PM_PRIEST)) obj->bknown = TRUE;
/*
* There are three types of filters possible and the first and
* third can have more than one entry:
* 1) object class (armor, potion, &c);
* 2) unpaid shop item;
* 3) bless/curse state (blessed, uncursed, cursed, BUC-unknown).
* When only one type is present, the situation is simple:
* to be accepted, obj's status must match one of the entries.
* When more than one type is present, the obj will now only
* be accepted when it matches one entry of each type.
* So ?!B will accept blessed scrolls or potions, and [u will
* accept unpaid armor. (In 3.4.3, an object was accepted by
* this filter if it met any entry of any type, so ?!B resulted
* in accepting all scrolls and potions regardless of bless/curse
* state plus all blessed non-scroll, non-potion objects.)
*/
/* if class is expected but obj's class is not in the list, reject */
if (class_filter && !index(valid_menu_classes, obj->oclass))
return FALSE;
/* if unpaid is expected and obj isn't unpaid, reject (treat a container
holding any unpaid object as unpaid even if isn't unpaid itself) */
if (shop_filter && !obj->unpaid
&& !(Has_contents(obj) && count_unpaid(obj) > 0))
return FALSE;
/* check for unpaid item */
if (index(valid_menu_classes, 'u') &&
(obj->unpaid || (Has_contents(obj) && count_unpaid(obj))))
return TRUE;
/* check for particular bless/curse state */
if (!obj->bknown ? index(valid_menu_classes, 'X') : /* unknown BUC state */
obj->blessed ? index(valid_menu_classes, 'B') : /* known blessed */
!obj->cursed ? index(valid_menu_classes, 'U') : /* known uncursed */
index(valid_menu_classes, 'C')) /* known cursed */
return TRUE;
/* obj isn't acceptable */
return FALSE;
if (bucx_filter) {
/* first categorize this object's bless/curse state */
char bucx = !obj->bknown ? 'X'
: obj->blessed ? 'B' : obj->cursed ? 'C' : 'U';
/* if its category is not in the list, reject */
if (!index(valid_menu_classes, bucx))
return FALSE;
}
/* obj didn't fail any of the filter checks, so accept */
return TRUE;
}
#if 0 /* not used */

View File

@@ -15,6 +15,7 @@ take_gold()
nobj = otmp->nobj;
if (otmp->oclass == COIN_CLASS) {
lost_money = 1;
remove_worn_item(otmp, FALSE);
delobj(otmp);
}
}

View File

@@ -1401,7 +1401,7 @@ int *spell_no;
Sprintf(buf, "Name\tLevel\tCategory\tFail\tRetention");
fmt = "%s\t%-d\t%s\t%-d%%\t%s";
}
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD, buf, MENU_UNSELECTED);
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings, buf, MENU_UNSELECTED);
for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++) {
splnum = !spl_orderindx ? i : spl_orderindx[i];
Sprintf(buf, fmt,

View File

@@ -516,8 +516,7 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
anger_guards = (mon->mpeaceful &&
(mon->ispriest || mon->isshk ||
mon->data == &mons[PM_WATCHMAN] ||
mon->data == &mons[PM_WATCH_CAPTAIN]));
is_watch(mon->data)));
result = hmon_hitmon(mon, obj, thrown);
if (mon->ispriest && !rn2(2)) ghod_hitsu(mon);
if (anger_guards) (void)angry_guards(!!Deaf);

View File

@@ -1,4 +1,4 @@
/* NetHack 3.5 zap.c $NHDT-Date: 1428207622 2015/04/05 04:20:22 $ $NHDT-Branch: nhmall-booktribute $:$NHDT-Revision: 1.215 $ */
/* NetHack 3.5 zap.c $NHDT-Date: 1430355196 2015/04/30 00:53:16 $ $NHDT-Branch: master $:$NHDT-Revision: 1.218 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -2869,9 +2869,11 @@ int skill;
else if (dex < 8)
hit_bon -= 1;
else if (dex < 14)
hit_bon -= 0; /* Will change when print stuff below removed */
/* Will change when print stuff below removed */
hit_bon -= 0;
else
hit_bon += dex - 14; /* Even increment for dextrous heroes (see weapon.c abon) */
/* Even increment for dextrous heroes (see weapon.c abon) */
hit_bon += dex - 14;
return hit_bon;
}