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

This commit is contained in:
keni
2016-10-23 15:21:59 -04:00
46 changed files with 988 additions and 611 deletions

View File

@@ -2695,7 +2695,7 @@ struct obj *obj;
pline1(msg_slipsfree);
}
if (mtmp)
wakeup(mtmp);
wakeup(mtmp, TRUE);
} else
pline1(msg_snap);
@@ -2789,7 +2789,7 @@ struct obj *obj;
} else {
pline1(msg_slipsfree);
}
wakeup(mtmp);
wakeup(mtmp, TRUE);
} else {
if (mtmp->m_ap_type && !Protection_from_shape_changers
&& !sensemon(mtmp))
@@ -3210,8 +3210,8 @@ struct obj *obj;
You("don't have the strength to break %s!", yname(obj));
return 0;
}
pline("Raising %s high above your %s, you break it in two!", yname(obj),
body_part(HEAD));
pline("Raising %s high above your %s, you %s it in two!", yname(obj),
body_part(HEAD), is_fragile ? "snap" : "break");
/* [ALI] Do this first so that wand is removed from bill. Otherwise,
* the freeinv() below also hides it from setpaid() which causes problems.

View File

@@ -3,6 +3,7 @@
/* NetHack may be freely redistributed. See license for details. */
#include "hack.h"
#include "lev.h"
#include "func_tab.h"
#ifdef ALTMETA
@@ -123,6 +124,7 @@ STATIC_PTR int NDECL(wiz_wish);
STATIC_PTR int NDECL(wiz_identify);
STATIC_PTR int NDECL(wiz_intrinsic);
STATIC_PTR int NDECL(wiz_map);
STATIC_PTR int NDECL(wiz_makemap);
STATIC_PTR int NDECL(wiz_genesis);
STATIC_PTR int NDECL(wiz_where);
STATIC_PTR int NDECL(wiz_detect);
@@ -327,8 +329,9 @@ doextcmd(VOID_ARGS)
return 0;
}
if (iflags.menu_requested && !accept_menu_prefix(func)) {
pline("'%s' prefix has no effect for this command.",
visctrl(Cmd.spkeys[NHKF_REQMENU]));
pline("'%s' prefix has no effect for the %s command.",
visctrl(Cmd.spkeys[NHKF_REQMENU]),
extcmdlist[idx].ef_txt);
iflags.menu_requested = FALSE;
}
retval = (*func)();
@@ -344,13 +347,18 @@ doextlist(VOID_ARGS)
register const struct ext_func_tab *efp;
char buf[BUFSZ];
winid datawin;
char ch = cmd_from_func(doextcmd);
datawin = create_nhwindow(NHW_TEXT);
putstr(datawin, 0, "");
putstr(datawin, 0, " Extended Commands List");
putstr(datawin, 0, "");
putstr(datawin, 0, " Press '#', then type:");
putstr(datawin, 0, "");
if (ch) {
Sprintf(buf, " Press '%s', then type:",
visctrl(ch));
putstr(datawin, 0, buf);
putstr(datawin, 0, "");
}
for (efp = extcmdlist; efp->ef_txt; efp++) {
if (!wizard && (efp->flags & WIZMODECMD))
@@ -610,6 +618,22 @@ wiz_identify(VOID_ARGS)
return 0;
}
STATIC_PTR int
wiz_makemap(VOID_ARGS)
{
if (wizard) {
savelev(-1, ledger_no(&u.uz), FREE_SAVE);
mklev();
reglyph_darkroom();
vision_reset();
vision_full_recalc = 1;
(void) safe_teleds(TRUE);
docrt();
flush_screen(1);
}
return 0;
}
/* ^F command - reveal the level map and any traps on it */
STATIC_PTR int
wiz_map(VOID_ARGS)
@@ -2812,6 +2836,7 @@ struct ext_func_tab extcmdlist[] = {
{ C('i'), "wizidentify", "identify all items in inventory", wiz_identify, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "wizintrinsic", "set intrinsic", wiz_intrinsic, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ C('v'), "wizlevelport", "teleport to another level", wiz_level_tele, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "wizmakemap", "recreate the current level", wiz_makemap, IFBURIED|WIZMODECMD },
{ C('f'), "wizmap", "map the level", wiz_map, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "wizrumorcheck", "verify rumor boundaries", wiz_rumor_check, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "wizsmell", "smell monster", wiz_smell, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
@@ -3519,9 +3544,11 @@ 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_INTERESTING_NEXT, 'a', "getpos.all.next" },
{ NHKF_GETPOS_INTERESTING_PREV, 'A', "getpos.all.prev" },
{ NHKF_GETPOS_HELP, '?', "getpos.help" },
{ NHKF_GETPOS_MENU, 'A', "getpos.menu" },
{ NHKF_GETPOS_MENU_FOV, 'a', "getpos.menu.cansee" }
{ NHKF_GETPOS_LIMITVIEW, '"', "getpos.inview" },
{ NHKF_GETPOS_MENU, '!', "getpos.menu" }
};
boolean
@@ -4702,7 +4729,7 @@ dotravel(VOID_ARGS)
}
iflags.getloc_travelmode = TRUE;
if (iflags.menu_requested) {
if (!getpos_menu(&cc, TRUE)) {
if (!getpos_menu(&cc, TRUE, GLOC_INTERESTING)) {
iflags.getloc_travelmode = FALSE;
return 0;
}

View File

@@ -2008,7 +2008,7 @@ struct monst *mtmp;
}
mtmp->mburied = TRUE;
wakeup(mtmp); /* at least give it a chance :-) */
wakeup(mtmp, FALSE); /* at least give it a chance :-) */
newsym(mtmp->mx, mtmp->my);
}

