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

This commit is contained in:
keni
2017-08-15 07:59:38 -04:00
51 changed files with 2521 additions and 1573 deletions
+83 -58
View File
@@ -13,6 +13,7 @@
#ifdef POSITIONBAR
STATIC_DCL void NDECL(do_positionbar);
#endif
STATIC_DCL void FDECL(regen_hp, (int));
STATIC_DCL void FDECL(interrupt_multi, (const char *));
void
@@ -185,66 +186,20 @@ boolean resuming;
/* One possible result of prayer is healing. Whether or
* not you get healed depends on your current hit points.
* If you are allowed to regenerate during the prayer, the
* end-of-prayer calculation messes up on this.
* If you are allowed to regenerate during the prayer,
* the end-of-prayer calculation messes up on this.
* Another possible result is rehumanization, which
* requires
* that encumbrance and movement rate be recalculated.
* requires that encumbrance and movement rate be
* recalculated.
*/
if (u.uinvulnerable) {
/* for the moment at least, you're in tiptop shape */
wtcap = UNENCUMBERED;
} else if (Upolyd && youmonst.data->mlet == S_EEL
&& !is_pool(u.ux, u.uy)
&& !Is_waterlevel(&u.uz)) {
/* eel out of water loses hp, same as for monsters;
as hp gets lower, rate of further loss slows down
*/
if (u.mh > 1 && rn2(u.mh) > rn2(8)
&& (!Half_physical_damage || !(moves % 2L))) {
u.mh--;
context.botl = 1;
} else if (u.mh < 1)
rehumanize();
} else if (Upolyd && u.mh < u.mhmax) {
if (u.mh < 1)
rehumanize();
else if (Regeneration
|| (wtcap < MOD_ENCUMBER && !(moves % 20))) {
context.botl = 1;
u.mh++;
if (u.mh >= u.mhmax)
interrupt_multi("You are in full health.");
}
} else if (u.uhp < u.uhpmax
&& (wtcap < MOD_ENCUMBER || !u.umoved
|| Regeneration)) {
if (u.ulevel > 9 && !(moves % 3)) {
int heal, Con = (int) ACURR(A_CON);
if (Con <= 12) {
heal = 1;
} else {
heal = rnd(Con);
if (heal > u.ulevel - 9)
heal = u.ulevel - 9;
}
context.botl = 1;
u.uhp += heal;
if (u.uhp > u.uhpmax)
u.uhp = u.uhpmax;
if (u.uhp >= u.uhpmax)
interrupt_multi("You are in full health.");
} else if (Regeneration
|| (u.ulevel <= 9
&& !(moves
% ((MAXULEV + 12) / (u.ulevel + 2)
+ 1)))) {
context.botl = 1;
u.uhp++;
if (u.uhp >= u.uhpmax)
interrupt_multi("You are in full health.");
}
} else if (!Upolyd ? (u.uhp < u.uhpmax)
: (u.mh < u.mhmax
|| youmonst.data->mlet == S_EEL)) {
/* maybe heal */
regen_hp(wtcap);
}
/* moving around while encumbered is hard work */
@@ -263,7 +218,7 @@ boolean resuming;
}
}
if ((u.uen < u.uenmax)
if (u.uen < u.uenmax
&& ((wtcap < MOD_ENCUMBER
&& (!(moves % ((MAXULEV + 8 - u.ulevel)
* (Role_if(PM_WIZARD) ? 3 : 4)
@@ -273,7 +228,7 @@ boolean resuming;
if (u.uen > u.uenmax)
u.uen = u.uenmax;
context.botl = 1;
if (u.uen >= u.uenmax)
if (u.uen == u.uenmax)
interrupt_multi("You feel full of energy.");
}
@@ -493,6 +448,76 @@ boolean resuming;
}
}
/* maybe recover some lost health (or lose some when an eel out of water) */
STATIC_OVL void
regen_hp(wtcap)
int wtcap;
{
int heal = 0;
boolean reached_full = FALSE,
encumbrance_ok = (wtcap < MOD_ENCUMBER || !u.umoved);
if (Upolyd) {
if (u.mh < 1) { /* shouldn't happen... */
rehumanize();
} else if (youmonst.data->mlet == S_EEL
&& !is_pool(u.ux, u.uy) && !Is_waterlevel(&u.uz)) {
/* eel out of water loses hp, similar to monster eels;
as hp gets lower, rate of further loss slows down */
if (u.mh > 1 && !Regeneration && rn2(u.mh) > rn2(8)
&& (!Half_physical_damage || !(moves % 2L)))
heal = -1;
} else if (u.mh < u.mhmax) {
if (Regeneration || (encumbrance_ok && !(moves % 20L)))
heal = 1;
}
if (heal) {
context.botl = 1;
u.mh += heal;
reached_full = (u.mh == u.mhmax);
}
/* !Upolyd */
} else {
/* [when this code was in-line within moveloop(), there was
no !Upolyd check here, so poly'd hero recovered lost u.uhp
once u.mh reached u.mhmax; that may have been convenient
for the player, but it didn't make sense for gameplay...] */
if (u.uhp < u.uhpmax && (encumbrance_ok || Regeneration)) {
if (u.ulevel > 9) {
if (!(moves % 3L)) {
int Con = (int) ACURR(A_CON);
if (Con <= 12) {
heal = 1;
} else {
heal = rnd(Con);
if (heal > u.ulevel - 9)
heal = u.ulevel - 9;
}
}
} else { /* u.ulevel <= 9 */
if (!(moves % (long) ((MAXULEV + 12) / (u.ulevel + 2) + 1)))
heal = 1;
}
if (Regeneration && !heal)
heal = 1;
if (heal) {
context.botl = 1;
u.uhp += heal;
if (u.uhp > u.uhpmax)
u.uhp = u.uhpmax;
/* stop voluntary multi-turn activity if now fully healed */
reached_full = (u.uhp == u.uhpmax);
}
}
}
if (reached_full)
interrupt_multi("You are in full health.");
}
void
stop_occupation()
{
@@ -561,7 +586,7 @@ newgame()
context.tribute.enabled = TRUE; /* turn on 3.6 tributes */
context.tribute.tributesz = sizeof(struct tribute_info);
for (i = 0; i < NUMMONS; i++)
for (i = LOW_PM; i < NUMMONS; i++)
mvitals[i].mvflags = mons[i].geno & G_NOCORPSE;
init_objects(); /* must be before u_init() */
+24 -8
View File
@@ -445,6 +445,8 @@ struct obj *obj;
} else {
You(whistle_str, obj->cursed ? "shrill" : "high");
wake_nearby();
if (obj->cursed)
vault_summon_gd();
}
}
@@ -1564,6 +1566,15 @@ boolean showmsg;
static int jumping_is_magic;
boolean
get_valid_jump_position(x,y)
int x,y;
{
return (isok(x, y)
&& (ACCESSIBLE(levl[x][y].typ) || Passes_walls)
&& is_valid_jump_pos(x, y, jumping_is_magic, FALSE));
}
void
display_jump_positions(state)
int state;
@@ -1577,9 +1588,7 @@ int state;
for (dy = -4; dy <= 4; dy++) {
x = dx + (int) u.ux;
y = dy + (int) u.uy;
if (isok(x, y)
&& (ACCESSIBLE(levl[x][y].typ) || Passes_walls)
&& is_valid_jump_pos(x, y, jumping_is_magic, FALSE))
if (get_valid_jump_position(x, y))
tmp_at(x, y);
}
} else {
@@ -1678,7 +1687,7 @@ int magic; /* 0=Physical, otherwise skill level */
cc.x = u.ux;
cc.y = u.uy;
jumping_is_magic = magic;
getpos_sethilite(display_jump_positions);
getpos_sethilite(display_jump_positions, get_valid_jump_position);
if (getpos(&cc, TRUE, "the desired position") < 0)
return 0; /* user pressed ESC */
if (!is_valid_jump_pos(cc.x, cc.y, magic, TRUE)) {
@@ -2851,6 +2860,15 @@ int min_range, max_range;
static int polearm_range_min = -1;
static int polearm_range_max = -1;
boolean
get_valid_polearm_position(x,y)
int x,y;
{
return (isok(x, y) && ACCESSIBLE(levl[x][y].typ)
&& distu(x, y) >= polearm_range_min
&& distu(x, y) <= polearm_range_max);
}
void
display_polearm_positions(state)
int state;
@@ -2864,9 +2882,7 @@ int state;
for (dy = -4; dy <= 4; dy++) {
x = dx + (int) u.ux;
y = dy + (int) u.uy;
if (isok(x, y) && ACCESSIBLE(levl[x][y].typ)
&& distu(x, y) >= polearm_range_min
&& distu(x, y) <= polearm_range_max) {
if (get_valid_polearm_position(x, y)) {
tmp_at(x, y);
}
}
@@ -2936,7 +2952,7 @@ struct obj *obj;
cc.x = hitm->mx;
cc.y = hitm->my;
}
getpos_sethilite(display_polearm_positions);
getpos_sethilite(display_polearm_positions, get_valid_polearm_position);
if (getpos(&cc, TRUE, "the spot to hit") < 0)
return res; /* ESC; uses turn iff polearm became wielded */
+20 -16
View File
@@ -498,7 +498,7 @@ long wp_mask;
for (obj = invent; obj; obj = obj->nobj) {
if (obj != otmp && obj->oartifact) {
art = get_artifact(obj);
if (art->cary.adtyp == dtyp) {
if (art && art->cary.adtyp == dtyp) {
mask = (long *) 0;
break;
}
@@ -519,7 +519,8 @@ long wp_mask;
for (obj = invent; obj; obj = obj->nobj)
if (obj != otmp && obj->oartifact) {
art = get_artifact(obj);
spfx &= ~art->cspfx;
if (art)
spfx &= ~art->cspfx;
}
}
@@ -653,16 +654,17 @@ struct monst *mon;
return 1;
yours = (mon == &youmonst);
/* all quest artifacts are self-willed; it this ever changes, `badclass'
/* all quest artifacts are self-willed; if this ever changes, `badclass'
will have to be extended to explicitly include quest artifacts */
self_willed = ((oart->spfx & SPFX_INTEL) != 0);
if (yours) {
badclass = self_willed
&& ((oart->role != NON_PM && !Role_if(oart->role))
|| (oart->race != NON_PM && !Race_if(oart->race)));
badalign =
(oart->spfx & SPFX_RESTR) && oart->alignment != A_NONE
&& (oart->alignment != u.ualign.type || u.ualign.record < 0);
badalign = ((oart->spfx & SPFX_RESTR) != 0
&& oart->alignment != A_NONE
&& (oart->alignment != u.ualign.type
|| u.ualign.record < 0));
} else if (!is_covetous(mon->data) && !is_mplayer(mon->data)) {
badclass = self_willed && oart->role != NON_PM
&& oart != &artilist[ART_EXCALIBUR];
@@ -1493,8 +1495,8 @@ struct obj *obj;
obj->age = 0;
return 0;
}
b_effect =
obj->blessed && (Role_switch == oart->role || !oart->role);
b_effect = (obj->blessed
&& (Role_switch == oart->role || !oart->role));
recharge(otmp, b_effect ? 1 : obj->cursed ? -1 : 0);
update_inventory();
break;
@@ -1583,9 +1585,8 @@ struct obj *obj;
} else
otmp->quan += rnd(5);
otmp->owt = weight(otmp);
otmp =
hold_another_object(otmp, "Suddenly %s out.",
aobjnam(otmp, "fall"), (const char *) 0);
otmp = hold_another_object(otmp, "Suddenly %s out.",
aobjnam(otmp, "fall"), (char *) 0);
break;
}
}
@@ -1883,12 +1884,11 @@ boolean loseit; /* whether to drop it if hero can longer touch it */
if (touch_artifact(obj, &youmonst)) {
char buf[BUFSZ];
int dmg = 0, tmp;
boolean ag =
(objects[obj->otyp].oc_material == SILVER && Hate_silver),
boolean ag = (objects[obj->otyp].oc_material == SILVER && Hate_silver),
bane = bane_applies(get_artifact(obj), &youmonst);
/* nothing else to do if hero can successfully handle this object */
if (!ag && !bane && !touch_blasted)
if (!ag && !bane)
return 1;
/* hero can't handle this object, but didn't get touch_artifact()'s
@@ -2008,11 +2008,15 @@ int dropflag; /* 0==don't drop, 1==drop all, 2==drop weapon */
dropit = (dropflag > 0); /* drop all or drop weapon */
/* check secondary weapon first, before possibly unwielding primary */
if (u.twoweap)
if (u.twoweap) {
bypass_obj(uswapwep); /* so loop below won't process it again */
(void) untouchable(uswapwep, dropit);
}
/* check primary weapon next so that they're handled together */
if (uwep)
if (uwep) {
bypass_obj(uwep); /* so loop below won't process it again */
(void) untouchable(uwep, dropit);
}
/* in case someone is daft enough to add artifact or silver saddle */
if (u.usteed && (obj = which_armor(u.usteed, W_SADDLE)) != 0) {
+3 -7
View File
@@ -48,14 +48,10 @@ STATIC_OVL void
goodfruit(id)
int id;
{
register struct fruit *f;
struct fruit *f = fruit_from_indx(-id);
for (f = ffruit; f; f = f->nextf) {
if (f->fid == -id) {
f->fid = id;
return;
}
}
if (f)
f->fid = id;
}
STATIC_OVL void
+23 -21
View File
@@ -13,6 +13,25 @@ const char *const enc_stat[] = { "", "Burdened", "Stressed",
STATIC_OVL NEARDATA int mrank_sz = 0; /* loaded by max_rank_sz (from u_init) */
STATIC_DCL const char *NDECL(rank);
static char *
get_strength_str()
{
static char buf[32];
int st = ACURR(A_STR);
if (st > 18) {
if (st > STR18(100))
Sprintf(buf, "%2d", st - 100);
else if (st < STR18(100))
Sprintf(buf, "18/%02d", st - 18);
else
Sprintf(buf, "18/**");
} else
Sprintf(buf, "%-1d", st);
return buf;
}
#if !defined(STATUS_VIA_WINDOWPORT) || defined(DUMPLOG)
char *
@@ -48,16 +67,9 @@ do_statusline1()
j = (int) ((nb + 2) - newbot1); /* strlen(newbot1) but less computation */
if ((i - j) > 0)
Sprintf(nb = eos(nb), "%*s", i - j, " "); /* pad with spaces */
if (ACURR(A_STR) > 18) {
if (ACURR(A_STR) > STR18(100))
Sprintf(nb = eos(nb), "St:%2d ", ACURR(A_STR) - 100);
else if (ACURR(A_STR) < STR18(100))
Sprintf(nb = eos(nb), "St:18/%02d ", ACURR(A_STR) - 18);
else
Sprintf(nb = eos(nb), "St:18/** ");
} else
Sprintf(nb = eos(nb), "St:%-1d ", ACURR(A_STR));
Sprintf(nb = eos(nb), "Dx:%-1d Co:%-1d In:%-1d Wi:%-1d Ch:%-1d",
Sprintf(nb = eos(nb), "St:%s Dx:%-1d Co:%-1d In:%-1d Wi:%-1d Ch:%-1d",
get_strength_str(),
ACURR(A_DEX), ACURR(A_CON), ACURR(A_INT), ACURR(A_WIS),
ACURR(A_CHA));
Sprintf(nb = eos(nb),
@@ -470,18 +482,8 @@ bot()
valset[BL_TITLE] = TRUE; /* indicate val already set */
/* Strength */
buf[0] = '\0';
blstats[idx][BL_STR].a.a_int = ACURR(A_STR);
if (ACURR(A_STR) > 18) {
if (ACURR(A_STR) > STR18(100))
Sprintf(buf, "%2d", ACURR(A_STR) - 100);
else if (ACURR(A_STR) < STR18(100))
Sprintf(buf, "18/%02d", ACURR(A_STR) - 18);
else
Sprintf(buf, "18/**");
} else
Sprintf(buf, "%-1d", ACURR(A_STR));
Strcpy(blstats[idx][BL_STR].val, buf);
Strcpy(blstats[idx][BL_STR].val, get_strength_str());
valset[BL_STR] = TRUE; /* indicate val already set */
/* Dexterity, constitution, intelligence, wisdom, charisma. */
+43 -17
View File
@@ -135,6 +135,7 @@ STATIC_PTR int NDECL(wiz_level_change);
STATIC_PTR int NDECL(wiz_show_seenv);
STATIC_PTR int NDECL(wiz_show_vision);
STATIC_PTR int NDECL(wiz_smell);
STATIC_PTR int NDECL(wiz_intrinsic);
STATIC_PTR int NDECL(wiz_mon_polycontrol);
STATIC_PTR int NDECL(wiz_show_wmodes);
STATIC_DCL void NDECL(wiz_map_levltyp);
@@ -1157,38 +1158,52 @@ STATIC_PTR int
wiz_intrinsic(VOID_ARGS)
{
if (wizard) {
extern const char *const propertynames[]; /* timeout.c */
extern const struct propname {
int prop_num;
const char *prop_name;
} propertynames[]; /* timeout.c */
static const char wizintrinsic[] = "#wizintrinsic";
static const char fmt[] = "You are%s %s.";
winid win;
anything any;
char buf[BUFSZ];
int i, n, p, amt, typ;
int i, j, n, p, amt, typ;
long oldtimeout, newtimeout;
const char *propname;
menu_item *pick_list = (menu_item *) 0;
any = zeroany;
win = create_nhwindow(NHW_MENU);
start_menu(win);
for (i = 1; (propname = propertynames[i]) != 0; ++i) {
if (i == HALLUC_RES) {
for (i = 0; (propname = propertynames[i].prop_name) != 0; ++i) {
p = propertynames[i].prop_num;
if (p == HALLUC_RES) {
/* Grayswandir vs hallucination; ought to be redone to
use u.uprops[HALLUC].blocked instead of being treated
as a separate property; letting in be manually toggled
even only in wizard mode would be asking for trouble... */
continue;
}
any.a_int = i;
add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, propname, FALSE);
if (p == FIRE_RES) {
any.a_int = 0;
add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "--", FALSE);
}
any.a_int = i + 1; /* +1: avoid 0 */
oldtimeout = u.uprops[p].intrinsic & TIMEOUT;
if (oldtimeout)
Sprintf(buf, "%-27s [%li]", propname, oldtimeout);
else
Sprintf(buf, "%s", propname);
add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
}
end_menu(win, "Which intrinsics?");
n = select_menu(win, PICK_ANY, &pick_list);
destroy_nhwindow(win);
amt = 30; /* TODO: prompt for duration */
for (i = 0; i < n; ++i) {
p = pick_list[i].item.a_int;
for (j = 0; j < n; ++j) {
i = pick_list[j].item.a_int - 1; /* -1: reverse +1 above */
p = propertynames[i].prop_num;
oldtimeout = u.uprops[p].intrinsic & TIMEOUT;
newtimeout = oldtimeout + (long) amt;
switch (p) {
@@ -1204,9 +1219,12 @@ wiz_intrinsic(VOID_ARGS)
case BLINDED:
make_blinded(newtimeout, TRUE);
break;
#if 0 /* make_confused() only gives feedback when confusion is
* ending so use the 'default' case for it instead */
case CONFUSION:
make_confused(newtimeout, TRUE);
break;
#endif /*0*/
case DEAF:
make_deaf(newtimeout, TRUE);
break;
@@ -1236,7 +1254,7 @@ wiz_intrinsic(VOID_ARGS)
pline1(buf);
break;
default:
pline("Timeout for %s %s %d.", propertynames[p],
pline("Timeout for %s %s %d.", propertynames[i].prop_name,
oldtimeout ? "increased by" : "set to", amt);
incr_itimeout(&u.uprops[p].intrinsic, amt);
break;
@@ -2458,14 +2476,15 @@ int final;
/* named fruit debugging (doesn't really belong here...); to enable,
include 'fruit' in DEBUGFILES list (even though it isn't a file...) */
if (wizard && explicitdebug("fruit")) {
int fcount = 0;
struct fruit *f;
char buf2[BUFSZ];
reorder_fruit(TRUE); /* sort by fruit index, from low to high;
* this modifies the ffruit chain, so could
* possibly mask or even introduce a problem,
* but it does useful sanity checking */
for (f = ffruit; f; f = f->nextf) {
Sprintf(buf, "Fruit %d ", ++fcount);
Sprintf(buf2, "%s (id %d)", f->fname, f->fid);
enl_msg(buf, "is ", "was ", buf2, "");
Sprintf(buf, "Fruit #%d ", f->fid);
enl_msg(buf, "is ", "was ", f->fname, "");
}
enl_msg("The current fruit ", "is ", "was ", pl_fruit, "");
Sprintf(buf, "%d", flags.made_fruit);
@@ -3724,10 +3743,13 @@ struct {
{ NHKF_GETPOS_DOOR_PREV, 'D', "getpos.door.prev" },
{ NHKF_GETPOS_UNEX_NEXT, 'x', "getpos.unexplored.next" },
{ NHKF_GETPOS_UNEX_PREV, 'X', "getpos.unexplored.prev" },
{ NHKF_GETPOS_VALID_NEXT, 'z', "getpos.valid.next" },
{ NHKF_GETPOS_VALID_PREV, 'Z', "getpos.valid.prev" },
{ NHKF_GETPOS_INTERESTING_NEXT, 'a', "getpos.all.next" },
{ NHKF_GETPOS_INTERESTING_PREV, 'A', "getpos.all.prev" },
{ NHKF_GETPOS_HELP, '?', "getpos.help" },
{ NHKF_GETPOS_LIMITVIEW, '"', "getpos.inview" },
{ NHKF_GETPOS_LIMITVIEW, '"', "getpos.filter" },
{ NHKF_GETPOS_MOVESKIP, '*', "getpos.moveskip" },
{ NHKF_GETPOS_MENU, '!', "getpos.menu" }
};
@@ -5016,10 +5038,14 @@ dotravel(VOID_ARGS)
}
iflags.getloc_travelmode = TRUE;
if (iflags.menu_requested) {
if (!getpos_menu(&cc, TRUE, GLOC_INTERESTING)) {
int gf = iflags.getloc_filter;
iflags.getloc_filter = GFILTER_VIEW;
if (!getpos_menu(&cc, GLOC_INTERESTING)) {
iflags.getloc_filter = gf;
iflags.getloc_travelmode = FALSE;
return 0;
}
iflags.getloc_filter = gf;
} else {
pline("Where do you want to travel to?");
if (getpos(&cc, TRUE, "the desired destination") < 0) {
+178 -20
View File
@@ -36,12 +36,15 @@ nextmbuf()
* parameter value 0 = initialize, 1 = highlight, 2 = done
*/
static void FDECL((*getpos_hilitefunc), (int)) = (void FDECL((*), (int))) 0;
static boolean FDECL((*getpos_getvalid), (int,int)) = (boolean FDECL((*), (int,int))) 0;
void
getpos_sethilite(f)
getpos_sethilite(f, d)
void FDECL((*f), (int));
boolean FDECL((*d), (int,int));
{
getpos_hilitefunc = f;
getpos_getvalid = d;
}
const char *const gloc_descr[NUM_GLOCS][4] = {
@@ -54,6 +57,11 @@ const char *const gloc_descr[NUM_GLOCS][4] = {
"anything interesting" }
};
const char *const gloc_filtertxt[NUM_GFILTER] = {
"",
" in view",
" in this area"
};
void
getpos_help_keyxhelp(tmpwin, k1, k2, gloc)
@@ -69,7 +77,7 @@ int gloc;
iflags.getloc_usemenu ? "get a menu of "
: "move the cursor to ",
gloc_descr[gloc][2 + iflags.getloc_usemenu],
iflags.getloc_limitview ? " in view" : "");
gloc_filtertxt[iflags.getloc_filter]);
putstr(tmpwin, 0, sbuf);
}
@@ -82,13 +90,17 @@ const char *goal;
char sbuf[BUFSZ];
boolean doing_what_is;
winid tmpwin = create_nhwindow(NHW_MENU);
const char *const fastmovemode[2] = { "8 units at a time",
"skipping same glyphs" };
Sprintf(sbuf,
"Use '%c', '%c', '%c', '%c' to move the cursor to %s.", /* hjkl */
Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E, goal);
putstr(tmpwin, 0, sbuf);
putstr(tmpwin, 0,
"Use 'H', 'J', 'K', 'L' to move the cursor 8 units at a time.");
Sprintf(sbuf,
"Use 'H', 'J', 'K', 'L' to fast-move the cursor, %s.",
fastmovemode[iflags.getloc_moveskip]);
putstr(tmpwin, 0, sbuf);
putstr(tmpwin, 0, "Or enter a background symbol (ex. '<').");
Sprintf(sbuf, "Use '%s' to move the cursor on yourself.",
visctrl(Cmd.spkeys[NHKF_GETPOS_SELF]));
@@ -121,15 +133,26 @@ const char *goal;
visctrl(Cmd.spkeys[NHKF_GETPOS_INTERESTING_PREV]),
GLOC_INTERESTING);
}
Sprintf(sbuf, "Use '%s' to change fast-move mode to %s.",
visctrl(Cmd.spkeys[NHKF_GETPOS_MOVESKIP]),
fastmovemode[!iflags.getloc_moveskip]);
putstr(tmpwin, 0, sbuf);
Sprintf(sbuf, "Use '%s' to toggle menu listing for possible targets.",
visctrl(Cmd.spkeys[NHKF_GETPOS_MENU]));
putstr(tmpwin, 0, sbuf);
Sprintf(sbuf,
"Use '%s' to toggle limiting possible targets to in view only.",
"Use '%s' to change the mode of limiting possible targets.",
visctrl(Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]));
putstr(tmpwin, 0, sbuf);
if (!iflags.terrainmode) {
char kbuf[BUFSZ];
if (getpos_getvalid) {
Sprintf(sbuf, "Use '%s' or '%s' to move to valid locations.",
visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_NEXT]),
visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_PREV]));
putstr(tmpwin, 0, sbuf);
}
if (getpos_hilitefunc) {
Sprintf(sbuf, "Use '%s' to display valid locations.",
visctrl(Cmd.spkeys[NHKF_GETPOS_SHOWVALID]));
@@ -214,6 +237,99 @@ const void *b;
&& glyph_to_cmap(levl[(x)][(y)].glyph) == S_stone \
&& !levl[(x)][(y)].seenv)
static struct opvar *gloc_filter_map = (struct opvar *) 0;
#define GLOC_SAME_AREA(x,y) \
(isok((x), (y)) \
&& (selection_getpoint((x),(y), gloc_filter_map)))
static int gloc_filter_floodfill_match_glyph;
int
gloc_filter_classify_glyph(glyph)
int glyph;
{
int c;
if (!glyph_is_cmap(glyph))
return 0;
c = glyph_to_cmap(glyph);
if (is_cmap_room(c) || is_cmap_furniture(c))
return 1;
else if (is_cmap_wall(c) || c == S_tree)
return 2;
else if (is_cmap_corr(c))
return 3;
else if (is_cmap_water(c))
return 4;
else if (is_cmap_lava(c))
return 5;
return 0;
}
STATIC_OVL int
gloc_filter_floodfill_matcharea(x,y)
int x,y;
{
int glyph = back_to_glyph(x, y);
if (!levl[x][y].seenv)
return FALSE;
if (glyph == gloc_filter_floodfill_match_glyph)
return TRUE;
if (gloc_filter_classify_glyph(glyph) == gloc_filter_classify_glyph(gloc_filter_floodfill_match_glyph))
return TRUE;
return FALSE;
}
void
gloc_filter_floodfill(x,y)
int x,y;
{
gloc_filter_floodfill_match_glyph = back_to_glyph(x,y);
set_selection_floodfillchk(gloc_filter_floodfill_matcharea);
selection_floodfill(gloc_filter_map, x,y, FALSE);
}
void
gloc_filter_init()
{
if (iflags.getloc_filter == GFILTER_AREA) {
if (!gloc_filter_map) {
gloc_filter_map = selection_opvar(NULL);
}
/* special case: if we're in a doorway, try to figure out which
direction we're moving, and use that side of the doorway */
if (IS_DOOR(levl[u.ux][u.uy].typ)) {
if (u.dx || u.dy) {
gloc_filter_floodfill(u.ux + u.dx, u.uy + u.dy);
} else {
/* TODO: maybe add both sides of the doorway? */
}
} else {
gloc_filter_floodfill(u.ux, u.uy);
}
}
}
void
gloc_filter_done()
{
if (gloc_filter_map) {
opvar_free_x(gloc_filter_map);
gloc_filter_map = NULL;
}
}
STATIC_OVL boolean
gather_locs_interesting(x,y, gloc)
int x,y, gloc;
@@ -223,7 +339,13 @@ int x,y, gloc;
*/
int glyph = glyph_at(x, y);
if (iflags.getloc_limitview && !cansee(x,y))
if (iflags.getloc_filter == GFILTER_VIEW && !cansee(x,y))
return FALSE;
if (iflags.getloc_filter == GFILTER_AREA && !GLOC_SAME_AREA(x,y)
&& !GLOC_SAME_AREA(x-1,y)
&& !GLOC_SAME_AREA(x,y-1)
&& !GLOC_SAME_AREA(x+1,y)
&& !GLOC_SAME_AREA(x,y+1))
return FALSE;
switch (gloc) {
@@ -272,6 +394,8 @@ int x,y, gloc;
|| glyph_to_cmap(glyph) == S_darkroom
|| glyph_to_cmap(glyph) == S_corr
|| glyph_to_cmap(glyph) == S_litcorr));
case GLOC_VALID:
return (getpos_getvalid && getpos_getvalid(x,y));
}
/*NOTREACHED*/
return FALSE;
@@ -297,6 +421,9 @@ int gloc;
* Hero's spot will always sort to array[0] because it will always
* be the shortest distance (namely, 0 units) away from <u.ux,u.uy>.
*/
gloc_filter_init();
*cnt_p = idx = 0;
for (pass = 0; pass < 2; pass++) {
for (x = 1; x < COLNO; x++)
@@ -318,6 +445,8 @@ int gloc;
else /* end of second pass */
qsort(*arr_p, *cnt_p, sizeof (coord), cmp_coord_distu);
} /* pass */
gloc_filter_done();
}
char *
@@ -413,7 +542,9 @@ int cx, cy;
if (do_screen_description(cc, TRUE, sym, tmpbuf, &firstmatch)) {
(void) coord_desc(cx, cy, tmpbuf, iflags.getpos_coords);
custompline(SUPPRESS_HISTORY,
"%s%s%s%s", firstmatch, *tmpbuf ? " " : "", tmpbuf,
"%s%s%s%s%s", firstmatch, *tmpbuf ? " " : "", tmpbuf,
(iflags.autodescribe && getpos_getvalid && !getpos_getvalid(cx,cy))
? " (illegal)" : "",
(iflags.getloc_travelmode && !is_valid_travelpt(cx, cy))
? " (no travel path)" : "");
curs(WIN_MAP, cx, cy);
@@ -422,9 +553,8 @@ int cx, cy;
}
boolean
getpos_menu(ccp, fovonly, gloc)
getpos_menu(ccp, gloc)
coord *ccp;
boolean fovonly;
int gloc;
{
coord *garr = DUMMY;
@@ -440,7 +570,8 @@ int gloc;
if (gcount < 2) { /* gcount always includes the hero */
free((genericptr_t) garr);
You("cannot %s %s.",
fovonly ? "see" : "detect", gloc_descr[gloc][0]);
iflags.getloc_filter == GFILTER_VIEW ? "see" : "detect",
gloc_descr[gloc][0]);
return FALSE;
}
@@ -466,7 +597,8 @@ int gloc;
}
Sprintf(tmpbuf, "Pick a target %s%s%s",
gloc_descr[gloc][1], fovonly ? " in view" : "",
gloc_descr[gloc][1],
gloc_filtertxt[iflags.getloc_filter],
iflags.getloc_travelmode ? " for travel" : "");
end_menu(tmpwin, tmpbuf);
pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
@@ -505,10 +637,12 @@ const char *goal;
NHKF_GETPOS_UNEX_NEXT,
NHKF_GETPOS_UNEX_PREV,
NHKF_GETPOS_INTERESTING_NEXT,
NHKF_GETPOS_INTERESTING_PREV
NHKF_GETPOS_INTERESTING_PREV,
NHKF_GETPOS_VALID_NEXT,
NHKF_GETPOS_VALID_PREV
};
char pick_chars[6];
char mMoOdDxX[11];
char mMoOdDxX[13];
int result = 0;
int cx, cy, i, c;
int sidx, tx, ty;
@@ -595,8 +729,23 @@ const char *goal;
} else if (Cmd.alphadirchars[i] == lowc((char) c)
|| (Cmd.num_pad && Cmd.dirchars[i] == (c & 0177))) {
/* a shifted movement letter or Meta-digit */
dx = 8 * xdir[i];
dy = 8 * ydir[i];
if (iflags.getloc_moveskip) {
/* skip same glyphs */
int glyph = glyph_at(cx, cy);
dx = xdir[i];
dy = ydir[i];
while (isok(cx + dx, cy + dy)
&& glyph == glyph_at(cx + dx, cy + dy)
&& isok(cx + dx+xdir[i], cy+dy+ydir[i])
&& glyph == glyph_at(cx + dx+xdir[i], cy + dy+ydir[i])) {
dx += xdir[i];
dy += ydir[i];
}
} else {
dx = 8 * xdir[i];
dy = 8 * ydir[i];
}
} else
continue;
@@ -646,7 +795,12 @@ const char *goal;
msg_given = TRUE;
goto nxtc;
} else if (c == Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]) {
iflags.getloc_limitview = !iflags.getloc_limitview;
const char *const view_filters[NUM_GFILTER] = {
"Not limiting targets",
"Limiting targets to in sight",
"Limiting targets to in same area"
};
iflags.getloc_filter = (iflags.getloc_filter + 1) % NUM_GFILTER;
for (i = 0; i < NUM_GLOCS; i++) {
if (garr[i]) {
free((genericptr_t) garr[i]);
@@ -654,8 +808,7 @@ const char *goal;
}
gidx[i] = gcount[i] = 0;
}
pline("%s possible targets to those in sight only.",
iflags.getloc_limitview ? "Limiting" : "Not limiting");
pline("%s.", view_filters[iflags.getloc_filter]);
msg_given = TRUE;
goto nxtc;
} else if (c == Cmd.spkeys[NHKF_GETPOS_MENU]) {
@@ -672,6 +825,10 @@ const char *goal;
cx = u.ux;
cy = u.uy;
goto nxtc;
} else if (c == Cmd.spkeys[NHKF_GETPOS_MOVESKIP]) {
iflags.getloc_moveskip = !iflags.getloc_moveskip;
pline("%skipping over similar terrain when fastmoving the cursor.",
iflags.getloc_moveskip ? "S" : "Not s");
} else if ((cp = index(mMoOdDxX, c)) != 0) { /* 'm|M', 'o|O', &c */
/* nearest or farthest monster or object or door or unexplored */
int gtmp = (int) (cp - mMoOdDxX), /* 0..7 */
@@ -679,7 +836,7 @@ const char *goal;
if (iflags.getloc_usemenu) {
coord tmpcrd;
if (getpos_menu(&tmpcrd, iflags.getloc_limitview, gloc)) {
if (getpos_menu(&tmpcrd, gloc)) {
cx = tmpcrd.x;
cy = tmpcrd.y;
}
@@ -808,6 +965,7 @@ const char *goal;
if (garr[i])
free((genericptr_t) garr[i]);
getpos_hilitefunc = (void FDECL((*), (int))) 0;
getpos_getvalid = (boolean FDECL((*), (int,int))) 0;
return result;
}
@@ -1880,7 +2038,7 @@ static const char *const sir_Terry_novels[] = {
"Lords and Ladies", "Men at Arms", "Soul Music", "Interesting Times",
"Maskerade", "Feet of Clay", "Hogfather", "Jingo", "The Last Continent",
"Carpe Jugulum", "The Fifth Elephant", "The Truth", "Thief of Time",
"The Last Hero", "The Amazing Maurice and his Educated Rodents",
"The Last Hero", "The Amazing Maurice and His Educated Rodents",
"Night Watch", "The Wee Free Men", "Monstrous Regiment",
"A Hat Full of Sky", "Going Postal", "Thud!", "Wintersmith",
"Making Money", "Unseen Academicals", "I Shall Wear Midnight", "Snuff",
+9 -5
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 dog.c $NHDT-Date: 1446808440 2015/11/06 11:14:00 $ $NHDT-Branch: master $:$NHDT-Revision: 1.52 $ */
/* NetHack 3.6 dog.c $NHDT-Date: 1502753406 2017/08/14 23:30:06 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.60 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -736,7 +736,8 @@ struct monst *mon;
register struct obj *obj;
{
struct permonst *mptr = mon->data, *fptr = 0;
boolean carni = carnivorous(mptr), herbi = herbivorous(mptr), starving;
boolean carni = carnivorous(mptr), herbi = herbivorous(mptr),
starving, mblind;
if (is_quest_artifact(obj) || obj_resists(obj, 0, 95))
return obj->cursed ? TABU : APPORT;
@@ -755,8 +756,10 @@ register struct obj *obj;
return obj->cursed ? UNDEF : APPORT;
/* a starving pet will eat almost anything */
starving =
(mon->mtame && !mon->isminion && EDOG(mon)->mhpmax_penalty);
starving = (mon->mtame && !mon->isminion
&& EDOG(mon)->mhpmax_penalty);
/* even carnivores will eat carrots if they're temporarily blind */
mblind = (!mon->mcansee && haseyes(mon->data));
/* ghouls prefer old corpses and unhatchable eggs, yum!
they'll eat fresh non-veggy corpses and hatchable eggs
@@ -813,8 +816,9 @@ register struct obj *obj;
case TIN:
return metallivorous(mptr) ? ACCFOOD : MANFOOD;
case APPLE:
case CARROT:
return herbi ? DOGFOOD : starving ? ACCFOOD : MANFOOD;
case CARROT:
return (herbi || mblind) ? DOGFOOD : starving ? ACCFOOD : MANFOOD;
case BANANA:
return (mptr->mlet == S_YETI && herbi)
? DOGFOOD /* for monkey and ape (tameable), sasquatch */
+5 -2
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 dogmove.c $NHDT-Date: 1463704424 2016/05/20 00:33:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.60 $ */
/* NetHack 3.6 dogmove.c $NHDT-Date: 1502753407 2017/08/14 23:30:07 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.63 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -209,7 +209,7 @@ int x, y; /* dog's starting location, might be different from current */
boolean devour;
{
register struct edog *edog = EDOG(mtmp);
boolean poly, grow, heal, slimer, deadmimic;
boolean poly, grow, heal, eyes, slimer, deadmimic;
int nutrit;
long oprice;
char objnambuf[BUFSZ];
@@ -226,6 +226,7 @@ boolean devour;
poly = polyfodder(obj);
grow = mlevelgain(obj);
heal = mhealup(obj);
eyes = (obj->otyp == CARROT);
if (devour) {
if (mtmp->meating > 1)
@@ -343,6 +344,8 @@ boolean devour;
}
if (heal)
mtmp->mhp = mtmp->mhpmax;
if ((eyes || heal) && !mtmp->mcansee)
mcureblindness(mtmp, canseemon(mtmp));
if (deadmimic)
quickmimic(mtmp);
return 1;
+23 -7
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 dothrow.c $NHDT-Date: 1455140444 2016/02/10 21:40:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.118 $ */
/* NetHack 3.6 dothrow.c $NHDT-Date: 1502243899 2017/08/09 01:58:19 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.125 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -448,7 +448,22 @@ genericptr_t arg;
int x, y, dx, dy, x_change, y_change, err, i, prev_x, prev_y;
boolean keep_going = TRUE;
/* Use Bresenham's Line Algorithm to walk from src to dest */
/* Use Bresenham's Line Algorithm to walk from src to dest.
*
* This should be replaced with a more versatile algorithm
* since it handles slanted moves in a suboptimal way.
* Going from 'x' to 'y' needs to pass through 'z', and will
* fail if there's an obstable there, but it could choose to
* pass through 'Z' instead if that way imposes no obstacle.
* ..y .Zy
* xz. vs x..
* Perhaps we should check both paths and accept whichever
* one isn't blocked. But then multiple zigs and zags could
* potentially produce a meandering path rather than the best
* attempt at a straight line. And (*check_proc)() would
* need to work more like 'travel', distinguishing between
* testing a possible move and actually attempting that move.
*/
dx = dest_cc->x - src_cc->x;
dy = dest_cc->y - src_cc->y;
prev_x = x = src_cc->x;
@@ -640,9 +655,11 @@ int x, y;
vision_recalc(1); /* update for new position */
flush_screen(1);
if (levl[x][y].typ == WATER && Is_waterlevel(&u.uz)) {
multi = 0;
drown();
if (is_pool(x, y) && !u.uinwater
&& ((Is_waterlevel(&u.uz) && levl[x][y].typ == WATER)
|| !(Levitation || Flying || Wwalking))) {
multi = 0; /* can move, so drown() allows crawling out of water */
(void) drown();
return FALSE;
}
@@ -768,8 +785,7 @@ boolean verbose;
(void) walk_path(&uc, &cc, hurtle_step, (genericptr_t) &range);
}
/* Move a monster through the air for a few squares.
*/
/* Move a monster through the air for a few squares. */
void
mhurtle(mon, dx, dy, range)
struct monst *mon;
+12 -11
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 eat.c $NHDT-Date: 1470272344 2016/08/04 00:59:04 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.172 $ */
/* NetHack 3.6 eat.c $NHDT-Date: 1502754159 2017/08/14 23:42:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.179 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -6,7 +6,7 @@
STATIC_PTR int NDECL(eatmdone);
STATIC_PTR int NDECL(eatfood);
STATIC_PTR void FDECL(costly_tin, (int));
STATIC_PTR struct obj *FDECL(costly_tin, (int));
STATIC_PTR int NDECL(opentin);
STATIC_PTR int NDECL(unfaint);
@@ -979,6 +979,7 @@ register int pm;
u.mh = u.mhmax;
else
u.uhp = u.uhpmax;
make_blinded(0L, !u.ucreamed);
context.botl = 1;
break;
case PM_STALKER:
@@ -1152,7 +1153,7 @@ violated_vegetarian()
/* common code to check and possibly charge for 1 context.tin.tin,
* will split() context.tin.tin if necessary */
STATIC_PTR void
STATIC_PTR struct obj *
costly_tin(alter_type)
int alter_type; /* COST_xxx */
{
@@ -1166,6 +1167,7 @@ int alter_type; /* COST_xxx */
}
costly_alteration(tin, alter_type);
}
return tin;
}
int
@@ -1293,7 +1295,7 @@ const char *mesg;
r = tin_variety(tin, FALSE);
if (tin->otrapped || (tin->cursed && r != HOMEMADE_TIN && !rn2(8))) {
b_trapped("tin", 0);
costly_tin(COST_DSTROY);
tin = costly_tin(COST_DSTROY);
goto use_up_tin;
}
@@ -1304,7 +1306,7 @@ const char *mesg;
if (mnum == NON_PM) {
pline("It turns out to be empty.");
tin->dknown = tin->known = 1;
costly_tin(COST_OPEN);
tin = costly_tin(COST_OPEN);
goto use_up_tin;
}
@@ -1333,7 +1335,7 @@ const char *mesg;
You("discard the open tin.");
if (!Hallucination)
tin->dknown = tin->known = 1;
costly_tin(COST_OPEN);
tin = costly_tin(COST_OPEN);
goto use_up_tin;
}
@@ -1352,7 +1354,7 @@ const char *mesg;
cpostfx(mnum);
/* charge for one at pre-eating cost */
costly_tin(COST_OPEN);
tin = costly_tin(COST_OPEN);
if (tintxts[r].nut < 0) /* rotten */
make_vomiting((long) rn1(15, 10), FALSE);
@@ -1378,7 +1380,7 @@ const char *mesg;
if (yn("Eat it?") == 'n') {
if (flags.verbose)
You("discard the open tin.");
costly_tin(COST_OPEN);
tin = costly_tin(COST_OPEN);
goto use_up_tin;
}
@@ -1386,14 +1388,13 @@ const char *mesg;
* Same order as with non-spinach above:
* conduct update, side-effects, shop handling, and nutrition.
*/
u.uconduct
.food++; /* don't need vegan/vegetarian checks for spinach */
u.uconduct.food++; /* don't need vegetarian checks for spinach */
if (!tin->cursed)
pline("This makes you feel like %s!",
Hallucination ? "Swee'pea" : "Popeye");
gainstr(tin, 0, FALSE);
costly_tin(COST_OPEN);
tin = costly_tin(COST_OPEN);
lesshungry(tin->blessed
? 600 /* blessed */
+25 -15
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 files.c $NHDT-Date: 1459987580 2016/04/07 00:06:20 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.205 $ */
/* NetHack 3.6 files.c $NHDT-Date: 1502581476 2017/08/12 23:44:36 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.211 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -617,6 +617,7 @@ const char *name;
int lev, oflag;
{
int reslt, fd;
if (!lftrack.init) {
lftrack.init = 1;
lftrack.fd = -1;
@@ -671,7 +672,7 @@ int fd;
}
return close(fd);
}
#else
#else /* !HOLD_LOCKFILE_OPEN */
int
nhclose(fd)
@@ -679,7 +680,7 @@ int fd;
{
return close(fd);
}
#endif
#endif /* ?HOLD_LOCKFILE_OPEN */
/* ---------- END LEVEL FILE HANDLING ----------- */
@@ -3065,8 +3066,8 @@ const char *dir UNUSED_if_not_OS2_CODEVIEW;
#ifdef VMS /* must be stream-lf to use UPDATE_RECORD_IN_PLACE */
if (!file_is_stmlf(fd)) {
raw_printf(
"Warning: scoreboard file %s is not in stream_lf format",
fq_record);
"Warning: scoreboard file '%s' is not in stream_lf format",
fq_record);
wait_synch();
}
#endif
@@ -3078,7 +3079,7 @@ const char *dir UNUSED_if_not_OS2_CODEVIEW;
(void) chmod(fq_record, FCMASK | 007);
#endif /* VMS && !SECURE */
} else {
raw_printf("Warning: cannot write scoreboard file %s", fq_record);
raw_printf("Warning: cannot write scoreboard file '%s'", fq_record);
wait_synch();
}
#endif /* !UNIX && !VMS */
@@ -3101,22 +3102,25 @@ const char *dir UNUSED_if_not_OS2_CODEVIEW;
#endif
if ((fd = open(fq_record, O_RDWR)) < 0) {
/* try to create empty record */
/* try to create empty 'record' */
#if defined(AZTEC_C) || defined(_DCC) \
|| (defined(__GNUC__) && defined(__AMIGA__))
/* Aztec doesn't use the third argument */
/* DICE doesn't like it */
if ((fd = open(fq_record, O_CREAT | O_RDWR)) < 0) {
fd = open(fq_record, O_CREAT | O_RDWR);
#else
if ((fd = open(fq_record, O_CREAT | O_RDWR, S_IREAD | S_IWRITE))
< 0) {
fd = open(fq_record, O_CREAT | O_RDWR, S_IREAD | S_IWRITE);
#endif
raw_printf("Warning: cannot write record %s", tmp);
if (fd = < 0) {
raw_printf("Warning: cannot write record '%s'", tmp);
wait_synch();
} else
} else {
(void) nhclose(fd);
} else /* open succeeded */
}
} else {
/* open succeeded => 'record' exists */
(void) nhclose(fd);
}
#else /* MICRO || WIN32*/
#ifdef MAC
@@ -3260,6 +3264,7 @@ recover_savefile()
raw_printf("\nError writing %s; recovery failed.", SAVEF);
(void) nhclose(gfd);
(void) nhclose(sfd);
(void) nhclose(lfd);
delete_savefile();
return FALSE;
}
@@ -3269,6 +3274,7 @@ recover_savefile()
SAVEF);
(void) nhclose(gfd);
(void) nhclose(sfd);
(void) nhclose(lfd);
delete_savefile();
return FALSE;
}
@@ -3279,6 +3285,7 @@ recover_savefile()
SAVEF);
(void) nhclose(gfd);
(void) nhclose(sfd);
(void) nhclose(lfd);
delete_savefile();
return FALSE;
}
@@ -3288,13 +3295,15 @@ recover_savefile()
SAVEF);
(void) nhclose(gfd);
(void) nhclose(sfd);
(void) nhclose(lfd);
delete_savefile();
return FALSE;
}
if (!copy_bytes(lfd, sfd)) {
(void) nhclose(lfd);
(void) nhclose(gfd);
(void) nhclose(sfd);
(void) nhclose(lfd);
delete_savefile();
return FALSE;
}
@@ -3302,7 +3311,7 @@ recover_savefile()
processed[savelev] = 1;
if (!copy_bytes(gfd, sfd)) {
(void) nhclose(lfd);
(void) nhclose(gfd);
(void) nhclose(sfd);
delete_savefile();
return FALSE;
@@ -3343,6 +3352,7 @@ recover_savefile()
for (lev = 0; lev < 256; lev++) {
if (processed[lev]) {
const char *fq_lock;
set_levelfile_name(lock, lev);
fq_lock = fqname(lock, LEVELPREFIX, 3);
(void) unlink(fq_lock);
+2 -1
View File
@@ -1747,7 +1747,8 @@ int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || ident
|| takeoff || take_out || put_in);
ininv = (*objchn == invent);
bycat = (menu_class_present('B') || menu_class_present('U')
bycat = (menu_class_present('u')
|| menu_class_present('B') || menu_class_present('U')
|| menu_class_present('C') || menu_class_present('X'));
/* someday maybe we'll sort by 'olets' too (temporarily replace
+32 -1
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 mkobj.c $NHDT-Date: 1462067745 2016/05/01 01:55:45 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.122 $ */
/* NetHack 3.6 mkobj.c $NHDT-Date: 1501725405 2017/08/03 01:56:45 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.124 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -2720,4 +2720,35 @@ struct obj **obj1, **obj2;
return (struct obj *) 0;
}
/* give a message if hero notices two globs merging [used to be in pline.c] */
void
pudding_merge_message(otmp, otmp2)
struct obj *otmp;
struct obj *otmp2;
{
boolean visible = (cansee(otmp->ox, otmp->oy)
|| cansee(otmp2->ox, otmp2->oy)),
onfloor = (otmp->where == OBJ_FLOOR || otmp2->where == OBJ_FLOOR),
inpack = (carried(otmp) || carried(otmp2));
/* the player will know something happened inside his own inventory */
if ((!Blind && visible) || inpack) {
if (Hallucination) {
if (onfloor) {
You_see("parts of the floor melting!");
} else if (inpack) {
Your("pack reaches out and grabs something!");
}
/* even though we can see where they should be,
* they'll be out of our view (minvent or container)
* so don't actually show anything */
} else if (onfloor || inpack) {
pline("The %s coalesce%s.", makeplural(obj_typename(otmp->otyp)),
inpack ? " inside your pack" : "");
}
} else {
You_hear("a faint sloshing sound.");
}
}
/*mkobj.c*/
+21 -1
View File
@@ -239,6 +239,26 @@ int type;
}
}
void
mk_zoo_thronemon(x,y)
int x,y;
{
int i = rnd(level_difficulty());
int pm = (i > 9) ? PM_OGRE_KING
: (i > 5) ? PM_ELVENKING
: (i > 2) ? PM_DWARF_KING
: PM_GNOME_KING;
struct monst *mon = makemon(&mons[pm], x, y, NO_MM_FLAGS);
if (mon) {
mon->msleeping = 1;
mon->mpeaceful = 0;
set_malign(mon);
/* Give him a sceptre to pound in judgment */
(void) mongets(mon, MACE);
}
}
void
fill_zoo(sroom)
struct mkroom *sroom;
@@ -265,7 +285,7 @@ struct mkroom *sroom;
ty = mm.y;
} while (occupied((xchar) tx, (xchar) ty) && --i > 0);
throne_placed:
/* TODO: try to ensure the enthroned monster is an M2_PRINCE */
mk_zoo_thronemon(tx, ty);
break;
case BEEHIVE:
tx = sroom->lx + (sroom->hx - sroom->lx + 1) / 2;
+6 -3
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 mon.c $NHDT-Date: 1496531114 2017/06/03 23:05:14 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.240 $ */
/* NetHack 3.6 mon.c $NHDT-Date: 1502753408 2017/08/14 23:30:08 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.242 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -886,9 +886,9 @@ int
meatobj(mtmp) /* for gelatinous cubes */
struct monst *mtmp;
{
register struct obj *otmp, *otmp2;
struct obj *otmp, *otmp2;
struct permonst *ptr, *original_ptr = mtmp->data;
int poly, grow, heal, count = 0, ecount = 0;
int poly, grow, heal, eyes, count = 0, ecount = 0;
char buf[BUFSZ];
buf[0] = '\0';
@@ -986,6 +986,7 @@ struct monst *mtmp;
poly = polyfodder(otmp);
grow = mlevelgain(otmp);
heal = mhealup(otmp);
eyes = (otmp->otyp == CARROT);
delobj(otmp); /* munch */
ptr = mtmp->data;
if (poly) {
@@ -996,6 +997,8 @@ struct monst *mtmp;
} else if (heal) {
mtmp->mhp = mtmp->mhpmax;
}
if ((eyes || heal) && !mtmp->mcansee)
mcureblindness(mtmp, canseemon(mtmp));
/* in case it polymorphed or died */
if (ptr != original_ptr)
return !ptr ? 2 : 1;
+23 -24
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 muse.c $NHDT-Date: 1469840918 2016/07/30 01:08:38 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.78 $ */
/* NetHack 3.6 muse.c $NHDT-Date: 1502753408 2017/08/14 23:30:08 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.79 $ */
/* Copyright (C) 1990 by Ken Arromdee */
/* NetHack may be freely redistributed. See license for details. */
@@ -603,7 +603,7 @@ struct monst *mtmp;
int i, fleetim, how = 0;
struct obj *otmp = m.defensive;
boolean vis, vismon, oseen;
const char *Mnam, *mcsa = "%s can see again.";
const char *Mnam;
if ((i = precheck(mtmp, otmp)) != 0)
return i;
@@ -628,10 +628,7 @@ struct monst *mtmp;
pline_The("tip of %s's horn glows!", mon_nam(mtmp));
}
if (!mtmp->mcansee) {
mtmp->mcansee = 1;
mtmp->mblinded = 0;
if (vismon)
pline(mcsa, Monnam(mtmp));
mcureblindness(mtmp, vismon);
} else if (mtmp->mconf || mtmp->mstun) {
mtmp->mconf = mtmp->mstun = 0;
if (vismon)
@@ -939,12 +936,8 @@ struct monst *mtmp;
mtmp->mhp += i;
if (mtmp->mhp > mtmp->mhpmax)
mtmp->mhp = ++mtmp->mhpmax;
if (!otmp->cursed && !mtmp->mcansee) {
mtmp->mcansee = 1;
mtmp->mblinded = 0;
if (vismon)
pline(mcsa, Monnam(mtmp));
}
if (!otmp->cursed && !mtmp->mcansee)
mcureblindness(mtmp, vismon);
if (vismon)
pline("%s looks better.", Monnam(mtmp));
if (oseen)
@@ -957,12 +950,8 @@ struct monst *mtmp;
mtmp->mhp += i;
if (mtmp->mhp > mtmp->mhpmax)
mtmp->mhp = (mtmp->mhpmax += (otmp->blessed ? 5 : 2));
if (!mtmp->mcansee) {
mtmp->mcansee = 1;
mtmp->mblinded = 0;
if (vismon)
pline(mcsa, Monnam(mtmp));
}
if (!mtmp->mcansee)
mcureblindness(mtmp, vismon);
if (vismon)
pline("%s looks much better.", Monnam(mtmp));
if (oseen)
@@ -974,12 +963,8 @@ struct monst *mtmp;
if (otmp->otyp == POT_SICKNESS)
unbless(otmp); /* Pestilence */
mtmp->mhp = (mtmp->mhpmax += (otmp->blessed ? 8 : 4));
if (!mtmp->mcansee && otmp->otyp != POT_SICKNESS) {
mtmp->mcansee = 1;
mtmp->mblinded = 0;
if (vismon)
pline(mcsa, Monnam(mtmp));
}
if (!mtmp->mcansee && otmp->otyp != POT_SICKNESS)
mcureblindness(mtmp, vismon);
if (vismon)
pline("%s looks completely healed.", Monnam(mtmp));
if (oseen)
@@ -2175,6 +2160,20 @@ const char *fmt, *str;
return FALSE;
}
/* cure mon's blindness (use_defensive, dog_eat, meatobj) */
void
mcureblindness(mon, verbos)
struct monst *mon;
boolean verbos;
{
if (!mon->mcansee) {
mon->mcansee = 1;
mon->mblinded = 0;
if (verbos && haseyes(mon->data))
pline("%s can see again.", Monnam(mon));
}
}
/* TRUE if the monster ate something */
boolean
munstone(mon, by_you)
+211 -61
View File
@@ -90,8 +90,12 @@ releaseobuf(bufp)
char *bufp;
{
/* caller may not know whether bufp is the most recently allocated
buffer; if it isn't, do nothing */
if (bufp == obufs[obufidx])
buffer; if it isn't, do nothing; note that because of the somewhat
obscure PREFIX handling for object name formatting by xname(),
the pointer our caller has and is passing to us might be into the
middle of an obuf rather than the address returned by nextobuf() */
if (bufp >= obufs[obufidx]
&& bufp < obufs[obufidx] + sizeof obufs[obufidx]) /* obufs[][BUFSZ] */
obufidx = (obufidx - 1 + NUMOBUF) % NUMOBUF;
}
@@ -100,11 +104,11 @@ obj_typename(otyp)
register int otyp;
{
char *buf = nextobuf();
register struct objclass *ocl = &objects[otyp];
register const char *actualn = OBJ_NAME(*ocl);
register const char *dn = OBJ_DESCR(*ocl);
register const char *un = ocl->oc_uname;
register int nn = ocl->oc_name_known;
struct objclass *ocl = &objects[otyp];
const char *actualn = OBJ_NAME(*ocl);
const char *dn = OBJ_DESCR(*ocl);
const char *un = ocl->oc_uname;
int nn = ocl->oc_name_known;
if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
actualn = Japanese_item_name(otyp);
@@ -251,6 +255,135 @@ boolean juice; /* whether or not to append " juice" to the name */
return buf;
}
/* look up a named fruit by index (1..127) */
struct fruit *
fruit_from_indx(indx)
int indx;
{
struct fruit *f;
for (f = ffruit; f; f = f->nextf)
if (f->fid == indx)
break;
return f;
}
/* look up a named fruit by name */
struct fruit *
fruit_from_name(fname, exact, highest_fid)
const char *fname;
boolean exact; /* False => prefix or exact match, True = exact match only */
int *highest_fid; /* optional output; only valid if 'fname' isn't found */
{
struct fruit *f, *tentativef;
char *altfname;
unsigned k;
/*
* note: named fruits are case-senstive...
*/
if (highest_fid)
*highest_fid = 0;
/* first try for an exact match */
for (f = ffruit; f; f = f->nextf)
if (!strcmp(f->fname, fname))
return f;
else if (highest_fid && f->fid > *highest_fid)
*highest_fid = f->fid;
/* didn't match as-is; if caller is willing to accept a prefix
match, try to find one; we want to find the longest prefix that
matches, not the first */
if (!exact) {
tentativef = 0;
for (f = ffruit; f; f = f->nextf) {
k = strlen(f->fname);
if (!strncmp(f->fname, fname, k)
&& (!fname[k] || fname[k] == ' ')
&& (!tentativef || k > strlen(tentativef->fname)))
tentativef = f;
}
f = tentativef;
}
/* if we still don't have a match, try singularizing the target;
for exact match, that's trivial, but for prefix, it's hard */
if (!f) {
altfname = makesingular(fname);
for (f = ffruit; f; f = f->nextf) {
if (!strcmp(f->fname, altfname))
break;
}
releaseobuf(altfname);
}
if (!f && !exact) {
char fnamebuf[BUFSZ], *p;
unsigned fname_k = strlen(fname); /* length of assumed plural fname */
tentativef = 0;
for (f = ffruit; f; f = f->nextf) {
k = strlen(f->fname);
/* reload fnamebuf[] each iteration in case it gets modified;
there's no need to recalculate fname_k */
Strcpy(fnamebuf, fname);
/* bug? if singular of fname is longer than plural,
failing the 'fname_k > k' test could skip a viable
candidate; unfortunately, we can't singularize until
after stripping off trailing stuff and we can't get
accurate fname_k until fname has been singularized;
compromise and use 'fname_k >= k' instead of '>',
accepting 1 char length discrepancy without risking
false match (I hope...) */
if (fname_k >= k && (p = index(&fnamebuf[k], ' ')) != 0) {
*p = '\0'; /* truncate at 1st space past length of f->fname */
altfname = makesingular(fnamebuf);
k = strlen(altfname); /* actually revised 'fname_k' */
if (!strcmp(f->fname, altfname)
&& (!tentativef || k > strlen(tentativef->fname)))
tentativef = f;
releaseobuf(altfname); /* avoid churning through all obufs */
}
}
f = tentativef;
}
return f;
}
/* sort the named-fruit linked list by fruit index number */
void
reorder_fruit(forward)
boolean forward;
{
struct fruit *f, *allfr[1 + 127];
int i, j, k = SIZE(allfr);
for (i = 0; i < k; ++i)
allfr[i] = (struct fruit *) 0;
for (f = ffruit; f; f = f->nextf) {
/* without sanity checking, this would reduce to 'allfr[f->fid]=f' */
j = f->fid;
if (j < 1 || j >= k) {
impossible("reorder_fruit: fruit index (%d) out of range", j);
return; /* don't sort after all; should never happen... */
} else if (allfr[j]) {
impossible("reorder_fruit: duplicate fruit index (%d)", j);
return;
}
allfr[j] = f;
}
ffruit = 0; /* reset linked list; we're rebuilding it from scratch */
/* slot [0] will always be empty; must start 'i' at 1 to avoid
[k - i] being out of bounds during first iteration */
for (i = 1; i < k; ++i) {
/* for forward ordering, go through indices from high to low;
for backward ordering, go from low to high */
j = forward ? (k - i) : i;
if (allfr[j]) {
allfr[j]->nextf = ffruit;
ffruit = allfr[j];
}
}
}
char *
xname(obj)
struct obj *obj;
@@ -388,23 +521,20 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
break;
case FOOD_CLASS:
if (typ == SLIME_MOLD) {
register struct fruit *f;
struct fruit *f = fruit_from_indx(obj->spe);
for (f = ffruit; f; f = f->nextf) {
if (f->fid == obj->spe) {
Strcpy(buf, f->fname);
break;
}
}
if (!f) {
impossible("Bad fruit #%d?", obj->spe);
Strcpy(buf, "fruit");
} else if (pluralize) {
/* ick; already pluralized fruit names
are allowed--we want to try to avoid
adding a redundant plural suffix */
Strcpy(buf, makeplural(makesingular(buf)));
pluralize = FALSE;
} else {
Strcpy(buf, f->fname);
if (pluralize) {
/* ick; already pluralized fruit names
are allowed--we want to try to avoid
adding a redundant plural suffix */
Strcpy(buf, makeplural(makesingular(buf)));
pluralize = FALSE;
}
}
break;
}
@@ -1493,7 +1623,10 @@ const char *str;
buf[0] = lowc(*str);
Strcpy(&buf[1], str + 1);
return buf;
} else if (*str < 'A' || *str > 'Z') {
} else if (*str < 'A' || *str > 'Z'
/* treat named fruit as not a proper name, even if player
has assigned a capitalized proper name as his/her fruit */
|| fruit_from_name(str, TRUE, (int *) 0)) {
/* not a proper name, needs an article */
insert_the = TRUE;
} else {
@@ -2010,10 +2143,14 @@ char *str;
return 0;
}
/* Plural routine; chiefly used for user-defined fruits. We have to try to
* account for everything reasonable the player has; something unreasonable
* can still break the code. However, it's still a lot more accurate than
* "just add an s at the end", which Rogue uses...
/* Plural routine; once upon a time it may have been chiefly used for
* user-defined fruits, but it is now used extensively throughout the
* program.
*
* For fruit, we have to try to account for everything reasonable the
* player has; something unreasonable can still break the code.
* However, it's still a lot more accurate than "just add an 's' at the
* end", which Rogue uses...
*
* Also used for plural monster names ("Wiped out all homunculi." or the
* vanquished monsters list) and body parts. A lot of unique monsters have
@@ -2847,9 +2984,14 @@ struct obj *no_wish;
if (!strstri(bp, "wand ") && !strstri(bp, "spellbook ")
&& !strstri(bp, "finger ")) {
if ((p = strstri(bp, "tin of ")) != 0) {
tmp = tin_variety_txt(p + 7, &tinv);
tvariety = tinv;
mntmp = name_to_mon(p + 7 + tmp);
if (!strcmpi(p + 7, "spinach")) {
contents = SPINACH;
mntmp = NON_PM;
} else {
tmp = tin_variety_txt(p + 7, &tinv);
tvariety = tinv;
mntmp = name_to_mon(p + 7 + tmp);
}
typ = TIN;
goto typfnd;
} else if ((p = strstri(bp, " of ")) != 0
@@ -2858,35 +3000,32 @@ struct obj *no_wish;
}
}
/* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */
if (strncmpi(bp, "samurai sword", 13)) /* not the "samurai" monster! */
if (strncmpi(bp, "wizard lock", 11)) /* not the "wizard" monster! */
if (strncmpi(bp, "ninja-to", 8)) /* not the "ninja" rank */
if (strncmpi(bp, "master key",
10)) /* not the "master" rank */
if (strncmpi(bp, "magenta", 7)) /* not the "mage" rank */
if (mntmp < LOW_PM && strlen(bp) > 2
&& (mntmp = name_to_mon(bp)) >= LOW_PM) {
int mntmptoo,
mntmplen; /* double check for rank title */
char *obp = bp;
mntmptoo = title_to_mon(bp, (int *) 0, &mntmplen);
bp += mntmp != mntmptoo
? (int) strlen(mons[mntmp].mname)
if (strncmpi(bp, "samurai sword", 13) /* not the "samurai" monster! */
&& strncmpi(bp, "wizard lock", 11) /* not the "wizard" monster! */
&& strncmpi(bp, "ninja-to", 8) /* not the "ninja" rank */
&& strncmpi(bp, "master key", 10) /* not the "master" rank */
&& strncmpi(bp, "magenta", 7)) { /* not the "mage" rank */
if (mntmp < LOW_PM && strlen(bp) > 2
&& (mntmp = name_to_mon(bp)) >= LOW_PM) {
int mntmptoo, mntmplen; /* double check for rank title */
char *obp = bp;
mntmptoo = title_to_mon(bp, (int *) 0, &mntmplen);
bp += (mntmp != mntmptoo) ? (int) strlen(mons[mntmp].mname)
: mntmplen;
if (*bp == ' ')
bp++;
else if (!strncmpi(bp, "s ", 2))
bp += 2;
else if (!strncmpi(bp, "es ", 3))
bp += 3;
else if (!*bp && !actualn && !dn && !un
&& !oclass) {
/* no referent; they don't really mean a
* monster type */
bp = obp;
mntmp = NON_PM;
}
}
if (*bp == ' ') {
bp++;
} else if (!strncmpi(bp, "s ", 2)) {
bp += 2;
} else if (!strncmpi(bp, "es ", 3)) {
bp += 3;
} else if (!*bp && !actualn && !dn && !un && !oclass) {
/* no referent; they don't really mean a monster type */
bp = obp;
mntmp = NON_PM;
}
}
}
/* first change to singular if necessary */
if (*bp) {
@@ -2952,7 +3091,8 @@ struct obj *no_wish;
* gold/money concept. Maybe we want to add other monetary units as
* well in the future. (TH)
*/
if (!BSTRCMPI(bp, p - 10, "gold piece") || !BSTRCMPI(bp, p - 7, "zorkmid")
if (!BSTRCMPI(bp, p - 10, "gold piece")
|| !BSTRCMPI(bp, p - 7, "zorkmid")
|| !strcmpi(bp, "gold") || !strcmpi(bp, "money")
|| !strcmpi(bp, "coin") || *bp == GOLD_SYM) {
if (cnt > 5000 && !wizard)
@@ -2975,15 +3115,19 @@ struct obj *no_wish;
/* Search for class names: XXXXX potion, scroll of XXXXX. Avoid */
/* false hits on, e.g., rings for "ring mail". */
if (strncmpi(bp, "enchant ", 8) && strncmpi(bp, "destroy ", 8)
if (strncmpi(bp, "enchant ", 8)
&& strncmpi(bp, "destroy ", 8)
&& strncmpi(bp, "detect food", 11)
&& strncmpi(bp, "food detection", 14) && strncmpi(bp, "ring mail", 9)
&& strncmpi(bp, "food detection", 14)
&& strncmpi(bp, "ring mail", 9)
&& strncmpi(bp, "studded leather armor", 21)
&& strncmpi(bp, "leather armor", 13)
&& strncmpi(bp, "tooled horn", 11) && strncmpi(bp, "food ration", 11)
&& strncmpi(bp, "tooled horn", 11)
&& strncmpi(bp, "food ration", 11)
&& strncmpi(bp, "meat ring", 9))
for (i = 0; i < (int) (sizeof wrpsym); i++) {
register int j = strlen(wrp[i]);
if (!strncmpi(bp, wrp[i], j)) {
oclass = wrpsym[i];
if (oclass != AMULET_CLASS) {
@@ -3099,11 +3243,17 @@ srch:
for (i = bases[GEM_CLASS]; i <= LAST_GEM; i++) {
register const char *zn;
if ((zn = OBJ_NAME(objects[i])) && !strcmpi(actualn, zn)) {
if ((zn = OBJ_NAME(objects[i])) != 0 && !strcmpi(actualn, zn)) {
typ = i;
goto typfnd;
}
}
/* "tin of foo" would be caught above, but plain "tin" has
a random chance of yielding "tin wand" unless we do this */
if (!strcmpi(actualn, "tin")) {
typ = TIN;
goto typfnd;
}
}
if (((typ = rnd_otyp_by_namedesc(actualn, oclass)) != STRANGE_OBJECT)
+103 -42
View File
@@ -233,7 +233,7 @@ static struct Bool_Opt {
{ "vt_tiledata", (boolean *) 0, FALSE, SET_IN_FILE },
#endif
{ "whatis_menu", &iflags.getloc_usemenu, FALSE, SET_IN_GAME },
{ "whatis_inview", &iflags.getloc_limitview, FALSE, SET_IN_GAME },
{ "whatis_moveskip", &iflags.getloc_moveskip, FALSE, SET_IN_GAME },
{ "wizweight", &iflags.wizweight, FALSE, SET_IN_WIZGAME },
{ "wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME },
#ifdef ZEROCOMP
@@ -403,6 +403,8 @@ static struct Comp_Opt {
#endif
{ "whatis_coord", "show coordinates when auto-describing cursor position",
1, SET_IN_GAME },
{ "whatis_filter", "filter coordinate locations when targeting next or previous",
1, SET_IN_GAME },
{ "windowcolors", "the foreground/background colors of windows", /*WC*/
80, DISP_IN_GAME },
{ "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME },
@@ -2341,32 +2343,32 @@ boolean tinitial, tfrom_file;
return;
if (!initial) {
struct fruit *f;
int fnum = 0;
num = 0;
for (f = ffruit; f; f = f->nextf) {
if (!strcmp(op, f->fname))
break;
num++;
}
if (!flags.made_fruit) {
for (forig = ffruit; forig; forig = forig->nextf) {
if (!strcmp(pl_fruit, forig->fname)) {
break;
}
/* count number of named fruits; if 'op' is found among them,
then the count doesn't matter because we won't be adding it */
f = fruit_from_name(op, FALSE, &fnum);
if (!f) {
if (!flags.made_fruit)
forig = fruit_from_name(pl_fruit, FALSE, (int *) 0);
if (!forig && fnum >= 100) {
pline("Doing that so many times isn't very fruitful.");
return;
}
}
if (!forig && num >= 100) {
pline("Doing that so many times isn't very fruitful.");
return;
}
}
goodfruit:
nmcpy(pl_fruit, op, PL_FSIZ);
sanitize_name(pl_fruit);
/* OBJ_NAME(objects[SLIME_MOLD]) won't work after initialization */
/* OBJ_NAME(objects[SLIME_MOLD]) won't work for this after
initialization; it gets changed to generic "fruit" */
if (!*pl_fruit)
nmcpy(pl_fruit, "slime mold", PL_FSIZ);
if (!initial) {
/* if 'forig' is nonNull, we replace it rather than add
a new fruit; it can only be nonNull if no fruits have
been created since the previous name was put in place */
(void) fruitadd(pl_fruit, forig);
pline("Fruit is now \"%s\".", pl_fruit);
}
@@ -2379,7 +2381,7 @@ boolean tinitial, tfrom_file;
}
fullname = "whatis_coord";
if (match_optname(opts, fullname, 6, TRUE)) {
if (match_optname(opts, fullname, 8, TRUE)) {
if (duplicate)
complain_about_duplicate(opts, 1);
if (negated) {
@@ -2399,6 +2401,33 @@ boolean tinitial, tfrom_file;
return;
}
fullname = "whatis_filter";
if (match_optname(opts, fullname, 8, TRUE)) {
if (duplicate)
complain_about_duplicate(opts, 1);
if (negated) {
iflags.getloc_filter = GFILTER_NONE;
return;
} else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
char c = lowc(*op);
switch (c) {
case 'n':
iflags.getloc_filter = GFILTER_NONE;
break;
case 'v':
iflags.getloc_filter = GFILTER_VIEW;
break;
case 'a':
iflags.getloc_filter = GFILTER_AREA;
break;
default:
badoption(opts);
}
}
return;
}
fullname = "warnings";
if (match_optname(opts, fullname, 5, TRUE)) {
if (duplicate)
@@ -4283,6 +4312,37 @@ boolean setinitial, setfromfile;
free((genericptr_t) window_pick);
}
destroy_nhwindow(tmpwin);
} else if (!strcmp("whatis_filter", optname)) {
menu_item *window_pick = (menu_item *) 0;
int pick_cnt;
char gf = iflags.getloc_filter;
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin);
any = zeroany;
any.a_char = (GFILTER_NONE + 1);
add_menu(tmpwin, NO_GLYPH, &any, 'n',
0, ATR_NONE, "no filtering",
(gf == GFILTER_NONE) ? MENU_SELECTED : MENU_UNSELECTED);
any.a_char = (GFILTER_VIEW + 1);
add_menu(tmpwin, NO_GLYPH, &any, 'v',
0, ATR_NONE, "in view only",
(gf == GFILTER_VIEW) ? MENU_SELECTED : MENU_UNSELECTED);
any.a_char = (GFILTER_AREA + 1);
add_menu(tmpwin, NO_GLYPH, &any, 'a',
0, ATR_NONE, "in same area",
(gf == GFILTER_AREA) ? MENU_SELECTED : MENU_UNSELECTED);
end_menu(tmpwin,
"Select location filtering when going for next/previous map position:");
if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &window_pick)) > 0) {
iflags.getloc_filter = (window_pick[0].item.a_char - 1);
/* PICK_ONE doesn't unselect preselected entry when
selecting another one */
if (pick_cnt > 1 && iflags.getloc_filter == gf)
iflags.getloc_filter = (window_pick[1].item.a_char - 1);
free((genericptr_t) window_pick);
}
destroy_nhwindow(tmpwin);
} else if (!strcmp("msg_window", optname)) {
#ifdef TTY_GRAPHICS
/* by Christian W. Cooper */
@@ -5057,6 +5117,11 @@ char *buf;
: (iflags.getpos_coords == GPCOORDS_COMFULL) ? "full compass"
: (iflags.getpos_coords == GPCOORDS_SCREEN) ? "screen"
: "none");
} else if (!strcmp(optname, "whatis_filter")) {
Sprintf(buf, "%s",
(iflags.getloc_filter == GFILTER_VIEW) ? "view"
: (iflags.getloc_filter == GFILTER_AREA) ? "area"
: "none");
} else if (!strcmp(optname, "scores")) {
Sprintf(buf, "%d top/%d around%s", flags.end_top, flags.end_around,
flags.end_own ? "/own" : "");
@@ -5574,7 +5639,6 @@ struct fruit *replace_fruit;
/* disallow naming after other foods (since it'd be impossible
* to tell the difference)
*/
for (i = bases[FOOD_CLASS]; objects[i].oc_class == FOOD_CLASS; i++) {
if (!strcmp(OBJ_NAME(objects[i]), pl_fruit)) {
found = TRUE;
@@ -5584,15 +5648,15 @@ struct fruit *replace_fruit;
{
char *c;
c = pl_fruit;
for (c = pl_fruit; *c >= '0' && *c <= '9'; c++)
;
continue;
if (isspace((uchar) *c) || *c == 0)
numeric = TRUE;
}
if (found || numeric || !strncmp(str, "cursed ", 7)
|| !strncmp(str, "uncursed ", 9) || !strncmp(str, "blessed ", 8)
if (found || numeric
|| !strncmp(str, "cursed ", 7)
|| !strncmp(str, "uncursed ", 9)
|| !strncmp(str, "blessed ", 8)
|| !strncmp(str, "partly eaten ", 13)
|| (!strncmp(str, "tin of ", 7)
&& (!strcmp(str + 7, "spinach")
@@ -5615,42 +5679,39 @@ struct fruit *replace_fruit;
*/
flags.made_fruit = FALSE;
if (replace_fruit) {
for (f = ffruit; f; f = f->nextf) {
if (f == replace_fruit) {
copynchars(f->fname, str, PL_FSIZ - 1);
goto nonew;
}
}
/* replace_fruit is already part of the fruit chain;
update it in place rather than looking it up again */
f = replace_fruit;
copynchars(f->fname, str, PL_FSIZ - 1);
goto nonew;
}
} else {
/* not user_supplied, so assumed to be from bones */
copynchars(altname, str, PL_FSIZ - 1);
sanitize_name(altname);
flags.made_fruit = TRUE; /* for safety. Any fruit name added from a
bones level should exist anyway. */
* bones level should exist anyway. */
}
for (f = ffruit; f; f = f->nextf) {
if (f->fid > highest_fruit_id)
highest_fruit_id = f->fid;
if (!strncmp(str, f->fname, PL_FSIZ - 1)
|| (*altname && !strcmp(altname, f->fname)))
goto nonew;
}
/* if adding another fruit would overflow spe, use a random
fruit instead... we've got a lot to choose from.
f = fruit_from_name(*altname ? altname : str, FALSE, &highest_fruit_id);
if (f)
goto nonew;
/* Maximum number of named fruits is 127, even if obj->spe can
handle bigger values. If adding another fruit would overflow,
use a random fruit instead... we've got a lot to choose from.
current_fruit remains as is. */
if (highest_fruit_id >= 127)
return rnd(127);
f = newfruit();
(void) memset((genericptr_t)f, 0, sizeof(struct fruit));
(void) memset((genericptr_t) f, 0, sizeof (struct fruit));
copynchars(f->fname, *altname ? altname : str, PL_FSIZ - 1);
f->fid = ++highest_fruit_id;
/* we used to go out of our way to add it at the end of the list,
but the order is arbitrary so use simpler insertion at start */
f->nextf = ffruit;
ffruit = f;
nonew:
nonew:
if (user_specified)
context.current_fruit = f->fid;
return f->fid;
+5 -3
View File
@@ -177,6 +177,8 @@ int *menu_on_demand;
}
if (itemcount && menu_on_demand)
ilets[iletct++] = 'm';
if (count_unpaid(objs))
ilets[iletct++] = 'u';
tally_BUCX(objs, here, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
if (bcnt)
@@ -222,8 +224,8 @@ int *menu_on_demand;
goto ask_again;
} else if (sym == 'm') {
m_seen = TRUE;
} else if (index("BUCX", sym)) {
add_valid_menu_class(sym); /* 'B','U','C',or 'X' */
} else if (index("uBUCX", sym)) {
add_valid_menu_class(sym); /* 'u' or 'B','U','C',or 'X' */
filtered = TRUE;
} else {
oc_of_sym = def_char_to_objclass(sym);
@@ -2666,7 +2668,7 @@ boolean put_in;
} else if (flags.menu_style == MENU_FULL) {
all_categories = FALSE;
Sprintf(buf, "%s what type of objects?", action);
mflags = (ALL_TYPES | BUCX_TYPES);
mflags = (ALL_TYPES | UNPAID_TYPES | BUCX_TYPES);
if (put_in)
mflags |= CHOOSE_ALL;
n = query_category(buf, put_in ? invent : current_container->cobj,
+6 -270
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 pline.c $NHDT-Date: 1490908465 2017/03/30 21:14:25 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.58 $ */
/* NetHack 3.6 pline.c $NHDT-Date: 1501803108 2017/08/03 23:31:48 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.61 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -435,276 +435,12 @@ VA_DECL(const char *, s)
Vsprintf(pbuf, s, VA_ARGS);
pbuf[BUFSZ - 1] = '\0'; /* sanity */
paniclog("impossible", pbuf);
pline("%s", pbuf);
pline("Program in disorder - perhaps you'd better #quit.");
pline("%s", VA_PASS1(pbuf));
pline("%s", VA_PASS1("Program in disorder - perhaps you'd better #quit."));
program_state.in_impossible = 0;
VA_END();
}
const char *
align_str(alignment)
aligntyp alignment;
{
switch ((int) alignment) {
case A_CHAOTIC:
return "chaotic";
case A_NEUTRAL:
return "neutral";
case A_LAWFUL:
return "lawful";
case A_NONE:
return "unaligned";
}
return "unknown";
}
void
mstatusline(mtmp)
register struct monst *mtmp;
{
aligntyp alignment = mon_aligntyp(mtmp);
char info[BUFSZ], monnambuf[BUFSZ];
info[0] = 0;
if (mtmp->mtame) {
Strcat(info, ", tame");
if (wizard) {
Sprintf(eos(info), " (%d", mtmp->mtame);
if (!mtmp->isminion)
Sprintf(eos(info), "; hungry %ld; apport %d",
EDOG(mtmp)->hungrytime, EDOG(mtmp)->apport);
Strcat(info, ")");
}
} else if (mtmp->mpeaceful)
Strcat(info, ", peaceful");
if (mtmp->data == &mons[PM_LONG_WORM]) {
int segndx, nsegs = count_wsegs(mtmp);
/* the worm code internals don't consider the head of be one of
the worm's segments, but we count it as such when presenting
worm feedback to the player */
if (!nsegs) {
Strcat(info, ", single segment");
} else {
++nsegs; /* include head in the segment count */
segndx = wseg_at(mtmp, bhitpos.x, bhitpos.y);
Sprintf(eos(info), ", %d%s of %d segments",
segndx, ordin(segndx), nsegs);
}
}
if (mtmp->cham >= LOW_PM && mtmp->data != &mons[mtmp->cham])
/* don't reveal the innate form (chameleon, vampire, &c),
just expose the fact that this current form isn't it */
Strcat(info, ", shapechanger");
/* pets eating mimic corpses mimic while eating, so this comes first */
if (mtmp->meating)
Strcat(info, ", eating");
/* a stethoscope exposes mimic before getting here so this
won't be relevant for it, but wand of probing doesn't */
if (mtmp->mundetected || mtmp->m_ap_type)
mhidden_description(mtmp, TRUE, eos(info));
if (mtmp->mcan)
Strcat(info, ", cancelled");
if (mtmp->mconf)
Strcat(info, ", confused");
if (mtmp->mblinded || !mtmp->mcansee)
Strcat(info, ", blind");
if (mtmp->mstun)
Strcat(info, ", stunned");
if (mtmp->msleeping)
Strcat(info, ", asleep");
#if 0 /* unfortunately mfrozen covers temporary sleep and being busy \
(donning armor, for instance) as well as paralysis */
else if (mtmp->mfrozen)
Strcat(info, ", paralyzed");
#else
else if (mtmp->mfrozen || !mtmp->mcanmove)
Strcat(info, ", can't move");
#endif
/* [arbitrary reason why it isn't moving] */
else if (mtmp->mstrategy & STRAT_WAITMASK)
Strcat(info, ", meditating");
if (mtmp->mflee)
Strcat(info, ", scared");
if (mtmp->mtrapped)
Strcat(info, ", trapped");
if (mtmp->mspeed)
Strcat(info, mtmp->mspeed == MFAST ? ", fast" : mtmp->mspeed == MSLOW
? ", slow"
: ", ???? speed");
if (mtmp->minvis)
Strcat(info, ", invisible");
if (mtmp == u.ustuck)
Strcat(info, sticks(youmonst.data)
? ", held by you"
: !u.uswallow ? ", holding you"
: attacktype_fordmg(u.ustuck->data,
AT_ENGL, AD_DGST)
? ", digesting you"
: is_animal(u.ustuck->data)
? ", swallowing you"
: ", engulfing you");
if (mtmp == u.usteed)
Strcat(info, ", carrying you");
/* avoid "Status of the invisible newt ..., invisible" */
/* and unlike a normal mon_nam, use "saddled" even if it has a name */
Strcpy(monnambuf, x_monnam(mtmp, ARTICLE_THE, (char *) 0,
(SUPPRESS_IT | SUPPRESS_INVISIBLE), FALSE));
pline("Status of %s (%s): Level %d HP %d(%d) AC %d%s.", monnambuf,
align_str(alignment), mtmp->m_lev, mtmp->mhp, mtmp->mhpmax,
find_mac(mtmp), info);
}
void
ustatusline()
{
char info[BUFSZ];
info[0] = '\0';
if (Sick) {
Strcat(info, ", dying from");
if (u.usick_type & SICK_VOMITABLE)
Strcat(info, " food poisoning");
if (u.usick_type & SICK_NONVOMITABLE) {
if (u.usick_type & SICK_VOMITABLE)
Strcat(info, " and");
Strcat(info, " illness");
}
}
if (Stoned)
Strcat(info, ", solidifying");
if (Slimed)
Strcat(info, ", becoming slimy");
if (Strangled)
Strcat(info, ", being strangled");
if (Vomiting)
Strcat(info, ", nauseated"); /* !"nauseous" */
if (Confusion)
Strcat(info, ", confused");
if (Blind) {
Strcat(info, ", blind");
if (u.ucreamed) {
if ((long) u.ucreamed < Blinded || Blindfolded
|| !haseyes(youmonst.data))
Strcat(info, ", cover");
Strcat(info, "ed by sticky goop");
} /* note: "goop" == "glop"; variation is intentional */
}
if (Stunned)
Strcat(info, ", stunned");
if (!u.usteed && Wounded_legs) {
const char *what = body_part(LEG);
if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES)
what = makeplural(what);
Sprintf(eos(info), ", injured %s", what);
}
if (Glib)
Sprintf(eos(info), ", slippery %s", makeplural(body_part(HAND)));
if (u.utrap)
Strcat(info, ", trapped");
if (Fast)
Strcat(info, Very_fast ? ", very fast" : ", fast");
if (u.uundetected)
Strcat(info, ", concealed");
if (Invis)
Strcat(info, ", invisible");
if (u.ustuck) {
if (sticks(youmonst.data))
Strcat(info, ", holding ");
else
Strcat(info, ", held by ");
Strcat(info, mon_nam(u.ustuck));
}
pline("Status of %s (%s): Level %d HP %d(%d) AC %d%s.", plname,
piousness(FALSE, align_str(u.ualign.type)),
Upolyd ? mons[u.umonnum].mlevel : u.ulevel, Upolyd ? u.mh : u.uhp,
Upolyd ? u.mhmax : u.uhpmax, u.uac, info);
}
void
self_invis_message()
{
pline("%s %s.",
Hallucination ? "Far out, man! You" : "Gee! All of a sudden, you",
See_invisible ? "can see right through yourself"
: "can't see yourself");
}
char *
piousness(showneg, suffix)
boolean showneg;
const char *suffix;
{
static char buf[32]; /* bigger than "insufficiently neutral" */
const char *pio;
/* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */
if (u.ualign.record >= 20)
pio = "piously";
else if (u.ualign.record > 13)
pio = "devoutly";
else if (u.ualign.record > 8)
pio = "fervently";
else if (u.ualign.record > 3)
pio = "stridently";
else if (u.ualign.record == 3)
pio = "";
else if (u.ualign.record > 0)
pio = "haltingly";
else if (u.ualign.record == 0)
pio = "nominally";
else if (!showneg)
pio = "insufficiently";
else if (u.ualign.record >= -3)
pio = "strayed";
else if (u.ualign.record >= -8)
pio = "sinned";
else
pio = "transgressed";
Sprintf(buf, "%s", pio);
if (suffix && (!showneg || u.ualign.record >= 0)) {
if (u.ualign.record != 3)
Strcat(buf, " ");
Strcat(buf, suffix);
}
return buf;
}
void
pudding_merge_message(otmp, otmp2)
struct obj *otmp;
struct obj *otmp2;
{
boolean visible =
cansee(otmp->ox, otmp->oy) || cansee(otmp2->ox, otmp2->oy);
boolean onfloor = otmp->where == OBJ_FLOOR || otmp2->where == OBJ_FLOOR;
boolean inpack = carried(otmp) || carried(otmp2);
/* the player will know something happened inside his own inventory */
if ((!Blind && visible) || inpack) {
if (Hallucination) {
if (onfloor) {
You_see("parts of the floor melting!");
} else if (inpack) {
Your("pack reaches out and grabs something!");
}
/* even though we can see where they should be,
* they'll be out of our view (minvent or container)
* so don't actually show anything */
} else if (onfloor || inpack) {
pline("The %s coalesce%s.", makeplural(obj_typename(otmp->otyp)),
inpack ? " inside your pack" : "");
}
} else {
You_hear("a faint sloshing sound.");
}
}
#if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__))
static boolean use_pline_handler = TRUE;
static void
@@ -732,16 +468,16 @@ const char *line;
(void) setuid(getuid());
(void) execv(args[0], (char *const *) args);
perror((char *) 0);
(void) fprintf(stderr, "Exec to message handler %s failed.\n",
env);
(void) fprintf(stderr, "Exec to message handler %s failed.\n", env);
terminate(EXIT_FAILURE);
} else if (f > 0) {
int status;
waitpid(f, &status, 0);
} else if (f == -1) {
perror((char *) 0);
use_pline_handler = FALSE;
pline("Fork to message handler failed.");
pline("%s", VA_PASS1("Fork to message handler failed."));
}
}
#endif /* defined(POSIX_TYPES) || defined(__GNUC__) */
+34 -7
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 potion.c $NHDT-Date: 1455407631 2016/02/13 23:53:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.129 $ */
/* NetHack 3.6 potion.c $NHDT-Date: 1502753790 2017/08/14 23:36:30 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.138 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -408,6 +408,16 @@ boolean talk;
}
}
void
self_invis_message()
{
pline("%s %s.",
Hallucination ? "Far out, man! You"
: "Gee! All of a sudden, you",
See_invisible ? "can see right through yourself"
: "can't see yourself");
}
STATIC_OVL void
ghost_from_bottle()
{
@@ -1333,15 +1343,22 @@ boolean your_fault;
if (useeit && !affected)
pline("%s %s wet.", buf, aobjnam(saddle, "get"));
} else {
boolean angermon = your_fault;
boolean angermon = your_fault, cureblind = FALSE;
switch (obj->otyp) {
case POT_HEALING:
case POT_EXTRA_HEALING:
case POT_FULL_HEALING:
cureblind = TRUE;
/*FALLTHRU*/
case POT_EXTRA_HEALING:
if (!obj->cursed)
cureblind = TRUE;
/*FALLTHRU*/
case POT_HEALING:
if (obj->blessed)
cureblind = TRUE;
if (mon->data == &mons[PM_PESTILENCE])
goto do_illness;
/*FALLTHRU*/
/*FALLTHRU*/
case POT_RESTORE_ABILITY:
case POT_GAIN_ABILITY:
do_healing:
@@ -1351,6 +1368,8 @@ boolean your_fault;
if (canseemon(mon))
pline("%s looks sound and hale again.", Monnam(mon));
}
if (cureblind)
mcureblindness(mon, canseemon(mon));
break;
case POT_SICKNESS:
if (mon->data == &mons[PM_PESTILENCE])
@@ -1409,7 +1428,7 @@ boolean your_fault;
break;
case POT_BLINDNESS:
if (haseyes(mon->data)) {
register int btmp = 64 + rn2(32)
int btmp = 64 + rn2(32)
+ rn2(32) * !resist(mon, POTION_CLASS, 0, NOTELL);
btmp += mon->mblinded;
@@ -1524,7 +1543,8 @@ void
potionbreathe(obj)
register struct obj *obj;
{
register int i, ii, isdone, kn = 0;
int i, ii, isdone, kn = 0;
boolean cureblind = FALSE;
switch (obj->otyp) {
case POT_RESTORE_ABILITY:
@@ -1559,18 +1579,25 @@ register struct obj *obj;
u.mh++, context.botl = 1;
if (u.uhp < u.uhpmax)
u.uhp++, context.botl = 1;
cureblind = TRUE;
/*FALLTHRU*/
case POT_EXTRA_HEALING:
if (Upolyd && u.mh < u.mhmax)
u.mh++, context.botl = 1;
if (u.uhp < u.uhpmax)
u.uhp++, context.botl = 1;
if (!obj->cursed)
cureblind = TRUE;
/*FALLTHRU*/
case POT_HEALING:
if (Upolyd && u.mh < u.mhmax)
u.mh++, context.botl = 1;
if (u.uhp < u.uhpmax)
u.uhp++, context.botl = 1;
if (obj->blessed)
cureblind = TRUE;
if (cureblind)
make_blinded(0L, !u.ucreamed);
exercise(A_CON, TRUE);
break;
case POT_SICKNESS:
+239 -1
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 priest.c $NHDT-Date: 1446892452 2015/11/07 10:34:12 $ $NHDT-Branch: master $:$NHDT-Revision: 1.41 $ */
/* NetHack 3.6 priest.c $NHDT-Date: 1501725407 2017/08/03 01:56:47 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.44 $ */
/* Copyright (c) Izchak Miller, Steve Linhart, 1989. */
/* NetHack may be freely redistributed. See license for details. */
@@ -852,4 +852,242 @@ boolean ghostly;
}
}
/*
* align_str(), piousness(), mstatusline() and ustatusline() used to be
* in pline.c, presumeably because the latter two generate one line of
* output. The USE_OLDARGS config gets warnings from 2016ish-vintage
* gcc (for -Wint-to-pointer-cast, activated by -Wall or -W) when they
* follow pline() itself. Fixing up the variadic calls like is done for
* lev_comp would be needlessly messy there.
*
* They don't belong here. If/when enlightenment ever gets split off
* from cmd.c (which definitely doesn't belong there), they should go
* with it.
*/
const char *
align_str(alignment)
aligntyp alignment;
{
switch ((int) alignment) {
case A_CHAOTIC:
return "chaotic";
case A_NEUTRAL:
return "neutral";
case A_LAWFUL:
return "lawful";
case A_NONE:
return "unaligned";
}
return "unknown";
}
/* used for self-probing */
char *
piousness(showneg, suffix)
boolean showneg;
const char *suffix;
{
static char buf[32]; /* bigger than "insufficiently neutral" */
const char *pio;
/* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */
if (u.ualign.record >= 20)
pio = "piously";
else if (u.ualign.record > 13)
pio = "devoutly";
else if (u.ualign.record > 8)
pio = "fervently";
else if (u.ualign.record > 3)
pio = "stridently";
else if (u.ualign.record == 3)
pio = "";
else if (u.ualign.record > 0)
pio = "haltingly";
else if (u.ualign.record == 0)
pio = "nominally";
else if (!showneg)
pio = "insufficiently";
else if (u.ualign.record >= -3)
pio = "strayed";
else if (u.ualign.record >= -8)
pio = "sinned";
else
pio = "transgressed";
Sprintf(buf, "%s", pio);
if (suffix && (!showneg || u.ualign.record >= 0)) {
if (u.ualign.record != 3)
Strcat(buf, " ");
Strcat(buf, suffix);
}
return buf;
}
/* stethoscope or probing applied to monster -- one-line feedback */
void
mstatusline(mtmp)
struct monst *mtmp;
{
aligntyp alignment = mon_aligntyp(mtmp);
char info[BUFSZ], monnambuf[BUFSZ];
info[0] = 0;
if (mtmp->mtame) {
Strcat(info, ", tame");
if (wizard) {
Sprintf(eos(info), " (%d", mtmp->mtame);
if (!mtmp->isminion)
Sprintf(eos(info), "; hungry %ld; apport %d",
EDOG(mtmp)->hungrytime, EDOG(mtmp)->apport);
Strcat(info, ")");
}
} else if (mtmp->mpeaceful)
Strcat(info, ", peaceful");
if (mtmp->data == &mons[PM_LONG_WORM]) {
int segndx, nsegs = count_wsegs(mtmp);
/* the worm code internals don't consider the head of be one of
the worm's segments, but we count it as such when presenting
worm feedback to the player */
if (!nsegs) {
Strcat(info, ", single segment");
} else {
++nsegs; /* include head in the segment count */
segndx = wseg_at(mtmp, bhitpos.x, bhitpos.y);
Sprintf(eos(info), ", %d%s of %d segments",
segndx, ordin(segndx), nsegs);
}
}
if (mtmp->cham >= LOW_PM && mtmp->data != &mons[mtmp->cham])
/* don't reveal the innate form (chameleon, vampire, &c),
just expose the fact that this current form isn't it */
Strcat(info, ", shapechanger");
/* pets eating mimic corpses mimic while eating, so this comes first */
if (mtmp->meating)
Strcat(info, ", eating");
/* a stethoscope exposes mimic before getting here so this
won't be relevant for it, but wand of probing doesn't */
if (mtmp->mundetected || mtmp->m_ap_type)
mhidden_description(mtmp, TRUE, eos(info));
if (mtmp->mcan)
Strcat(info, ", cancelled");
if (mtmp->mconf)
Strcat(info, ", confused");
if (mtmp->mblinded || !mtmp->mcansee)
Strcat(info, ", blind");
if (mtmp->mstun)
Strcat(info, ", stunned");
if (mtmp->msleeping)
Strcat(info, ", asleep");
#if 0 /* unfortunately mfrozen covers temporary sleep and being busy \
(donning armor, for instance) as well as paralysis */
else if (mtmp->mfrozen)
Strcat(info, ", paralyzed");
#else
else if (mtmp->mfrozen || !mtmp->mcanmove)
Strcat(info, ", can't move");
#endif
/* [arbitrary reason why it isn't moving] */
else if (mtmp->mstrategy & STRAT_WAITMASK)
Strcat(info, ", meditating");
if (mtmp->mflee)
Strcat(info, ", scared");
if (mtmp->mtrapped)
Strcat(info, ", trapped");
if (mtmp->mspeed)
Strcat(info, (mtmp->mspeed == MFAST) ? ", fast"
: (mtmp->mspeed == MSLOW) ? ", slow"
: ", [? speed]");
if (mtmp->minvis)
Strcat(info, ", invisible");
if (mtmp == u.ustuck)
Strcat(info, sticks(youmonst.data) ? ", held by you"
: !u.uswallow ? ", holding you"
: attacktype_fordmg(u.ustuck->data, AT_ENGL, AD_DGST)
? ", digesting you"
: is_animal(u.ustuck->data) ? ", swallowing you"
: ", engulfing you");
if (mtmp == u.usteed)
Strcat(info, ", carrying you");
/* avoid "Status of the invisible newt ..., invisible" */
/* and unlike a normal mon_nam, use "saddled" even if it has a name */
Strcpy(monnambuf, x_monnam(mtmp, ARTICLE_THE, (char *) 0,
(SUPPRESS_IT | SUPPRESS_INVISIBLE), FALSE));
pline("Status of %s (%s): Level %d HP %d(%d) AC %d%s.", monnambuf,
align_str(alignment), mtmp->m_lev, mtmp->mhp, mtmp->mhpmax,
find_mac(mtmp), info);
}
/* stethoscope or probing applied to hero -- one-line feedback */
void
ustatusline()
{
char info[BUFSZ];
info[0] = '\0';
if (Sick) {
Strcat(info, ", dying from");
if (u.usick_type & SICK_VOMITABLE)
Strcat(info, " food poisoning");
if (u.usick_type & SICK_NONVOMITABLE) {
if (u.usick_type & SICK_VOMITABLE)
Strcat(info, " and");
Strcat(info, " illness");
}
}
if (Stoned)
Strcat(info, ", solidifying");
if (Slimed)
Strcat(info, ", becoming slimy");
if (Strangled)
Strcat(info, ", being strangled");
if (Vomiting)
Strcat(info, ", nauseated"); /* !"nauseous" */
if (Confusion)
Strcat(info, ", confused");
if (Blind) {
Strcat(info, ", blind");
if (u.ucreamed) {
if ((long) u.ucreamed < Blinded || Blindfolded
|| !haseyes(youmonst.data))
Strcat(info, ", cover");
Strcat(info, "ed by sticky goop");
} /* note: "goop" == "glop"; variation is intentional */
}
if (Stunned)
Strcat(info, ", stunned");
if (!u.usteed && Wounded_legs) {
const char *what = body_part(LEG);
if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES)
what = makeplural(what);
Sprintf(eos(info), ", injured %s", what);
}
if (Glib)
Sprintf(eos(info), ", slippery %s", makeplural(body_part(HAND)));
if (u.utrap)
Strcat(info, ", trapped");
if (Fast)
Strcat(info, Very_fast ? ", very fast" : ", fast");
if (u.uundetected)
Strcat(info, ", concealed");
if (Invis)
Strcat(info, ", invisible");
if (u.ustuck) {
if (sticks(youmonst.data))
Strcat(info, ", holding ");
else
Strcat(info, ", held by ");
Strcat(info, mon_nam(u.ustuck));
}
pline("Status of %s (%s): Level %d HP %d(%d) AC %d%s.", plname,
piousness(FALSE, align_str(u.ualign.type)),
Upolyd ? mons[u.umonnum].mlevel : u.ulevel, Upolyd ? u.mh : u.uhp,
Upolyd ? u.mhmax : u.uhpmax, u.uac, info);
}
/*priest.c*/
+12 -3
View File
@@ -915,12 +915,21 @@ struct obj *sobj;
return 0;
}
boolean
get_valid_stinking_cloud_pos(x,y)
int x,y;
{
return (!(!isok(x,y) || !cansee(x, y)
|| !ACCESSIBLE(levl[x][y].typ)
|| distu(x, y) >= 32));
}
boolean
is_valid_stinking_cloud_pos(x, y, showmsg)
int x, y;
boolean showmsg;
{
if (!cansee(x, y) || !ACCESSIBLE(levl[x][y].typ) || distu(x, y) >= 32) {
if (get_valid_stinking_cloud_pos(x,y)) {
if (showmsg)
You("smell rotten eggs.");
return FALSE;
@@ -942,7 +951,7 @@ int state;
for (dy = -dist; dy <= dist; dy++) {
x = u.ux + dx;
y = u.uy + dy;
if (isok(x, y) && is_valid_stinking_cloud_pos(x, y, FALSE))
if (get_valid_stinking_cloud_pos(x,y))
tmp_at(x, y);
}
} else {
@@ -1633,7 +1642,7 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
already_known ? "stinking " : "");
cc.x = u.ux;
cc.y = u.uy;
getpos_sethilite(display_stinking_cloud_positions);
getpos_sethilite(display_stinking_cloud_positions, get_valid_stinking_cloud_pos);
if (getpos(&cc, TRUE, "the desired position") < 0) {
pline1(Never_mind);
break;
+5 -9
View File
@@ -36,7 +36,6 @@ STATIC_DCL struct opvar *FDECL(opvar_new_coord, (int, int));
#if 0
STATIC_DCL struct opvar * FDECL(opvar_new_region, (int,int, int,int));
#endif /*0*/
STATIC_DCL void FDECL(opvar_free_x, (struct opvar *));
STATIC_DCL struct opvar *FDECL(opvar_clone, (struct opvar *));
STATIC_DCL struct opvar *FDECL(opvar_var_conversion, (struct sp_coder *,
struct opvar *));
@@ -114,8 +113,6 @@ STATIC_DCL void FDECL(spo_altar, (struct sp_coder *));
STATIC_DCL void FDECL(spo_trap, (struct sp_coder *));
STATIC_DCL void FDECL(spo_gold, (struct sp_coder *));
STATIC_DCL void FDECL(spo_corridor, (struct sp_coder *));
STATIC_DCL struct opvar *FDECL(selection_opvar, (char *));
STATIC_DCL xchar FDECL(selection_getpoint, (int, int, struct opvar *));
STATIC_DCL void FDECL(selection_setpoint, (int, int, struct opvar *, XCHAR_P));
STATIC_DCL struct opvar *FDECL(selection_not, (struct opvar *));
STATIC_DCL struct opvar *FDECL(selection_logical_oper, (struct opvar *,
@@ -126,11 +123,8 @@ STATIC_DCL void FDECL(selection_filter_percent, (struct opvar *, int));
STATIC_DCL int FDECL(selection_rndcoord, (struct opvar *, schar *, schar *,
BOOLEAN_P));
STATIC_DCL void FDECL(selection_do_grow, (struct opvar *, int));
STATIC_DCL void FDECL(set_selection_floodfillchk, (int FDECL((*), (int,int))));
STATIC_DCL int FDECL(floodfillchk_match_under, (int, int));
STATIC_DCL int FDECL(floodfillchk_match_accessible, (int, int));
STATIC_DCL void FDECL(selection_floodfill, (struct opvar *, int, int,
BOOLEAN_P));
STATIC_DCL void FDECL(selection_do_ellipse, (struct opvar *, int, int,
int, int, int));
STATIC_DCL long FDECL(line_dist_coord, (long, long, long, long, long, long));
@@ -3052,6 +3046,7 @@ struct sp_coder *coder;
while ((nparams++ < (SP_O_V_END + 1)) && (OV_typ(varparam) == SPOVAR_INT)
&& (OV_i(varparam) >= 0) && (OV_i(varparam) < SP_O_V_END)) {
struct opvar *parm;
OV_pop(parm);
switch (OV_i(varparam)) {
case SP_O_V_NAME:
@@ -3063,11 +3058,12 @@ struct sp_coder *coder;
char monclass = SP_MONST_CLASS(OV_i(parm));
int monid = SP_MONST_PM(OV_i(parm));
if (monid >= 0 && monid < NUMMONS) {
if (monid >= LOW_PM && monid < NUMMONS) {
tmpobj.corpsenm = monid;
break; /* we're done! */
} else {
struct permonst *pm = (struct permonst *) 0;
if (def_char_to_monclass(monclass) != MAXMCLASSES) {
pm = mkclass(def_char_to_monclass(monclass), G_NOGEN);
} else {
@@ -3780,7 +3776,7 @@ int dir;
STATIC_VAR int FDECL((*selection_flood_check_func), (int, int));
STATIC_VAR schar floodfillchk_match_under_typ;
STATIC_OVL void
void
set_selection_floodfillchk(f)
int FDECL((*f), (int, int));
{
@@ -3803,7 +3799,7 @@ int x, y;
|| levl[x][y].typ == SCORR);
}
STATIC_OVL void
void
selection_floodfill(ov, x, y, diagonals)
struct opvar *ov;
int x, y;
+90 -42
View File
@@ -15,43 +15,83 @@ STATIC_DCL void FDECL(see_lamp_flicker, (struct obj *, const char *));
STATIC_DCL void FDECL(lantern_message, (struct obj *));
STATIC_DCL void FDECL(cleanup_burn, (ANY_P *, long));
/* the order of these must match their numerical sequence in prop.h
because the property number is inferred from the array index;
used by wizard mode #timeout and #wizintrinsic */
const char *const propertynames[] = {
"0: not used",
/* Resistances */
/* 1..2 */ "fire resistance", "cold resistance",
/* 3..4 */ "sleep resistance", "disintegration resistance",
/* 5..6 */ "shock resistance", "poison resistance",
/* 7..8 */ "acid resistance", "stoning resistance",
/* 9..10 */ "drain resistance", "sickness resistance",
/* 11..12 */ "invulnerable", "magic resistance",
/* Troubles */
/* 13..16 */ "stunned", "confused", "blinded", "deafness",
/* 17..20 */ "fatally sick", "petrifying", "strangling", "vomiting",
/* 21..22 */ "slippery fingers", "becoming slime",
/* 23..24 */ "hallucinating", "halluicination resistance",
/* 25..28 */ "fumbling", "wounded legs", "sleepy", "voracious hunger",
/* Vision and senses */
/* 29..30 */ "see invisible", "telepathic",
/* 31..33 */ "warning", "warn:monster", "warn:undead",
/* 34..37 */ "searching", "clairvoyant", "infravision", "monster detection",
/* Appearance and behavior */
/* 38..41 */ "adorned (+/-Cha)", "invisible", "displaced", "stealthy",
/* 42..43 */ "monster aggrevation", "conflict",
/* Transportation */
/* 44..46 */ "jumping", "teleporting", "teleport control",
/* 47..49 */ "levitating", "flying", "water walking",
/* 50..52 */ "swimming", "magical breathing", "pass thru walls",
/* Physical attributes */
/* 53..55 */ "slow digestion", "half spell damage", "half physical damage",
/* 56..58 */ "HP regeneration", "energy regeneration", "extra protection",
/* 59 */ "protection from shape changers",
/* 60..62 */ "polymorphing", "polymorph control", "unchanging",
/* 63..66 */ "fast", "reflecting", "free action", "fixed abilites",
/* 67 */ "life will be saved",
0 /* sentinel */
/* used by wizard mode #timeout and #wizintrinsic; order by 'interest'
for timeout countdown, where most won't occur in normal play */
const struct propname {
int prop_num;
const char *prop_name;
} propertynames[] = {
{ INVULNERABLE, "invulnerable" },
{ STONED, "petrifying" },
{ SLIMED, "becoming slime" },
{ STRANGLED, "strangling" },
{ SICK, "fatally sick" },
{ STUNNED, "stunned" },
{ CONFUSION, "confused" },
{ HALLUC, "hallucinating" },
{ BLINDED, "blinded" },
{ DEAF, "deafness" },
{ VOMITING, "vomiting" },
{ GLIB, "slippery fingers" },
{ WOUNDED_LEGS, "wounded legs" },
{ SLEEPY, "sleepy" },
{ TELEPORT, "teleporting" },
{ POLYMORPH, "polymorphing" },
{ LEVITATION, "levitating" },
{ FAST, "very fast" }, /* timed 'FAST' is very fast */
{ CLAIRVOYANT, "clairvoyant" },
{ DETECT_MONSTERS, "monster detection" },
{ SEE_INVIS, "see invisible" },
{ INVIS, "invisible" },
/* properties beyond here don't have timed values during normal play,
so there's no much point in trying to order them sensibly;
they're either on or off based on equipment, role, actions, &c */
{ FIRE_RES, "fire resistance" },
{ COLD_RES, "cold resistance" },
{ SLEEP_RES, "sleep resistance" },
{ DISINT_RES, "disintegration resistance" },
{ SHOCK_RES, "shock resistance" },
{ POISON_RES, "poison resistance" },
{ ACID_RES, "acid resistance" },
{ STONE_RES, "stoning resistance" },
{ DRAIN_RES, "drain resistance" },
{ SICK_RES, "sickness resistance" },
{ ANTIMAGIC, "magic resistance" },
{ HALLUC_RES, "hallucination resistance" },
{ FUMBLING, "fumbling" },
{ HUNGER, "voracious hunger" },
{ TELEPAT, "telepathic" },
{ WARNING, "warning" },
{ WARN_OF_MON, "warn: monster type or class" },
{ WARN_UNDEAD, "warn: undead" },
{ SEARCHING, "searching" },
{ INFRAVISION, "infravision" },
{ ADORNED, "adorned (+/- Cha)" },
{ DISPLACED, "displaced" },
{ STEALTH, "stealthy" },
{ AGGRAVATE_MONSTER, "monster aggravation" },
{ CONFLICT, "conflict" },
{ JUMPING, "jumping" },
{ TELEPORT_CONTROL, "teleport control" },
{ FLYING, "flying" },
{ WWALKING, "water walking" },
{ SWIMMING, "swimming" },
{ MAGICAL_BREATHING, "magical breathing" },
{ PASSES_WALLS, "pass thru walls" },
{ SLOW_DIGESTION, "slow digestion" },
{ HALF_SPDAM, "half spell damage" },
{ HALF_PHDAM, "half physical damage" },
{ REGENERATION, "HP regeneration" },
{ ENERGY_REGENERATION, "energy regeneration" },
{ PROTECTION, "extra protection" },
{ PROT_FROM_SHAPE_CHANGERS, "protection from shape changers" },
{ POLYMORPH_CONTROL, "polymorph control" },
{ UNCHANGING, "unchanging" },
{ REFLECTING, "reflecting" },
{ FREE_ACTION, "free action" },
{ FIXED_ABIL, "fixed abilites" },
{ LIFESAVED, "life will be saved" },
{ 0, 0 },
};
/* He is being petrified - dialogue by inmet!tower */
@@ -1544,7 +1584,7 @@ wiz_timeout_queue()
char buf[BUFSZ];
const char *propname;
long intrinsic;
int i, count, longestlen, ln;
int i, p, count, longestlen, ln, specindx = 0;
win = create_nhwindow(NHW_MENU); /* corner text window */
if (win == WIN_ERR)
@@ -1562,13 +1602,16 @@ wiz_timeout_queue()
* normal play but those can be forced via the #wizintrinsic command.
*/
count = longestlen = 0;
for (i = 1; (propname = propertynames[i]) != 0; ++i) { /* [0] not used */
intrinsic = u.uprops[i].intrinsic;
for (i = 0; (propname = propertynames[i].prop_name) != 0; ++i) {
p = propertynames[i].prop_num;
intrinsic = u.uprops[p].intrinsic;
if (intrinsic & TIMEOUT) {
++count;
if ((ln = (int) strlen(propname)) > longestlen)
longestlen = ln;
}
if (specindx == 0 && p == FIRE_RES)
specindx = i;
}
putstr(win, 0, "");
if (!count) {
@@ -1576,9 +1619,14 @@ wiz_timeout_queue()
} else {
putstr(win, 0, "Timed properties:");
putstr(win, 0, "");
for (i = 1; (propname = propertynames[i]) != 0; ++i) {
intrinsic = u.uprops[i].intrinsic;
for (i = 0; (propname = propertynames[i].prop_name) != 0; ++i) {
p = propertynames[i].prop_num;
intrinsic = u.uprops[p].intrinsic;
if (intrinsic & TIMEOUT) {
if (specindx > 0 && i >= specindx) {
putstr(win, 0, " -- settable via #wizinstrinc only --");
specindx = 0;
}
/* timeout value can be up to 16777215 (0x00ffffff) but
width of 4 digits should result in values lining up
almost all the time (if/when they don't, it won't
+9 -1
View File
@@ -191,6 +191,13 @@ findgd()
return (struct monst *) 0;
}
void
vault_summon_gd()
{
if (vault_occupied(u.urooms) && !findgd())
u.uinvault = (VAULT_GUARD_TIME - 1);
}
char
vault_occupied(array)
char *array;
@@ -221,7 +228,8 @@ invault()
vaultroom -= ROOMOFFSET;
guard = findgd();
if (++u.uinvault % 30 == 0 && !guard) { /* if time ok and no guard now. */
if (++u.uinvault % VAULT_GUARD_TIME == 0 && !guard) {
/* if time ok and no guard now. */
char buf[BUFSZ];
register int x, y, dd, gx, gy;
int lx = 0, ly = 0;