Merge remote-tracking branch 'origin/NetHack-3.6.0'

This commit is contained in:
keni
2017-09-24 13:58:17 -04:00
160 changed files with 6441 additions and 1061 deletions
+71 -45
View File
@@ -12,7 +12,7 @@ STATIC_DCL boolean FDECL(its_dead, (int, int, int *));
STATIC_DCL int FDECL(use_stethoscope, (struct obj *));
STATIC_DCL void FDECL(use_whistle, (struct obj *));
STATIC_DCL void FDECL(use_magic_whistle, (struct obj *));
STATIC_DCL void FDECL(use_leash, (struct obj *));
STATIC_DCL int FDECL(use_leash, (struct obj *));
STATIC_DCL int FDECL(use_mirror, (struct obj *));
STATIC_DCL void FDECL(use_bell, (struct obj **));
STATIC_DCL void FDECL(use_candelabrum, (struct obj *));
@@ -38,6 +38,8 @@ STATIC_DCL void FDECL(add_class, (char *, CHAR_P));
STATIC_DCL void FDECL(setapplyclasses, (char *));
STATIC_PTR boolean FDECL(check_jump, (genericptr_t, int, int));
STATIC_DCL boolean FDECL(is_valid_jump_pos, (int, int, int, BOOLEAN_P));
STATIC_DCL boolean FDECL(get_valid_jump_position, (int, int));
STATIC_DCL boolean FDECL(get_valid_polearm_position, (int, int));
STATIC_DCL boolean FDECL(find_poleable_mon, (coord *, int, int));
#ifdef AMIGA
@@ -571,6 +573,10 @@ unleash_all()
#define MAXLEASHED 2
/* TODO:
* This ought to exclude various other things, such as lights and gas
* spore, is_whirly() critters, ethereal creatures, possibly others.
*/
static boolean
leashable(mtmp)
struct monst *mtmp;
@@ -579,82 +585,102 @@ struct monst *mtmp;
}
/* ARGSUSED */
STATIC_OVL void
STATIC_OVL int
use_leash(obj)
struct obj *obj;
{
coord cc;
register struct monst *mtmp;
struct monst *mtmp;
int spotmon;
if (u.uswallow) {
/* if the leash isn't in use, assume we're trying to leash
the engulfer; if it is use, distinguish between removing
it from the engulfer versus from some other creature
(note: the two in-use cases can't actually occur; all
leashes are released when the hero gets engulfed) */
You_cant((!obj->leashmon
? "leash %s from inside."
: (obj->leashmon == (int) u.ustuck->m_id)
? "unleash %s from inside."
: "unleash anything from inside %s."),
noit_mon_nam(u.ustuck));
return 0;
}
if (!obj->leashmon && number_leashed() >= MAXLEASHED) {
You("cannot leash any more pets.");
return;
return 0;
}
if (!get_adjacent_loc((char *) 0, (char *) 0, u.ux, u.uy, &cc))
return;
return 0;
if ((cc.x == u.ux) && (cc.y == u.uy)) {
if (cc.x == u.ux && cc.y == u.uy) {
if (u.usteed && u.dz > 0) {
mtmp = u.usteed;
spotmon = 1;
goto got_target;
}
pline("Leash yourself? Very funny...");
return;
return 0;
}
/*
* From here on out, return value is 1 == a move is used.
*/
if (!(mtmp = m_at(cc.x, cc.y))) {
There("is no creature there.");
return;
if (glyph_is_invisible(levl[cc.x][cc.y].glyph)) {
unmap_object(cc.x, cc.y);
newsym(cc.x, cc.y);
}
return 1;
}
spotmon = canspotmon(mtmp);
got_target:
got_target:
if (!mtmp->mtame) {
if (!spotmon)
There("is no creature there.");
else
pline("%s %s leashed!", Monnam(mtmp),
(!obj->leashmon) ? "cannot be" : "is not");
return;
}
if (!obj->leashmon) {
if (!spotmon && !glyph_is_invisible(levl[cc.x][cc.y].glyph)) {
/* for the unleash case, we don't verify whether this unseen
monster is the creature attached to the current leash */
You("fail to %sleash something.", obj->leashmon ? "un" : "");
/* trying again will work provided the monster is tame
(and also that it doesn't change location by retry time) */
map_invisible(cc.x, cc.y);
} else if (!mtmp->mtame) {
pline("%s %s leashed!", Monnam(mtmp),
(!obj->leashmon) ? "cannot be" : "is not");
} else if (!obj->leashmon) {
/* applying a leash which isn't currently in use */
if (mtmp->mleashed) {
pline("This %s is already leashed.",
spotmon ? l_monnam(mtmp) : "monster");
return;
}
if (!leashable(mtmp)) {
spotmon ? l_monnam(mtmp) : "creature");
} else if (!leashable(mtmp)) {
pline("The leash won't fit onto %s%s.", spotmon ? "your " : "",
l_monnam(mtmp));
return;
} else {
You("slip the leash around %s%s.", spotmon ? "your " : "",
l_monnam(mtmp));
mtmp->mleashed = 1;
obj->leashmon = (int) mtmp->m_id;
mtmp->msleeping = 0;
}
You("slip the leash around %s%s.", spotmon ? "your " : "",
l_monnam(mtmp));
mtmp->mleashed = 1;
obj->leashmon = (int) mtmp->m_id;
mtmp->msleeping = 0;
return;
}
if (obj->leashmon != (int) mtmp->m_id) {
pline("This leash is not attached to that creature.");
return;
} else {
if (obj->cursed) {
/* applying a leash which is currently in use */
if (obj->leashmon != (int) mtmp->m_id) {
pline("This leash is not attached to that creature.");
} else if (obj->cursed) {
pline_The("leash would not come off!");
obj->bknown = TRUE;
return;
obj->bknown = 1;
} else {
mtmp->mleashed = 0;
obj->leashmon = 0;
You("remove the leash from %s%s.",
spotmon ? "your " : "", l_monnam(mtmp));
}
mtmp->mleashed = 0;
obj->leashmon = 0;
You("remove the leash from %s%s.", spotmon ? "your " : "",
l_monnam(mtmp));
}
return;
return 1;
}
/* assuming mtmp->mleashed has been checked */
@@ -1566,7 +1592,7 @@ boolean showmsg;
static int jumping_is_magic;
boolean
STATIC_OVL boolean
get_valid_jump_position(x,y)
int x,y;
{
@@ -2860,7 +2886,7 @@ int min_range, max_range;
static int polearm_range_min = -1;
static int polearm_range_max = -1;
boolean
STATIC_OVL boolean
get_valid_polearm_position(x,y)
int x,y;
{
@@ -3553,7 +3579,7 @@ doapply()
use_tinning_kit(obj);
break;
case LEASH:
use_leash(obj);
res = use_leash(obj);
break;
case SADDLE:
res = use_saddle(obj);
+11 -3
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 bones.c $NHDT-Date: 1450432756 2015/12/18 09:59:16 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.68 $ */
/* NetHack 3.6 bones.c $NHDT-Date: 1503309019 2017/08/21 09:50:19 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.70 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985,1993. */
/* NetHack may be freely redistributed. See license for details. */
@@ -552,7 +552,7 @@ getbones()
{
register int fd;
register int ok;
char c, *bonesid, oldbonesid[10];
char c, *bonesid, oldbonesid[40]; /* was [10]; more should be safer */
if (discover) /* save bones files for real games */
return 0;
@@ -584,7 +584,15 @@ getbones()
}
mread(fd, (genericptr_t) &c, sizeof c); /* length incl. '\0' */
mread(fd, (genericptr_t) oldbonesid, (unsigned) c); /* DD.nnn */
if (strcmp(bonesid, oldbonesid) != 0) {
if (strcmp(bonesid, oldbonesid) != 0
/* from 3.3.0 through 3.6.0, bones in the quest branch stored
a bogus bonesid in the file; 3.6.1 fixed that, but for
3.6.0 bones to remain compatible, we need an extra test;
once compatibility with 3.6.x goes away, this can too
(we don't try to make this conditional upon the value of
VERSION_COMPATIBILITY because then we'd need patchlevel.h) */
&& (strlen(bonesid) <= 2
|| strcmp(bonesid + 2, oldbonesid) != 0)) {
char errbuf[BUFSZ];
Sprintf(errbuf, "This is bones level '%s', not '%s'!", oldbonesid,
+12 -1
View File
@@ -83,6 +83,16 @@ do_statusline1()
return newbot1;
}
void
check_gold_symbol()
{
int goldch, goldoc;
unsigned int goldos;
int goldglyph = objnum_to_glyph(GOLD_PIECE);
(void) mapglyph(goldglyph, &goldch, &goldoc, &goldos, 0, 0);
iflags.invis_goldsym = ((char)goldch <= ' ');
}
char *
do_statusline2()
{
@@ -110,7 +120,8 @@ do_statusline2()
if ((money = money_cnt(invent)) < 0L)
money = 0L; /* ought to issue impossible() and then discard gold */
Sprintf(eos(dloc), "%s:%-2ld", /* strongest hero can lift ~300000 gold */
iflags.in_dumplog ? "$" : encglyph(objnum_to_glyph(GOLD_PIECE)),
(iflags.in_dumplog || iflags.invis_goldsym) ? "$"
: encglyph(objnum_to_glyph(GOLD_PIECE)),
min(money, 999999L));
dln = strlen(dloc);
/* '$' encoded as \GXXXXNNNN is 9 chars longer than display will need */
+52 -42
View File
@@ -381,8 +381,10 @@ doextlist(VOID_ARGS)
#define MAX_EXT_CMD 200 /* Change if we ever have more ext cmds */
/*
* This is currently used only by the tty port and is
* controlled via runtime option 'extmenu'.
* This is currently used only by the tty interface and is
* controlled via runtime option 'extmenu'. (Most other interfaces
* already use a menu all the time for extended commands.)
*
* ``# ?'' is counted towards the limit of the number of commands,
* so we actually support MAX_EXT_CMD-1 "real" extended commands.
*
@@ -399,9 +401,10 @@ extcmd_via_menu()
char buf[BUFSZ];
char cbuf[QBUFSZ], prompt[QBUFSZ], fmtstr[20];
int i, n, nchoices, acount;
int ret, biggest;
int ret, len, biggest;
int accelerator, prevaccelerator;
int matchlevel = 0;
boolean wastoolong, one_per_line;
ret = 0;
cbuf[0] = '\0';
@@ -416,10 +419,8 @@ extcmd_via_menu()
continue;
if (!matchlevel || !strncmp(efp->ef_txt, cbuf, matchlevel)) {
choices[i] = efp;
if ((int) strlen(efp->ef_desc) > biggest) {
biggest = strlen(efp->ef_desc);
Sprintf(fmtstr, "%%-%ds", biggest + 15);
}
if ((len = (int) strlen(efp->ef_desc)) > biggest)
biggest = len;
if (++i > MAX_EXT_CMD) {
#if defined(BETA)
impossible(
@@ -434,25 +435,33 @@ extcmd_via_menu()
choices[i] = (struct ext_func_tab *) 0;
nchoices = i;
/* if we're down to one, we have our selection so get out of here */
if (nchoices == 1) {
for (i = 0; extcmdlist[i].ef_txt != (char *) 0; i++)
if ((extcmdlist[i].flags & AUTOCOMPLETE)
&& !(!wizard && (extcmdlist[i].flags & WIZMODECMD))
&& !strncmpi(extcmdlist[i].ef_txt, cbuf, matchlevel)) {
ret = i;
break;
}
if (nchoices <= 1) {
ret = (nchoices == 1) ? (int) (choices[0] - extcmdlist) : -1;
break;
}
/* otherwise... */
win = create_nhwindow(NHW_MENU);
start_menu(win);
Sprintf(fmtstr, "%%-%ds", biggest + 15);
prompt[0] = '\0';
wastoolong = FALSE; /* True => had to wrap due to line width
* ('w' in wizard mode) */
/* -3: two line menu header, 1 line menu footer (for prompt) */
one_per_line = (nchoices < ROWNO - 3);
accelerator = prevaccelerator = 0;
acount = 0;
for (i = 0; choices[i]; ++i) {
accelerator = choices[i]->ef_txt[matchlevel];
if (accelerator != prevaccelerator || nchoices < (ROWNO - 3)) {
if (accelerator != prevaccelerator || one_per_line)
wastoolong = FALSE;
if (accelerator != prevaccelerator || one_per_line
|| (acount >= 2
/* +4: + sizeof " or " - sizeof "" */
&& (strlen(prompt) + 4 + strlen(choices[i]->ef_txt)
/* -6: enough room for 1 space left margin
* + "%c - " menu selector + 1 space right margin */
>= min(sizeof prompt, COLNO - 6)))) {
if (acount) {
/* flush extended cmds for that letter already in buf */
Sprintf(buf, fmtstr, prompt);
@@ -460,15 +469,17 @@ extcmd_via_menu()
add_menu(win, NO_GLYPH, &any, any.a_char, 0, ATR_NONE,
buf, FALSE);
acount = 0;
if (!(accelerator != prevaccelerator || one_per_line))
wastoolong = TRUE;
}
}
prevaccelerator = accelerator;
if (!acount || nchoices < (ROWNO - 3)) {
Sprintf(prompt, "%s [%s]", choices[i]->ef_txt,
choices[i]->ef_desc);
if (!acount || one_per_line) {
Sprintf(prompt, "%s%s [%s]", wastoolong ? "or " : "",
choices[i]->ef_txt, choices[i]->ef_desc);
} else if (acount == 1) {
Sprintf(prompt, "%s or %s", choices[i - 1]->ef_txt,
choices[i]->ef_txt);
Sprintf(prompt, "%s%s or %s", wastoolong ? "or " : "",
choices[i - 1]->ef_txt, choices[i]->ef_txt);
} else {
Strcat(prompt, " or ");
Strcat(prompt, choices[i]->ef_txt);
@@ -626,6 +637,7 @@ wiz_makemap(VOID_ARGS)
if (wizard) {
struct monst *mtmp;
rm_mapseen(ledger_no(&u.uz));
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
if (mtmp->isshk)
setpaid(mtmp);
@@ -2857,7 +2869,7 @@ int final;
struct ext_func_tab extcmdlist[] = {
{ '#', "#", "perform an extended command",
doextcmd, IFBURIED | GENERALCMD },
{ M('?'), "?", "get this list of extended commands",
{ M('?'), "?", "list all extended commands",
doextlist, IFBURIED | AUTOCOMPLETE | GENERALCMD },
{ M('a'), "adjust", "adjust inventory letters",
doorganize, IFBURIED | AUTOCOMPLETE },
@@ -3056,7 +3068,7 @@ uchar key;
return (char *) 0;
}
void
boolean
bind_key(key, command)
uchar key;
const char *command;
@@ -3066,19 +3078,17 @@ const char *command;
/* special case: "nothing" is reserved for unbinding */
if (!strcmp(command, "nothing")) {
Cmd.commands[key] = (struct ext_func_tab *) 0;
return;
return TRUE;
}
for (extcmd = extcmdlist; extcmd->ef_txt; extcmd++) {
if (strcmp(command, extcmd->ef_txt))
continue;
Cmd.commands[key] = extcmd;
return;
return TRUE;
}
pline(
"Bad command %s matched with key %c (ASCII %i). Ignoring command.\n",
command, key, key);
return FALSE;
}
/* initialize all keyboard commands */
@@ -3091,27 +3101,27 @@ commands_init()
if (extcmd->key)
Cmd.commands[extcmd->key] = extcmd;
bind_key(C('l'), "redraw"); /* if number_pad is set */
(void) bind_key(C('l'), "redraw"); /* if number_pad is set */
/* 'b', 'B' : go sw */
/* 'F' : fight (one time) */
/* 'g', 'G' : multiple go */
/* 'h', 'H' : go west */
bind_key('h', "help"); /* if number_pad is set */
bind_key('j', "jump"); /* if number_pad is on */
(void) bind_key('h', "help"); /* if number_pad is set */
(void) bind_key('j', "jump"); /* if number_pad is on */
/* 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' move commands */
bind_key('k', "kick"); /* if number_pad is on */
bind_key('l', "loot"); /* if number_pad is on */
bind_key(C('n'), "annotate"); /* if number_pad is on */
bind_key(M('n'), "name");
bind_key(M('N'), "name");
bind_key('u', "untrap"); /* if number_pad is on */
(void) bind_key('k', "kick"); /* if number_pad is on */
(void) bind_key('l', "loot"); /* if number_pad is on */
(void) bind_key(C('n'), "annotate"); /* if number_pad is on */
(void) bind_key(M('n'), "name");
(void) bind_key(M('N'), "name");
(void) bind_key('u', "untrap"); /* if number_pad is on */
/* alt keys: */
bind_key(M('O'), "overview");
bind_key(M('2'), "twoweapon");
(void) bind_key(M('O'), "overview");
(void) bind_key(M('2'), "twoweapon");
/* wait_on_space */
bind_key(' ', "wait");
(void) bind_key(' ', "wait");
}
int
@@ -4007,7 +4017,7 @@ boolean initial;
}
backed_dir_cmd = TRUE;
for (i = 0; i < 8; i++)
bind_key(Cmd.dirchars[i], "nothing");
(void) bind_key(Cmd.dirchars[i], "nothing");
}
}
@@ -4965,7 +4975,7 @@ end_of_input()
if (iflags.window_inited)
exit_nhwindows((char *) 0);
clearlocks();
terminate(EXIT_SUCCESS);
nh_terminate(EXIT_SUCCESS);
/*NOTREACHED*/ /* not necessarily true for vms... */
return;
}
+21 -21
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 dbridge.c $NHDT-Date: 1449269914 2015/12/04 22:58:34 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.35 $ */
/* NetHack 3.6 dbridge.c $NHDT-Date: 1503355815 2017/08/21 22:50:15 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.39 $ */
/* Copyright (c) 1989 by Jean-Christophe Collet */
/* NetHack may be freely redistributed. See license for details. */
@@ -230,7 +230,6 @@ int *x, *y;
* dir is the direction.
* flag must be put to TRUE if we want the drawbridge to be opened.
*/
boolean
create_drawbridge(x, y, dir, flag)
int x, y, dir;
@@ -375,7 +374,6 @@ struct entity *etmp;
* Generates capitalized entity name, makes 2nd -> 3rd person conversion on
* verb, where necessary.
*/
STATIC_OVL const char *
E_phrase(etmp, verb)
struct entity *etmp;
@@ -397,7 +395,6 @@ const char *verb;
/*
* Simple-minded "can it be here?" routine
*/
STATIC_OVL boolean
e_survives_at(etmp, x, y)
struct entity *etmp;
@@ -486,7 +483,6 @@ int xkill_flags, how;
/*
* These are never directly affected by a bridge or portcullis.
*/
STATIC_OVL boolean
automiss(etmp)
struct entity *etmp;
@@ -498,7 +494,6 @@ struct entity *etmp;
/*
* Does falling drawbridge or portcullis miss etmp?
*/
STATIC_OVL boolean
e_missed(etmp, chunks)
struct entity *etmp;
@@ -536,7 +531,6 @@ boolean chunks;
/*
* Can etmp jump from death?
*/
STATIC_OVL boolean
e_jumps(etmp)
struct entity *etmp;
@@ -604,6 +598,11 @@ struct entity *etmp;
}
} else {
if (crm->typ == DRAWBRIDGE_DOWN) {
if (is_u(etmp)) {
killer.format = NO_KILLER_PREFIX;
Strcpy(killer.name,
"crushed to death underneath a drawbridge");
}
pline("%s crushed underneath the drawbridge.",
E_phrase(etmp, "are")); /* no jump */
e_died(etmp,
@@ -639,11 +638,10 @@ struct entity *etmp;
/*
* Here's where we try to do relocation. Assumes that etmp is not
* arriving
* at the portcullis square while the drawbridge is falling, since this
* square
* would be inaccessible (i.e. etmp started on drawbridge square) or
* unnecessary (i.e. etmp started here) in such a situation.
* arriving at the portcullis square while the drawbridge is
* falling, since this square would be inaccessible (i.e. etmp
* started on drawbridge square) or unnecessary (i.e. etmp started
* here) in such a situation.
*/
debugpline0("Doing relocation.");
newx = oldx;
@@ -654,12 +652,10 @@ struct entity *etmp;
debugpline0("Checking new square for occupancy.");
if (relocates && (e_at(newx, newy))) {
/*
* Standoff problem: one or both entities must die, and/or both
* switch
* places. Avoid infinite recursion by checking first whether the
* other
* entity is staying put. Clean up if we happen to move/die in
* recursion.
* Standoff problem: one or both entities must die, and/or
* both switch places. Avoid infinite recursion by checking
* first whether the other entity is staying put. Clean up if
* we happen to move/die in recursion.
*/
struct entity *other;
@@ -763,10 +759,12 @@ struct entity *etmp;
}
}
/* clear stale reason for death before returning */
#define nokiller() (killer.name[0] = '\0', killer.format = 0)
/*
* Close the drawbridge located at x,y
*/
void
close_drawbridge(x, y)
int x, y;
@@ -823,12 +821,12 @@ int x, y;
newsym(x, y);
newsym(x2, y2);
block_point(x2, y2); /* vision */
nokiller();
}
/*
* Open the drawbridge located at x,y
*/
void
open_drawbridge(x, y)
int x, y;
@@ -870,12 +868,12 @@ int x, y;
unblock_point(x2, y2); /* vision */
if (Is_stronghold(&u.uz))
u.uevent.uopened_dbridge = TRUE;
nokiller();
}
/*
* Let's destroy the drawbridge located at x,y
*/
void
destroy_drawbridge(x, y)
int x, y;
@@ -898,6 +896,7 @@ int x, y;
|| (lev1->drawbridgemask & DB_UNDER) == DB_LAVA) {
struct obj *otmp2;
boolean lava = (lev1->drawbridgemask & DB_UNDER) == DB_LAVA;
if (lev1->typ == DRAWBRIDGE_UP) {
if (cansee(x2, y2))
pline_The("portcullis of the drawbridge falls into the %s!",
@@ -999,6 +998,7 @@ int x, y;
do_entity(etmp1);
}
}
nokiller();
}
/*dbridge.c*/
+1 -1
View File
@@ -333,7 +333,7 @@ NEARDATA struct savefile_info sfrestinfo, sfsaveinfo = {
struct plinemsg_type *plinemsg_types = (struct plinemsg_type *) 0;
#ifdef PANICTRACE
char *ARGV0;
const char *ARGV0;
#endif
/* XXX see comment in save.c */
+3 -3
View File
@@ -1571,9 +1571,9 @@ boolean via_warning;
Blind ? "to check nearby" : "look close by");
display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */
}
mtmp->mundetected = 0;
newsym(x, y);
goto find;
mtmp->mundetected = 0;
newsym(x, y);
goto find;
}
return 0;
}
+5 -5
View File
@@ -404,7 +404,7 @@ dig(VOID_ARGS)
}
} else if (IS_WALL(lev->typ)) {
if (shopedge) {
add_damage(dpx, dpy, 10L * ACURRSTR);
add_damage(dpx, dpy, SHOP_WALL_DMG);
dmgtxt = "damage";
}
if (level.flags.is_maze_lev) {
@@ -424,7 +424,7 @@ dig(VOID_ARGS)
} else if (closed_door(dpx, dpy)) {
digtxt = "You break through the door.";
if (shopedge) {
add_damage(dpx, dpy, 400L);
add_damage(dpx, dpy, SHOP_DOOR_COST);
dmgtxt = "break";
}
if (!(lev->doormask & D_TRAPPED))
@@ -1485,7 +1485,7 @@ zap_dig()
}
} else if (closed_door(zx, zy) || room->typ == SDOOR) {
if (*in_rooms(zx, zy, SHOPBASE)) {
add_damage(zx, zy, 400L);
add_damage(zx, zy, SHOP_DOOR_COST);
shopdoor = TRUE;
}
if (room->typ == SDOOR)
@@ -1502,7 +1502,7 @@ zap_dig()
if (IS_WALL(room->typ)) {
if (!(room->wall_info & W_NONDIGGABLE)) {
if (*in_rooms(zx, zy, SHOPBASE)) {
add_damage(zx, zy, 200L);
add_damage(zx, zy, SHOP_WALL_COST);
shopwall = TRUE;
}
room->typ = ROOM;
@@ -1530,7 +1530,7 @@ zap_dig()
break;
if (IS_WALL(room->typ) || room->typ == SDOOR) {
if (*in_rooms(zx, zy, SHOPBASE)) {
add_damage(zx, zy, 200L);
add_damage(zx, zy, SHOP_WALL_COST);
shopwall = TRUE;
}
watch_dig((struct monst *) 0, zx, zy, TRUE);
+2 -1
View File
@@ -190,7 +190,7 @@ const char *verb;
newsym(x, y);
return TRUE;
} else if (is_lava(x, y)) {
return fire_damage(obj, FALSE, x, y);
return lava_damage(obj, x, y);
} else if (is_pool(x, y)) {
/* Reasonably bulky objects (arbitrary) splash when dropped.
* If you're floating above the water even small things make
@@ -1254,6 +1254,7 @@ boolean at_stairs, falling, portal;
#ifdef USE_TILES
substitute_tiles(newlevel);
#endif
check_gold_symbol();
/* record this level transition as a potential seen branch unless using
* some non-standard means of transportation (level teleport).
*/
+1
View File
@@ -10,6 +10,7 @@ STATIC_DCL int FDECL(CFDECLSPEC cmp_coord_distu, (const void *,
const void *));
STATIC_DCL boolean FDECL(gather_locs_interesting, (int, int, int));
STATIC_DCL void FDECL(gather_locs, (coord **, int *, int));
STATIC_DCL int FDECL(gloc_filter_floodfill_matcharea, (int, int));
STATIC_DCL void FDECL(auto_describe, (int, int));
STATIC_DCL void NDECL(do_mname);
STATIC_DCL boolean FDECL(alreadynamed, (struct monst *, char *, char *));
+1 -1
View File
@@ -1278,7 +1278,7 @@ dokick()
feel_newsym(x, y); /* we know we broke it */
unblock_point(x, y); /* vision */
if (shopdoor) {
add_damage(x, y, 400L);
add_damage(x, y, SHOP_DOOR_COST);
pay_for_damage("break", FALSE);
}
if (in_town(x, y))
+48 -3
View File
@@ -57,6 +57,7 @@ STATIC_DCL boolean FDECL(unreachable_level, (d_level *, BOOLEAN_P));
STATIC_DCL void FDECL(tport_menu, (winid, char *, struct lchoice *, d_level *,
BOOLEAN_P));
STATIC_DCL const char *FDECL(br_string, (int));
STATIC_DCL char FDECL(chr_u_on_lvl, (d_level *));
STATIC_DCL void FDECL(print_branch, (winid, int, int, int, BOOLEAN_P,
struct lchoice *));
STATIC_DCL mapseen *FDECL(load_mapseen, (int));
@@ -247,7 +248,7 @@ dlb *stream;
panic(
"Premature EOF on dungeon description file!\r\nExpected %d bytes - got %d.",
(size * nitems), (size * cnt));
terminate(EXIT_FAILURE);
nh_terminate(EXIT_FAILURE);
}
}
@@ -1794,6 +1795,13 @@ int type;
return " (unknown)";
}
STATIC_OVL char
chr_u_on_lvl(dlev)
d_level *dlev;
{
return u.uz.dnum == dlev->dnum && u.uz.dlevel == dlev->dlevel ? '*' : ' ';
}
/* Print all child branches between the lower and upper bounds. */
STATIC_OVL void
print_branch(win, dnum, lower_bound, upper_bound, bymenu, lchoices_p)
@@ -1811,7 +1819,9 @@ struct lchoice *lchoices_p;
for (br = branches; br; br = br->next) {
if (br->end1.dnum == dnum && lower_bound < br->end1.dlevel
&& br->end1.dlevel <= upper_bound) {
Sprintf(buf, " %s to %s: %d", br_string(br->type),
Sprintf(buf, "%c %s to %s: %d",
bymenu ? chr_u_on_lvl(&br->end1) : ' ',
br_string(br->type),
dungeons[br->end2.dnum].dname, depth(&br->end1));
if (bymenu)
tport_menu(win, buf, lchoices_p, &br->end1,
@@ -1885,7 +1895,9 @@ xchar *rdgn;
print_branch(win, i, last_level, slev->dlevel.dlevel, bymenu,
&lchoices);
Sprintf(buf, " %s: %d", slev->proto, depth(&slev->dlevel));
Sprintf(buf, "%c %s: %d",
chr_u_on_lvl(&slev->dlevel),
slev->proto, depth(&slev->dlevel));
if (Is_stronghold(&slev->dlevel))
Sprintf(eos(buf), " (tune %s)", tune);
if (bymenu)
@@ -2109,6 +2121,39 @@ int ledger_num;
}
}
void
rm_mapseen(ledger_num)
int ledger_num;
{
mapseen *mptr, *mprev = (mapseen *)0;
struct cemetery *bp, *bpnext;
for (mptr = mapseenchn; mptr; mprev = mptr, mptr = mptr->next)
if (dungeons[mptr->lev.dnum].ledger_start + mptr->lev.dlevel == ledger_num)
break;
if (!mptr)
return;
if (mptr->custom)
free((genericptr_t) mptr->custom);
bp = mptr->final_resting_place;
while (bp) {
bpnext = bp->next;
free(bp);
bp = bpnext;
}
if (mprev) {
mprev->next = mptr->next;
free(mptr);
} else {
mapseenchn = mptr->next;
free(mptr);
}
}
STATIC_OVL void
save_mapseen(fd, mptr)
int fd;
+15 -5
View File
@@ -1708,8 +1708,12 @@ struct obj *otmp;
{
const char *old_nomovemsg, *save_nomovemsg;
debugpline2("start_eating: %lx (victual = %lx)", (unsigned long) otmp,
(unsigned long) context.victual.piece);
debugpline2("start_eating: %s (victual = %s)",
/* note: fmt_ptr() returns a static buffer but supports
several such so we don't need to copy the first result
before calling it a second time */
fmt_ptr((genericptr_t) otmp),
fmt_ptr((genericptr_t) context.victual.piece));
debugpline1("reqtime = %d", context.victual.reqtime);
debugpline1("(original reqtime = %d)", objects[otmp->otyp].oc_delay);
debugpline1("nmod = %d", context.victual.nmod);
@@ -3125,9 +3129,15 @@ vomit() /* A good idea from David Neves */
Your("jaw gapes convulsively.");
else
make_sick(0L, (char *) 0, TRUE, SICK_VOMITABLE);
nomul(-2);
multi_reason = "vomiting";
nomovemsg = You_can_move_again;
/* nomul()/You_can_move_again used to be unconditional, which was
viable while eating but not for Vomiting countdown where hero might
be immobilized for some other reason at the time vomit() is called */
if (multi >= -2) {
nomul(-2);
multi_reason = "vomiting";
nomovemsg = You_can_move_again;
}
}
int
+4 -4
View File
@@ -1373,7 +1373,7 @@ int how;
if (!done_stopprint)
artifact_score(invent, FALSE, endwin); /* list artifacts */
#if DUMPLOG
#ifdef DUMPLOG
dump_redirect(TRUE);
artifact_score(invent, FALSE, 0);
dump_redirect(FALSE);
@@ -1457,7 +1457,7 @@ int how;
raw_print("");
raw_print("");
}
terminate(EXIT_SUCCESS);
nh_terminate(EXIT_SUCCESS);
}
void
@@ -1532,7 +1532,7 @@ boolean identified, all_containers, reportempty;
/* should be called with either EXIT_SUCCESS or EXIT_FAILURE */
void
terminate(status)
nh_terminate(status)
int status;
{
program_state.in_moveloop = 0; /* won't be returning to normal play */
@@ -1549,7 +1549,7 @@ int status;
#ifdef VMS
/*
* This is liable to draw a warning if compiled with gcc, but it's
* more important to flag panic() -> really_done() -> terminate()
* more important to flag panic() -> really_done() -> nh_terminate()
* as __noreturn__ then to avoid the warning.
*/
/* don't call exit() if already executing within an exit handler;
+4 -2
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 explode.c $NHDT-Date: 1496103440 2017/05/30 00:17:20 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.49 $ */
/* NetHack 3.6 explode.c $NHDT-Date: 1503355817 2017/08/21 22:50:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.50 $ */
/* Copyright (C) 1990 by Ken Arromdee */
/* NetHack may be freely redistributed. See license for details. */
@@ -90,7 +90,9 @@ int expltype;
if (olet == MON_EXPLODE) {
str = killer.name;
do_hallu = Hallucination && strstri(str, "'s explosion");
do_hallu = (Hallucination
&& (strstri(str, "'s explosion")
|| strstri(str, "s' explosion")));
adtyp = AD_PHYS;
} else
switch (abs(type) % 10) {
+518 -159
View File
@@ -1,7 +1,9 @@
/* NetHack 3.6 files.c $NHDT-Date: 1502581476 2017/08/12 23:44:36 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.211 $ */
/* NetHack 3.6 files.c $NHDT-Date: 1503309020 2017/08/21 09:50:20 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.215 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
#define NEED_VARARGS
#include "hack.h"
#include "dlb.h"
@@ -190,14 +192,22 @@ STATIC_DCL char *FDECL(make_lockname, (const char *, char *));
#endif
STATIC_DCL void FDECL(set_configfile_name, (const char *));
STATIC_DCL FILE *FDECL(fopen_config_file, (const char *, int));
STATIC_DCL int FDECL(get_uchars, (FILE *, char *, char *, uchar *, BOOLEAN_P,
STATIC_DCL int FDECL(get_uchars, (char *, uchar *, BOOLEAN_P,
int, const char *));
int FDECL(parse_config_line, (FILE *, char *, int));
boolean FDECL(proc_wizkit_line, (char *));
boolean FDECL(parse_config_line, (char *));
STATIC_DCL boolean FDECL(parse_conf_file, (FILE *, boolean (*proc)(char *)));
STATIC_DCL FILE *NDECL(fopen_sym_file);
boolean FDECL(proc_symset_line, (char *));
STATIC_DCL void FDECL(set_symhandling, (char *, int));
#ifdef NOCWD_ASSUMPTIONS
STATIC_DCL void FDECL(adjust_prefix, (char *, int));
#endif
STATIC_DCL boolean FDECL(config_error_nextline, (const char *));
STATIC_DCL void NDECL(free_config_sections);
STATIC_DCL char *FDECL(choose_random_part, (char *, CHAR_P));
STATIC_DCL boolean FDECL(is_config_section, (const char *));
STATIC_DCL boolean FDECL(handle_config_section, (char *));
#ifdef SELF_RECOVER
STATIC_DCL boolean FDECL(copy_bytes, (int, int));
#endif
@@ -205,6 +215,10 @@ STATIC_DCL boolean FDECL(copy_bytes, (int, int));
STATIC_DCL int FDECL(open_levelfile_exclusively, (const char *, int, int));
#endif
static char *config_section_chosen = (char *) 0;
static char *config_section_current = (char *) 0;
/*
* fname_encode()
*
@@ -697,17 +711,47 @@ d_level *lev;
s_level *sptr;
char *dptr;
Sprintf(file, "bon%c%s", dungeons[lev->dnum].boneid,
/*
* "bonD0.nn" = bones for level nn in the main dungeon;
* "bonM0.T" = bones for Minetown;
* "bonQBar.n" = bones for level n in the Barbarian quest;
* "bon3D0.nn" = \
* "bon3M0.T" = > same as above, but for bones pool #3.
* "bon3QBar.n" = /
*
* Return value for content validation skips "bon" and the
* pool number (if present), making it feasible for the admin
* to manually move a bones file from one pool to another by
* renaming it.
*/
Strcpy(file, "bon");
#ifdef SYSCF
if (sysopt.bones_pools > 1) {
unsigned poolnum = min((unsigned) sysopt.bones_pools, 10);
poolnum = (unsigned) ubirthday % poolnum; /* 0..9 */
Sprintf(eos(file), "%u", poolnum);
}
#endif
dptr = eos(file); /* this used to be after the following Sprintf()
and the return value was (dptr - 2) */
/* when this naming scheme was adopted, 'filecode' was one letter;
3.3.0 turned it into a three letter string (via roles[] in role.c);
from that version through 3.6.0, 'dptr' pointed past the filecode
and the return value of (dptr - 2) was wrong for bones produced
in the quest branch, skipping the boneid character 'Q' and the
first letter of the role's filecode; bones loading still worked
because the bonesid used for validation had the same error */
Sprintf(dptr, "%c%s", dungeons[lev->dnum].boneid,
In_quest(lev) ? urole.filecode : "0");
dptr = eos(file);
if ((sptr = Is_special(lev)) != 0)
Sprintf(dptr, ".%c", sptr->boneid);
Sprintf(eos(dptr), ".%c", sptr->boneid);
else
Sprintf(dptr, ".%d", lev->dlevel);
Sprintf(eos(dptr), ".%d", lev->dlevel);
#ifdef VMS
Strcat(dptr, ";1");
#endif
return (dptr - 2);
return dptr;
}
/* set up temporary file name for writing bones, to avoid another game's
@@ -1205,7 +1249,7 @@ boolean uncomp;
if (freopen(filename, mode, stream) == (FILE *) 0) {
(void) fprintf(stderr, "freopen of %s for %scompress failed\n",
filename, uncomp ? "un" : "");
terminate(EXIT_FAILURE);
nh_terminate(EXIT_FAILURE);
}
}
@@ -1311,7 +1355,7 @@ boolean uncomp;
perror((char *) 0);
(void) fprintf(stderr, "Exec to %scompress %s failed.\n",
uncomp ? "un" : "", filename);
terminate(EXIT_FAILURE);
nh_terminate(EXIT_FAILURE);
} else if (f == -1) {
perror((char *) 0);
pline("Fork to %scompress %s failed.", uncomp ? "un" : "", filename);
@@ -1643,8 +1687,10 @@ int retryct;
#ifdef USE_FCNTL
lockfd = open(filename, O_RDWR);
if (lockfd == -1) {
HUP raw_printf("Cannot open file %s. This is a program bug.",
HUP raw_printf("Cannot open file %s. Is NetHack installed correctly?",
filename);
nesting--;
return FALSE;
}
sflock.l_type = F_WRLCK;
sflock.l_whence = SEEK_SET;
@@ -2004,15 +2050,13 @@ int src;
}
/*
* Retrieve a list of integers from a file into a uchar array.
* Retrieve a list of integers from buf into a uchar array.
*
* NOTE: zeros are inserted unless modlist is TRUE, in which case the list
* location is unchanged. Callers must handle zeros if modlist is FALSE.
*/
STATIC_OVL int
get_uchars(fp, buf, bufp, list, modlist, size, name)
FILE *fp; /* input file pointer */
char *buf; /* read buffer, must be of size BUFSZ */
get_uchars(bufp, list, modlist, size, name)
char *bufp; /* current pointer */
uchar *list; /* return list */
boolean modlist; /* TRUE: list is being modified in place */
@@ -2058,13 +2102,7 @@ const char *name; /* name of option for error message */
break;
case '\\':
if (fp == (FILE *) 0)
goto gi_error;
do {
if (!fgets(buf, BUFSZ, fp))
goto gi_error;
} while (buf[0] == '#');
bufp = buf;
goto gi_error;
break;
default:
@@ -2098,13 +2136,111 @@ int prefixid;
}
#endif
/* Choose at random one of the sep separated parts from str. Mangles str. */
STATIC_OVL char *
choose_random_part(str,sep)
char *str;
char sep;
{
int nsep = 1;
int csep;
int len = 0;
char *begin = str;
if (!str)
return (char *) 0;
while (*str) {
if (*str == sep) nsep++;
str++;
}
csep = rn2(nsep);
str = begin;
while ((csep > 0) && *str) {
str++;
if (*str == sep) csep--;
}
if (*str) {
if (*str == sep) str++;
begin = str;
while (*str && *str != sep) {
str++;
len++;
}
*str = '\0';
if (len)
return begin;
}
return (char *) 0;
}
STATIC_OVL void
free_config_sections()
{
if (config_section_chosen) {
free(config_section_chosen);
config_section_chosen = NULL;
}
if (config_section_current) {
free(config_section_current);
config_section_current = NULL;
}
}
STATIC_OVL boolean
is_config_section(str)
const char *str;
{
const char *a = rindex(str, ']');
return (a && *str == '[' && *(a+1) == '\0' && (int)(a - str) > 0);
}
STATIC_OVL boolean
handle_config_section(buf)
char *buf;
{
if (is_config_section(buf)) {
char *send;
if (config_section_current) {
free(config_section_current);
}
config_section_current = dupstr(&buf[1]);
send = rindex(config_section_current, ']');
*send = '\0';
debugpline1("set config section: '%s'", config_section_current);
return TRUE;
}
if (config_section_current) {
if (!config_section_chosen)
return TRUE;
if (strcmp(config_section_current, config_section_chosen))
return TRUE;
}
return FALSE;
}
#define match_varname(INP, NAM, LEN) match_optname(INP, NAM, LEN, TRUE)
int
parse_config_line(fp, origbuf, src)
FILE *fp;
/* find the '=' or ':' */
char *
find_optparam(buf)
const char *buf;
{
char *bufp, *altp;
bufp = index(buf, '=');
altp = index(buf, ':');
if (!bufp || (altp && altp < bufp))
bufp = altp;
return bufp;
}
boolean
parse_config_line(origbuf)
char *origbuf;
int src;
{
#if defined(MICRO) && !defined(NOCWD_ASSUMPTIONS)
static boolean ramdisk_specified = FALSE;
@@ -2112,25 +2248,23 @@ int src;
#ifdef SYSCF
int n;
#endif
char *bufp, *altp, buf[4 * BUFSZ];
char *bufp, buf[4 * BUFSZ];
uchar translate[MAXPCHARS];
int len;
boolean retval = TRUE;
int src = iflags.parse_config_file_src;
/* convert any tab to space, condense consecutive spaces into one,
remove leading and trailing spaces (exception: if there is nothing
but spaces, one of them will be kept even though it leads/trails) */
mungspaces(strcpy(buf, origbuf));
/* lines beginning with '#' are comments; accept empty lines too */
if (!*buf || *buf == '#' || !strcmp(buf, " "))
return 1;
/* find the '=' or ':' */
bufp = index(buf, '=');
altp = index(buf, ':');
if (!bufp || (altp && altp < bufp))
bufp = altp;
if (!bufp)
return 0;
bufp = find_optparam(buf);
if (!bufp) {
config_error_add("Not a config statement, missing '='");
return FALSE;
}
/* skip past '=', then space between it and value, if any */
++bufp;
if (*bufp == ' ')
@@ -2144,21 +2278,21 @@ int src;
/* hack: un-mungspaces to allow consecutive spaces in
general options until we verify that this is unnecessary;
'=' or ':' is guaranteed to be present */
bufp = index(origbuf, '=');
altp = index(origbuf, ':');
if (!bufp || (altp && altp < bufp))
bufp = altp;
bufp = find_optparam(origbuf);
++bufp; /* skip '='; parseoptions() handles spaces */
parseoptions(bufp, TRUE, TRUE);
if (!parseoptions(bufp, TRUE, TRUE))
retval = FALSE;
} else if (match_varname(buf, "AUTOPICKUP_EXCEPTION", 5)) {
add_autopickup_exception(bufp);
} else if (match_varname(buf, "BINDINGS", 4)) {
parsebindings(bufp);
if (!parsebindings(bufp))
retval = FALSE;
} else if (match_varname(buf, "AUTOCOMPLETE", 5)) {
parseautocomplete(bufp, TRUE);
} else if (match_varname(buf, "MSGTYPE", 7)) {
(void) msgtype_parse_add(bufp);
if (!msgtype_parse_add(bufp))
retval = FALSE;
#ifdef NOCWD_ASSUMPTIONS
} else if (match_varname(buf, "HACKDIR", 4)) {
adjust_prefix(bufp, HACKPREFIX);
@@ -2278,6 +2412,14 @@ int src;
if (sysopt.genericusers)
free((genericptr_t) sysopt.genericusers);
sysopt.genericusers = dupstr(bufp);
} else if (src == SET_IN_SYS && match_varname(buf, "BONES_POOLS", 10)) {
/* max value of 10 guarantees (N % bones.pools) will be one digit
so we don't lose control of the length of bones file names */
n = atoi(bufp);
sysopt.bones_pools = (n <= 0) ? 0 : min(n, 10);
/* note: right now bones_pools==0 is the same as bones_pools==1,
but we could change that and make bones_pools==0 become an
indicator to suppress bones usage altogether */
} else if (src == SET_IN_SYS && match_varname(buf, "SUPPORT", 7)) {
if (sysopt.support)
free((genericptr_t) sysopt.support);
@@ -2298,8 +2440,8 @@ int src;
n = !!atoi(bufp); /* XXX this could be tighter */
/* allow anyone to turn it off, but only sysconf to turn it on*/
if (src != SET_IN_SYS && n != 0) {
raw_printf("Illegal value in SEDUCE");
return 0;
config_error_add("Illegal value in SEDUCE");
return FALSE;
}
sysopt.seduce = n;
sysopt_seduce_set(sysopt.seduce);
@@ -2307,45 +2449,45 @@ int src;
n = atoi(bufp);
/* XXX to get more than 25, need to rewrite all lock code */
if (n < 0 || n > 25) {
raw_printf("Illegal value in MAXPLAYERS (maximum is 25).");
return 0;
config_error_add("Illegal value in MAXPLAYERS (maximum is 25).");
return FALSE;
}
sysopt.maxplayers = n;
} else if (src == SET_IN_SYS && match_varname(buf, "PERSMAX", 7)) {
n = atoi(bufp);
if (n < 1) {
raw_printf("Illegal value in PERSMAX (minimum is 1).");
return 0;
config_error_add("Illegal value in PERSMAX (minimum is 1).");
return FALSE;
}
sysopt.persmax = n;
} else if (src == SET_IN_SYS && match_varname(buf, "PERS_IS_UID", 11)) {
n = atoi(bufp);
if (n != 0 && n != 1) {
raw_printf("Illegal value in PERS_IS_UID (must be 0 or 1).");
return 0;
config_error_add("Illegal value in PERS_IS_UID (must be 0 or 1).");
return FALSE;
}
sysopt.pers_is_uid = n;
} else if (src == SET_IN_SYS && match_varname(buf, "ENTRYMAX", 8)) {
n = atoi(bufp);
if (n < 10) {
raw_printf("Illegal value in ENTRYMAX (minimum is 10).");
return 0;
config_error_add("Illegal value in ENTRYMAX (minimum is 10).");
return FALSE;
}
sysopt.entrymax = n;
} else if ((src == SET_IN_SYS) && match_varname(buf, "POINTSMIN", 9)) {
n = atoi(bufp);
if (n < 1) {
raw_printf("Illegal value in POINTSMIN (minimum is 1).");
return 0;
config_error_add("Illegal value in POINTSMIN (minimum is 1).");
return FALSE;
}
sysopt.pointsmin = n;
} else if (src == SET_IN_SYS
&& match_varname(buf, "MAX_STATUENAME_RANK", 10)) {
n = atoi(bufp);
if (n < 1) {
raw_printf(
config_error_add(
"Illegal value in MAX_STATUENAME_RANK (minimum is 1).");
return 0;
return FALSE;
}
sysopt.tt_oname_maxrank = n;
@@ -2355,8 +2497,8 @@ int src;
n = atoi(bufp);
#if defined(PANICTRACE) && defined(PANICTRACE_LIBC)
if (n < 0 || n > 2) {
raw_printf("Illegal value in PANICTRACE_LIBC (not 0,1,2).");
return 0;
config_error_add("Illegal value in PANICTRACE_LIBC (not 0,1,2).");
return FALSE;
}
#endif
sysopt.panictrace_libc = n;
@@ -2365,16 +2507,16 @@ int src;
n = atoi(bufp);
#if defined(PANICTRACE)
if (n < 0 || n > 2) {
raw_printf("Illegal value in PANICTRACE_GDB (not 0,1,2).");
return 0;
config_error_add("Illegal value in PANICTRACE_GDB (not 0,1,2).");
return FALSE;
}
#endif
sysopt.panictrace_gdb = n;
} else if (src == SET_IN_SYS && match_varname(buf, "GDBPATH", 7)) {
#if defined(PANICTRACE) && !defined(VMS)
if (!file_exists(bufp)) {
raw_printf("File specified in GDBPATH does not exist.");
return 0;
config_error_add("File specified in GDBPATH does not exist.");
return FALSE;
}
#endif
if (sysopt.gdbpath)
@@ -2383,8 +2525,8 @@ int src;
} else if (src == SET_IN_SYS && match_varname(buf, "GREPPATH", 7)) {
#if defined(PANICTRACE) && !defined(VMS)
if (!file_exists(bufp)) {
raw_printf("File specified in GREPPATH does not exist.");
return 0;
config_error_add("File specified in GREPPATH does not exist.");
return FALSE;
}
#endif
if (sysopt.greppath)
@@ -2393,45 +2535,20 @@ int src;
#endif /* SYSCF */
} else if (match_varname(buf, "BOULDER", 3)) {
(void) get_uchars(fp, buf, bufp, &iflags.bouldersym, TRUE, 1,
(void) get_uchars(bufp, &iflags.bouldersym, TRUE, 1,
"BOULDER");
} else if (match_varname(buf, "MENUCOLOR", 9)) {
(void) add_menu_coloring(bufp);
if (!add_menu_coloring(bufp))
retval = FALSE;
} else if (match_varname(buf, "WARNINGS", 5)) {
(void) get_uchars(fp, buf, bufp, translate, FALSE, WARNCOUNT,
(void) get_uchars(bufp, translate, FALSE, WARNCOUNT,
"WARNINGS");
assign_warnings(translate);
} else if (match_varname(buf, "SYMBOLS", 4)) {
char *op, symbuf[BUFSZ];
boolean morelines;
do {
/* check for line continuation (trailing '\') */
op = eos(bufp);
morelines = (--op >= bufp && *op == '\\');
if (morelines) {
*op = '\0';
/* strip trailing space now that '\' is gone */
if (--op >= bufp && *op == ' ')
*op = '\0';
}
/* parse here */
if (!parsesymbols(bufp)) {
raw_printf("Error in SYMBOLS definition '%s'.\n", bufp);
wait_synch();
}
if (morelines) {
do {
*symbuf = '\0';
if (!fgets(symbuf, BUFSZ, fp)) {
morelines = FALSE;
break;
}
mungspaces(symbuf);
bufp = symbuf;
} while (*bufp == '#');
}
} while (morelines);
if (!parsesymbols(bufp)) {
config_error_add("Error in SYMBOLS definition '%s'", bufp);
retval = FALSE;
}
switch_symbols(TRUE);
} else if (match_varname(buf, "WIZKIT", 6)) {
(void) strncpy(wizkit, bufp, WIZKIT_MAX - 1);
@@ -2574,9 +2691,11 @@ int src;
qt_compact_mode = atoi(bufp);
#endif
} else
return 0;
return 1;
} else {
config_error_add("Unknown config statement");
return FALSE;
}
return retval;
}
#ifdef USER_SOUNDS
@@ -2588,43 +2707,148 @@ const char *filename;
}
#endif /* USER_SOUNDS */
struct _config_error_frame {
int line_num;
int num_errors;
boolean origline_shown;
boolean fromfile;
boolean secure;
char origline[4 * BUFSZ];
char source[BUFSZ];
struct _config_error_frame *next;
};
struct _config_error_frame *config_error_data = (struct _config_error_frame *)0;
void
config_error_init(from_file, sourcename, secure)
boolean from_file;
const char *sourcename;
boolean secure;
{
struct _config_error_frame *tmp = (struct _config_error_frame *)
alloc(sizeof(struct _config_error_frame));
tmp->line_num = 0;
tmp->num_errors = 0;
tmp->origline_shown = FALSE;
tmp->fromfile = from_file;
tmp->secure = secure;
tmp->origline[0] = '\0';
if (sourcename && sourcename[0]) {
(void) strncpy(tmp->source, sourcename, sizeof(tmp->source)-1);
tmp->source[sizeof(tmp->source)-1] = '\0';
} else
tmp->source[0] = '\0';
tmp->next = config_error_data;
config_error_data = tmp;
}
STATIC_OVL boolean
config_error_nextline(line)
const char *line;
{
struct _config_error_frame *ced = config_error_data;
if (!ced)
return FALSE;
if (ced->num_errors && ced->secure)
return FALSE;
ced->line_num++;
ced->origline_shown = FALSE;
if (line && line[0]) {
(void) strncpy(ced->origline, line, sizeof(ced->origline)-1);
ced->origline[sizeof(ced->origline)-1] = '\0';
} else
ced->origline[0] = '\0';
return TRUE;
}
/*VARARGS1*/
void config_error_add
VA_DECL(const char *, str)
{
char buf[BUFSZ];
char lineno[QBUFSZ];
VA_START(str);
VA_INIT(str, char *);
Vsprintf(buf, str, VA_ARGS);
if (!config_error_data) {
pline("%s.", *buf ? buf : "Unknown error");
wait_synch();
return;
}
config_error_data->num_errors++;
if (!config_error_data->origline_shown
&& !config_error_data->secure) {
pline("\n%s", config_error_data->origline);
config_error_data->origline_shown = TRUE;
}
if (config_error_data->line_num > 0
&& !config_error_data->secure) {
Sprintf(lineno, "Line %i: ", config_error_data->line_num);
} else
lineno[0] = '\0';
pline("%s %s%s.",
config_error_data->secure ? "Error:" : " *",
lineno,
*buf ? buf : "Unknown error");
VA_END();
}
int
config_error_done()
{
int n;
struct _config_error_frame *tmp = config_error_data;
if (!config_error_data)
return 0;
n = config_error_data->num_errors;
if (n) {
pline("\n%i error%s in %s.\n", n,
(n > 1) ? "s" : "",
*config_error_data->source
? config_error_data->source : configfile);
wait_synch();
}
config_error_data = tmp->next;
free(tmp);
return n;
}
boolean
read_config_file(filename, src)
const char *filename;
int src;
{
char buf[4 * BUFSZ];
FILE *fp;
boolean rv = TRUE; /* assume successful parse */
boolean rv = TRUE;
if (!(fp = fopen_config_file(filename, src)))
return FALSE;
/* begin detection of duplicate configfile options */
set_duplicate_opt_detection(1);
free_config_sections();
iflags.parse_config_file_src = src;
while (fgets(buf, sizeof buf, fp)) {
#ifdef notyet
/*
XXX Don't call read() in parse_config_line, read as callback or reassemble
line at this level.
OR: Forbid multiline stuff for alternate config sources.
*/
#endif
if (!parse_config_line(fp, strip_newline(buf), src)) {
static const char badoptionline[] = "Bad option line: \"%s\"";
/* truncate buffer if it's long; this is actually conservative */
if (strlen(buf) > BUFSZ - sizeof badoptionline)
buf[BUFSZ - sizeof badoptionline] = '\0';
raw_printf(badoptionline, buf);
wait_synch();
rv = FALSE;
}
}
rv = parse_conf_file(fp, parse_config_line);
(void) fclose(fp);
free_config_sections();
/* turn off detection of duplicate configfile options */
set_duplicate_opt_detection(0);
return rv;
@@ -2728,47 +2952,171 @@ struct obj *obj;
}
}
boolean
proc_wizkit_line(buf)
char *buf;
{
struct obj *otmp = readobjnam(buf, (struct obj *) 0);
if (otmp) {
if (otmp != &zeroobj)
wizkit_addinv(otmp);
} else {
/* .60 limits output line width to 79 chars */
config_error_add("Bad wizkit item: \"%.60s\"", buf);
return FALSE;
}
return TRUE;
}
void
read_wizkit()
{
FILE *fp;
char *ep, buf[BUFSZ];
struct obj *otmp;
boolean bad_items = FALSE, skip = FALSE;
if (!wizard || !(fp = fopen_wizkit_file()))
return;
program_state.wizkit_wishing = 1;
while (fgets(buf, (int) (sizeof buf), fp)) {
ep = index(buf, '\n');
config_error_init(TRUE, "WIZKIT", FALSE);
parse_conf_file(fp, proc_wizkit_line);
(void) fclose(fp);
config_error_done();
program_state.wizkit_wishing = 0;
return;
}
/* parse_conf_file
*
* Read from file fp, handling comments, empty lines, config sections,
* CHOOSE, and line continuation, calling proc for every valid line.
*
* Continued lines are merged together with one space in between.
*/
STATIC_OVL boolean
parse_conf_file(fp, proc)
FILE *fp;
boolean FDECL((*proc), (char *));
{
char inbuf[4 * BUFSZ];
boolean rv = TRUE; /* assume successful parse */
char *ep;
boolean skip = FALSE, morelines = FALSE;
char *buf = (char *) 0;
free_config_sections();
while (fgets(inbuf, (int) (sizeof inbuf), fp)) {
ep = index(inbuf, '\n');
if (skip) { /* in case previous line was too long */
if (ep)
skip = FALSE; /* found newline; next line is normal */
} else {
if (!ep)
if (!ep) {
config_error_add("Line too long, skipping");
skip = TRUE; /* newline missing; discard next fgets */
else
} else {
char *tmpbuf = (char *) 0;
int len;
boolean ignoreline = FALSE;
boolean oldline = FALSE;
*ep = '\0'; /* remove newline */
if (buf[0]) {
otmp = readobjnam(buf, (struct obj *) 0);
if (otmp) {
if (otmp != &zeroobj)
wizkit_addinv(otmp);
} else {
/* .60 limits output line width to 79 chars */
raw_printf("Bad wizkit item: \"%.60s\"", buf);
bad_items = TRUE;
/* line continuation (trailing '\') */
morelines = (--ep >= inbuf && *ep == '\\');
if (morelines)
*ep = '\0';
/* trim off spaces at end of line */
while (--ep >= inbuf && (*ep == ' ' || *ep == '\t' || *ep == '\r'))
*ep = '\0';
if (!config_error_nextline(inbuf)) {
rv = FALSE;
if (buf)
free(buf), buf = (char *) 0;
break;
}
ep = inbuf;
while (*ep == ' ' || *ep == '\t') ep++;
/* lines beginning with '#' are comments. ignore empty lines. */
if (!*ep || *ep == '#')
ignoreline = TRUE;
if (buf)
oldline = TRUE;
/* merge now read line with previous ones, if necessary */
if (!ignoreline) {
len = strlen(inbuf) + 1;
if (buf)
len += strlen(buf);
tmpbuf = (char *) alloc(len);
if (buf) {
Sprintf(tmpbuf, "%s %s", buf, inbuf);
free(buf);
} else
Strcpy(tmpbuf, inbuf);
buf = tmpbuf;
}
if (morelines || (ignoreline && !oldline))
continue;
if (handle_config_section(ep)) {
free(buf);
buf = (char *) 0;
continue;
}
/* from here onwards, we'll handle buf only */
if (match_varname(buf, "CHOOSE", 6)) {
char *section;
char *bufp = find_optparam(buf);
if (!bufp) {
config_error_add("Format is CHOOSE=section1,section2,...");
rv = FALSE;
free(buf);
buf = (char *) 0;
continue;
}
bufp++;
if (config_section_chosen)
free(config_section_chosen);
section = choose_random_part(bufp, ',');
if (section)
config_section_chosen = dupstr(section);
else {
config_error_add("No config section to choose");
rv = FALSE;
}
free(buf);
buf = (char *) 0;
continue;
}
if (!proc(buf))
rv = FALSE;
free(buf);
buf = (char *) 0;
}
}
}
program_state.wizkit_wishing = 0;
if (bad_items)
wait_synch();
(void) fclose(fp);
return;
if (buf)
free(buf);
free_config_sections();
return rv;
}
extern struct symsetentry *symset_list; /* options.c */
@@ -2777,6 +3125,7 @@ extern const char *known_handling[]; /* drawing.c */
extern const char *known_restrictions[]; /* drawing.c */
static int symset_count = 0; /* for pick-list building only */
static boolean chosen_symset_start = FALSE, chosen_symset_end = FALSE;
static int symset_which_set = 0;
STATIC_OVL
FILE *
@@ -2796,7 +3145,6 @@ int
read_sym_file(which_set)
int which_set;
{
char buf[4 * BUFSZ];
FILE *fp;
if (!(fp = fopen_sym_file()))
@@ -2804,13 +3152,13 @@ int which_set;
symset_count = 0;
chosen_symset_start = chosen_symset_end = FALSE;
while (fgets(buf, 4 * BUFSZ, fp)) {
if (!parse_sym_line(buf, which_set)) {
raw_printf("Bad symbol line: \"%.50s\"", buf);
wait_synch();
}
}
symset_which_set = which_set;
config_error_init(TRUE, "symbols", FALSE);
parse_conf_file(fp, proc_symset_line);
(void) fclose(fp);
if (!chosen_symset_start && !chosen_symset_end) {
/* name caller put in symset[which_set].name was not found;
if it looks like "Default symbols", null it out and return
@@ -2820,17 +3168,26 @@ int which_set;
" -_", TRUE)
|| !strcmpi(symset[which_set].name, "default")))
clear_symsetentry(which_set, TRUE);
config_error_done();
return (symset[which_set].name == 0) ? 1 : 0;
}
if (!chosen_symset_end) {
raw_printf("Missing finish for symset \"%s\"",
if (!chosen_symset_end)
config_error_add("Missing finish for symset \"%s\"",
symset[which_set].name ? symset[which_set].name
: "unknown");
wait_synch();
}
config_error_done();
return 1;
}
boolean
proc_symset_line(buf)
char *buf;
{
return !((boolean) parse_sym_line(buf, symset_which_set));
}
/* returns 0 on error */
int
parse_sym_line(buf, which_set)
@@ -2844,8 +3201,7 @@ int which_set;
/* convert each instance of whitespace (tabs, consecutive spaces)
into a single space; leading and trailing spaces are stripped */
mungspaces(buf);
if (!*buf || *buf == '#' || !strcmp(buf, " "))
return 1;
/* remove trailing comment, if any (this isn't strictly needed for
individual symbols, and it won't matter if "X#comment" without
separating space slips through; for handling or set description,
@@ -2867,6 +3223,7 @@ int which_set;
chosen_symset_start = FALSE;
return 1;
}
config_error_add("No \"finish\"");
return 0;
}
/* skip '=' and space which follows, if any */
@@ -2875,8 +3232,10 @@ int which_set;
++bufp;
symp = match_sym(buf);
if (!symp)
if (!symp) {
config_error_add("Unknown sym keyword");
return 0;
}
if (!symset[which_set].name) {
/* A null symset name indicates that we're just
@@ -3111,7 +3470,7 @@ const char *dir UNUSED_if_not_OS2_CODEVIEW;
#else
fd = open(fq_record, O_CREAT | O_RDWR, S_IREAD | S_IWRITE);
#endif
if (fd = < 0) {
if (fd <= 0) {
raw_printf("Warning: cannot write record '%s'", tmp);
wait_synch();
} else {
+6 -5
View File
@@ -442,7 +442,7 @@ xchar x, y;
} else if (IS_WALL(lev->typ)) {
if (*in_rooms(x, y, SHOPBASE)) {
add_damage(x, y, 10L * ACURRSTR);
add_damage(x, y, SHOP_WALL_DMG);
dmgtxt = "damage";
}
digtxt = "chew a hole in the wall.";
@@ -472,7 +472,7 @@ xchar x, y;
} else if (IS_DOOR(lev->typ)) {
if (*in_rooms(x, y, SHOPBASE)) {
add_damage(x, y, 400L);
add_damage(x, y, SHOP_DOOR_COST);
dmgtxt = "break";
}
if (lev->doormask & D_TRAPPED) {
@@ -722,9 +722,10 @@ int mode;
&& In_sokoban(&u.uz))
pline_The("Sokoban walls resist your ability.");
else if (iflags.mention_walls)
pline("It's %s.", IS_WALL(tmpr->typ) ? "a wall"
: IS_TREE(tmpr->typ) ? "a tree"
: "solid stone");
pline("It's %s.",
(IS_WALL(tmpr->typ) || tmpr->typ == SDOOR) ? "a wall"
: IS_TREE(tmpr->typ) ? "a tree"
: "solid stone");
}
return FALSE;
}
+40 -12
View File
@@ -23,7 +23,7 @@ STATIC_PTR int FDECL(ckvalidcat, (struct obj *));
STATIC_PTR char *FDECL(safeq_xprname, (struct obj *));
STATIC_PTR char *FDECL(safeq_shortxprname, (struct obj *));
STATIC_DCL char FDECL(display_pickinv, (const char *, const char *,
BOOLEAN_P, long *));
const char *, BOOLEAN_P, long *));
STATIC_DCL char FDECL(display_used_invlets, (CHAR_P));
STATIC_DCL boolean FDECL(this_type_only, (struct obj *));
STATIC_DCL void NDECL(dounpaid);
@@ -1080,6 +1080,8 @@ register const char *let, *word;
xchar foox = 0;
long cnt;
boolean cntgiven = FALSE;
boolean msggiven = FALSE;
boolean oneloop = FALSE;
long dummymask;
if (*let == ALLOW_COUNT)
@@ -1288,15 +1290,24 @@ register const char *let, *word;
for (;;) {
cnt = 0;
cntgiven = FALSE;
if (!buf[0]) {
Sprintf(qbuf, "What do you want to %s? [*]", word);
} else {
Sprintf(qbuf, "What do you want to %s? [%s or ?*]", word, buf);
}
Sprintf(qbuf, "What do you want to %s?", word);
if (in_doagain)
ilet = readchar();
else
else if (iflags.force_invmenu) {
/* don't overwrite a possible quitchars */
if (!oneloop)
ilet = *let ? '?' : '*';
if (!msggiven)
putmsghistory(qbuf, FALSE);
msggiven = TRUE;
oneloop = TRUE;
} else {
if (!buf[0])
Strcat(qbuf, " [*]");
else
Sprintf(eos(qbuf), " [%s or ?*]", buf);
ilet = yn_function(qbuf, (char *) 0, '\0');
}
if (digit(ilet)) {
long tmpcnt = 0;
@@ -1335,13 +1346,17 @@ register const char *let, *word;
}
return (allownone ? &zeroobj : (struct obj *) 0);
}
redo_menu:
/* since gold is now kept in inventory, we need to do processing for
select-from-invent before checking whether gold has been picked */
if (ilet == '?' || ilet == '*') {
char *allowed_choices = (ilet == '?') ? lets : (char *) 0;
long ctmp = 0;
char menuquery[QBUFSZ];
qbuf[0] = '\0';
menuquery[0] = qbuf[0] = '\0';
if (iflags.force_invmenu)
Sprintf(menuquery, "What do you want to %s?", word);
if (!strcmp(word, "grease"))
Sprintf(qbuf, "your %s", makeplural(body_part(FINGER)));
else if (!strcmp(word, "write with"))
@@ -1357,6 +1372,7 @@ register const char *let, *word;
if (ilet == '?' && !*lets && *altlets)
allowed_choices = altlets;
ilet = display_pickinv(allowed_choices, *qbuf ? qbuf : (char *) 0,
menuquery,
TRUE, allowcnt ? &ctmp : (long *) 0);
if (!ilet)
continue;
@@ -1367,6 +1383,8 @@ register const char *let, *word;
pline1(Never_mind);
return (struct obj *) 0;
}
if (ilet == '*')
goto redo_menu;
if (allowcnt && ctmp >= 0) {
cnt = ctmp;
cntgiven = TRUE;
@@ -2144,9 +2162,10 @@ free_pickinv_cache()
* any count returned from the menu selection is placed here.
*/
STATIC_OVL char
display_pickinv(lets, xtra_choice, want_reply, out_cnt)
display_pickinv(lets, xtra_choice, query, want_reply, out_cnt)
register const char *lets;
const char *xtra_choice; /* "fingers", pick hands rather than an object */
const char *query;
boolean want_reply;
long *out_cnt;
{
@@ -2204,7 +2223,7 @@ long *out_cnt;
if (!flags.invlet_constant)
reassign();
if (n == 1) {
if (n == 1 && !iflags.force_invmenu) {
/* when only one item of interest, use pline instead of menus;
we actually use a fake message-line menu in order to allow
the user to perform selection at the --More-- prompt for tty */
@@ -2284,7 +2303,15 @@ nextclass:
goto nextclass;
}
}
end_menu(win, (char *) 0);
if (iflags.force_invmenu && lets && want_reply) {
any = zeroany;
add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, "Special", MENU_UNSELECTED);
any.a_char = '*';
add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "(list everything)", MENU_UNSELECTED);
}
end_menu(win, query && *query ? query : (char *) 0);
n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected);
if (n > 0) {
@@ -2310,7 +2337,8 @@ display_inventory(lets, want_reply)
const char *lets;
boolean want_reply;
{
return display_pickinv(lets, (char *) 0, want_reply, (long *) 0);
return display_pickinv(lets, (char *) 0, (char *) 0,
want_reply, (long *) 0);
}
/*
+2 -2
View File
@@ -112,7 +112,7 @@ picklock(VOID_ARGS)
xlock.door->doormask = D_NODOOR;
unblock_point(u.ux + u.dx, u.uy + u.dy);
if (*in_rooms(u.ux + u.dx, u.uy + u.dy, SHOPBASE))
add_damage(u.ux + u.dx, u.uy + u.dy, 0L);
add_damage(u.ux + u.dx, u.uy + u.dy, SHOP_DOOR_COST);
newsym(u.ux + u.dx, u.uy + u.dy);
} else if (xlock.door->doormask & D_LOCKED)
xlock.door->doormask = D_CLOSED;
@@ -659,7 +659,7 @@ int x, y;
b_trapped("door", FINGER);
door->doormask = D_NODOOR;
if (*in_rooms(cc.x, cc.y, SHOPBASE))
add_damage(cc.x, cc.y, 0L);
add_damage(cc.x, cc.y, SHOP_DOOR_COST);
} else
door->doormask = D_ISOPEN;
feel_newsym(cc.x, cc.y); /* the hero knows she opened it */
+1 -1
View File
@@ -641,7 +641,7 @@ struct obj *otmp UNUSED;
if (child(1)) {
(void) execl(mr, mr, (char *) 0);
terminate(EXIT_FAILURE);
nh_terminate(EXIT_FAILURE);
}
#else
#ifndef AMS /* AMS mailboxes are directories */
+4 -2
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 mhitm.c $NHDT-Date: 1496860757 2017/06/07 18:39:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.97 $ */
/* NetHack 3.6 mhitm.c $NHDT-Date: 1504999944 2017/09/09 23:32:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.98 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1273,6 +1273,7 @@ register struct attack *mattk;
| (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
if (pa->mlet == S_NYMPH && !tele_restrict(magr)) {
boolean couldspot = canspotmon(magr);
(void) rloc(magr, TRUE);
if (vis && couldspot && !canspotmon(magr))
pline("%s suddenly disappears!", buf);
@@ -1282,7 +1283,8 @@ register struct attack *mattk;
break;
case AD_DREN:
if (!cancelled && !rn2(4))
xdrainenergym(mdef, vis && canspotmon(mdef) && mattk->aatyp != AT_ENGL);
xdrainenergym(mdef, (boolean) (vis && canspotmon(mdef)
&& mattk->aatyp != AT_ENGL));
tmp = 0;
break;
case AD_DRST:
+60 -44
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 mhitu.c $NHDT-Date: 1496619132 2017/06/04 23:32:12 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.146 $ */
/* NetHack 3.6 mhitu.c $NHDT-Date: 1505001092 2017/09/09 23:51:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.147 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -26,8 +26,8 @@ static int dieroll;
STATIC_OVL void
hitmsg(mtmp, mattk)
register struct monst *mtmp;
register struct attack *mattk;
struct monst *mtmp;
struct attack *mattk;
{
int compat;
const char *pfmt = 0;
@@ -139,8 +139,8 @@ u_slow_down()
/* monster attacked your displaced image */
STATIC_OVL void
wildmiss(mtmp, mattk)
register struct monst *mtmp;
register struct attack *mattk;
struct monst *mtmp;
struct attack *mattk;
{
int compat;
const char *Monst_name; /* Monnam(mtmp) */
@@ -225,17 +225,14 @@ boolean message;
You("get regurgitated!");
} else {
char blast[40];
register int i;
struct attack *attk = attacktype_fordmg(mdat, AT_ENGL, AD_ANY);
blast[0] = '\0';
for (i = 0; i < NATTK; i++)
if (mdat->mattk[i].aatyp == AT_ENGL)
break;
if (mdat->mattk[i].aatyp != AT_ENGL) {
if (!attk) {
impossible("Swallower has no engulfing attack?");
} else {
if (is_whirly(mdat)) {
switch (mdat->mattk[i].adtyp) {
switch (attk->adtyp) {
case AD_ELEC:
Strcpy(blast, " in a shower of sparks");
break;
@@ -243,8 +240,9 @@ boolean message;
Strcpy(blast, " in a blast of frost");
break;
}
} else
} else {
Strcpy(blast, " with a squelch");
}
You("get expelled from %s%s!", mon_nam(mtmp), blast);
}
}
@@ -907,8 +905,8 @@ hitmu(mtmp, mattk)
register struct monst *mtmp;
register struct attack *mattk;
{
register struct permonst *mdat = mtmp->data;
register int uncancelled, ptmp;
struct permonst *mdat = mtmp->data;
int uncancelled, ptmp;
int dmg, armpro, permdmg;
char buf[BUFSZ];
struct permonst *olduasmon = youmonst.data;
@@ -972,6 +970,7 @@ register struct attack *mattk;
}
} else { /* hand to hand weapon */
struct obj *otmp = mon_currwep;
if (mattk->aatyp == AT_WEAP && otmp) {
int tmp;
@@ -1177,7 +1176,7 @@ register struct attack *mattk;
}
break;
case AD_LEGS: {
register long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
const char *sidestr = (side == RIGHT_SIDE) ? "right" : "left",
*Monst_name = Monnam(mtmp), *leg = body_part(LEG);
@@ -1718,13 +1717,13 @@ gulp_blnd_check()
/* monster swallows you, or damage if u.uswallow */
STATIC_OVL int
gulpmu(mtmp, mattk)
register struct monst *mtmp;
register struct attack *mattk;
struct monst *mtmp;
struct attack *mattk;
{
struct trap *t = t_at(u.ux, u.uy);
int tmp = d((int) mattk->damn, (int) mattk->damd);
int tim_tmp;
register struct obj *otmp2;
struct obj *otmp2;
int i;
boolean physical_damage = FALSE;
@@ -1769,6 +1768,7 @@ register struct attack *mattk;
i = number_leashed();
if (i > 0) {
const char *s = (i > 1) ? "leashes" : "leash";
pline_The("%s %s loose.", s, vtense(s, "snap"));
unleash_all();
}
@@ -1961,8 +1961,8 @@ register struct attack *mattk;
/* monster explodes in your face */
STATIC_OVL int
explmu(mtmp, mattk, ufound)
register struct monst *mtmp;
register struct attack *mattk;
struct monst *mtmp;
struct attack *mattk;
boolean ufound;
{
boolean physical_damage = TRUE, kill_agr = TRUE;
@@ -1976,8 +1976,8 @@ boolean ufound;
levl[mtmp->mux][mtmp->muy].typ == WATER ? "empty water"
: "thin air");
else {
register int tmp = d((int) mattk->damn, (int) mattk->damd);
register boolean not_affected = defends((int) mattk->adtyp, uwep);
int tmp = d((int) mattk->damn, (int) mattk->damd);
boolean not_affected = defends((int) mattk->adtyp, uwep);
hitmsg(mtmp, mattk);
@@ -2059,8 +2059,8 @@ boolean ufound;
/* monster gazes at you */
int
gazemu(mtmp, mattk)
register struct monst *mtmp;
register struct attack *mattk;
struct monst *mtmp;
struct attack *mattk;
{
static const char *const reactions[] = {
"confused", /* [0] */
@@ -2275,8 +2275,8 @@ register struct attack *mattk;
/* mtmp hits you for n points damage */
void
mdamageu(mtmp, n)
register struct monst *mtmp;
register int n;
struct monst *mtmp;
int n;
{
context.botl = 1;
if (Upolyd) {
@@ -2299,7 +2299,7 @@ could_seduce(magr, mdef, mattk)
struct monst *magr, *mdef;
struct attack *mattk;
{
register struct permonst *pagr;
struct permonst *pagr;
boolean agrinvis, defperc;
xchar genagr, gendef;
@@ -2340,9 +2340,9 @@ struct attack *mattk;
/* Returns 1 if monster teleported */
int
doseduce(mon)
register struct monst *mon;
struct monst *mon;
{
register struct obj *ring, *nring;
struct obj *ring, *nring;
boolean fem = (mon->data == &mons[PM_SUCCUBUS]); /* otherwise incubus */
int attr_tot, tried_gloves = 0;
char qbuf[QBUFSZ];
@@ -2613,7 +2613,7 @@ register struct monst *mon;
STATIC_OVL void
mayberem(obj, str)
register struct obj *obj;
struct obj *obj;
const char *str;
{
char qbuf[QBUFSZ];
@@ -2648,34 +2648,50 @@ const char *str;
remove_worn_item(obj, TRUE);
}
/* FIXME:
* sequencing issue: a monster's attack might cause poly'd hero
* to revert to normal form. The messages for passive counterattack
* would look better if they came before reverting form, but we need
* to know whether hero reverted in order to decide whether passive
* damage applies.
*/
STATIC_OVL int
passiveum(olduasmon, mtmp, mattk)
struct permonst *olduasmon;
register struct monst *mtmp;
register struct attack *mattk;
struct monst *mtmp;
struct attack *mattk;
{
int i, tmp;
struct attack *oldu_mattk = 0;
for (i = 0;; i++) {
/*
* mattk == mtmp's attack that hit you;
* oldu_mattk == your passive counterattack (even if mtmp's attack
* has already caused you to revert to normal form).
*/
for (i = 0; !oldu_mattk; i++) {
if (i >= NATTK)
return 1;
if (olduasmon->mattk[i].aatyp == AT_NONE
|| olduasmon->mattk[i].aatyp == AT_BOOM)
break;
oldu_mattk = &olduasmon->mattk[i];
}
if (olduasmon->mattk[i].damn)
tmp =
d((int) olduasmon->mattk[i].damn, (int) olduasmon->mattk[i].damd);
else if (olduasmon->mattk[i].damd)
tmp = d((int) olduasmon->mlevel + 1, (int) olduasmon->mattk[i].damd);
if (oldu_mattk->damn)
tmp = d((int) oldu_mattk->damn, (int) oldu_mattk->damd);
else if (oldu_mattk->damd)
tmp = d((int) olduasmon->mlevel + 1, (int) oldu_mattk->damd);
else
tmp = 0;
/* These affect the enemy even if you were "killed" (rehumanized) */
switch (olduasmon->mattk[i].adtyp) {
switch (oldu_mattk->adtyp) {
case AD_ACID:
if (!rn2(2)) {
pline("%s is splashed by your %s!", Monnam(mtmp), hliquid("acid"));
pline("%s is splashed by %s%s!", Monnam(mtmp),
/* temporary? hack for sequencing issue: "your acid"
looks strange coming immediately after player has
been told that hero has reverted to normal form */
!Upolyd ? "" : "your ", hliquid("acid"));
if (resists_acid(mtmp)) {
pline("%s is not affected.", Monnam(mtmp));
tmp = 0;
@@ -2729,9 +2745,9 @@ register struct attack *mattk;
/* These affect the enemy only if you are still a monster */
if (rn2(3))
switch (youmonst.data->mattk[i].adtyp) {
switch (oldu_mattk->adtyp) {
case AD_PHYS:
if (youmonst.data->mattk[i].aatyp == AT_BOOM) {
if (oldu_mattk->aatyp == AT_BOOM) {
You("explode!");
/* KMH, balance patch -- this is okay with unchanging */
rehumanize();
@@ -2828,7 +2844,7 @@ assess_dmg:
struct monst *
cloneu()
{
register struct monst *mon;
struct monst *mon;
int mndx = monsndx(youmonst.data);
if (u.mh <= 1)
+35 -13
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 mon.c $NHDT-Date: 1502753408 2017/08/14 23:30:08 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.242 $ */
/* NetHack 3.6 mon.c $NHDT-Date: 1505266804 2017/09/13 01:40:04 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.244 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1994,6 +1994,8 @@ boolean was_swallowed; /* digestion */
Sprintf(killer.name, "%s explosion", s_suffix(mdat->mname));
killer.format = KILLED_BY_AN;
explode(mon->mx, mon->my, -1, tmp, MON_EXPLODE, EXPL_NOXIOUS);
killer.name[0] = '\0';
killer.format = 0;
return FALSE;
}
}
@@ -3034,9 +3036,9 @@ decide_to_shapeshift(mon, shiftflags)
struct monst *mon;
int shiftflags;
{
struct permonst *ptr;
unsigned was_female = mon->female;
boolean msg = FALSE;
struct permonst *ptr = 0;
unsigned mndx, was_female = mon->female;
boolean msg = FALSE, dochng = FALSE;
if ((shiftflags & SHIFT_MSG)
|| ((shiftflags & SHIFT_SEENMSG) && sensemon(mon)))
@@ -3045,28 +3047,48 @@ int shiftflags;
if (!is_vampshifter(mon)) {
/* regular shapeshifter */
if (!rn2(6))
(void) newcham(mon, (struct permonst *) 0, FALSE, msg);
dochng = TRUE;
} else {
/* The vampire has to be in good health (mhp) to maintain
* its shifted form.
*
* If we're shifted and getting low on hp, maybe shift back.
* If we're shifted and getting low on hp, maybe shift back, or
* if we're a fog cloud at full hp, maybe pick a different shape.
* If we're not already shifted and in good health, maybe shift.
*/
if (mon->data->mlet != S_VAMPIRE) {
if ((mon->mhp <= (mon->mhpmax + 5) / 6) && rn2(4)
&& mon->cham >= LOW_PM)
(void) newcham(mon, &mons[mon->cham], FALSE, msg);
&& mon->cham >= LOW_PM) {
ptr = &mons[mon->cham];
dochng = TRUE;
} else if (mon->data == &mons[PM_FOG_CLOUD]
&& mon->mhp == mon->mhpmax && !rn2(4)
&& (!canseemon(mon)
|| distu(mon->mx, mon->my) > BOLT_LIM * BOLT_LIM)) {
/* if a fog cloud, maybe change to wolf or vampire bat;
those are more likely to take damage--at least when
tame--and then switch back to vampire; they'll also
switch to fog cloud if they encounter a closed door */
mndx = pickvampshape(mon);
if (mndx >= LOW_PM) {
ptr = &mons[mndx];
dochng = (ptr != mon->data);
}
}
} else {
if (mon->mhp >= 9 * mon->mhpmax / 10 && !rn2(6)
&& (!canseemon(mon)
|| distu(mon->mx, mon->my) > BOLT_LIM * BOLT_LIM))
(void) newcham(mon, (struct permonst *) 0, FALSE, msg);
dochng = TRUE; /* 'ptr' stays Null */
}
}
if (dochng) {
if (newcham(mon, ptr, FALSE, msg) && is_vampshifter(mon)) {
/* for vampshift, override the 10% chance for sex change */
ptr = mon->data;
if (!is_male(ptr) && !is_female(ptr) && !is_neuter(ptr))
mon->female = was_female;
}
/* override the 10% chance for sex change */
ptr = mon->data;
if (!is_male(ptr) && !is_female(ptr) && !is_neuter(ptr))
mon->female = was_female;
}
}
+10 -9
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 monmove.c $NHDT-Date: 1496534703 2017/06/04 00:05:03 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.91 $ */
/* NetHack 3.6 monmove.c $NHDT-Date: 1505265968 2017/09/13 01:26:08 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.93 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -134,8 +134,6 @@ onscary(x, y, mtmp)
int x, y;
struct monst *mtmp;
{
boolean epresent = sengr_at("Elbereth", x, y, TRUE);
/* creatures who are directly resistant to magical scaring:
* Rodney, lawful minions, angels, the Riders */
if (mtmp->iswiz || is_lminion(mtmp) || mtmp->data == &mons[PM_ANGEL]
@@ -152,16 +150,18 @@ struct monst *mtmp;
if (sobj_at(SCR_SCARE_MONSTER, x, y))
return TRUE;
/* creatures who don't (or can't) fear a written Elbereth:
/*
* Creatures who don't (or can't) fear a written Elbereth:
* all the above plus shopkeepers, guards, blind or
* peaceful monsters, humans, and minotaurs.
*
* if the player isn't actually on the square OR the player's image
* isn't displaced to the square, no protection is being granted
* If the player isn't actually on the square OR the player's image
* isn't displaced to the square, no protection is being granted.
*
* Elbereth doesn't work in Gehennom, the Elemental Planes, or the
* Astral Plane; the influence of the Valar only reaches so far. */
return (epresent
* Astral Plane; the influence of the Valar only reaches so far.
*/
return (sengr_at("Elbereth", x, y, TRUE)
&& ((u.ux == x && u.uy == y)
|| (Displaced && mtmp->mux == x && mtmp->muy == y))
&& !(mtmp->isshk || mtmp->isgd || !mtmp->mcansee
@@ -752,6 +752,7 @@ register int after;
boolean uses_items = 0, setlikes = 0;
boolean avoid = FALSE;
boolean better_with_displacing = FALSE;
boolean sawmon = canspotmon(mtmp); /* before it moved */
struct permonst *ptr;
struct monst *mtoo;
schar mmoved = 0; /* not strictly nec.: chi >= 0 will do */
@@ -1249,7 +1250,7 @@ postmov:
&& (amorphous(ptr)
|| (can_fog(mtmp)
&& vamp_shift(mtmp, &mons[PM_FOG_CLOUD],
canspotmon(mtmp))))) {
sawmon)))) {
/* update cached value for vamp_shift() case */
ptr = mtmp->data;
if (flags.verbose && canseemon(mtmp))
+7 -3
View File
@@ -39,6 +39,9 @@ void NDECL(monst_init);
* resistances, resistances conferred (both MR_* defines),
* 3 * flag bitmaps (M1_*, M2_*, and M3_* defines respectively)
* symbol color (C(x) macro)
*
* For AT_BREA attacks, '# sides' is ignored; 6 is used for most
* damage types, 25 for sleep, not applicable for death or poison.
*/
#define MON(nam, sym, lvl, gen, atk, siz, mr1, mr2, flg1, flg2, flg3, col) \
{ \
@@ -253,7 +256,7 @@ NEARDATA struct permonst mons[] = {
M2_NOPOLY | M2_WERE | M2_HOSTILE, M3_INFRAVISIBLE, CLR_BROWN),
MON("winter wolf cub", S_DOG, LVL(5, 12, 4, 0, -5),
(G_NOHELL | G_GENO | G_SGROUP | 2),
A(ATTK(AT_BITE, AD_PHYS, 1, 8), ATTK(AT_BREA, AD_COLD, 1, 8), NO_ATTK,
A(ATTK(AT_BITE, AD_PHYS, 1, 8), ATTK(AT_BREA, AD_COLD, 1, 6), NO_ATTK,
NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(250, 200, MS_BARK, MZ_SMALL), MR_COLD, MR_COLD,
M1_ANIMAL | M1_NOHANDS | M1_CARNIVORE, M2_HOSTILE, 0, CLR_CYAN),
@@ -1211,8 +1214,9 @@ NEARDATA struct permonst mons[] = {
| M1_CARNIVORE,
M2_HOSTILE | M2_STRONG | M2_NASTY | M2_GREEDY | M2_JEWELS | M2_MAGIC,
0, CLR_ORANGE),
/* disintegration breath is actually all or nothing, not 1d255 */
MON("black dragon", S_DRAGON, LVL(15, 9, -1, 20, -6), (G_GENO | 1),
A(ATTK(AT_BREA, AD_DISN, 4, 10), ATTK(AT_BITE, AD_PHYS, 3, 8),
A(ATTK(AT_BREA, AD_DISN, 1, 255), ATTK(AT_BITE, AD_PHYS, 3, 8),
ATTK(AT_CLAW, AD_PHYS, 1, 4), ATTK(AT_CLAW, AD_PHYS, 1, 4), NO_ATTK,
NO_ATTK),
SIZ(WT_DRAGON, 1500, MS_ROAR, MZ_GIGANTIC), MR_DISINT, MR_DISINT,
@@ -2996,7 +3000,7 @@ struct permonst _mons2[] = {
*/
MON("Chromatic Dragon", S_DRAGON, LVL(16, 12, 0, 30, -14),
(G_NOGEN | G_UNIQ),
A(ATTK(AT_BREA, AD_RBRE, 6, 8), ATTK(AT_MAGC, AD_SPEL, 0, 0),
A(ATTK(AT_BREA, AD_RBRE, 6, 6), ATTK(AT_MAGC, AD_SPEL, 0, 0),
ATTK(AT_CLAW, AD_SAMU, 2, 8), ATTK(AT_BITE, AD_PHYS, 4, 8),
ATTK(AT_BITE, AD_PHYS, 4, 8), ATTK(AT_STNG, AD_PHYS, 1, 6)),
SIZ(WT_DRAGON, 1700, MS_NEMESIS, MZ_GIGANTIC),
+21 -1
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 muse.c $NHDT-Date: 1502753408 2017/08/14 23:30:08 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.79 $ */
/* NetHack 3.6 muse.c $NHDT-Date: 1505181522 2017/09/12 01:58:42 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.80 $ */
/* Copyright (C) 1990 by Ken Arromdee */
/* NetHack may be freely redistributed. See license for details. */
@@ -1129,6 +1129,24 @@ struct monst *mtmp;
m.offensive = obj;
m.has_offense = MUSE_WAN_STRIKING;
}
#if 0 /* use_offensive() has had some code to support wand of teleportation
* for a long time, but find_offensive() never selected one;
* so for the time being, this is still disabled */
nomore(MUSE_WAN_TELEPORTATION);
if (obj->otyp == WAN_TELEPORTATION && obj->spe > 0
/* don't give controlled hero a free teleport */
&& !Teleport_control
/* do try to move hero to a more vulnerable spot */
&& (onscary(u.ux, u.uy, mtmp)
|| (u.ux == xupstair && u.uy == yupstair)
|| (u.ux == xdnstair && u.uy == ydnstair)
|| (u.ux == sstairs.sx && u.uy == sstairs.sy)
|| (u.ux == xupladder && u.uy == yupladder)
|| (u.ux == xdnladder && u.uy == ydnladder))) {
m.offensive = obj;
m.has_offense = MUSE_WAN_TELEPORTATION;
}
#endif
nomore(MUSE_POT_PARALYSIS);
if (obj->otyp == POT_PARALYSIS && multi >= 0) {
m.offensive = obj;
@@ -1233,6 +1251,7 @@ register struct obj *otmp;
makeknown(WAN_STRIKING);
}
break;
#if 0 /* disabled because find_offensive() never picks WAN_TELEPORTATION */
case WAN_TELEPORTATION:
if (mtmp == &youmonst) {
if (zap_oseen)
@@ -1247,6 +1266,7 @@ register struct obj *otmp;
(void) rloc(mtmp, TRUE);
}
break;
#endif
case WAN_CANCELLATION:
case SPE_CANCELLATION:
(void) cancel_monst(mtmp, otmp, FALSE, TRUE, FALSE);
+549 -396
View File
File diff suppressed because it is too large Load Diff
+14 -5
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 pager.c $NHDT-Date: 1471112245 2016/08/13 18:17:25 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.112 $ */
/* NetHack 3.6 pager.c $NHDT-Date: 1505299155 2017/09/13 10:39:15 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.118 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -328,11 +328,20 @@ int x, y;
Strcat(monbuf, ", ");
}
if (how_seen & MONSEEN_WARNMON) {
if (Hallucination)
if (Hallucination) {
Strcat(monbuf, "paranoid delusion");
else
Sprintf(eos(monbuf), "warned of %s",
makeplural(mtmp->data->mname));
} else {
unsigned long mW = (context.warntype.obj
| context.warntype.polyd),
m2 = mtmp->data->mflags2;
const char *whom = ((mW & M2_HUMAN & m2) ? "human"
: (mW & M2_ELF & m2) ? "elf"
: (mW & M2_ORC & m2) ? "orc"
: (mW & M2_DEMON & m2) ? "demon"
: mtmp->data->mname);
Sprintf(eos(monbuf), "warned of %s", makeplural(whom));
}
how_seen &= ~MONSEEN_WARNMON;
if (how_seen)
Strcat(monbuf, ", ");
+43 -23
View File
@@ -29,6 +29,7 @@ STATIC_DCL long FDECL(carry_count, (struct obj *, struct obj *, long,
STATIC_DCL int FDECL(lift_object, (struct obj *, struct obj *, long *,
BOOLEAN_P));
STATIC_DCL boolean FDECL(mbag_explodes, (struct obj *, int));
STATIC_DCL long FDECL(boh_loss, (struct obj *container, int));
STATIC_PTR int FDECL(in_container, (struct obj *));
STATIC_PTR int FDECL(out_container, (struct obj *));
STATIC_DCL void FDECL(removed_from_icebox, (struct obj *));
@@ -707,7 +708,7 @@ int what; /* should be a long */
/* position may need updating (invisible hero) */
if (n_picked)
newsym(u.ux, u.uy);
newsym_force(u.ux, u.uy);
/* check if there's anything else here after auto-pickup is done */
if (autopickup)
@@ -840,7 +841,7 @@ menu_item **pick_list; /* return list of items picked */
int how; /* type of query */
boolean FDECL((*allow), (OBJ_P)); /* allow function */
{
int i, n, actualn;
int i, n;
winid win;
struct obj *curr, *last, fake_hero_object, *olist = *olist_p;
char *pack;
@@ -859,7 +860,6 @@ boolean FDECL((*allow), (OBJ_P)); /* allow function */
last = curr;
n++;
}
actualn = n;
if (engulfer) {
++n;
/* don't autoselect swallowed hero if it's the only choice */
@@ -2019,6 +2019,28 @@ int depthin;
return FALSE;
}
STATIC_OVL long
boh_loss(container, held)
struct obj *container;
int held;
{
/* sometimes toss objects if a cursed magic bag */
if (Is_mbag(container) && container->cursed && Has_contents(container)) {
long loss = 0L;
struct obj *curr, *otmp;
for (curr = container->cobj; curr; curr = otmp) {
otmp = curr->nobj;
if (!rn2(13)) {
obj_extract_self(curr);
loss += mbag_item_gone(held, curr);
}
}
return loss;
}
return 0;
}
/* Returns: -1 to stop, 1 item was inserted, 0 item was not inserted. */
STATIC_PTR int
in_container(obj)
@@ -2326,13 +2348,18 @@ explain_container_prompt(more_containers)
boolean more_containers;
{
static const char *const explaintext[] = {
"Container actions:", "", " : -- Look: examine contents",
" o -- Out: take things out", " i -- In: put things in",
"Container actions:",
"",
" : -- Look: examine contents",
" o -- Out: take things out",
" i -- In: put things in",
" b -- Both: first take things out, then put things in",
" r -- Reversed: put things in, then take things out",
" s -- Stash: put one item in", "",
" n -- Next: loot next selected container", " q -- Quit: finished",
" ? -- Help: display this text.", "", 0
" n -- Next: loot next selected container",
" q -- Quit: finished",
" ? -- Help: display this text.",
"", 0
};
const char *const *txtpp;
winid win;
@@ -2370,11 +2397,12 @@ struct obj **objp;
int held;
boolean more_containers; /* True iff #loot multiple and this isn't last one */
{
struct obj *curr, *otmp, *obj = *objp;
struct obj *otmp, *obj = *objp;
boolean quantum_cat, cursed_mbag, loot_out, loot_in, loot_in_first,
stash_one, inokay, outokay, outmaybe;
char c, emptymsg[BUFSZ], qbuf[QBUFSZ], pbuf[QBUFSZ], xbuf[QBUFSZ];
int used = 0;
long loss;
abort_looting = FALSE;
emptymsg[0] = '\0';
@@ -2415,22 +2443,14 @@ boolean more_containers; /* True iff #loot multiple and this isn't last one */
observe_quantum_cat(current_container);
used = 1;
}
/* sometimes toss objects if a cursed magic bag */
cursed_mbag = (Is_mbag(current_container) && current_container->cursed
&& Has_contents(current_container));
if (cursed_mbag) {
long loss = 0L;
for (curr = current_container->cobj; curr; curr = otmp) {
otmp = curr->nobj;
if (!rn2(13)) {
obj_extract_self(curr);
loss += mbag_item_gone(held, curr);
used = 1;
}
}
if (loss)
You("owe %ld %s for lost merchandise.", loss, currency(loss));
cursed_mbag = Is_mbag(current_container)
&& current_container->cursed
&& Has_contents(current_container);
if (cursed_mbag
&& (loss = boh_loss(current_container, held)) != 0) {
used = 1;
You("owe %ld %s for lost merchandise.", loss, currency(loss));
current_container->owt = weight(current_container);
}
inokay = (invent != 0
+1 -1
View File
@@ -469,7 +469,7 @@ const char *line;
(void) execv(args[0], (char *const *) args);
perror((char *) 0);
(void) fprintf(stderr, "Exec to message handler %s failed.\n", env);
terminate(EXIT_FAILURE);
nh_terminate(EXIT_FAILURE);
} else if (f > 0) {
int status;
+16 -2
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 quest.c $NHDT-Date: 1446191878 2015/10/30 07:57:58 $ $NHDT-Branch: master $:$NHDT-Revision: 1.20 $ */
/* NetHack 3.6 quest.c $NHDT-Date: 1505170343 2017/09/11 22:52:23 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.21 $ */
/* Copyright 1991, M. Stephenson */
/* NetHack may be freely redistributed. See license for details. */
@@ -68,7 +68,20 @@ on_goal()
qt_pager(QT_FIRSTGOAL);
Qstat(made_goal) = 1;
} else {
qt_pager(QT_NEXTGOAL);
/*
* Some QT_NEXTGOAL messages reference the quest artifact;
* find out if it is still present. If not, request an
* alternate message (qt_pager() will revert to delivery
* of QT_NEXTGOAL if current role doesn't have QT_ALTGOAL).
* Note: if hero is already carrying it, it is treated as
* being absent from the level for quest message purposes.
*/
unsigned whichobjchains = ((1 << OBJ_FLOOR)
| (1 << OBJ_MINVENT)
| (1 << OBJ_BURIED));
struct obj *qarti = find_quest_artifact(whichobjchains);
qt_pager(qarti ? QT_NEXTGOAL : QT_ALTGOAL);
if (Qstat(made_goal) < 7)
Qstat(made_goal)++;
}
@@ -179,6 +192,7 @@ boolean seal;
schedule_goto(dest, FALSE, FALSE, portal_flag, (char *) 0, (char *) 0);
if (seal) { /* remove the portal to the quest - sealing it off */
int reexpelled = u.uevent.qexpelled;
u.uevent.qexpelled = 1;
remdun_mapseen(quest_dnum);
/* Delete the near portal now; the far (main dungeon side)
+66 -2
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 questpgr.c $NHDT-Date: 1448541043 2015/11/26 12:30:43 $ $NHDT-Branch: master $:$NHDT-Revision: 1.36 $ */
/* NetHack 3.6 questpgr.c $NHDT-Date: 1505172128 2017/09/11 23:22:08 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.38 $ */
/* Copyright 1991, M. Stephenson */
/* NetHack may be freely redistributed. See license for details. */
@@ -22,6 +22,7 @@ static void NDECL(dump_qtlist);
static void FDECL(Fread, (genericptr_t, int, int, dlb *));
STATIC_DCL struct qtmsg *FDECL(construct_qtlist, (long));
STATIC_DCL const char *NDECL(intermed);
STATIC_DCL struct obj *FDECL(find_qarti, (struct obj *));
STATIC_DCL const char *NDECL(neminame);
STATIC_DCL const char *NDECL(guardname);
STATIC_DCL const char *NDECL(homebase);
@@ -196,6 +197,58 @@ struct obj *otmp;
return (boolean) (otmp->oartifact == urole.questarti);
}
STATIC_OVL struct obj *
find_qarti(ochain)
struct obj *ochain;
{
struct obj *otmp, *qarti;
for (otmp = ochain; otmp; otmp = otmp->nobj) {
if (is_quest_artifact(otmp))
return otmp;
if (Has_contents(otmp) && (qarti = find_qarti(otmp->cobj)) != 0)
return qarti;
}
return (struct obj *) 0;
}
/* check several object chains for the quest artifact to determine
whether it is present on the current level */
struct obj *
find_quest_artifact(whichchains)
unsigned whichchains;
{
struct monst *mtmp;
struct obj *qarti = 0;
if ((whichchains & (1 << OBJ_INVENT)) != 0)
qarti = find_qarti(invent);
if (!qarti && (whichchains & (1 << OBJ_FLOOR)) != 0)
qarti = find_qarti(fobj);
if (!qarti && (whichchains & (1 << OBJ_MINVENT)) != 0)
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp))
continue;
if ((qarti = find_qarti(mtmp->minvent)) != 0)
break;
}
if (!qarti && (whichchains & (1 << OBJ_MIGRATING)) != 0) {
/* check migrating objects and minvent of migrating monsters */
for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp))
continue;
if ((qarti = find_qarti(mtmp->minvent)) != 0)
break;
}
if (!qarti)
qarti = find_qarti(migrating_objs);
}
if (!qarti && (whichchains & (1 << OBJ_BURIED)) != 0)
qarti = find_qarti(level.buriedobjlist);
return qarti;
}
/* return your role nemesis' name */
STATIC_OVL const char *
neminame()
@@ -573,7 +626,18 @@ int msgnum;
if (skip_pager(FALSE))
return;
if (!(qt_msg = msg_in(qt_list.chrole, msgnum))) {
qt_msg = msg_in(qt_list.chrole, msgnum);
if (!qt_msg) {
/* some roles have an alternate message for return to the goal
level when the quest artifact is absent (handled by caller)
but some don't; for the latter, use the normal goal message;
note: for first visit, artifact is assumed to always be
present which might not be true for wizard mode but we don't
worry about quest message references in that situation */
if (msgnum == QT_ALTGOAL)
qt_msg = msg_in(qt_list.chrole, QT_NEXTGOAL);
}
if (!qt_msg) {
impossible("qt_pager: message %d not found.", msgnum);
return;
}
+30 -8
View File
@@ -29,6 +29,7 @@ STATIC_DCL void FDECL(forget, (int));
STATIC_DCL int FDECL(maybe_tame, (struct monst *, struct obj *));
STATIC_DCL boolean FDECL(is_valid_stinking_cloud_pos, (int, int, BOOLEAN_P));
STATIC_DCL void FDECL(display_stinking_cloud_positions, (int));
STATIC_DCL boolean FDECL(get_valid_stinking_cloud_pos, (int, int));
STATIC_PTR void FDECL(set_lit, (int, int, genericptr));
STATIC_OVL boolean
@@ -915,7 +916,7 @@ struct obj *sobj;
return 0;
}
boolean
STATIC_OVL boolean
get_valid_stinking_cloud_pos(x,y)
int x,y;
{
@@ -929,7 +930,7 @@ is_valid_stinking_cloud_pos(x, y, showmsg)
int x, y;
boolean showmsg;
{
if (get_valid_stinking_cloud_pos(x,y)) {
if (!get_valid_stinking_cloud_pos(x,y)) {
if (showmsg)
You("smell rotten eggs.");
return FALSE;
@@ -1555,8 +1556,14 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
pline("Thinking of Maud you forget everything else.");
exercise(A_WIS, FALSE);
break;
case SCR_FIRE:
case SCR_FIRE: {
coord cc;
int dam;
cc.x = u.ux;
cc.y = u.uy;
cval = bcsign(sobj);
dam = (2 * (rn1(3, 3) + 2 * cval) + 1) / 3;
useup(sobj);
sobj = 0; /* it's gone */
if (!already_known)
@@ -1580,13 +1587,28 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
if (Underwater) {
pline_The("%s around you vaporizes violently!", hliquid("water"));
} else {
pline_The("scroll erupts in a tower of flame!");
iflags.last_msg = PLNMSG_TOWER_OF_FLAME; /* for explode() */
burn_away_slime();
if (sblessed) {
if (!already_known)
pline("This is a scroll of fire!");
dam *= 5;
pline("Where do you want to center the explosion?");
getpos_sethilite(display_stinking_cloud_positions, get_valid_stinking_cloud_pos);
(void) getpos(&cc, TRUE, "the desired position");
if (!is_valid_stinking_cloud_pos(cc.x, cc.y, FALSE)) {
/* try to reach too far, get burned */
cc.x = u.ux;
cc.y = u.uy;
}
}
if (cc.x == u.ux && cc.y == u.uy) {
pline_The("scroll erupts in a tower of flame!");
iflags.last_msg = PLNMSG_TOWER_OF_FLAME; /* for explode() */
burn_away_slime();
}
}
explode(u.ux, u.uy, 11, (2 * (rn1(3, 3) + 2 * cval) + 1) / 3,
SCROLL_CLASS, EXPL_FIERY);
explode(cc.x, cc.y, 11, dam, SCROLL_CLASS, EXPL_FIERY);
break;
}
case SCR_EARTH:
/* TODO: handle steeds */
if (!Is_rogue_level(&u.uz) && has_ceiling(&u.uz)
+1 -1
View File
@@ -744,7 +744,7 @@ xchar ltmp;
}
#endif /* ?AMIGA */
pline("Be seeing you...");
terminate(EXIT_SUCCESS);
nh_terminate(EXIT_SUCCESS);
}
#endif /* MFLOPPY */
bufon(nfd);
+15 -12
View File
@@ -64,8 +64,6 @@ static struct save_procs {
#endif
};
static long nulls[sizeof(struct trap) + sizeof(struct fruit)];
#if defined(UNIX) || defined(VMS) || defined(__EMX__) || defined(WIN32)
#define HUP if (!program_state.done_hup)
#else
@@ -94,7 +92,7 @@ dosave()
/* make sure they see the Saving message */
display_nhwindow(WIN_MESSAGE, TRUE);
exit_nhwindows("Be seeing you...");
terminate(EXIT_SUCCESS);
nh_terminate(EXIT_SUCCESS);
} else
(void) doredraw();
}
@@ -728,7 +726,7 @@ register unsigned num;
if (failed) {
#if defined(UNIX) || defined(VMS) || defined(__EMX__)
if (program_state.done_hup)
terminate(EXIT_FAILURE);
nh_terminate(EXIT_FAILURE);
else
#endif
panic("cannot write %u bytes to file #%d", num, fd);
@@ -834,7 +832,7 @@ register int fd;
if (write(fd, outbuf, outbufp) != outbufp) {
#if defined(UNIX) || defined(VMS) || defined(__EMX__)
if (program_state.done_hup)
terminate(EXIT_FAILURE);
nh_terminate(EXIT_FAILURE);
else
#endif
zerocomp_bclose(fd); /* panic (outbufp != 0) */
@@ -860,7 +858,7 @@ register unsigned num;
if ((unsigned) write(fd, loc, num) != num) {
#if defined(UNIX) || defined(VMS) || defined(__EMX__)
if (program_state.done_hup)
terminate(EXIT_FAILURE);
nh_terminate(EXIT_FAILURE);
else
#endif
panic("cannot write %u bytes to file #%d", num, fd);
@@ -1175,23 +1173,26 @@ register struct monst *mtmp;
bwrite(fd, (genericptr_t) &minusone, sizeof(int));
}
/* save traps; ftrap is the only trap chain so the 2nd arg is superfluous */
STATIC_OVL void
savetrapchn(fd, trap, mode)
register int fd, mode;
int fd;
register struct trap *trap;
int mode;
{
static struct trap zerotrap;
register struct trap *trap2;
while (trap) {
trap2 = trap->ntrap;
if (perform_bwrite(mode))
bwrite(fd, (genericptr_t) trap, sizeof(struct trap));
bwrite(fd, (genericptr_t) trap, sizeof (struct trap));
if (release_data(mode))
dealloc_trap(trap);
trap = trap2;
}
if (perform_bwrite(mode))
bwrite(fd, (genericptr_t) nulls, sizeof(struct trap));
bwrite(fd, (genericptr_t) &zerotrap, sizeof zerotrap);
}
/* save all the fruit names and ID's; this is used only in saving whole games
@@ -1201,21 +1202,22 @@ register struct trap *trap;
*/
void
savefruitchn(fd, mode)
register int fd, mode;
int fd, mode;
{
static struct fruit zerofruit;
register struct fruit *f2, *f1;
f1 = ffruit;
while (f1) {
f2 = f1->nextf;
if (f1->fid >= 0 && perform_bwrite(mode))
bwrite(fd, (genericptr_t) f1, sizeof(struct fruit));
bwrite(fd, (genericptr_t) f1, sizeof (struct fruit));
if (release_data(mode))
dealloc_fruit(f1);
f1 = f2;
}
if (perform_bwrite(mode))
bwrite(fd, (genericptr_t) nulls, sizeof(struct fruit));
bwrite(fd, (genericptr_t) &zerofruit, sizeof zerofruit);
if (release_data(mode))
ffruit = 0;
}
@@ -1225,6 +1227,7 @@ store_plname_in_file(fd)
int fd;
{
int plsiztmp = PL_NSIZ;
bufoff(fd);
/* bwrite() before bufon() uses plain write() */
bwrite(fd, (genericptr_t) &plsiztmp, sizeof(plsiztmp));
+20 -4
View File
@@ -883,7 +883,7 @@ int spell;
boolean atme;
{
int energy, damage, chance, n, intell;
int skill, role_skill;
int skill, role_skill, res = 0;
boolean confused = (Confusion != 0);
boolean physical_damage = FALSE;
struct obj *pseudo;
@@ -933,13 +933,29 @@ boolean atme;
return 1;
}
if (u.uhave.amulet) {
/* if the cast attempt is already going to fail due to insufficient
energy (ie, u.uen < energy), the Amulet's drain effect won't kick
in and no turn will be consumed; however, when it does kick in,
the attempt may fail due to lack of energy after the draining, in
which case a turn will be used up in addition to the energy loss */
if (u.uhave.amulet && u.uen >= energy) {
You_feel("the amulet draining your energy away.");
energy += rnd(2 * energy);
/* this used to be 'energy += rnd(2 * energy)' (without 'res'),
so if amulet-induced cost was more than u.uen, nothing
(except the "don't have enough energy" message) happened
and player could just try again (and again and again...);
now we drain some energy immediately, which has a
side-effect of not increasing the hunger aspect of casting */
u.uen -= rnd(2 * energy);
if (u.uen < 0)
u.uen = 0;
context.botl = 1;
res = 1; /* time is going to elapse even if spell doesn't get cast */
}
if (energy > u.uen) {
You("don't have enough energy to cast that spell.");
return 0;
return res;
} else {
if (spellid(spell) != SPE_DETECT_FOOD) {
int hungr = energy * 2;
+1
View File
@@ -40,6 +40,7 @@ sys_early_init()
sysopt.explorers = (char *) 0;
sysopt.genericusers = (char *) 0;
sysopt.maxplayers = 0; /* XXX eventually replace MAX_NR_OF_PLAYERS */
sysopt.bones_pools = 0;
/* record file */
sysopt.persmax = PERSMAX;
+20 -5
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 timeout.c $NHDT-Date: 1496619133 2017/06/04 23:32:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.71 $ */
/* NetHack 3.6 timeout.c $NHDT-Date: 1505214876 2017/09/12 11:14:36 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.75 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -145,13 +145,13 @@ stoned_dialogue()
exercise(A_DEX, FALSE);
}
/* He is getting sicker and sicker prior to vomiting */
/* hero is getting sicker and sicker prior to vomiting */
static NEARDATA const char *const vomiting_texts[] = {
"are feeling mildly nauseated.", /* 14 */
"feel slightly confused.", /* 11 */
"can't seem to think straight.", /* 8 */
"feel incredibly sick.", /* 5 */
"suddenly vomit!" /* 2 */
"are about to vomit." /* 2 */
};
STATIC_OVL void
@@ -188,12 +188,25 @@ vomiting_dialogue()
case 2:
txt = vomiting_texts[4];
if (cantvomit(youmonst.data))
txt = "gag uncontrolably.";
txt = "gag uncontrollably.";
else if (Hallucination)
/* "hurl" is short for "hurl chunks" which is slang for
relatively violent vomiting... */
txt = "are about to hurl!";
break;
case 0:
stop_occupation();
if (!cantvomit(youmonst.data))
if (!cantvomit(youmonst.data)) {
morehungry(20);
/* case 2 used to be "You suddenly vomit!" but it wasn't sudden
since you've just been through the earlier messages of the
countdown, and it was still possible to move around between
that message and "You can move again." (from vomit()'s
nomul(-2)) with no intervening message; give one here to
have a more specific at which hero became unable to move
[vomit() issues its own message for the cantvomit() case] */
You("%s!", !Hallucination ? "vomit" : "hurl chunks");
}
vomit();
break;
default:
@@ -363,6 +376,8 @@ nh_timeout()
if (u.mtimedone && !--u.mtimedone) {
if (Unchanging)
u.mtimedone = rnd(100 * youmonst.data->mlevel + 1);
else if (is_were(youmonst.data))
you_unwere(FALSE); /* if polycontrl, asks whether to rehumanize */
else
rehumanize();
}
+47 -1
View File
@@ -409,7 +409,7 @@ int x, y, typ;
add_damage(x, y, /* schedule repair */
((IS_DOOR(lev->typ) || IS_WALL(lev->typ))
&& !context.mon_moving)
? 200L
? SHOP_HOLE_COST
: 0L);
lev->doormask = 0; /* subsumes altarmask, icedpool... */
if (IS_ROOM(lev->typ)) /* && !IS_AIR(lev->typ) */
@@ -3287,6 +3287,7 @@ xchar x, y;
{
struct obj *obj, *nobj;
int num = 0;
for (obj = chain; obj; obj = nobj) {
nobj = here ? obj->nexthere : obj->nobj;
if (fire_damage(obj, force, x, y))
@@ -3298,6 +3299,51 @@ xchar x, y;
return num;
}
/* obj has been thrown or dropped into lava; damage is worse than mere fire */
boolean
lava_damage(obj, x, y)
struct obj *obj;
xchar x, y;
{
int otyp = obj->otyp, ocls = obj->oclass;
/* the Amulet, invocation items, and Rider corpses are never destroyed
(let Book of the Dead fall through to fire_damage() to get feedback) */
if (obj_resists(obj, 0, 0) && otyp != SPE_BOOK_OF_THE_DEAD)
return FALSE;
/* destroy liquid (venom), wax, veggy, flesh, paper (except for scrolls
and books--let fire damage deal with them), cloth, leather, wood, bone
unless it's inherently or explicitly fireproof or contains something;
note: potions are glass so fall through to fire_damage() and boil */
if (objects[otyp].oc_material < DRAGON_HIDE
&& ocls != SCROLL_CLASS && ocls != SPBOOK_CLASS
&& objects[otyp].oc_oprop != FIRE_RES
&& otyp != WAN_FIRE && otyp != FIRE_HORN
/* assumes oerodeproof isn't overloaded for some other purpose on
non-eroding items */
&& !obj->oerodeproof
/* fire_damage() knows how to deal with containers and contents */
&& !Has_contents(obj)) {
if (cansee(x, y)) {
/* this feedback is pretty clunky and can become very verbose
when former contents of a burned container get here via
flooreffects() */
if (obj == thrownobj || obj == kickedobj)
pline("%s %s up!", is_plural(obj) ? "They" : "It",
otense(obj, "burn"));
else
You_see("%s hit lava and burn up!", doname(obj));
}
if (carried(obj)) { /* shouldn't happen */
remove_worn_item(obj, TRUE);
useupall(obj);
} else
delobj(obj);
return TRUE;
}
return fire_damage(obj, TRUE, x, y);
}
void
acid_damage(obj)
struct obj *obj;
+2 -2
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 u_init.c $NHDT-Date: 1454660565 2016/02/05 08:22:45 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.37 $ */
/* NetHack 3.6 u_init.c $NHDT-Date: 1503960969 2017/08/28 22:56:09 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.40 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -124,7 +124,7 @@ static struct trobj Rogue[] = {
{ DAGGER, 0, WEAPON_CLASS, 10, 0 }, /* quan is variable */
{ LEATHER_ARMOR, 1, ARMOR_CLASS, 1, UNDEF_BLESS },
{ POT_SICKNESS, 0, POTION_CLASS, 1, 0 },
{ LOCK_PICK, 9, TOOL_CLASS, 1, 0 },
{ LOCK_PICK, 0, TOOL_CLASS, 1, 0 },
{ SACK, 0, TOOL_CLASS, 1, 0 },
{ 0, 0, 0, 0, 0 }
};
+4 -3
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 uhitm.c $NHDT-Date: 1496860757 2017/06/07 18:39:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.166 $ */
/* NetHack 3.6 uhitm.c $NHDT-Date: 1504999056 2017/09/09 23:17:36 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.167 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1609,8 +1609,9 @@ register struct attack *mattk;
pline("%s suddenly seems weaker!", Monnam(mdef));
mdef->mhpmax -= xtmp;
mdef->mhp -= xtmp;
/* !m_lev: level 0 monster is killed rather than drop to -1 */
if (mdef->mhp <= 0 && !mdef->m_lev) {
/* !m_lev: level 0 monster is killed regardless of hit points
rather than drop to level -1 */
if (mdef->mhp <= 0 || !mdef->m_lev) {
pline("%s dies!", Monnam(mdef));
xkilled(mdef, XKILL_NOMSG);
} else
+6 -3
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 were.c $NHDT-Date: 1432512763 2015/05/25 00:12:43 $ $NHDT-Branch: master $:$NHDT-Revision: 1.18 $ */
/* NetHack 3.6 were.c $NHDT-Date: 1505214877 2017/09/12 11:14:37 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.21 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -183,7 +183,7 @@ you_were()
/* `+4' => skip "were" prefix to get name of beast */
Sprintf(qbuf, "Do you want to change into %s?",
an(mons[u.ulycn].mname + 4));
if (yn(qbuf) == 'n')
if (!paranoid_query(ParanoidWerechange, qbuf))
return;
}
(void) polymon(u.ulycn);
@@ -200,8 +200,11 @@ boolean purify;
set_ulycn(NON_PM); /* cure lycanthropy */
}
if (!Unchanging && is_were(youmonst.data)
&& (!controllable_poly || yn("Remain in beast form?") == 'n'))
&& (!controllable_poly
|| !paranoid_query(ParanoidWerechange, "Remain in beast form?")))
rehumanize();
else if (is_were(youmonst.data) && !u.mtimedone)
u.mtimedone = rn1(200, 200); /* 40% of initial were change */
}
/* lycanthropy is being caught or cured, but no shape change is involved */
+20 -14
View File
@@ -57,6 +57,18 @@ extern void *FDECL(trace_procs_chain, (int, int, void *, void *, void *));
STATIC_DCL void FDECL(def_raw_print, (const char *s));
#ifdef DUMPLOG
STATIC_DCL winid FDECL(dump_create_nhwindow, (int));
STATIC_DCL void FDECL(dump_clear_nhwindow, (winid));
STATIC_DCL void FDECL(dump_display_nhwindow, (winid, BOOLEAN_P));
STATIC_DCL void FDECL(dump_destroy_nhwindow, (winid));
STATIC_DCL void FDECL(dump_start_menu, (winid));
STATIC_DCL void FDECL(dump_add_menu, (winid, int, const ANY_P *, CHAR_P, CHAR_P, int, const char *, BOOLEAN_P));
STATIC_DCL void FDECL(dump_end_menu, (winid, const char *));
STATIC_DCL int FDECL(dump_select_menu, (winid, int, MENU_ITEM_P **));
STATIC_DCL void FDECL(dump_putstr, (winid, int, const char *));
#endif /* DUMPLOG */
#ifdef HANGUPHANDLING
volatile
#endif
@@ -226,22 +238,25 @@ const char *s;
exit(EXIT_FAILURE);
}
if (!winchoices[1].procs) {
raw_printf("Window type %s not recognized. The only choice is: %s.",
config_error_add("Window type %s not recognized. The only choice is: %s",
s, winchoices[0].procs->name);
} else {
raw_printf("Window type %s not recognized. Choices are:", s);
char buf[BUFSZ];
boolean first = TRUE;
buf[0] = '\0';
for (i = 0; winchoices[i].procs; i++) {
if ('+' == winchoices[i].procs->name[0])
continue;
if ('-' == winchoices[i].procs->name[0])
continue;
raw_printf(" %s", winchoices[i].procs->name);
Sprintf(eos(buf), "%s%s", first ? "" : ",", winchoices[i].procs->name);
first = FALSE;
}
config_error_add("Window type %s not recognized. Choices are: %s", s, buf);
}
if (windowprocs.win_raw_print == def_raw_print)
terminate(EXIT_SUCCESS);
wait_synch();
nh_terminate(EXIT_SUCCESS);
}
#ifdef WINCHAIN
@@ -1157,15 +1172,6 @@ dump_close_log()
}
}
void
dump_putc(ch)
int ch;
{
/* Not very efficient, but we mostly don't care. */
if (dumplog_file)
putc(ch, dumplog_file);
}
void
dump_forward_putstr(win, attr, str, no_forward)
winid win;
+11 -9
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 zap.c $NHDT-Date: 1470819844 2016/08/10 09:04:04 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.263 $ */
/* NetHack 3.6 zap.c $NHDT-Date: 1505475171 2017/09/15 11:32:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.267 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -2127,6 +2127,7 @@ backfire(otmp)
struct obj *otmp;
{
int dmg;
otmp->in_use = TRUE; /* in case losehp() is fatal */
pline("%s suddenly explodes!", The(xname(otmp)));
dmg = d(otmp->spe + 2, 6);
@@ -3070,6 +3071,7 @@ int range, *skipstart, *skipend;
{
int tr = (range / 4);
int tmp = range - ((tr > 0) ? rnd(tr) : 0);
*skipstart = tmp;
*skipend = tmp - ((tmp / 4) * rnd(3));
if (*skipend >= tmp)
@@ -3300,7 +3302,7 @@ struct obj **pobj; /* object tossed/used, set to NULL
if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN
&& *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) {
shopdoor = TRUE;
add_damage(bhitpos.x, bhitpos.y, 400L);
add_damage(bhitpos.x, bhitpos.y, SHOP_DOOR_COST);
}
}
break;
@@ -3880,10 +3882,10 @@ const char *fltxt;
}
void
buzz(type,nd,sx,sy,dx,dy)
buzz(type, nd, sx, sy, dx, dy)
int type, nd;
xchar sx,sy;
int dx,dy;
xchar sx, sy;
int dx, dy;
{
dobuzz(type, nd, sx, sy, dx, dy, TRUE);
}
@@ -3898,7 +3900,7 @@ int dx,dy;
* called with dx = dy = 0 with vertical bolts
*/
void
dobuzz(type, nd, sx, sy, dx, dy,say)
dobuzz(type, nd, sx, sy, dx, dy, say)
register int type, nd;
register xchar sx, sy;
register int dx, dy;
@@ -4145,7 +4147,7 @@ boolean say; /* Announce out of sight hit/miss events if true */
? "shatter"
/* "damage" indicates wall rather than door */
: abstype == ZT_ACID
? "damage"
? "damage"
: abstype == ZT_DEATH
? "disintegrate"
: "destroy",
@@ -4410,7 +4412,7 @@ short exploding_wand_typ;
lev->typ = ROOM;
if (see_it)
newsym(x, y);
add_damage(x, y, (type >= 0) ? 300L : 0L);
add_damage(x, y, (type >= 0) ? SHOP_BARS_COST : 0L);
if (type >= 0)
*shopdamage = TRUE;
} else {
@@ -4508,7 +4510,7 @@ short exploding_wand_typ;
if (new_doormask >= 0) { /* door gets broken */
if (*in_rooms(x, y, SHOPBASE)) {
if (type >= 0) {
add_damage(x, y, 400L);
add_damage(x, y, SHOP_DOOR_COST);
*shopdamage = TRUE;
} else /* caused by monster */
add_damage(x, y, 0L);