View File

@@ -44,6 +44,35 @@ void FDECL((*f), (int));
getpos_hilitefunc = f;
}
const char *const gloc_descr[NUM_GLOCS][4] = {
{ "any monsters", "monster", "next monster", "monsters" },
{ "any items", "item", "next object", "objects" },
{ "any doors", "door", "next door or doorway", "doors or doorways" },
{ "any unexplored areas", "unexplored area", "unexplored location",
"unexplored locations" },
{ "anything interesting", "interesting thing", "anything interesting",
"anything interesting" }
};
void
getpos_help_keyxhelp(tmpwin, k1, k2, gloc)
winid tmpwin;
const char *k1;
const char *k2;
int gloc;
{
char sbuf[BUFSZ];
Sprintf(sbuf, "Use '%s' or '%s' to %s%s%s.",
k1, k2,
iflags.getloc_usemenu ? "get a menu of "
: "move the cursor to ",
gloc_descr[gloc][2 + iflags.getloc_usemenu],
iflags.getloc_limitview ? " in view" : "");
putstr(tmpwin, 0, sbuf);
}
/* the response for '?' help request in getpos() */
STATIC_OVL void
getpos_help(force, goal)
@@ -54,46 +83,51 @@ const char *goal;
boolean doing_what_is;
winid tmpwin = create_nhwindow(NHW_MENU);
Sprintf(sbuf, "Use '%c', '%c', '%c', '%c' to move the cursor to %s.", /* hjkl */
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.");
putstr(tmpwin, 0,
"Use 'H', 'J', 'K', 'L' to move the cursor 8 units at a time.");
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]));
putstr(tmpwin, 0, sbuf);
if (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0) {
Sprintf(sbuf, "Use '%s' or '%s' to move the cursor to next monster.",
visctrl(Cmd.spkeys[NHKF_GETPOS_MON_NEXT]),
visctrl(Cmd.spkeys[NHKF_GETPOS_MON_PREV]));
putstr(tmpwin, 0, sbuf);
getpos_help_keyxhelp(tmpwin,
visctrl(Cmd.spkeys[NHKF_GETPOS_MON_NEXT]),
visctrl(Cmd.spkeys[NHKF_GETPOS_MON_PREV]),
GLOC_MONS);
}
if (!iflags.terrainmode || (iflags.terrainmode & TER_OBJ) != 0) {
Sprintf(sbuf, "Use '%s' or '%s' to move the cursor to next object.",
visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_NEXT]),
visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_PREV]));
putstr(tmpwin, 0, sbuf);
getpos_help_keyxhelp(tmpwin,
visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_NEXT]),
visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_PREV]),
GLOC_OBJS);
}
if (!iflags.terrainmode || (iflags.terrainmode & TER_MAP) != 0) {
/* both of these are primarily useful when choosing a travel
/* these are primarily useful when choosing a travel
destination for the '_' command */
Sprintf(sbuf,
"Use '%s' or '%s' to move the cursor to next door or doorway.",
visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_NEXT]),
visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_PREV]));
putstr(tmpwin, 0, sbuf);
Sprintf(sbuf,
"Use '%s' or '%s' to move the cursor to unexplored location.",
visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_NEXT]),
visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_PREV]));
putstr(tmpwin, 0, sbuf);
getpos_help_keyxhelp(tmpwin,
visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_NEXT]),
visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_PREV]),
GLOC_DOOR);
getpos_help_keyxhelp(tmpwin,
visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_NEXT]),
visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_PREV]),
GLOC_EXPLORE);
getpos_help_keyxhelp(tmpwin,
visctrl(Cmd.spkeys[NHKF_GETPOS_INTERESTING_NEXT]),
visctrl(Cmd.spkeys[NHKF_GETPOS_INTERESTING_PREV]),
GLOC_INTERESTING);
}
Sprintf(sbuf, "Use '%s' for a menu of interesting targets in view.",
visctrl(Cmd.spkeys[NHKF_GETPOS_MENU_FOV]));
putstr(tmpwin, 0, sbuf);
Sprintf(sbuf, "Use '%s' for a menu of all interesting targets.",
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.",
visctrl(Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]));
putstr(tmpwin, 0, sbuf);
if (!iflags.terrainmode) {
char kbuf[BUFSZ];
if (getpos_hilitefunc) {
@@ -127,7 +161,7 @@ const char *goal;
putstr(tmpwin, 0, sbuf);
if (doing_what_is) {
Sprintf(sbuf,
" '%s' describe current spot, show 'more info', move to another spot.",
" '%s' describe current spot, show 'more info', move to another spot.",
visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
putstr(tmpwin, 0, sbuf);
Sprintf(sbuf,
@@ -174,19 +208,6 @@ const void *b;
return dist_1 - dist_2;
}
enum gloctypes {
GLOC_MONS = 0,
GLOC_OBJS,
GLOC_DOOR,
GLOC_EXPLORE,
NUM_GLOCS,
GLOC_INTERESTING,
GLOC_INTERESTING_FOV
};
#define IS_UNEXPLORED_LOC(x,y) \
(isok((x), (y)) \
&& glyph_is_cmap(levl[(x)][(y)].glyph) \
@@ -202,6 +223,9 @@ int x,y, gloc;
*/
int glyph = glyph_at(x, y);
if (iflags.getloc_limitview && !cansee(x,y))
return FALSE;
switch (gloc) {
default:
case GLOC_MONS:
@@ -231,9 +255,6 @@ int x,y, gloc;
|| IS_UNEXPLORED_LOC(x - 1, y)
|| IS_UNEXPLORED_LOC(x, y + 1)
|| IS_UNEXPLORED_LOC(x, y - 1)));
case GLOC_INTERESTING_FOV:
if (!cansee(x,y))
return FALSE;
case GLOC_INTERESTING:
return gather_locs_interesting(x,y, GLOC_DOOR)
|| !(glyph_is_cmap(glyph)
@@ -400,9 +421,10 @@ int cx, cy;
}
boolean
getpos_menu(ccp, fovonly)
getpos_menu(ccp, fovonly, gloc)
coord *ccp;
boolean fovonly;
int gloc;
{
coord *garr = DUMMY;
int gcount = 0;
@@ -412,10 +434,12 @@ boolean fovonly;
menu_item *picks = (menu_item *) 0;
char tmpbuf[BUFSZ];
gather_locs(&garr, &gcount,
fovonly ? GLOC_INTERESTING_FOV : GLOC_INTERESTING);
gather_locs(&garr, &gcount, gloc);
if (gcount < 2) { /* gcount always includes the hero */
You("cannot %s anything interesting.", fovonly ? "see" : "detect");
free((genericptr_t) garr);
You("cannot %s %s.",
fovonly ? "see" : "detect", gloc_descr[gloc][0]);
return FALSE;
}
@@ -423,7 +447,8 @@ boolean fovonly;
start_menu(tmpwin);
any = zeroany;
for (i = 0; i < gcount; i++) {
/* gather_locs returns array[0] == you. skip it. */
for (i = 1; i < gcount; i++) {
char fullbuf[BUFSZ];
coord tmpcc;
const char *firstmatch = "unknown";
@@ -439,8 +464,8 @@ boolean fovonly;
}
}
Sprintf(tmpbuf, "Pick a target%s%s",
fovonly ? " in view" : "",
Sprintf(tmpbuf, "Pick a target %s%s%s",
gloc_descr[gloc][1], fovonly ? " in view" : "",
iflags.getloc_travelmode ? " for travel" : "");
end_menu(tmpwin, tmpbuf);
pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
@@ -477,10 +502,12 @@ const char *goal;
NHKF_GETPOS_DOOR_NEXT,
NHKF_GETPOS_DOOR_PREV,
NHKF_GETPOS_UNEX_NEXT,
NHKF_GETPOS_UNEX_PREV
NHKF_GETPOS_UNEX_PREV,
NHKF_GETPOS_INTERESTING_NEXT,
NHKF_GETPOS_INTERESTING_PREV
};
char pick_chars[6];
char mMoOdDxX[9];
char mMoOdDxX[11];
int result = 0;
int cx, cy, i, c;
int sidx, tx, ty;
@@ -617,13 +644,24 @@ const char *goal;
show_goal_msg = TRUE;
msg_given = TRUE;
goto nxtc;
} else if (c == Cmd.spkeys[NHKF_GETPOS_MENU]
|| c == Cmd.spkeys[NHKF_GETPOS_MENU_FOV]) {
coord tmpcrd;
if (getpos_menu(&tmpcrd, (c == Cmd.spkeys[NHKF_GETPOS_MENU_FOV]))) {
cx = tmpcrd.x;
cy = tmpcrd.y;
} else if (c == Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]) {
iflags.getloc_limitview = !iflags.getloc_limitview;
for (i = 0; i < NUM_GLOCS; i++) {
if (garr[i]) {
free((genericptr_t) garr[i]);
garr[i] = NULL;
}
gidx[i] = gcount[i] = 0;
}
pline("%s possible targets to those in sight only.",
iflags.getloc_limitview ? "Limiting" : "Not limiting");
msg_given = TRUE;
goto nxtc;
} else if (c == Cmd.spkeys[NHKF_GETPOS_MENU]) {
iflags.getloc_usemenu = !iflags.getloc_usemenu;
pline("%s a menu to show possible targets.",
iflags.getloc_usemenu ? "Using" : "Not using");
msg_given = TRUE;
goto nxtc;
} else if (c == Cmd.spkeys[NHKF_GETPOS_SELF]) {
/* reset 'm&M', 'o&O', &c; otherwise, there's no way for player
@@ -638,6 +676,15 @@ const char *goal;
int gtmp = (int) (cp - mMoOdDxX), /* 0..7 */
gloc = gtmp >> 1; /* 0..3 */
if (iflags.getloc_usemenu) {
coord tmpcrd;
if (getpos_menu(&tmpcrd, iflags.getloc_limitview, gloc)) {
cx = tmpcrd.x;
cy = tmpcrd.y;
}
goto nxtc;
}
if (!garr[gloc]) {
gather_locs(&garr[gloc], &gcount[gloc], gloc);
gidx[gloc] = 0; /* garr[][0] is hero's spot */

View File

@@ -156,7 +156,7 @@ xchar x, y;
int i, j;
/* anger target even if wild miss will occur */
setmangry(mon);
setmangry(mon, TRUE);
if (Levitation && !rn2(3) && verysmall(mon->data)
&& !is_flyer(mon->data)) {
@@ -298,7 +298,7 @@ register struct obj *gold;
if (!likes_gold(mtmp->data) && !mtmp->isshk && !mtmp->ispriest
&& !mtmp->isgd && !is_mercenary(mtmp->data)) {
wakeup(mtmp);
wakeup(mtmp, TRUE);
} else if (!mtmp->mcanmove) {
/* too light to do real damage */
if (canseemon(mtmp)) {
@@ -312,7 +312,7 @@ register struct obj *gold;
mtmp->msleeping = 0;
finish_meating(mtmp);
if (!mtmp->isgd && !rn2(4)) /* not always pleasing */
setmangry(mtmp);
setmangry(mtmp, TRUE);
/* greedy monsters catch gold */
if (cansee(mtmp->mx, mtmp->my))
pline("%s catches the gold.", Monnam(mtmp));

View File

@@ -608,7 +608,8 @@ int x, y;
if ((mon = m_at(x, y)) != 0) {
You("bump into %s.", a_monnam(mon));
wakeup(mon);
wakeup(mon, FALSE);
setmangry(mon, FALSE);
wake_nearto(x,y, 10);
return FALSE;
}
@@ -1346,7 +1347,7 @@ boolean maybe_wakeup;
else
miss(missile, mon);
if (maybe_wakeup && !rn2(3))
wakeup(mon);
wakeup(mon, TRUE);
return;
}
@@ -1448,7 +1449,8 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
at leader... (kicked artifact is ok too; HMON_APPLIED could
occur if quest artifact polearm or grapnel ever gets added) */
if (hmode != HMON_APPLIED && quest_arti_hits_leader(obj, mon)) {
/* not wakeup(), which angers non-tame monsters */
/* AIS: changes to wakeup() means that it's now less inappropriate here
than it used to be, but the manual version works just as well */
mon->msleeping = 0;
mon->mstrategy &= ~STRAT_WAITMASK;
@@ -1562,7 +1564,7 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
} else {
tmiss(obj, mon, TRUE);
if (hmode == HMON_APPLIED)
wakeup(mon);
wakeup(mon, TRUE);
}
} else if (otyp == HEAVY_IRON_BALL) {
@@ -1610,7 +1612,7 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
}
} else if (guaranteed_hit) {
/* this assumes that guaranteed_hit is due to swallowing */
wakeup(mon);
wakeup(mon, TRUE);
if (obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])) {
if (is_animal(u.ustuck->data)) {
minstapetrify(u.ustuck, TRUE);

View File

@@ -62,6 +62,7 @@ STATIC_DCL void FDECL(print_branch, (winid, int, int, int, BOOLEAN_P,
STATIC_DCL mapseen *FDECL(load_mapseen, (int));
STATIC_DCL void FDECL(save_mapseen, (int, mapseen *));
STATIC_DCL mapseen *FDECL(find_mapseen, (d_level *));
STATIC_DCL mapseen *FDECL(find_mapseen_by_str, (const char *));
STATIC_DCL void FDECL(print_mapseen, (winid, mapseen *, int, int, BOOLEAN_P));
STATIC_DCL boolean FDECL(interest_mapseen, (mapseen *));
STATIC_DCL void FDECL(traverse_mapseenchn, (BOOLEAN_P, winid,
@@ -1642,25 +1643,35 @@ const char *nam;
const char *p;
int idx, idxtoo;
char buf[BUFSZ];
mapseen *mseen;
/* allow strings like "the oracle level" to find "oracle" */
if (!strncmpi(nam, "the ", 4))
nam += 4;
if ((p = strstri(nam, " level")) != 0 && p == eos((char *) nam) - 6) {
nam = strcpy(buf, nam);
*(eos(buf) - 6) = '\0';
}
/* hell is the old name, and wouldn't match; gehennom would match its
branch, yielding the castle level instead of the valley of the dead */
if (!strcmpi(nam, "gehennom") || !strcmpi(nam, "hell")) {
if (In_V_tower(&u.uz))
nam = " to Vlad's tower"; /* branch to... */
else
nam = "valley";
/* look at the player's custom level annotations first */
if ((mseen = find_mapseen_by_str(nam)) != 0) {
dlev = mseen->lev;
} else {
/* no matching annotation, check whether they used a name we know */
/* allow strings like "the oracle level" to find "oracle" */
if (!strncmpi(nam, "the ", 4))
nam += 4;
if ((p = strstri(nam, " level")) != 0 && p == eos((char *) nam) - 6) {
nam = strcpy(buf, nam);
*(eos(buf) - 6) = '\0';
}
/* hell is the old name, and wouldn't match; gehennom would match its
branch, yielding the castle level instead of the valley of the dead */
if (!strcmpi(nam, "gehennom") || !strcmpi(nam, "hell")) {
if (In_V_tower(&u.uz))
nam = " to Vlad's tower"; /* branch to... */
else
nam = "valley";
}
if ((slev = find_level(nam)) != 0)
dlev = slev->dlevel;
}
if ((slev = find_level(nam)) != 0) {
dlev = slev->dlevel;
if (mseen || slev) {
idx = ledger_no(&dlev);
if ((dlev.dnum == u.uz.dnum
/* within same branch, or else main dungeon <-> gehennom */
@@ -1672,7 +1683,7 @@ const char *nam;
wizard
|| (level_info[idx].flags & (FORGOTTEN | VISITED))
== VISITED)) {
lev = depth(&slev->dlevel);
lev = depth(&dlev);
}
} else { /* not a specific level; try branch names */
idx = find_branch(nam, (struct proto_dungeon *) 0);
@@ -2055,6 +2066,20 @@ d_level *lev;
return mptr;
}
STATIC_OVL mapseen *
find_mapseen_by_str(s)
const char *s;
{
mapseen *mptr;
for (mptr = mapseenchn; mptr; mptr = mptr->next)
if (mptr->custom && !strcmpi(s, mptr->custom))
break;
return mptr;
}
void
forget_mapseen(ledger_num)
int ledger_num;

View File

@@ -257,8 +257,7 @@ xchar x, y;
* Ignore headstones, in case the player names herself "Elbereth".
*
* If strict checking is requested, the word is only considered to be
* present if it is intact and is the first word in the engraving.
* ("Elbereth burrito" matches; "o Elbereth" does not.)
* present if it is intact and is the entire content of the engraving.
*/
int
sengr_at(s, x, y, strict)
@@ -269,9 +268,10 @@ boolean strict;
register struct engr *ep = engr_at(x, y);
if (ep && ep->engr_type != HEADSTONE && ep->engr_time <= moves) {
return strict ? (strncmpi(ep->engr_txt, s, strlen(s)) == 0)
return strict ? (fuzzymatch(ep->engr_txt, s, "", TRUE))
: (strstri(ep->engr_txt, s) != 0);
}
return FALSE;
}

View File

@@ -433,7 +433,7 @@ int expltype;
monkilled(mtmp, "", (int) adtyp);
} else if (!context.mon_moving) {
/* all affected monsters, even if mdef is set */
setmangry(mtmp);
setmangry(mtmp, TRUE);
}
}

View File

@@ -57,6 +57,13 @@ struct monst *mon;
if (mon) {
ptr = mon->data;
if (uwep && uwep->oartifact == ART_DEMONBANE && is_demon(ptr)) {
if (canseemon(mon))
pline("%s looks puzzled for a moment.", Monnam(mon));
return 0;
}
atyp = mon->ispriest ? EPRI(mon)->shralign
: mon->isminion ? EMIN(mon)->min_align
: (ptr->maligntyp == A_NONE)

View File

@@ -629,6 +629,153 @@ fixup_special()
num_lregions = 0;
}
boolean
maze_inbounds(x, y)
int x, y;
{
return (x >= 2 && y >= 2
&& x < x_maze_max && y < y_maze_max && isok(x, y));
}
void
maze_remove_deadends(typ)
xchar typ;
{
char dirok[4];
int x, y, dir, idx, idx2, dx, dy, dx2, dy2;
dirok[0] = 0; /* lint suppression */
for (x = 2; x < x_maze_max; x++)
for (y = 2; y < y_maze_max; y++)
if (ACCESSIBLE(levl[x][y].typ) && (x % 2) && (y % 2)) {
idx = idx2 = 0;
for (dir = 0; dir < 4; dir++) {
/* note: mz_move() is a macro which modifies
one of its first two parameters */
dx = dx2 = x;
dy = dy2 = y;
mz_move(dx, dy, dir);
if (!maze_inbounds(dx, dy)) {
idx2++;
continue;
}
mz_move(dx2, dy2, dir);
mz_move(dx2, dy2, dir);
if (!maze_inbounds(dx2, dy2)) {
idx2++;
continue;
}
if (!ACCESSIBLE(levl[dx][dy].typ)
&& ACCESSIBLE(levl[dx2][dy2].typ)) {
dirok[idx++] = dir;
idx2++;
}
}
if (idx2 >= 3 && idx > 0) {
dx = x;
dy = y;
dir = dirok[rn2(idx)];
mz_move(dx, dy, dir);
levl[dx][dy].typ = typ;
}
}
}
/* Create a maze with specified corridor width and wall thickness
* TODO: rewrite walkfrom so it works on temp space, not levl
*/
void
create_maze(corrwid, wallthick)
int corrwid;
int wallthick;
{
int x,y;
coord mm;
int tmp_xmax = x_maze_max;
int tmp_ymax = y_maze_max;
int rdx = 0;
int rdy = 0;
int scale;
if (wallthick < 1)
wallthick = 1;
else if (wallthick > 5)
wallthick = 5;
if (corrwid < 1)
corrwid = 1;
else if (corrwid > 5)
corrwid = 5;
scale = corrwid + wallthick;
rdx = (x_maze_max / scale);
rdy = (y_maze_max / scale);
if (level.flags.corrmaze)
for (x = 2; x < (rdx * 2); x++)
for (y = 2; y < (rdy * 2); y++)
levl[x][y].typ = STONE;
else
for (x = 2; x <= (rdx * 2); x++)
for (y = 2; y <= (rdy * 2); y++)
levl[x][y].typ = ((x % 2) && (y % 2)) ? STONE : HWALL;
/* set upper bounds for maze0xy and walkfrom */
x_maze_max = (rdx * 2);
y_maze_max = (rdy * 2);
/* create maze */
maze0xy(&mm);
walkfrom((int) mm.x, (int) mm.y, 0);
if (!rn2(5))
maze_remove_deadends((level.flags.corrmaze) ? CORR : ROOM);
/* restore bounds */
x_maze_max = tmp_xmax;
y_maze_max = tmp_ymax;
/* scale maze up if needed */
if (scale > 2) {
char tmpmap[COLNO][ROWNO];
int rx = 1, ry = 1;
/* back up the existing smaller maze */
for (x = 1; x < x_maze_max; x++)
for (y = 1; y < y_maze_max; y++) {
tmpmap[x][y] = levl[x][y].typ;
}
/* do the scaling */
rx = x = 2;
while (rx < x_maze_max) {
int mx = (x % 2) ? corrwid
: ((x == 2 || x == (rdx * 2)) ? 1
: wallthick);
ry = y = 2;
while (ry < y_maze_max) {
int dx = 0, dy = 0;
int my = (y % 2) ? corrwid
: ((y == 2 || y == (rdy * 2)) ? 1
: wallthick);
for (dx = 0; dx < mx; dx++)
for (dy = 0; dy < my; dy++) {
if (rx+dx >= x_maze_max
|| ry+dy >= y_maze_max)
break;
levl[rx + dx][ry + dy].typ = tmpmap[x][y];
}
ry += my;
y++;
}
rx += mx;
x++;
}
}
}
void
makemaz(s)
const char *s;
@@ -697,19 +844,12 @@ const char *s;
level.flags.is_maze_lev = TRUE;
level.flags.corrmaze = !rn2(3);
if (level.flags.corrmaze)
for (x = 2; x < x_maze_max; x++)
for (y = 2; y < y_maze_max; y++)
levl[x][y].typ = STONE;
else
for (x = 2; x <= x_maze_max; x++)
for (y = 2; y <= y_maze_max; y++)
levl[x][y].typ = ((x % 2) && (y % 2)) ? STONE : HWALL;
maze0xy(&mm);
walkfrom((int) mm.x, (int) mm.y, 0);
/* put a boulder at the maze center */
(void) mksobj_at(BOULDER, (int) mm.x, (int) mm.y, TRUE, FALSE);
if (!Invocation_lev(&u.uz) && rn2(2)) {
int corrscale = rnd(4);
create_maze(corrscale,rnd(4)-corrscale);
} else {
create_maze(1,1);
}
if (!level.flags.corrmaze)
wallification(2, 2, x_maze_max, y_maze_max);
@@ -891,8 +1031,8 @@ coord *cc;
int cpt = 0;
do {
cc->x = 3 + 2 * rn2((x_maze_max >> 1) - 1);
cc->y = 3 + 2 * rn2((y_maze_max >> 1) - 1);
cc->x = 1 + rn2(x_maze_max);
cc->y = 1 + rn2(y_maze_max);
cpt++;
} while (cpt < 100
&& levl[cc->x][cc->y].typ
@@ -901,10 +1041,10 @@ coord *cc;
int x, y;
/* last try */
for (x = 0; x < (x_maze_max >> 1) - 1; x++)
for (y = 0; y < (y_maze_max >> 1) - 1; y++) {
cc->x = 3 + 2 * x;
cc->y = 3 + 2 * y;
for (x = 1; x < x_maze_max; x++)
for (y = 1; y < y_maze_max; y++) {
cc->x = x;
cc->y = y;
if (levl[cc->x][cc->y].typ
== (level.flags.corrmaze ? CORR : ROOM))
return;

View File

@@ -380,12 +380,16 @@ struct mkroom *sroom;
}
switch (type) {
case COURT: {
struct obj *chest;
struct obj *chest, *gold;
levl[tx][ty].typ = THRONE;
(void) somexy(sroom, &mm);
(void) mkgold((long) rn1(50 * level_difficulty(), 10), mm.x, mm.y);
gold = mksobj(GOLD_PIECE, TRUE, FALSE);
gold->quan = (long) rn1(50 * level_difficulty(), 10);
gold->owt = weight(gold);
/* the royal coffers */
chest = mksobj_at(CHEST, mm.x, mm.y, TRUE, FALSE);
add_to_container(chest, gold);
chest->owt = weight(chest);
chest->spe = 2; /* so it can be found later */
level.flags.has_court = 1;
break;

View File

@@ -2583,10 +2583,33 @@ struct monst *mtmp;
}
}
/* Called whenever the player attacks mtmp; also called in other situations
where mtmp gets annoyed at the player. Handles mtmp getting annoyed at the
attack and any ramifications that might have. Useful also in situations where
mtmp was already hostile; it checks for situations where the player shouldn't
be attacking and any ramifications /that/ might have. */
void
setmangry(mtmp)
setmangry(mtmp, via_attack)
struct monst *mtmp;
boolean via_attack;
{
if (via_attack && sengr_at("Elbereth", u.ux, u.uy, TRUE)) {
You_feel("like a hypocrite.");
/* AIS: Yes, I know alignment penalties and bonuses aren't balanced at
the moment. This is about correct relative to other "small"
penalties; it should be fairly large, as attacking while standing on
an Elbereth means that you're requesting peace and then violating
your own request. I know 5 isn't actually large, but it's
intentionally larger than the 1s and 2s that are normally given for
this sort of thing. */
adjalign(-5);
if (!Blind)
pline("The engraving beneath you fades.");
del_engr_at(u.ux, u.uy);
}
/* AIS: Should this be in both places, or just in wakeup()? */
mtmp->mstrategy &= ~STRAT_WAITMASK;
if (!mtmp->mpeaceful)
return;
@@ -2681,14 +2704,16 @@ struct monst *mtmp;
}
/* wake up a monster, usually making it angry in the process */
/* wake up a monster, possibly making it angry in the process */
void
wakeup(mtmp)
wakeup(mtmp, via_attack)
register struct monst *mtmp;
boolean via_attack;
{
mtmp->msleeping = 0;
finish_meating(mtmp);
setmangry(mtmp);
if (via_attack)
setmangry(mtmp, TRUE);
if (mtmp->m_ap_type) {
seemimic(mtmp);
} else if (context.forcefight && !context.mon_moving

View File

@@ -320,12 +320,6 @@ int *inrange, *nearby, *scared;
|| (!mtmp->mpeaceful && in_your_sanctuary(mtmp, 0, 0)))) {
*scared = 1;
monflee(mtmp, rnd(rn2(7) ? 10 : 100), TRUE, TRUE);
/* magical protection won't last forever, so there'll be a
* chance of the magic being used up regardless of type */
if (sawscary) {
wipe_engr_at(seescaryx, seescaryy, 1, TRUE);
}
} else
*scared = 0;
}

View File

@@ -263,7 +263,7 @@ int force;
for (x = start_x; x <= end_x; x++)
for (y = start_y; y <= end_y; y++) {
if ((mtmp = m_at(x, y)) != 0) {
wakeup(mtmp); /* peaceful monster will become hostile */
wakeup(mtmp, TRUE); /* peaceful monster will become hostile */
if (mtmp->mundetected && is_hider(mtmp->data)) {
mtmp->mundetected = 0;
if (cansee(x, y))

View File

@@ -230,6 +230,8 @@ static struct Bool_Opt {
#else
{ "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 },
{ "wizweight", &iflags.wizweight, FALSE, SET_IN_WIZGAME },
{ "wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME },
#ifdef ZEROCOMP

View File

@@ -1310,8 +1310,8 @@ dogaze()
mon_nam(mtmp));
if (yn(qbuf) != 'y')
continue;
setmangry(mtmp);
}
setmangry(mtmp, TRUE);
if (!mtmp->mcanmove || mtmp->mstun || mtmp->msleeping
|| !mtmp->mcansee || !haseyes(mtmp->data)) {
looked--;

View File

@@ -1488,7 +1488,7 @@ boolean your_fault;
/* target might have been killed */
if (mon->mhp > 0) {
if (angermon)
wakeup(mon);
wakeup(mon, TRUE);
else
mon->msleeping = 0;
}

View File

@@ -795,7 +795,8 @@ angry_priest()
if ((priest = findpriest(temple_occupied(u.urooms))) != 0) {
struct epri *eprip = EPRI(priest);
wakeup(priest);
wakeup(priest, FALSE);
setmangry(priest, FALSE);
/*
* If the altar has been destroyed or converted, let the
* priest run loose.

View File

@@ -901,7 +901,7 @@ struct obj *sobj;
unsigned was_peaceful = mtmp->mpeaceful;
if (sobj->cursed) {
setmangry(mtmp);
setmangry(mtmp, FALSE);
if (was_peaceful && !mtmp->mpeaceful)
return -1;
} else {

View File

@@ -974,7 +974,7 @@ genericptr_t p2;
if (cansee(mtmp->mx, mtmp->my))
pline("%s coughs!", Monnam(mtmp));
if (heros_fault(reg))
setmangry(mtmp);
setmangry(mtmp, TRUE);
if (haseyes(mtmp->data) && mtmp->mcansee) {
mtmp->mblinded = 1;
mtmp->mcansee = 0;

View File

@@ -609,9 +609,9 @@ level_tele()
do {
if (++trycnt == 2) {
if (wizard)
Strcat(qbuf, " [type a number or ? for a menu]");
Strcat(qbuf, " [type a number, name, or ? for a menu]");
else
Strcat(qbuf, " [type a number]");
Strcat(qbuf, " [type a number or name]");
}
getlin(qbuf, buf);
if (!strcmp(buf, "\033")) { /* cancelled */

View File

@@ -2119,7 +2119,7 @@ register struct monst *mtmp;
Recognizing who made the trap isn't completely
unreasonable; everybody has their own style. */
if (trap->madeby_u && rnl(5))
setmangry(mtmp);
setmangry(mtmp, TRUE);
in_sight = canseemon(mtmp);
see_it = cansee(mtmp->mx, mtmp->my);
@@ -4541,7 +4541,7 @@ boolean *noticed; /* set to true iff hero notices the effect; */
or if you sense the monster who becomes trapped */
*noticed = cansee(t->tx, t->ty) || canspotmon(mon);
/* monster will be angered; mintrap doesn't handle that */
wakeup(mon);
wakeup(mon, TRUE);
++force_mintrap;
result = (mintrap(mon) != 0);
--force_mintrap;

View File

@@ -145,7 +145,7 @@ struct obj *wep; /* uwep for attack(), null for kick_monster() */
if (!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data, AD_STCK))
u.ustuck = mtmp;
}
wakeup(mtmp); /* always necessary; also un-mimics mimics */
wakeup(mtmp, TRUE); /* always necessary; also un-mimics mimics */
return TRUE;
}
@@ -190,7 +190,7 @@ struct obj *wep; /* uwep for attack(), null for kick_monster() */
*/
if ((mtmp->mundetected || mtmp->m_ap_type) && sensemon(mtmp)) {
mtmp->mundetected = 0;
wakeup(mtmp);
wakeup(mtmp, TRUE);
}
if (flags.confirm && mtmp->mpeaceful && !Confusion && !Hallucination
@@ -573,7 +573,7 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
unconventional[0] = '\0';
saved_oname[0] = '\0';
wakeup(mon);
wakeup(mon, TRUE);
if (!obj) { /* attack with bare hands */
if (mdat == &mons[PM_SHADE])
tmp = 0;
@@ -894,7 +894,7 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
pline("%s %s over %s!", what,
vtense(what, "splash"), whom);
}
setmangry(mon);
setmangry(mon, TRUE);
mon->mcansee = 0;
tmp = rn1(25, 21);
if (((int) mon->mblinded + tmp) > 127)
@@ -903,7 +903,7 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
mon->mblinded += tmp;
} else {
pline(obj->otyp == CREAM_PIE ? "Splat!" : "Splash!");
setmangry(mon);
setmangry(mon, TRUE);
}
if (thrown)
obfree(obj, (struct obj *) 0);
@@ -2097,7 +2097,7 @@ boolean wouldhavehit;
else
You("miss it.");
if (!mdef->msleeping && mdef->mcanmove)
wakeup(mdef);
wakeup(mdef, TRUE);
}
/* attack monster as a monster. */
@@ -2178,7 +2178,7 @@ register struct monst *mon;
sum[i] = damageum(mon, mattk);
break;
}
wakeup(mon);
wakeup(mon, TRUE);
/* maybe this check should be in damageum()? */
if (mon->data == &mons[PM_SHADE]
&& !(mattk->aatyp == AT_KICK && uarmf
@@ -2212,7 +2212,7 @@ register struct monst *mon;
* already grabbed in a previous attack
*/
dhit = 1;
wakeup(mon);
wakeup(mon, TRUE);
if (mon->data == &mons[PM_SHADE])
Your("hug passes harmlessly through %s.", mon_nam(mon));
else if (!sticks(mon->data) && !u.uswallow) {
@@ -2230,7 +2230,7 @@ register struct monst *mon;
case AT_EXPL: /* automatic hit if next to */
dhit = -1;
wakeup(mon);
wakeup(mon, TRUE);
sum[i] = explum(mon, mattk);
break;
@@ -2238,7 +2238,7 @@ register struct monst *mon;
tmp = find_roll_to_hit(mon, mattk->aatyp, (struct obj *) 0,
&attknum, &armorpenalty);
if ((dhit = (tmp > rnd(20 + i)))) {
wakeup(mon);
wakeup(mon, TRUE);
if (mon->data == &mons[PM_SHADE])
Your("attempt to surround %s is harmless.", mon_nam(mon));
else {
@@ -2637,7 +2637,7 @@ struct monst *mtmp;
if (what)
pline(fmt, what);
wakeup(mtmp); /* clears mimicking */
wakeup(mtmp, FALSE); /* clears mimicking */
/* if hero is blind, wakeup() won't display the monster even though
it's no longer concealed */
if (!canspotmon(mtmp)
@@ -2695,7 +2695,7 @@ struct obj *otmp; /* source of flash */
}
if (mtmp->mhp > 0) {
if (!context.mon_moving)
setmangry(mtmp);
setmangry(mtmp, TRUE);
if (tmp < 9 && !mtmp->isshk && rn2(4))
monflee(mtmp, rn2(4) ? rnd(100) : 0, FALSE, TRUE);
mtmp->mcansee = 0;

View File

@@ -400,7 +400,7 @@ invault()
}
mongone(guard);
} else {
setmangry(guard);
setmangry(guard, FALSE);
if (Deaf) {
if (!Blind)
pline("%s mouths something and looks very angry!",

View File

@@ -426,7 +426,7 @@ struct obj *otmp;
}
if (wake) {
if (mtmp->mhp > 0) {
wakeup(mtmp);
wakeup(mtmp, TRUE);
m_respond(mtmp);
if (mtmp->isshk && !*u.ushops)
hot_pursuit(mtmp);
@@ -748,7 +748,9 @@ boolean by_hero;
x = xy.x, y = xy.y;
}
if (mons[montype].mlet == S_EEL && !IS_POOL(levl[x][y].typ)) {
if ((mons[montype].mlet == S_EEL && !IS_POOL(levl[x][y].typ))
|| (mons[montype].mlet == S_TROLL
&& uwep && uwep->oartifact == ART_TROLLSBANE)) {
if (by_hero && cansee(x,y))
pline("%s twitches feebly.",
upstart(corpse_xname(corpse, (const char *) 0, CXN_PFX_THE)));
@@ -4533,12 +4535,9 @@ short exploding_wand_typ;
You("%s of smoke.", !Blind ? "see a puff" : "smell a whiff");
}
if ((mon = m_at(x, y)) != 0) {
/* Cannot use wakeup() which also angers the monster */
mon->msleeping = 0;
if (mon->m_ap_type)
seemimic(mon);
wakeup(mon, FALSE);
if (type >= 0) {
setmangry(mon);
setmangry(mon, TRUE);
if (mon->ispriest && *in_rooms(mon->mx, mon->my, TEMPLE))
ghod_hitsu(mon);
if (mon->isshk && !*u.ushops)