Merge branch 'NetHack-3.6.0' of https://rodney.nethack.org:20040/git/NHsource into NetHack-3.6.0

This commit is contained in:
nhmall
2016-01-06 20:21:29 -05:00
33 changed files with 449 additions and 135 deletions

View File

@@ -773,8 +773,6 @@ beautiful()
: "ugly");
}
#define WEAK 3 /* from eat.c */
static const char look_str[] = "look %s.";
STATIC_OVL int

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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;
{

View File

@@ -1431,6 +1431,8 @@ struct obj *otmp;
case ELVEN_DAGGER:
case ORCISH_DAGGER:
case ATHAME:
case KNIFE:
case STILETTO:
case CRYSKNIFE:
tmp = 3;
break;

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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();

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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)

View File

@@ -3118,8 +3118,6 @@ quit:
return 0;
}
#define HUNGRY 2
STATIC_OVL long
getprice(obj, shk_buying)
register struct obj *obj;

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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) {