This commit is contained in:
keni
2015-04-30 22:01:12 -04:00
29 changed files with 634 additions and 245 deletions

View File

@@ -1,4 +1,4 @@
.\" $NHDT-Branch$:$NHDT-Revision$ $NHDT-Date$
.\" $NHDT-Branch: master $:$NHDT-Revision: 1.160 $ $NHDT-Date: 1430043650 2015/04/26 10:20:50 $
.\" $Revision: 1.130 $ $Date: 2015/03/27 00:38:30 $
.ds h0 "NetHack Guidebook
.ds h1
@@ -607,12 +607,17 @@ is true.
.lp i
List your inventory (everything you're carrying).
.lp I
List selected parts of your inventory.
List selected parts of your inventory, usually be specifying the character
for a particular set of objects, like `[' for armor or `!' for potions.
.sd
.si
I* - list all gems in inventory;
Iu - list all unpaid items;
Ix - list all used up items that are on your shopping bill;
IB - list all items known to be blessed;
IU - list all items known to be uncursed;
IC - list all items known to be cursed;
IX - list all items whose bless/curse status is known;
I$ - count your money.
.ei
.ed
@@ -1256,6 +1261,11 @@ Objects can also be blessed. Blessed items usually work better or
more beneficially than normal uncursed items. For example, a blessed
weapon will do more damage against demons.
.pg
Objects which are neither cursed nor blessed are referred to as uncursed.
They could just as easily have been described as unblessed, but the
uncursed designation is what you will see within the game. A ``glass
half full versus glass half empty'' situation; make of that what you will.
.pg
There are magical means of bestowing or removing curses upon objects,
so even if you are stuck with one, you can still have the curse
lifted and the item removed. Priests and Priestesses have an innate
@@ -1266,6 +1276,8 @@ An item with unknown status will be reported in your inventory with no prefix.
An item which you know the state of will be distinguished in your inventory
by the presence of the word ``cursed'', ``uncursed'' or ``blessed'' in the
description of the item.
In some cases ``uncursed'' will be omitted as being redundant when
enough other information is displayed.
.hn 2
Weapons (`)')
.pg
@@ -2085,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

@@ -742,12 +742,18 @@ something appropriate if {\it autoquiver\/} is true.
List your inventory (everything you're carrying).
%.lp
\item[\tb{I}]
List selected parts of your inventory.\\
List selected parts of your inventory, usually be specifying the character
for a particular set of objects, like `{\tt [}' for armor or `{\tt !}'
for potions.\\
%.sd
%.si
{\tt I*} --- list all gems in inventory;\\
{\tt Iu} --- list all unpaid items;\\
{\tt Ix} --- list all used up items that are on your shopping bill;\\
{\tt IB} --- list all items known to be blessed;\\
{\tt IU} --- list all items known to be uncursed;\\
{\tt IC} --- list all items known to be cursed;\\
{\tt IX} --- list all items whose bless/curse status is unknown;\\
{\tt I\$} --- count your money.
%.ei
%.ed
@@ -1543,6 +1549,12 @@ Objects can also be blessed. Blessed items usually work better or
more beneficially than normal uncursed items. For example, a blessed
weapon will do more damage against demons.
%.pg
Objects which are neither cursed nor blessed are referred to as uncursed.
They could just as easily have been described as unblessed, but the
uncursed designation is what you will see within the game. A ``glass
half full versus glass half empty'' situation; make of that what you will.
%.pg
There are magical means of bestowing or removing curses upon objects,
so even if you are stuck with one, you can still have the curse
@@ -1555,6 +1567,8 @@ An item with unknown status will be reported in your inventory with no prefix.
An item which you know the state of will be distinguished in your inventory
by the presence of the word ``cursed'', ``uncursed'' or ``blessed'' in the
description of the item.
In some cases ``uncursed'' will be omitted as being redundant when
enough other information is displayed.
%.hn 2
\subsection*{Weapons (`{\tt )}')}
@@ -2516,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
@@ -1128,6 +1131,8 @@ Some levels in Gehennom now use the old corridor-style maze instead of
"beetle legs" are restored.
gnomes will occasionally have a candle
stop travel or run when you get hungry
'I' command can accept 'B','U','C',or 'X' as an alternative to normal object
class character to show inventory of items known to be blessed,&c
Platform- and/or Interface-Specific New Features

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*));
@@ -570,6 +571,7 @@ E boolean FDECL(Invocation_lev, (d_level *));
E xchar NDECL(level_difficulty);
E schar FDECL(lev_by_name, (const char *));
E schar FDECL(print_dungeon, (BOOLEAN_P,schar *,xchar *));
E char *FDECL(get_annotation, (d_level *));
E int NDECL(donamelevel);
E int NDECL(dooverview);
E void FDECL(show_overview, (int,int));
@@ -1372,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

@@ -103,6 +103,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

@@ -1171,8 +1171,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

@@ -1069,6 +1069,7 @@ boolean at_stairs, falling, portal;
boolean new = FALSE; /* made a new level? */
struct monst *mtmp;
char whynot[BUFSZ];
char *annotation;
if (dunlev(newlevel) > dunlevs_in_dungeon(newlevel))
newlevel->dlevel = dunlevs_in_dungeon(newlevel);
@@ -1458,6 +1459,9 @@ boolean at_stairs, falling, portal;
save_currentstate();
#endif
if ((annotation = get_annotation(&u.uz)))
You("remember this level as %s.", annotation);
/* assume this will always return TRUE when changing level */
(void) in_out_region(u.ux, u.uy);
(void) pickup(1);

View File

@@ -596,6 +596,9 @@ docallcmd()
any.a_char = 'd'; /* entry 'd' (or 'b'), group accelator 'd' */
add_menu(win, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
"the type of an object on discoveries list", MENU_UNSELECTED);
any.a_char = 'e';
add_menu(win, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
"the current level", MENU_UNSELECTED);
#if 0
any.a_char = 'f'; /* entry 'e' (or 'c'), group accelator 'f' */
add_menu(win, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
@@ -643,6 +646,9 @@ docallcmd()
case 'd': /* name a type of object on the discoveries list */
rename_disco();
break;
case 'e': /* annotate level */
donamelevel();
break;
#if 0
case 'f': /* name a type of object visible on the floor */
/* [not implemented] */

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

@@ -1848,6 +1848,16 @@ d_level *dest;
}
}
char *
get_annotation(lev)
d_level *lev;
{
mapseen *mptr;
if ((mptr = find_mapseen(lev)))
return mptr->custom;
return NULL;
}
/* #annotate command - add a custom name to the current level */
int
donamelevel()
@@ -1857,8 +1867,15 @@ donamelevel()
if (!(mptr = find_mapseen(&u.uz))) return 0;
getlin("What do you want to call this dungeon level?", nbuf);
if (mptr->custom) {
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;
(void)mungspaces(nbuf);
/* discard old annotation, if any */
if (mptr->custom) {
@@ -2190,12 +2207,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

@@ -169,8 +169,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

@@ -24,6 +24,7 @@ STATIC_PTR char *FDECL(safeq_xprname, (struct obj *));
STATIC_PTR char *FDECL(safeq_shortxprname, (struct obj *));
STATIC_DCL char FDECL(display_pickinv, (const char *,BOOLEAN_P, long *));
STATIC_DCL char FDECL(display_used_invlets, (CHAR_P));
STATIC_DCL void FDECL(tally_BUCX, (struct obj *,int *,int *,int *,int *,int *));
STATIC_DCL boolean FDECL(this_type_only, (struct obj *));
STATIC_DCL void NDECL(dounpaid);
STATIC_DCL struct obj *FDECL(find_unpaid,(struct obj *,struct obj **));
@@ -394,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");
@@ -410,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 */
@@ -2067,6 +2073,33 @@ count_buc(list, type)
return count;
}
/* similar to count_buc(), but tallies all states at once
rather than looking for a specific type */
STATIC_OVL void
tally_BUCX(list, bcp, ucp, ccp, xcp, ocp)
struct obj *list;
int *bcp, *ucp, *ccp, *xcp, *ocp;
{
*bcp = *ucp = *ccp = *xcp = *ocp = 0;
for ( ; list; list = list->nobj) {
if (list->oclass == COIN_CLASS) {
++(*ocp); /* "other" */
continue;
}
/* priests always know bless/curse state */
if (Role_if(PM_PRIEST)) list->bknown = 1;
if (!list->bknown)
++(*xcp);
else if (list->blessed)
++(*bcp);
else if (list->cursed)
++(*ccp);
else /* neither blessed nor cursed => uncursed */
++(*ucp);
}
}
long
count_contents(container, nested, quantity, everything)
struct obj *container;
@@ -2189,7 +2222,18 @@ STATIC_OVL boolean
this_type_only(obj)
struct obj *obj;
{
return (obj->oclass == this_type);
boolean res = (obj->oclass == this_type);
if (obj->oclass != COIN_CLASS) {
switch (this_type) {
case 'B': res = (obj->bknown && obj->blessed); break;
case 'U': res = (obj->bknown && !(obj->blessed || obj->cursed)); break;
case 'C': res = (obj->bknown && obj->cursed); break;
case 'X': res = !obj->bknown; break;
default: break; /* use 'res' as-is */
}
}
return res;
}
/* the 'I' command */
@@ -2200,6 +2244,7 @@ dotypeinv()
int n, i = 0;
char *extra_types, types[BUFSZ];
int class_count, oclass, unpaid_count, itemcount;
int bcnt, ccnt, ucnt, xcnt, ocnt;
boolean billx = *u.ushops && doinvbill(0);
menu_item *pick_list;
boolean traditional = TRUE;
@@ -2210,12 +2255,18 @@ dotypeinv()
return 0;
}
unpaid_count = count_unpaid(invent);
tally_BUCX(invent, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
if (flags.menu_style != MENU_TRADITIONAL) {
if (flags.menu_style == MENU_FULL ||
flags.menu_style == MENU_PARTIAL) {
traditional = FALSE;
i = UNPAID_TYPES;
if (billx) i |= BILLED_TYPES;
if (bcnt) i |= BUC_BLESSED;
if (ucnt) i |= BUC_UNCURSED;
if (ccnt) i |= BUC_CURSED;
if (xcnt) i |= BUC_UNKNOWN;
n = query_category(prompt, invent, i, &pick_list, PICK_ONE);
if (!n) return 0;
this_type = c = pick_list[0].item.a_int;
@@ -2225,73 +2276,96 @@ dotypeinv()
if (traditional) {
/* collect a list of classes of objects carried, for use as a prompt */
types[0] = 0;
class_count = collect_obj_classes(types, invent,
FALSE,
(boolean FDECL((*),(OBJ_P))) 0, &itemcount);
if (unpaid_count) {
Strcat(types, "u");
class_count++;
}
if (billx) {
Strcat(types, "x");
class_count++;
}
class_count = collect_obj_classes(types, invent, FALSE,
(boolean FDECL((*),(OBJ_P))) 0,
&itemcount);
if (unpaid_count || billx || (bcnt + ccnt + ucnt + xcnt) != 0)
types[class_count++] = ' ';
if (unpaid_count) types[class_count++] = 'u';
if (billx) types[class_count++] = 'x';
if (bcnt) types[class_count++] = 'B';
if (ucnt) types[class_count++] = 'U';
if (ccnt) types[class_count++] = 'C';
if (xcnt) types[class_count++] = 'X';
types[class_count] = '\0';
/* add everything not already included; user won't see these */
extra_types = eos(types);
*extra_types++ = '\033';
if (!unpaid_count) *extra_types++ = 'u';
if (!billx) *extra_types++ = 'x';
if (!bcnt) *extra_types++ = 'B';
if (!ucnt) *extra_types++ = 'U';
if (!ccnt) *extra_types++ = 'C';
if (!xcnt) *extra_types++ = 'X';
*extra_types = '\0'; /* for index() */
for (i = 0; i < MAXOCLASSES; i++)
if (!index(types, def_oc_syms[i].sym)) {
*extra_types++ = def_oc_syms[i].sym;
*extra_types = '\0';
}
if (!index(types, def_oc_syms[i].sym)) {
*extra_types++ = def_oc_syms[i].sym;
*extra_types = '\0';
}
if(class_count > 1) {
c = yn_function(prompt, types, '\0');
savech(c);
if(c == '\0') {
clear_nhwindow(WIN_MESSAGE);
return 0;
}
if (class_count > 1) {
c = yn_function(prompt, types, '\0');
savech(c);
if (c == '\0') {
clear_nhwindow(WIN_MESSAGE);
return 0;
}
} else {
/* only one thing to itemize */
if (unpaid_count)
c = 'u';
else if (billx)
c = 'x';
else
c = types[0];
/* only one thing to itemize */
if (unpaid_count)
c = 'u';
else if (billx)
c = 'x';
else
c = types[0];
}
}
if (c == 'x') {
if (c == 'x' || (c == 'X' && billx && !xcnt)) {
if (billx)
(void) doinvbill(1);
else
pline("No used-up objects on your shopping bill.");
(void) doinvbill(1);
else
pline("No used-up objects%s.",
unpaid_count ? " on your shopping bill" : "");
return 0;
}
if (c == 'u') {
if (c == 'u' || (c == 'U' && unpaid_count && !ucnt)) {
if (unpaid_count)
dounpaid();
dounpaid();
else
You("are not carrying any unpaid objects.");
You("are not carrying any unpaid objects.");
return 0;
}
if (traditional) {
oclass = def_char_to_objclass(c); /* change to object class */
if (oclass == COIN_CLASS) {
return doprgold();
} else if (index(types, c) > index(types, '\033')) {
You("have no such objects.");
return 0;
if (index("BUCX", c))
oclass = c; /* not a class but understood by this_type_only() */
else
oclass = def_char_to_objclass(c); /* change to object class */
if (oclass == COIN_CLASS)
return doprgold();
if (index(types, c) > index(types, '\033')) {
/* '> ESC' => "hidden choice", something known not to be carried */
const char *which = 0;
switch (c) {
case 'B': which = "known to be blessed"; break;
case 'U': which = "known to be uncursed"; break;
case 'C': which = "known to be cursed"; break;
case 'X': You(
"have no objects whose blessed/uncursed/cursed status is unknown.");
break; /* better phrasing is desirable */
default: which = "such"; break;
}
if (which)
You("have no %s objects.", which);
return 0;
}
this_type = oclass;
}
if (query_objlist((char *) 0, invent,
(flags.invlet_constant ? USE_INVLET : 0)|INVORDER_SORT,
&pick_list, PICK_NONE, this_type_only) > 0)
(flags.invlet_constant ? USE_INVLET : 0)|INVORDER_SORT,
&pick_list, PICK_NONE, this_type_only) > 0)
free((genericptr_t)pick_list);
return 0;
}

View File

@@ -1157,12 +1157,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

@@ -2194,7 +2194,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: 1430396792 2015/04/30 12:26:32 $ $NHDT-Branch: master $:$NHDT-Revision: 1.169 $ */
/* NetHack 3.5 mon.c $Date: 2012/05/16 02:15:10 $ $Revision: 1.126 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1850,7 +1850,7 @@ register struct monst *mtmp;
u.uy = mtmp->my;
u.uswallow = 0;
u.uswldtim = 0;
if (Punished) placebc();
if (Punished && uball->where == OBJ_FREE) placebc();
vision_full_recalc = 1;
docrt();
}
@@ -3117,9 +3117,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++;
@@ -3157,9 +3155,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: 1430441885 2015/05/01 00:58:05 $ $NHDT-Branch: master $:$NHDT-Revision: 1.191 $ */
/* NetHack 3.5 options.c $Date: 2012/04/09 02:56:30 $ $Revision: 1.153 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -283,7 +283,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 },
@@ -498,6 +498,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, (const 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
@@ -1163,13 +1170,117 @@ 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)
const 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;
@@ -1212,20 +1323,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
@@ -1252,11 +1350,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)
@@ -2618,14 +2753,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;
}
@@ -3087,6 +3220,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;
@@ -3138,6 +3276,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 ? "!" : "",
@@ -3177,6 +3319,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 */
@@ -3454,79 +3647,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]);
@@ -3546,6 +3730,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) {
@@ -3870,10 +4056,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 $ */
/* NetHack 3.5 pickup.c $Date: 2012/02/16 03:01:38 $ $Revision: 1.123 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -308,8 +308,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)
@@ -317,10 +319,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';
}
@@ -345,26 +356,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 $ */
/* NetHack 3.5 zap.c $Date: 2013/11/05 00:57:56 $ $Revision: 1.183 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -2870,9 +2870,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;
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.5 winX.c $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$ */
/* NetHack 3.5 winX.c $NHDT-Date: 1430040327 2015/04/26 09:25:27 $ $NHDT-Branch: master $:$NHDT-Revision: 1.28 $ */
/* NetHack 3.5 winX.c $Date: 2012/01/24 04:26:26 $ $Revision: 1.27 $ */
/* Copyright (c) Dean Luick, 1992 */
/* NetHack may be freely redistributed. See license for details. */
@@ -1532,6 +1532,7 @@ static char yn_esc_map; /* ESC maps to this char. */
static Widget yn_popup; /* popup for the yn fuction (created once) */
static Widget yn_label; /* label for yn function (created once) */
static boolean yn_getting_num; /* TRUE if accepting digits */
static boolean yn_preserve_case; /* default is to force yn to lower case */
static int yn_ndigits; /* digit count */
static long yn_val; /* accumulated value */
@@ -1604,7 +1605,8 @@ yn_key(w, event, params, num_params)
if (!yn_choices) { /* accept any input */
yn_return = ch;
} else {
ch = lowc(ch); /* move to lower case */
if (!yn_preserve_case)
ch = lowc(ch); /* move to lower case */
if (ch == '\033') {
yn_getting_num = FALSE;
@@ -1664,6 +1666,7 @@ X11_yn_function(ques, choices, def)
yn_choices = choices; /* set up globals for callback to use */
yn_def = def;
yn_preserve_case = !choices; /* preserve when arbitrary response allowed */
/*
* This is sort of a kludge. There are quite a few places in the main
@@ -1679,6 +1682,14 @@ X11_yn_function(ques, choices, def)
char *cb, choicebuf[QBUFSZ];
Strcpy(choicebuf, choices); /* anything beyond <esc> is hidden */
/* default when choices are present is to force yn answer to
lowercase unless one or more choices are explicitly uppercase;
check this before stripping the hidden choices */
for (cb = choicebuf; *cb; ++cb)
if ('A' <= *cb && *cb <= 'Z') {
yn_preserve_case = TRUE;
break;
}
if ((cb = index(choicebuf, '\033')) != 0) *cb = '\0';
/* ques [choices] (def) */
if ((int)(1 + strlen(ques) + 2 + strlen(choicebuf) + 4) >= BUFSZ)

View File

@@ -1,4 +1,4 @@
/* NetHack 3.5 topl.c $NHDT-Date: 1425081315 2015/02/27 23:55:15 $ $NHDT-Branch: master $:$NHDT-Revision: 1.24 $ */
/* NetHack 3.5 topl.c $NHDT-Date: 1430040322 2015/04/26 09:25:22 $ $NHDT-Branch: master $:$NHDT-Revision: 1.29 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -333,7 +333,7 @@ char def;
{
register char q;
char rtmp[40];
boolean digit_ok, allow_num;
boolean digit_ok, allow_num, preserve_case = FALSE;
struct WinDesc *cw = wins[WIN_MESSAGE];
boolean doprev = 0;
char prompt[BUFSZ];
@@ -347,6 +347,14 @@ char def;
allow_num = (index(resp, '#') != 0);
Strcpy(respbuf, resp);
/* normally we force lowercase, but if any uppercase letters
are present in the allowed response, preserve case;
check this before stripping the hidden choices */
for (rb = respbuf; *rb; ++rb)
if ('A' <= *rb && *rb <= 'Z') {
preserve_case = TRUE;
break;
}
/* any acceptable responses that follow <esc> aren't displayed */
if ((rb = index(respbuf, '\033')) != 0) *rb = '\0';
(void)strncpy(prompt, query, QBUFSZ-1);
@@ -358,13 +366,16 @@ char def;
Strcat(prompt, " ");
pline("%s", prompt);
} else {
/* no restriction on allowed response, so always preserve case */
/* preserve_case = TRUE; -- moot since we're jumping to the end */
pline("%s ", query);
q = readchar();
goto clean_up;
}
do { /* loop until we get valid input */
q = lowc(readchar());
q = readchar();
if (!preserve_case) q = lowc(q);
if (q == '\020') { /* ctrl-P */
if (iflags.prevmsg_window != 's') {
int sav = ttyDisplay->inread;
@@ -422,7 +433,8 @@ char def;
q = '#';
}
do { /* loop until we get a non-digit */
z = lowc(readchar());
z = readchar();
if (!preserve_case) z = lowc(z);
if (digit(z)) {
value = (10 * value) + (z - '0');
if (value < 0) break; /* overflow: try again */