Merge branch 'NetHack-3.6.0' of https://rodney.nethack.org:20040/git/NHsource into NetHack-3.6.0
This commit is contained in:
@@ -773,8 +773,6 @@ beautiful()
|
||||
: "ugly");
|
||||
}
|
||||
|
||||
#define WEAK 3 /* from eat.c */
|
||||
|
||||
static const char look_str[] = "look %s.";
|
||||
|
||||
STATIC_OVL int
|
||||
|
||||
81
src/cmd.c
81
src/cmd.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 cmd.c $NHDT-Date: 1451082253 2015/12/25 22:24:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.212 $ */
|
||||
/* NetHack 3.6 cmd.c $NHDT-Date: 1452123457 2016/01/06 23:37:37 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.216 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -3864,6 +3864,60 @@ int x, y, mod;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
char
|
||||
get_count(allowchars, inkey, maxcount, count)
|
||||
char *allowchars;
|
||||
char inkey;
|
||||
long maxcount;
|
||||
long *count;
|
||||
{
|
||||
char qbuf[QBUFSZ];
|
||||
int key;
|
||||
long cnt = 0L;
|
||||
boolean backspaced = FALSE;
|
||||
/* this should be done in port code so that we have erase_char
|
||||
and kill_char available; we can at least fake erase_char */
|
||||
#define STANDBY_erase_char '\177'
|
||||
|
||||
for (;;) {
|
||||
if (inkey) {
|
||||
key = inkey;
|
||||
inkey = '\0';
|
||||
} else
|
||||
key = readchar();
|
||||
|
||||
if (digit(key)) {
|
||||
cnt = 10L * cnt + (long) (key - '0');
|
||||
if (cnt < 0)
|
||||
cnt = 0;
|
||||
else if (maxcount > 0 && cnt > maxcount)
|
||||
cnt = maxcount;
|
||||
} else if (key == '\b' || key == STANDBY_erase_char) {
|
||||
cnt = cnt / 10;
|
||||
backspaced = TRUE;
|
||||
} else if (key == '\033') {
|
||||
break;
|
||||
} else if (!allowchars || index(allowchars, key)) {
|
||||
*count = cnt;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cnt > 9 || backspaced) {
|
||||
clear_nhwindow(WIN_MESSAGE);
|
||||
if (backspaced && !cnt) {
|
||||
Sprintf(qbuf, "Count: ");
|
||||
} else {
|
||||
Sprintf(qbuf, "Count: %ld", cnt);
|
||||
backspaced = FALSE;
|
||||
}
|
||||
pline1(qbuf);
|
||||
mark_synch();
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
STATIC_OVL char *
|
||||
parse()
|
||||
{
|
||||
@@ -3882,25 +3936,12 @@ parse()
|
||||
#ifdef ALTMETA
|
||||
alt_esc = iflags.altmeta; /* readchar() hack */
|
||||
#endif
|
||||
if (!Cmd.num_pad || (foo = readchar()) == 'n')
|
||||
for (;;) {
|
||||
foo = readchar();
|
||||
if (foo >= '0' && foo <= '9') {
|
||||
multi = 10 * multi + foo - '0';
|
||||
if (multi < 0 || multi >= LARGEST_INT)
|
||||
multi = LARGEST_INT;
|
||||
if (multi > 9) {
|
||||
clear_nhwindow(WIN_MESSAGE);
|
||||
Sprintf(in_line, "Count: %d", multi);
|
||||
pline1(in_line);
|
||||
mark_synch();
|
||||
}
|
||||
last_multi = multi;
|
||||
if (!multi && foo == '0')
|
||||
prezero = TRUE;
|
||||
} else
|
||||
break; /* not a digit */
|
||||
}
|
||||
if (!Cmd.num_pad || (foo = readchar()) == 'n') {
|
||||
long tmpmulti = multi;
|
||||
|
||||
foo = get_count(NULL, '\0', LARGEST_INT, &tmpmulti);
|
||||
last_multi = multi = tmpmulti;
|
||||
}
|
||||
#ifdef ALTMETA
|
||||
alt_esc = FALSE; /* readchar() reset */
|
||||
#endif
|
||||
|
||||
@@ -1201,8 +1201,7 @@ set_mimic_blocking()
|
||||
for (mon = fmon; mon; mon = mon->nmon) {
|
||||
if (DEADMONSTER(mon))
|
||||
continue;
|
||||
if (mon->minvis && (is_door_mappear(mon)
|
||||
|| is_obj_mappear(mon,BOULDER))) {
|
||||
if (mon->minvis && is_lightblocker_mappear(mon)) {
|
||||
if (See_invisible)
|
||||
block_point(mon->mx, mon->my);
|
||||
else
|
||||
|
||||
133
src/do_name.c
133
src/do_name.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 do_name.c $NHDT-Date: 1450178550 2015/12/15 11:22:30 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.80 $ */
|
||||
/* NetHack 3.6 do_name.c $NHDT-Date: 1452064740 2016/01/06 07:19:00 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.84 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
|
||||
STATIC_DCL char *NDECL(nextmbuf);
|
||||
STATIC_DCL void FDECL(getpos_help, (BOOLEAN_P, const char *));
|
||||
STATIC_DCL int FDECL(CFDECLSPEC cmp_coord_distu, (const void *,
|
||||
const void *));
|
||||
STATIC_OVL void FDECL(gather_locs, (coord **, int *, BOOLEAN_P));
|
||||
STATIC_DCL void NDECL(do_mname);
|
||||
STATIC_DCL boolean FDECL(alreadynamed, (struct monst *, char *, char *));
|
||||
STATIC_DCL void FDECL(do_oname, (struct obj *));
|
||||
@@ -30,7 +33,7 @@ nextmbuf()
|
||||
/* function for getpos() to highlight desired map locations.
|
||||
* parameter value 0 = initialize, 1 = highlight, 2 = done
|
||||
*/
|
||||
void FDECL((*getpos_hilitefunc), (int)) = (void FDECL((*), (int))) 0;
|
||||
static void FDECL((*getpos_hilitefunc), (int)) = (void FDECL((*), (int))) 0;
|
||||
|
||||
void
|
||||
getpos_sethilite(f)
|
||||
@@ -55,6 +58,8 @@ const char *goal;
|
||||
putstr(tmpwin, 0, "Use [HJKL] to move the cursor 8 units at a time.");
|
||||
putstr(tmpwin, 0, "Or enter a background symbol (ex. <).");
|
||||
putstr(tmpwin, 0, "Use @ to move the cursor on yourself.");
|
||||
putstr(tmpwin, 0, "Use m or M to move the cursor to next monster.");
|
||||
putstr(tmpwin, 0, "Use o or O to move the cursor to next object.");
|
||||
if (getpos_hilitefunc)
|
||||
putstr(tmpwin, 0, "Use $ to display valid locations.");
|
||||
putstr(tmpwin, 0, "Use # to toggle automatic description.");
|
||||
@@ -71,6 +76,80 @@ const char *goal;
|
||||
destroy_nhwindow(tmpwin);
|
||||
}
|
||||
|
||||
STATIC_OVL int
|
||||
cmp_coord_distu(a, b)
|
||||
const void *a;
|
||||
const void *b;
|
||||
{
|
||||
const coord *c1 = a;
|
||||
const coord *c2 = b;
|
||||
int dx, dy, dist_1, dist_2;
|
||||
|
||||
dx = u.ux - c1->x;
|
||||
dy = u.uy - c1->y;
|
||||
dist_1 = dx * dx + dy * dy;
|
||||
dx = u.ux - c2->x;
|
||||
dy = u.uy - c2->y;
|
||||
dist_2 = dx * dx + dy * dy;
|
||||
|
||||
return dist_1 - dist_2;
|
||||
}
|
||||
|
||||
/* gather locations for monsters or objects shown on the map */
|
||||
STATIC_OVL void
|
||||
gather_locs(arr_p, cnt_p, do_mons)
|
||||
coord **arr_p;
|
||||
int *cnt_p;
|
||||
boolean do_mons;
|
||||
{
|
||||
int x, y, pass, glyph, idx;
|
||||
|
||||
*cnt_p = idx = 0;
|
||||
for (pass = 0; pass < 2; pass++) {
|
||||
if (pass) {
|
||||
/* *cnt_p + 1: always allocate a non-zero amount */
|
||||
*arr_p = (coord *) alloc(sizeof (coord) * (*cnt_p + 1));
|
||||
if (!*cnt_p) {
|
||||
/* needed for caller's mon[0].x,.y==u.ux,.uy check */
|
||||
(*arr_p)[0].x = (*arr_p)[0].y = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (x = 1; x < COLNO; x++)
|
||||
for (y = 0; y < ROWNO; y++) {
|
||||
glyph = glyph_at(x, y);
|
||||
if (do_mons) {
|
||||
/* unlike '/M', this skips monsters revealed by
|
||||
* warning glyphs and remembered invisible ones;
|
||||
* TODO: skip worm tails
|
||||
*/
|
||||
if (glyph_is_monster(glyph)) {
|
||||
if (!pass) {
|
||||
++*cnt_p;
|
||||
} else {
|
||||
(*arr_p)[idx].x = x;
|
||||
(*arr_p)[idx].y = y;
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
} else { /* objects */
|
||||
/* TODO: skip boulders and rocks */
|
||||
if (glyph_is_object(glyph)) {
|
||||
if (!pass) {
|
||||
++*cnt_p;
|
||||
} else {
|
||||
(*arr_p)[idx].x = x;
|
||||
(*arr_p)[idx].y = y;
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* pass */
|
||||
if (*cnt_p)
|
||||
qsort(*arr_p, *cnt_p, sizeof (coord), cmp_coord_distu);
|
||||
}
|
||||
|
||||
int
|
||||
getpos(ccp, force, goal)
|
||||
coord *ccp;
|
||||
@@ -85,6 +164,8 @@ const char *goal;
|
||||
static const char pick_chars[] = ".,;:";
|
||||
const char *cp;
|
||||
boolean hilite_state = FALSE;
|
||||
coord *monarr = (coord *) 0, *objarr = (coord *) 0;
|
||||
int moncount = 0, monidx = 0, objcount = 0, objidx = 0;
|
||||
|
||||
if (!goal)
|
||||
goal = "desired location";
|
||||
@@ -192,7 +273,7 @@ const char *goal;
|
||||
if (c == '?' || redraw_cmd(c)) {
|
||||
if (c == '?')
|
||||
getpos_help(force, goal);
|
||||
else /* ^R */
|
||||
else /* ^R */
|
||||
docrt(); /* redraw */
|
||||
/* update message window to reflect that we're still targetting */
|
||||
show_goal_msg = TRUE;
|
||||
@@ -217,10 +298,52 @@ const char *goal;
|
||||
cx = u.ux;
|
||||
cy = u.uy;
|
||||
goto nxtc;
|
||||
} else if (c == 'm' || c == 'M') {
|
||||
if (!monarr) {
|
||||
gather_locs(&monarr, &moncount, TRUE);
|
||||
/* when hero is first element (always, unless unseen),
|
||||
we want first increment to reach 1 (nearest aside
|
||||
from hero) or first decrement to reach moncount-1
|
||||
(farthest); if hero is not first element, we want
|
||||
first increment to end up with 0 (nearest monster),
|
||||
first decrement should still choose moncount-1 */
|
||||
monidx = (monarr[0].x == u.ux && monarr[0].y == u.uy) ? 0
|
||||
: (c == 'm') ? -1 : 0;
|
||||
}
|
||||
if (moncount) {
|
||||
if (c == 'm') {
|
||||
monidx = (monidx + 1) % moncount;
|
||||
} else {
|
||||
if (--monidx < 0)
|
||||
monidx = moncount - 1;
|
||||
}
|
||||
cx = monarr[monidx].x;
|
||||
cy = monarr[monidx].y;
|
||||
goto nxtc;
|
||||
}
|
||||
} else if (c == 'o' || c == 'O') {
|
||||
if (!objarr) {
|
||||
gather_locs(&objarr, &objcount, FALSE);
|
||||
/* ready for first increment to change to zero
|
||||
or first decrement to change to objcount-1 */
|
||||
objidx = (c == 'o') ? -1 : 0;
|
||||
}
|
||||
if (objcount) {
|
||||
if (c == 'o') {
|
||||
objidx = (objidx + 1) % objcount;
|
||||
} else {
|
||||
if (--objidx < 0)
|
||||
objidx = objcount - 1;
|
||||
}
|
||||
cx = objarr[objidx].x;
|
||||
cy = objarr[objidx].y;
|
||||
goto nxtc;
|
||||
}
|
||||
} else {
|
||||
if (!index(quitchars, c)) {
|
||||
char matching[MAXPCHARS];
|
||||
int pass, lo_x, lo_y, hi_x, hi_y, k = 0;
|
||||
|
||||
(void) memset((genericptr_t) matching, 0, sizeof matching);
|
||||
for (sidx = 1; sidx < MAXPCHARS; sidx++)
|
||||
if (c == defsyms[sidx].sym || c == (int) showsyms[sidx])
|
||||
@@ -307,6 +430,10 @@ const char *goal;
|
||||
clear_nhwindow(WIN_MESSAGE);
|
||||
ccp->x = cx;
|
||||
ccp->y = cy;
|
||||
if (monarr)
|
||||
free((genericptr_t) monarr);
|
||||
if (objarr)
|
||||
free((genericptr_t) objarr);
|
||||
getpos_hilitefunc = (void FDECL((*), (int))) 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -325,7 +325,7 @@ boolean with_you;
|
||||
xyflags = mtmp->mtrack[0].y;
|
||||
xlocale = mtmp->mtrack[1].x;
|
||||
ylocale = mtmp->mtrack[1].y;
|
||||
memset(mtmp->mtrack, MTSZ, sizeof(coord));
|
||||
memset(mtmp->mtrack, 0, sizeof(mtmp->mtrack));
|
||||
|
||||
if (mtmp == u.usteed)
|
||||
return; /* don't place steed on the map */
|
||||
|
||||
@@ -16,7 +16,6 @@ STATIC_DCL void FDECL(check_shop_obj, (struct obj *, XCHAR_P, XCHAR_P,
|
||||
BOOLEAN_P));
|
||||
STATIC_DCL void FDECL(breakmsg, (struct obj *, BOOLEAN_P));
|
||||
STATIC_DCL boolean FDECL(toss_up, (struct obj *, BOOLEAN_P));
|
||||
STATIC_DCL boolean FDECL(throwing_weapon, (struct obj *));
|
||||
STATIC_DCL void FDECL(sho_obj_return_to_u, (struct obj * obj));
|
||||
STATIC_DCL boolean FDECL(mhurtle_step, (genericptr_t, int, int));
|
||||
|
||||
@@ -943,7 +942,7 @@ boolean hitsroof;
|
||||
}
|
||||
|
||||
/* return true for weapon meant to be thrown; excludes ammo */
|
||||
STATIC_OVL boolean
|
||||
boolean
|
||||
throwing_weapon(obj)
|
||||
struct obj *obj;
|
||||
{
|
||||
|
||||
@@ -1431,6 +1431,8 @@ struct obj *otmp;
|
||||
case ELVEN_DAGGER:
|
||||
case ORCISH_DAGGER:
|
||||
case ATHAME:
|
||||
case KNIFE:
|
||||
case STILETTO:
|
||||
case CRYSKNIFE:
|
||||
tmp = 3;
|
||||
break;
|
||||
|
||||
16
src/hack.c
16
src/hack.c
@@ -827,6 +827,9 @@ int mode;
|
||||
} else if (mode == TEST_TRAV) {
|
||||
struct obj *obj;
|
||||
|
||||
/* never travel through boulders in Sokoban */
|
||||
if (Sokoban) return FALSE;
|
||||
|
||||
/* don't pick two boulders in a row, unless there's a way thru */
|
||||
if (sobj_at(BOULDER, ux, uy) && !Sokoban) {
|
||||
if (!Passes_walls
|
||||
@@ -1434,6 +1437,19 @@ domove()
|
||||
}
|
||||
}
|
||||
|
||||
if (context.forcefight && levl[x][y].typ == IRONBARS && uwep) {
|
||||
struct obj *obj = uwep;
|
||||
if (breaktest(obj)) {
|
||||
if (obj->quan > 1L)
|
||||
obj = splitobj(obj, 1L);
|
||||
else
|
||||
setuwep((struct obj *)0);
|
||||
freeinv(obj);
|
||||
}
|
||||
hit_bars(&obj, u.ux, u.uy, x, y, TRUE, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* specifying 'F' with no monster wastes a turn */
|
||||
if (context.forcefight
|
||||
/* remembered an 'I' && didn't use a move command */
|
||||
|
||||
67
src/invent.c
67
src/invent.c
@@ -434,6 +434,7 @@ struct obj *obj;
|
||||
{
|
||||
struct obj *otmp, *prev;
|
||||
int saved_otyp = (int) obj->otyp; /* for panic */
|
||||
boolean obj_was_thrown;
|
||||
|
||||
if (obj->where != OBJ_FREE)
|
||||
panic("addinv: obj not free");
|
||||
@@ -442,6 +443,7 @@ struct obj *obj;
|
||||
obj->no_charge = 0; /* should not be set in hero's invent */
|
||||
if (Has_contents(obj))
|
||||
picked_container(obj); /* clear no_charge */
|
||||
obj_was_thrown = obj->was_thrown;
|
||||
obj->was_thrown = 0; /* not meaningful for invent */
|
||||
|
||||
addinv_core1(obj);
|
||||
@@ -476,6 +478,10 @@ struct obj *obj;
|
||||
}
|
||||
obj->where = OBJ_INVENT;
|
||||
|
||||
/* fill empty quiver if obj was thrown */
|
||||
if (flags.pickup_thrown && !uquiver && obj_was_thrown
|
||||
&& (throwing_weapon(obj) || is_ammo(obj)))
|
||||
setuqwep(obj);
|
||||
added:
|
||||
addinv_core2(obj);
|
||||
carry_obj_effects(obj); /* carrying affects the obj */
|
||||
@@ -964,8 +970,8 @@ register const char *let, *word;
|
||||
boolean allownone = FALSE;
|
||||
boolean useboulder = FALSE;
|
||||
xchar foox = 0;
|
||||
long cnt, prevcnt;
|
||||
boolean prezero;
|
||||
long cnt;
|
||||
boolean cntgiven = FALSE;
|
||||
long dummymask;
|
||||
|
||||
if (*let == ALLOW_COUNT)
|
||||
@@ -1157,9 +1163,7 @@ register const char *let, *word;
|
||||
}
|
||||
for (;;) {
|
||||
cnt = 0;
|
||||
if (allowcnt == 2)
|
||||
allowcnt = 1; /* abort previous count */
|
||||
prezero = FALSE;
|
||||
cntgiven = FALSE;
|
||||
if (!buf[0]) {
|
||||
Sprintf(qbuf, "What do you want to %s? [*]", word);
|
||||
} else {
|
||||
@@ -1169,28 +1173,17 @@ register const char *let, *word;
|
||||
ilet = readchar();
|
||||
else
|
||||
ilet = yn_function(qbuf, (char *) 0, '\0');
|
||||
if (digit(ilet) && !allowcnt) {
|
||||
pline("No count allowed with this command.");
|
||||
continue;
|
||||
}
|
||||
if (ilet == '0')
|
||||
prezero = TRUE;
|
||||
while (digit(ilet)) {
|
||||
if (ilet != '?' && ilet != '*')
|
||||
savech(ilet);
|
||||
/* accumulate unless cnt has overflowed */
|
||||
if (allowcnt < 3) {
|
||||
prevcnt = cnt;
|
||||
cnt = 10L * cnt + (long) (ilet - '0');
|
||||
/* signal presence of cnt */
|
||||
allowcnt = (cnt >= prevcnt) ? 2 : 3;
|
||||
if (digit(ilet)) {
|
||||
long tmpcnt = 0;
|
||||
if (!allowcnt) {
|
||||
pline("No count allowed with this command.");
|
||||
continue;
|
||||
}
|
||||
ilet = get_count(NULL, ilet, LARGEST_INT, &tmpcnt);
|
||||
if (tmpcnt) {
|
||||
cnt = tmpcnt;
|
||||
cntgiven = TRUE;
|
||||
}
|
||||
ilet = readchar();
|
||||
}
|
||||
if (allowcnt == 3) {
|
||||
/* overflow detected; force cnt to be invalid */
|
||||
cnt = -1L;
|
||||
allowcnt = 2;
|
||||
}
|
||||
if (index(quitchars, ilet)) {
|
||||
if (flags.verbose)
|
||||
@@ -1231,9 +1224,7 @@ register const char *let, *word;
|
||||
continue;
|
||||
if (allowcnt && ctmp >= 0) {
|
||||
cnt = ctmp;
|
||||
if (!cnt)
|
||||
prezero = TRUE;
|
||||
allowcnt = 2;
|
||||
cntgiven = TRUE;
|
||||
}
|
||||
if (ilet == '\033') {
|
||||
if (flags.verbose)
|
||||
@@ -1261,23 +1252,21 @@ register const char *let, *word;
|
||||
* to your money supply. The LRS is the tax bureau
|
||||
* from Larn.
|
||||
*/
|
||||
if (allowcnt == 2 && cnt <= 0) {
|
||||
if (cnt < 0 || !prezero)
|
||||
if (cntgiven && cnt <= 0) {
|
||||
if (cnt < 0)
|
||||
pline_The(
|
||||
"LRS would be very interested to know you have that much.");
|
||||
return (struct obj *) 0;
|
||||
}
|
||||
}
|
||||
if (allowcnt == 2 && !strcmp(word, "throw")) {
|
||||
if (cntgiven && !strcmp(word, "throw")) {
|
||||
/* permit counts for throwing gold, but don't accept
|
||||
* counts for other things since the throw code will
|
||||
* split off a single item anyway */
|
||||
if (ilet != def_oc_syms[COIN_CLASS].sym
|
||||
&& !(otmp && otmp->oclass == COIN_CLASS))
|
||||
allowcnt = 1;
|
||||
if (cnt == 0 && prezero)
|
||||
if (cnt == 0)
|
||||
return (struct obj *) 0;
|
||||
if (cnt > 1) {
|
||||
if (cnt > 1 && (ilet != def_oc_syms[COIN_CLASS].sym
|
||||
&& !(otmp && otmp->oclass == COIN_CLASS))) {
|
||||
You("can only throw one item at a time.");
|
||||
continue;
|
||||
}
|
||||
@@ -1305,7 +1294,7 @@ register const char *let, *word;
|
||||
silly_thing(word, otmp);
|
||||
return (struct obj *) 0;
|
||||
}
|
||||
if (allowcnt == 2) { /* cnt given */
|
||||
if (cntgiven) {
|
||||
if (cnt == 0)
|
||||
return (struct obj *) 0;
|
||||
if (cnt != otmp->quan) {
|
||||
@@ -2193,7 +2182,7 @@ char avoidlet;
|
||||
}
|
||||
end_menu(win, "Inventory letters used:");
|
||||
|
||||
n = select_menu(win, PICK_NONE, &selected);
|
||||
n = select_menu(win, PICK_ONE, &selected);
|
||||
if (n > 0) {
|
||||
ret = selected[0].item.a_char;
|
||||
free((genericptr_t) selected);
|
||||
|
||||
@@ -19,7 +19,6 @@ STATIC_DCL void FDECL(maze0xy, (coord *));
|
||||
STATIC_DCL boolean FDECL(put_lregion_here, (XCHAR_P, XCHAR_P, XCHAR_P,
|
||||
XCHAR_P, XCHAR_P, XCHAR_P,
|
||||
XCHAR_P, BOOLEAN_P, d_level *));
|
||||
STATIC_DCL void NDECL(fixup_special);
|
||||
STATIC_DCL void NDECL(setup_waterlevel);
|
||||
STATIC_DCL void NDECL(unsetup_waterlevel);
|
||||
|
||||
@@ -362,7 +361,7 @@ d_level *lev;
|
||||
static boolean was_waterlevel; /* ugh... this shouldn't be needed */
|
||||
|
||||
/* this is special stuff that the level compiler cannot (yet) handle */
|
||||
STATIC_OVL void
|
||||
void
|
||||
fixup_special()
|
||||
{
|
||||
register lev_region *r = lregions;
|
||||
@@ -577,7 +576,6 @@ register const char *s;
|
||||
if (*protofile) {
|
||||
Strcat(protofile, LEV_EXT);
|
||||
if (load_special(protofile)) {
|
||||
fixup_special();
|
||||
/* some levels can end up with monsters
|
||||
on dead mon list, including light source monsters */
|
||||
dmonsfree();
|
||||
|
||||
@@ -1653,6 +1653,8 @@ struct permonst *mptr; /* reflects mtmp->data _prior_ to mtmp's death */
|
||||
remove_monster(mtmp->mx, mtmp->my);
|
||||
if (emits_light(mptr))
|
||||
del_light_source(LS_MONSTER, monst_to_any(mtmp));
|
||||
if (mtmp->m_ap_type)
|
||||
seemimic(mtmp);
|
||||
newsym(mtmp->mx, mtmp->my);
|
||||
unstuck(mtmp);
|
||||
fill_pit(mtmp->mx, mtmp->my);
|
||||
@@ -2616,8 +2618,7 @@ void
|
||||
seemimic(mtmp)
|
||||
register struct monst *mtmp;
|
||||
{
|
||||
boolean is_blocker_appear = (is_door_mappear(mtmp)
|
||||
|| is_obj_mappear(mtmp, BOULDER));
|
||||
boolean is_blocker_appear = (is_lightblocker_mappear(mtmp));
|
||||
|
||||
if (has_mcorpsenm(mtmp))
|
||||
freemcorpsenm(mtmp);
|
||||
|
||||
@@ -272,7 +272,7 @@ boolean fleemsg;
|
||||
mtmp->mflee = 1;
|
||||
}
|
||||
/* ignore recently-stepped spaces when made to flee */
|
||||
memset(mtmp->mtrack, MTSZ, sizeof(coord));
|
||||
memset(mtmp->mtrack, 0, sizeof(mtmp->mtrack));
|
||||
}
|
||||
|
||||
STATIC_OVL void
|
||||
|
||||
@@ -318,7 +318,9 @@ struct obj *obj; /* missile (or stack providing it) */
|
||||
|| IS_ROCK(levl[bhitpos.x + dx][bhitpos.y + dy].typ)
|
||||
|| closed_door(bhitpos.x + dx, bhitpos.y + dy)
|
||||
|| (levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS
|
||||
&& hits_bars(&singleobj, bhitpos.x, bhitpos.y, 0, 0))) {
|
||||
&& hits_bars(&singleobj,
|
||||
bhitpos.x, bhitpos.y,
|
||||
bhitpos.x + dx, bhitpos.y + dy, 0, 0))) {
|
||||
(void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
|
||||
return;
|
||||
}
|
||||
@@ -455,7 +457,10 @@ struct obj *obj; /* missile (or stack providing it) */
|
||||
|| closed_door(bhitpos.x + dx, bhitpos.y + dy)
|
||||
/* missile might hit iron bars */
|
||||
|| (levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS
|
||||
&& hits_bars(&singleobj, bhitpos.x, bhitpos.y, !rn2(5), 0))
|
||||
&& hits_bars(&singleobj,
|
||||
bhitpos.x, bhitpos.y,
|
||||
bhitpos.x + dx, bhitpos.y + dy,
|
||||
!rn2(5), 0))
|
||||
/* Thrown objects "sink" */
|
||||
|| IS_SINK(levl[bhitpos.x][bhitpos.y].typ)) {
|
||||
if (singleobj) /* hits_bars might have destroyed it */
|
||||
@@ -831,11 +836,45 @@ int type;
|
||||
return (struct obj *) 0;
|
||||
}
|
||||
|
||||
void
|
||||
hit_bars(objp, objx, objy, barsx, barsy, your_fault, from_invent)
|
||||
struct obj **objp; /* *objp will be set to NULL if object breaks */
|
||||
int objx, objy, barsx, barsy;
|
||||
boolean your_fault, from_invent;
|
||||
{
|
||||
struct obj *otmp = *objp;
|
||||
int obj_type = otmp->otyp;
|
||||
boolean unbreakable = (levl[barsx][barsy].wall_info & W_NONDIGGABLE) != 0;
|
||||
|
||||
if (your_fault
|
||||
? hero_breaks(otmp, objx, objy, from_invent)
|
||||
: breaks(otmp, objx, objy)) {
|
||||
*objp = 0; /* object is now gone */
|
||||
/* breakage makes its own noises */
|
||||
if (obj_type == POT_ACID) {
|
||||
if (cansee(barsx, barsy) && !unbreakable)
|
||||
pline_The("iron bars are dissolved!");
|
||||
else
|
||||
You_hear(Hallucination ? "angry snakes!" : "a hissing noise.");
|
||||
if (!unbreakable)
|
||||
dissolve_bars(barsx, barsy);
|
||||
}
|
||||
}
|
||||
else if (obj_type == BOULDER || obj_type == HEAVY_IRON_BALL)
|
||||
pline("Whang!");
|
||||
else if (otmp->oclass == COIN_CLASS
|
||||
|| objects[obj_type].oc_material == GOLD
|
||||
|| objects[obj_type].oc_material == SILVER)
|
||||
pline("Clink!");
|
||||
else
|
||||
pline("Clonk!");
|
||||
}
|
||||
|
||||
/* TRUE iff thrown/kicked/rolled object doesn't pass through iron bars */
|
||||
boolean
|
||||
hits_bars(obj_p, x, y, always_hit, whodidit)
|
||||
hits_bars(obj_p, x, y, barsx, barsy, always_hit, whodidit)
|
||||
struct obj **obj_p; /* *obj_p will be set to NULL if object breaks */
|
||||
int x, y;
|
||||
int x, y, barsx, barsy;
|
||||
int always_hit; /* caller can force a hit for items which would fit through */
|
||||
int whodidit; /* 1==hero, 0=other, -1==just check whether it'll pass thru */
|
||||
{
|
||||
@@ -885,17 +924,7 @@ int whodidit; /* 1==hero, 0=other, -1==just check whether it'll pass thru */
|
||||
}
|
||||
|
||||
if (hits && whodidit != -1) {
|
||||
if (whodidit ? hero_breaks(otmp, x, y, FALSE) : breaks(otmp, x, y))
|
||||
*obj_p = otmp = 0; /* object is now gone */
|
||||
/* breakage makes its own noises */
|
||||
else if (obj_type == BOULDER || obj_type == HEAVY_IRON_BALL)
|
||||
pline("Whang!");
|
||||
else if (otmp->oclass == COIN_CLASS
|
||||
|| objects[obj_type].oc_material == GOLD
|
||||
|| objects[obj_type].oc_material == SILVER)
|
||||
pline("Clink!");
|
||||
else
|
||||
pline("Clonk!");
|
||||
hit_bars(obj_p, x,y, barsx,barsy, whodidit, FALSE);
|
||||
}
|
||||
|
||||
return hits;
|
||||
|
||||
20
src/music.c
20
src/music.c
@@ -426,6 +426,23 @@ int force;
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
generic_lvl_desc()
|
||||
{
|
||||
if (Is_astralevel(&u.uz))
|
||||
return "astral plane";
|
||||
else if (In_endgame(&u.uz))
|
||||
return "plane";
|
||||
else if (Is_sanctum(&u.uz))
|
||||
return "sanctum";
|
||||
else if (In_sokoban(&u.uz))
|
||||
return "puzzle";
|
||||
else if (In_V_tower(&u.uz))
|
||||
return "tower";
|
||||
else
|
||||
return "dungeon";
|
||||
}
|
||||
|
||||
/*
|
||||
* The player is trying to extract something from his/her instrument.
|
||||
*/
|
||||
@@ -537,7 +554,8 @@ struct obj *instr;
|
||||
consume_obj_charge(instr, TRUE);
|
||||
|
||||
You("produce a heavy, thunderous rolling!");
|
||||
pline_The("entire dungeon is shaking around you!");
|
||||
pline_The("entire %s is shaking around you!",
|
||||
generic_lvl_desc());
|
||||
do_earthquake((u.ulevel - 1) / 3 + 1);
|
||||
/* shake up monsters in a much larger radius... */
|
||||
awaken_monsters(ROWNO * COLNO);
|
||||
|
||||
18
src/objnam.c
18
src/objnam.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 objnam.c $NHDT-Date: 1451683056 2016/01/01 21:17:36 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.162 $ */
|
||||
/* NetHack 3.6 objnam.c $NHDT-Date: 1452043772 2016/01/06 01:29:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.163 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -1102,6 +1102,8 @@ register struct obj *otmp;
|
||||
|| is_flammable(otmp));
|
||||
}
|
||||
|
||||
/* format a corpse name (xname() omits monster type; doname() calls us);
|
||||
eatcorpse() also uses us for death reason when eating tainted glob */
|
||||
char *
|
||||
corpse_xname(otmp, adjective, cxn_flags)
|
||||
struct obj *otmp;
|
||||
@@ -1118,10 +1120,14 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
|
||||
/* include "an" for "an ogre corpse */
|
||||
any_prefix = (cxn_flags & CXN_ARTICLE) != 0,
|
||||
/* leave off suffix (do_name() appends "corpse" itself) */
|
||||
omit_corpse = (cxn_flags & CXN_NOCORPSE) != 0, possessive = FALSE;
|
||||
omit_corpse = (cxn_flags & CXN_NOCORPSE) != 0,
|
||||
possessive = FALSE,
|
||||
glob = (otmp->otyp != CORPSE && otmp->globby);
|
||||
const char *mname;
|
||||
|
||||
if (omndx == NON_PM) { /* paranoia */
|
||||
if (glob) {
|
||||
mname = OBJ_NAME(objects[otmp->otyp]); /* "glob of <monster>" */
|
||||
} else if (omndx == NON_PM) { /* paranoia */
|
||||
mname = "thing";
|
||||
/* [Possible enhancement: check whether corpse has monster traits
|
||||
attached in order to use priestname() for priests and minions.] */
|
||||
@@ -1172,7 +1178,9 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
|
||||
any_prefix = FALSE;
|
||||
}
|
||||
|
||||
if (!omit_corpse) {
|
||||
if (glob) {
|
||||
; /* omit_corpse doesn't apply; quantity is always 1 */
|
||||
} else if (!omit_corpse) {
|
||||
Strcat(nambuf, " corpse");
|
||||
/* makeplural(nambuf) => append "s" to "corpse" */
|
||||
if (otmp->quan > 1L && !ignore_quan) {
|
||||
@@ -3525,7 +3533,7 @@ typfnd:
|
||||
}
|
||||
otmp->owt = weight(otmp);
|
||||
if (very && otmp->otyp == HEAVY_IRON_BALL)
|
||||
otmp->owt += 160;
|
||||
otmp->owt += IRON_BALL_W_INCR;
|
||||
|
||||
return otmp;
|
||||
}
|
||||
|
||||
@@ -3384,6 +3384,7 @@ boolean tinitial, tfrom_file;
|
||||
need_redraw = TRUE; /* darkroom refresh */
|
||||
} else if ((boolopt[i].addr) == &iflags.use_inverse
|
||||
|| (boolopt[i].addr) == &flags.showrace
|
||||
|| (boolopt[i].addr) == &iflags.hilite_pile
|
||||
|| (boolopt[i].addr) == &iflags.hilite_pet) {
|
||||
need_redraw = TRUE;
|
||||
#ifdef TEXTCOLOR
|
||||
|
||||
@@ -2271,7 +2271,7 @@ struct obj *sobj;
|
||||
You("are being punished for your misbehavior!");
|
||||
if (Punished) {
|
||||
Your("iron ball gets heavier.");
|
||||
uball->owt += 160 * (1 + sobj->cursed);
|
||||
uball->owt += IRON_BALL_W_INCR * (1 + sobj->cursed);
|
||||
return;
|
||||
}
|
||||
if (amorphous(youmonst.data) || is_whirly(youmonst.data)
|
||||
|
||||
@@ -3118,8 +3118,6 @@ quit:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define HUNGRY 2
|
||||
|
||||
STATIC_OVL long
|
||||
getprice(obj, shk_buying)
|
||||
register struct obj *obj;
|
||||
|
||||
18
src/sp_lev.c
18
src/sp_lev.c
@@ -1873,11 +1873,12 @@ struct mkroom *croom;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
struct obj *cobj = container_obj[container_idx - 1];
|
||||
remove_object(otmp);
|
||||
if (container_obj[container_idx - 1])
|
||||
(void) add_to_container(container_obj[container_idx - 1],
|
||||
otmp);
|
||||
else {
|
||||
if (cobj) {
|
||||
(void) add_to_container(cobj, otmp);
|
||||
cobj->owt = weight(cobj);
|
||||
} else {
|
||||
obj_extract_self(otmp);
|
||||
obfree(otmp, NULL);
|
||||
return;
|
||||
@@ -5863,11 +5864,16 @@ sp_lev *lvl;
|
||||
|
||||
count_features();
|
||||
|
||||
if (coder->premapped)
|
||||
sokoban_detect();
|
||||
if (coder->solidify)
|
||||
solidify_map();
|
||||
|
||||
/* This must be done before sokoban_detect(),
|
||||
* otherwise branch stairs won't be premapped. */
|
||||
fixup_special();
|
||||
|
||||
if (coder->premapped)
|
||||
sokoban_detect();
|
||||
|
||||
if (coder->frame) {
|
||||
struct sp_frame *tmpframe;
|
||||
do {
|
||||
|
||||
@@ -980,7 +980,7 @@ register int x, y;
|
||||
}
|
||||
}
|
||||
|
||||
memset(mtmp->mtrack, MTSZ, sizeof(coord));
|
||||
memset(mtmp->mtrack, 0, sizeof(mtmp->mtrack));
|
||||
place_monster(mtmp, x, y); /* put monster down */
|
||||
update_monster_region(mtmp);
|
||||
|
||||
|
||||
13
src/trap.c
13
src/trap.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 trap.c $NHDT-Date: 1451176031 2015/12/27 00:27:11 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.252 $ */
|
||||
/* NetHack 3.6 trap.c $NHDT-Date: 1452039453 2016/01/06 00:17:33 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.253 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -1889,7 +1889,9 @@ int style;
|
||||
if (dist > 0 && isok(bhitpos.x + dx, bhitpos.y + dy)
|
||||
&& levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS) {
|
||||
x2 = bhitpos.x, y2 = bhitpos.y; /* object stops here */
|
||||
if (hits_bars(&singleobj, x2, y2, !rn2(20), 0)) {
|
||||
if (hits_bars(&singleobj,
|
||||
x2, y2, x2+dx, y2+dy,
|
||||
!rn2(20), 0)) {
|
||||
if (!singleobj) {
|
||||
used_up = TRUE;
|
||||
launch_drop_spot((struct obj *) 0, 0, 0);
|
||||
@@ -4999,13 +5001,13 @@ lava_effects()
|
||||
&& objects[obj->otyp].oc_oprop != FIRE_RES
|
||||
&& obj->otyp != SCR_FIRE && obj->otyp != SPE_FIREBALL
|
||||
&& !obj_resists(obj, 0, 0)) /* for invocation items */
|
||||
obj->in_use = TRUE;
|
||||
obj->in_use = 1;
|
||||
|
||||
/* Check whether we should burn away boots *first* so we know whether to
|
||||
* make the player sink into the lava. Assumption: water walking only
|
||||
* comes from boots.
|
||||
*/
|
||||
if (Wwalking && uarmf && is_organic(uarmf) && !uarmf->oerodeproof) {
|
||||
if (uarmf && is_organic(uarmf) && !uarmf->oerodeproof) {
|
||||
obj = uarmf;
|
||||
pline("%s into flame!", Yobjnam2(obj, "burst"));
|
||||
iflags.in_lava_effects++; /* (see above) */
|
||||
@@ -5119,6 +5121,9 @@ sink_into_lava()
|
||||
You("sink below the surface and die.");
|
||||
burn_away_slime(); /* add insult to injury? */
|
||||
done(DISSOLVED);
|
||||
/* can only get here via life-saving; try to get away from lava */
|
||||
u.utrap = 0;
|
||||
(void) safe_teleds(TRUE);
|
||||
} else if (!u.umoved) {
|
||||
/* can't fully turn into slime while in lava, but might not
|
||||
have it be burned away until you've come awfully close */
|
||||
|
||||
@@ -380,7 +380,7 @@ invault()
|
||||
getlin(Deaf ? "You are required to sign in with your name. -" :
|
||||
"\"Hello stranger, who are you?\" -", buf);
|
||||
(void) mungspaces(buf);
|
||||
} while (!letter(buf[0]) && --trycount > 0);
|
||||
} while (!buf[0] && --trycount > 0);
|
||||
|
||||
if (u.ualign.type == A_LAWFUL
|
||||
/* ignore trailing text, in case player includes rank */
|
||||
|
||||
@@ -175,9 +175,9 @@ register struct rm *lev;
|
||||
if (obj->otyp == BOULDER)
|
||||
return 1;
|
||||
|
||||
/* Mimics mimicing a door or boulder block light. */
|
||||
/* Mimics mimicing a door or boulder or ... block light. */
|
||||
if ((mon = m_at(x, y)) && (!mon->minvis || See_invisible)
|
||||
&& (is_door_mappear(mon) || is_obj_mappear(mon,BOULDER)))
|
||||
&& is_lightblocker_mappear(mon))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -304,12 +304,12 @@ struct monst *mon;
|
||||
if (ptr == &mons[PM_SHADE] && !shade_glare(otmp))
|
||||
tmp = 0;
|
||||
|
||||
/* "very heavy iron ball"; weight increase is in increments of 160 */
|
||||
/* "very heavy iron ball"; weight increase is in increments */
|
||||
if (otyp == HEAVY_IRON_BALL && tmp > 0) {
|
||||
int wt = (int) objects[HEAVY_IRON_BALL].oc_weight;
|
||||
|
||||
if ((int) otmp->owt > wt) {
|
||||
wt = ((int) otmp->owt - wt) / 160;
|
||||
wt = ((int) otmp->owt - wt) / IRON_BALL_W_INCR;
|
||||
tmp += rnd(4 * wt);
|
||||
if (tmp > 25)
|
||||
tmp = 25; /* objects[].oc_wldam */
|
||||
|
||||
13
src/zap.c
13
src/zap.c
@@ -2368,7 +2368,13 @@ boolean ordinary;
|
||||
}
|
||||
if (u.utrap) { /* escape web or bear trap */
|
||||
(void) openholdingtrap(&youmonst, &learn_it);
|
||||
} else { /* trigger previously escaped trapdoor */
|
||||
} else {
|
||||
struct obj *otmp;
|
||||
/* unlock carried boxes */
|
||||
for (otmp = invent; otmp; otmp = otmp->nobj)
|
||||
if (Is_box(otmp))
|
||||
(void) boxlock(otmp, obj);
|
||||
/* trigger previously escaped trapdoor */
|
||||
(void) openfallingtrap(&youmonst, TRUE, &learn_it);
|
||||
}
|
||||
break;
|
||||
@@ -3097,6 +3103,7 @@ struct obj **pobj; /* object tossed/used, set to NULL
|
||||
/* iron bars will block anything big enough */
|
||||
if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
|
||||
&& typ == IRONBARS && hits_bars(pobj, x - ddx, y - ddy,
|
||||
bhitpos.x, bhitpos.y,
|
||||
point_blank ? 0 : !rn2(5), 1)) {
|
||||
/* caveat: obj might now be null... */
|
||||
obj = *pobj;
|
||||
@@ -4305,6 +4312,10 @@ short exploding_wand_typ;
|
||||
}
|
||||
break; /* ZT_COLD */
|
||||
|
||||
case ZT_POISON_GAS:
|
||||
(void) create_gas_cloud(x, y, 1, 8);
|
||||
break;
|
||||
|
||||
case ZT_ACID:
|
||||
if (lev->typ == IRONBARS) {
|
||||
if ((lev->wall_info & W_NONDIGGABLE) != 0) {
|
||||
|
||||
Reference in New Issue
Block a user