Merge branch 'NetHack-3.6'
This commit is contained in:
19
dat/help
19
dat/help
@@ -125,21 +125,24 @@ Commands:
|
||||
O Review current options and possibly change them.
|
||||
A menu displaying the option settings will be displayed
|
||||
and most can be changed by simply selecting their entry.
|
||||
Options are usually set before the game with a NETHACKOPTIONS
|
||||
environment variable, or via a config file (defaults.nh,
|
||||
NetHack Defaults, nethack.cnf, .nethackrc, etc.), not with
|
||||
the 'O' command.
|
||||
Options are usually set before the game with NETHACKOPTIONS
|
||||
environment variable or via a configuration file (defaults.nh,
|
||||
NetHack Defaults, nethack.cnf, ~/.nethackrc, etc.) rather
|
||||
than with the 'O' command.
|
||||
p Pay your shopping bill.
|
||||
P Put on an accessory (ring, amulet, etc).
|
||||
^P Repeat last message (subsequent ^P's repeat earlier messages).
|
||||
The behavior can be varied via the msg_window option.
|
||||
q Drink (quaff) something (potion, water, etc).
|
||||
Q Select ammunition for quiver.
|
||||
#quit Exit the program without saving the current game.
|
||||
r Read a scroll or spellbook.
|
||||
R Remove an accessory (ring, amulet, etc).
|
||||
^R Redraw the screen.
|
||||
s Search for secret doors and traps around you.
|
||||
S Save the game.
|
||||
S Save the game. Also exits the program.
|
||||
[To restore, just play again and use the same character name.]
|
||||
[There is no "save current data but keep playing" capability.]
|
||||
t Throw an object or shoot a projectile.
|
||||
T Take off armor.
|
||||
^T Teleport, if you are able.
|
||||
@@ -151,9 +154,12 @@ Commands:
|
||||
x Swap wielded and secondary weapons.
|
||||
X Toggle two-weapon combat.
|
||||
^X Show your attributes.
|
||||
#explore Switch to Explore Mode (aka Discovery Mode) where dying and
|
||||
deleting the save file during restore can both be overridden.
|
||||
z Zap a wand. (Use y instead of z if number_pad is -1.)
|
||||
Z Cast a spell. (Use Y instead of Z if number_pad is -1.)
|
||||
^Z Suspend the game. (^Y instead of ^Z if number_pad is -1.)
|
||||
[To resume, use the shell command 'fg'.]
|
||||
: Look at what is here.
|
||||
; Look at what is somewhere else.
|
||||
, Pick up some things.
|
||||
@@ -170,6 +176,7 @@ Commands:
|
||||
\ Show what types of objects have been discovered.
|
||||
` Show discovered types for one class of objects.
|
||||
! Escape to a shell, if supported in your version and OS.
|
||||
[To resume play, terminate the shell subprocess via 'exit'.]
|
||||
# Introduces one of the "extended" commands. To get a list of
|
||||
the commands you can use with "#" type "#?". The extended
|
||||
commands you can use depends upon what options the game was
|
||||
@@ -192,7 +199,7 @@ Commands:
|
||||
u Untrap a trapped object or door.
|
||||
|
||||
You can put a number before a command to repeat it that many times,
|
||||
as in "40." or "20s.". If you have the number_pad option set, you
|
||||
as in "40." or "20s". If you have the number_pad option set, you
|
||||
must type 'n' to prefix the count, as in "n40." or "n20s".
|
||||
|
||||
|
||||
|
||||
4
dat/hh
4
dat/hh
@@ -25,8 +25,10 @@ General commands:
|
||||
? help display one of several informative texts
|
||||
#quit quit end the game without saving current game
|
||||
S save save the game (to be continued later) and exit
|
||||
! sh escape to some SHELL (if allowed)
|
||||
[to restore, play again and use the same character name]
|
||||
! sh escape to some SHELL (if allowed; 'exit' to resume play)
|
||||
^Z suspend suspend the game (independent of your current suspend char)
|
||||
[on UNIX(tm)-based systems, use the 'fg' command to resume]
|
||||
O options set options
|
||||
/ what-is tell what a map symbol represents
|
||||
\ known display list of what's been discovered
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.29 $ $NHDT-Date: 1559313320 2019/05/31 14:35:20 $
|
||||
$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.31 $ $NHDT-Date: 1559422205 2019/06/01 20:50:05 $
|
||||
|
||||
This fixes36.3 file is here to capture information about updates in the 3.6.x
|
||||
lineage following the release of 3.6.2 in May 2019. Please note, however,
|
||||
@@ -35,6 +35,9 @@ fix a memory leak that occurred if player used wizard mode to leave and return
|
||||
free sortloot data if object handling is short-circuited by cockatrice corpse
|
||||
on the Plane of Water, make water go all the way to the edges of the level
|
||||
on the Plane of Air, make clouds disrupt line of sight along the edges
|
||||
have '&' (whatdoes) command describe movement keystrokes instead of reporting
|
||||
them as unknown or showing their number_pad action when that is Off
|
||||
some improvement to the handling of endgame levels filling up with monsters
|
||||
|
||||
|
||||
Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 extern.h $NHDT-Date: 1558485640 2019/05/22 00:40:40 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.706 $ */
|
||||
/* NetHack 3.6 extern.h $NHDT-Date: 1559422206 2019/06/01 20:50:06 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.707 $ */
|
||||
/* Copyright (c) Steve Creps, 1988. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -1391,6 +1391,7 @@ E int FDECL(can_carry, (struct monst *, struct obj *));
|
||||
E int FDECL(mfndpos, (struct monst *, coord *, long *, long));
|
||||
E boolean FDECL(monnear, (struct monst *, int, int));
|
||||
E void NDECL(dmonsfree);
|
||||
E void FDECL(elemental_clog, (struct monst *));
|
||||
E int FDECL(mcalcmove, (struct monst *));
|
||||
E void NDECL(mcalcdistress);
|
||||
E void FDECL(replmon, (struct monst *, struct monst *));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 monst.h $NHDT-Date: 1550524559 2019/02/18 21:15:59 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.28 $ */
|
||||
/* NetHack 3.6 monst.h $NHDT-Date: 1559422218 2019/06/01 20:50:18 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.31 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Robert Patrick Rankin, 2016. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -50,6 +50,17 @@ enum m_ap_types {
|
||||
M_AP_MONSTER = 3 /* a monster; mostly used for cloned Wizard */
|
||||
};
|
||||
|
||||
#define MON_FLOOR 0x00
|
||||
#define MON_OFFMAP 0x01
|
||||
#define MON_DETACH 0x02
|
||||
#define MON_MIGRATING 0x04
|
||||
#define MON_LIMBO 0x08
|
||||
#define MON_BUBBLEMOVE 0x10
|
||||
#define MON_ENDGAME_FREE 0x20
|
||||
#define MON_ENDGAME_MIGR 0x40
|
||||
#define MON_OBLITERATE 0x80
|
||||
#define MSTATE_MASK 0xFF
|
||||
|
||||
#define M_AP_TYPMASK 0x7
|
||||
#define M_AP_F_DKNOWN 0x8
|
||||
#define U_AP_TYPE (g.youmonst.m_ap_type & M_AP_TYPMASK)
|
||||
@@ -149,8 +160,8 @@ struct monst {
|
||||
long mtrapseen; /* bitmap of traps we've been trapped in */
|
||||
long mlstmv; /* for catching up with lost time */
|
||||
long mspare1;
|
||||
#define mstate mspare1 /* only for debug exam right now, not code flow */
|
||||
struct obj *minvent; /* mon's inventory */
|
||||
|
||||
struct obj *mw; /* mon's weapon */
|
||||
long misc_worn_check; /* mon's wornmask */
|
||||
xchar weapon_check; /* flag for whether to try switching weapons */
|
||||
|
||||
69
src/cmd.c
69
src/cmd.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 cmd.c $NHDT-Date: 1557088405 2019/05/05 20:33:25 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.333 $ */
|
||||
/* NetHack 3.6 cmd.c $NHDT-Date: 1559382745 2019/06/01 09:52:25 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.335 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Robert Patrick Rankin, 2013. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -23,6 +23,9 @@
|
||||
#define C(c) (0x1f & (c))
|
||||
#endif
|
||||
|
||||
#define unctrl(c) ((c) <= C('z') ? (0x60 | (c)) : (c))
|
||||
#define unmeta(c) (0x7f & (c))
|
||||
|
||||
#ifdef ALTMETA
|
||||
STATIC_VAR boolean alt_esc = FALSE;
|
||||
#endif
|
||||
@@ -3444,14 +3447,71 @@ struct ext_func_tab extcmdlist[] = {
|
||||
{ '\0', (char *) 0, (char *) 0, donull, 0, (char *) 0 } /* sentinel */
|
||||
};
|
||||
|
||||
/* for key2extcmddesc() to support dowhatdoes() */
|
||||
struct movcmd {
|
||||
uchar k1, k2, k3, k4; /* 'normal', 'qwertz', 'numpad', 'phone' */
|
||||
const char *txt, *alt; /* compass direction, screen direction */
|
||||
};
|
||||
static const struct movcmd movtab[] = {
|
||||
{ 'h', 'h', '4', '4', "west", "left" },
|
||||
{ 'j', 'j', '2', '8', "south", "down" },
|
||||
{ 'k', 'k', '8', '2', "north", "up" },
|
||||
{ 'l', 'l', '6', '6', "east", "right" },
|
||||
{ 'b', 'b', '1', '7', "southwest", "lower left" },
|
||||
{ 'n', 'n', '3', '9', "southeast", "lower right" },
|
||||
{ 'u', 'u', '9', '3', "northeast", "upper right" },
|
||||
{ 'y', 'z', '7', '1', "northwest", "upper left" },
|
||||
{ 0, 0, 0, 0, (char *) 0, (char *) 0 }
|
||||
};
|
||||
|
||||
int extcmdlist_length = SIZE(extcmdlist) - 1;
|
||||
|
||||
const char *
|
||||
key2extcmddesc(key)
|
||||
uchar key;
|
||||
{
|
||||
if (g.Cmd.commands[key] && g.Cmd.commands[key]->ef_txt)
|
||||
return g.Cmd.commands[key]->ef_desc;
|
||||
static char key2cmdbuf[48];
|
||||
const struct movcmd *mov;
|
||||
int k, c;
|
||||
uchar M_5 = (uchar) M('5'), M_0 = (uchar) M('0');
|
||||
|
||||
/* need to check for movement commands before checking the extended
|
||||
commands table because it contains entries for number_pad commands
|
||||
that match !number_pad movement (like 'j' for "jump") */
|
||||
key2cmdbuf[0] = '\0';
|
||||
if (movecmd(k = key))
|
||||
Strcpy(key2cmdbuf, "move"); /* "move or attack"? */
|
||||
else if (movecmd(k = unctrl(key)))
|
||||
Strcpy(key2cmdbuf, "rush");
|
||||
else if (movecmd(k = (g.Cmd.num_pad ? unmeta(key) : lowc(key))))
|
||||
Strcpy(key2cmdbuf, "run");
|
||||
if (*key2cmdbuf) {
|
||||
for (mov = &movtab[0]; mov->k1; ++mov) {
|
||||
c = !g.Cmd.num_pad ? (!g.Cmd.swap_yz ? mov->k1 : mov->k2)
|
||||
: (!g.Cmd.phone_layout ? mov->k3 : mov->k4);
|
||||
if (c == k) {
|
||||
Sprintf(eos(key2cmdbuf), " %s (screen %s)",
|
||||
mov->txt, mov->alt);
|
||||
return key2cmdbuf;
|
||||
}
|
||||
}
|
||||
} else if (digit(key) || (g.Cmd.num_pad && digit(unmeta(key)))) {
|
||||
key2cmdbuf[0] = '\0';
|
||||
if (!g.Cmd.num_pad)
|
||||
Strcpy(key2cmdbuf, "start of, or continuation of, a count");
|
||||
else if (key == '5' || key == M_5)
|
||||
Sprintf(key2cmdbuf, "%s prefix",
|
||||
(!!g.Cmd.pcHack_compat ^ (key == M_5)) ? "run" : "rush");
|
||||
else if (key == '0' || (g.Cmd.pcHack_compat && key == M_0))
|
||||
Strcpy(key2cmdbuf, "synonym for 'i'");
|
||||
if (*key2cmdbuf)
|
||||
return key2cmdbuf;
|
||||
}
|
||||
if (g.Cmd.commands[key]) {
|
||||
if (g.Cmd.commands[key]->ef_txt)
|
||||
return g.Cmd.commands[key]->ef_desc;
|
||||
|
||||
}
|
||||
return (char *) 0;
|
||||
}
|
||||
|
||||
@@ -4122,9 +4182,6 @@ wiz_migrate_mons()
|
||||
}
|
||||
#endif
|
||||
|
||||
#define unctrl(c) ((c) <= C('z') ? (0x60 | (c)) : (c))
|
||||
#define unmeta(c) (0x7f & (c))
|
||||
|
||||
struct {
|
||||
int nhkf;
|
||||
char key;
|
||||
|
||||
17
src/mkmaze.c
17
src/mkmaze.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 mkmaze.c $NHDT-Date: 1559299316 2019/05/31 10:41:56 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.73 $ */
|
||||
/* NetHack 3.6 mkmaze.c $NHDT-Date: 1559422240 2019/06/01 20:50:40 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.74 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Pasi Kallinen, 2018. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -644,14 +644,14 @@ unsigned long mflags;
|
||||
/* once in a blue moon, he won't be at the very bottom */
|
||||
if (!rn2(40))
|
||||
nlev--;
|
||||
mtmp->mspare1 = MIGR_LEFTOVERS;
|
||||
mtmp->mspare1 |= MIGR_LEFTOVERS;
|
||||
} else {
|
||||
nlev = rn2((max_depth - cur_depth) + 1) + cur_depth;
|
||||
if (nlev == cur_depth)
|
||||
nlev++;
|
||||
if (nlev > max_depth)
|
||||
nlev = max_depth;
|
||||
mtmp->mspare1 = 0L;
|
||||
mtmp->mspare1 = (mtmp->mspare1 & ~MIGR_LEFTOVERS);
|
||||
}
|
||||
get_level(&dest, nlev);
|
||||
migrate_to_level(mtmp, ledger_no(&dest), MIGR_RANDOM, (coord *) 0);
|
||||
@@ -1456,6 +1456,7 @@ movebubbles()
|
||||
|
||||
newsym(x, y); /* clean up old position */
|
||||
mon->mx = mon->my = 0;
|
||||
mon->mstate |= MON_BUBBLEMOVE;
|
||||
}
|
||||
if (!u.uswallow && x == u.ux && y == u.uy) {
|
||||
cons = (struct container *) alloc(sizeof *cons);
|
||||
@@ -1887,12 +1888,10 @@ boolean ini;
|
||||
case CONS_MON: {
|
||||
struct monst *mon = (struct monst *) cons->list;
|
||||
|
||||
/* mnearto() might fail, and putting the monster into limbo
|
||||
to try next time hero comes to this level makes no sense
|
||||
because we can't leave and return (outside wizard mode) */
|
||||
if (!mnearto(mon, cons->x, cons->y, TRUE)) {
|
||||
; /* ? */
|
||||
}
|
||||
/* mnearto() might fail. We can jump right to elemental_clog
|
||||
from here rather than deal_with_overcrowding() */
|
||||
if (!mnearto(mon, cons->x, cons->y, TRUE))
|
||||
elemental_clog(mon);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
178
src/mon.c
178
src/mon.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 mon.c $NHDT-Date: 1559227828 2019/05/30 14:50:28 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.286 $ */
|
||||
/* NetHack 3.6 mon.c $NHDT-Date: 1559422247 2019/06/01 20:50:47 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.287 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Derek S. Ray, 2015. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -26,6 +26,9 @@ STATIC_DCL struct permonst *FDECL(accept_newcham_form, (int));
|
||||
STATIC_DCL struct obj *FDECL(make_corpse, (struct monst *, unsigned));
|
||||
STATIC_DCL void FDECL(m_detach, (struct monst *, struct permonst *));
|
||||
STATIC_DCL void FDECL(lifesaved_monster, (struct monst *));
|
||||
STATIC_DCL void FDECL(migrate_mon, (struct monst *, XCHAR_P, XCHAR_P));
|
||||
STATIC_DCL boolean FDECL(ok_to_obliterate, (struct monst *));
|
||||
STATIC_DCL void FDECL(deal_with_overcrowding, (struct monst *));
|
||||
|
||||
/* note: duplicated in dog.c */
|
||||
#define LEVEL_SPECIFIC_NOCORPSE(mdat) \
|
||||
@@ -612,7 +615,8 @@ register struct monst *mtmp;
|
||||
xkilled(mtmp, XKILL_NOMSG);
|
||||
if (!DEADMONSTER(mtmp)) {
|
||||
water_damage_chain(mtmp->minvent, FALSE);
|
||||
(void) rloc(mtmp, FALSE);
|
||||
if (!rloc(mtmp, TRUE))
|
||||
deal_with_overcrowding(mtmp);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -1599,7 +1603,9 @@ dmonsfree()
|
||||
{
|
||||
struct monst **mtmp, *freetmp;
|
||||
int count = 0;
|
||||
char buf[QBUFSZ];
|
||||
|
||||
buf[0] = '\0';
|
||||
for (mtmp = &fmon; *mtmp;) {
|
||||
freetmp = *mtmp;
|
||||
if (DEADMONSTER(freetmp) && !freetmp->isgd) {
|
||||
@@ -1611,9 +1617,11 @@ dmonsfree()
|
||||
mtmp = &(freetmp->nmon);
|
||||
}
|
||||
|
||||
if (count != iflags.purge_monsters)
|
||||
impossible("dmonsfree: %d removed doesn't match %d pending",
|
||||
count, iflags.purge_monsters);
|
||||
if (count != iflags.purge_monsters) {
|
||||
describe_level(buf);
|
||||
impossible("dmonsfree: %d removed doesn't match %d pending on %s",
|
||||
count, iflags.purge_monsters, buf);
|
||||
}
|
||||
iflags.purge_monsters = 0;
|
||||
}
|
||||
|
||||
@@ -1789,8 +1797,13 @@ void
|
||||
dealloc_monst(mon)
|
||||
struct monst *mon;
|
||||
{
|
||||
if (mon->nmon)
|
||||
panic("dealloc_monst with nmon");
|
||||
char buf[QBUFSZ];
|
||||
|
||||
buf[0] = '\0';
|
||||
if (mon->nmon) {
|
||||
describe_level(buf);
|
||||
panic("dealloc_monst with nmon on %s", buf);
|
||||
}
|
||||
if (mon->mextra)
|
||||
dealloc_mextra(mon);
|
||||
free((genericptr_t) mon);
|
||||
@@ -1832,6 +1845,11 @@ struct permonst *mptr; /* reflects mtmp->data _prior_ to mtmp's death */
|
||||
shkgone(mtmp);
|
||||
if (mtmp->wormno)
|
||||
wormgone(mtmp);
|
||||
if (In_endgame(&u.uz)) {
|
||||
mtmp->mx = mtmp->my = 0;
|
||||
mtmp->mstate |= MON_ENDGAME_FREE;
|
||||
}
|
||||
mtmp->mstate |= MON_DETACH;
|
||||
iflags.purge_monsters++;
|
||||
}
|
||||
|
||||
@@ -2571,10 +2589,121 @@ struct monst *mtmp;
|
||||
void
|
||||
m_into_limbo(mtmp)
|
||||
struct monst *mtmp;
|
||||
{
|
||||
xchar target_lev = ledger_no(&u.uz), xyloc = MIGR_APPROX_XY;
|
||||
|
||||
mtmp->mstate |= MON_LIMBO;
|
||||
migrate_mon(mtmp, target_lev, xyloc);
|
||||
}
|
||||
|
||||
STATIC_OVL void
|
||||
migrate_mon(mtmp, target_lev, xyloc)
|
||||
struct monst *mtmp;
|
||||
xchar target_lev, xyloc;
|
||||
{
|
||||
unstuck(mtmp);
|
||||
mdrop_special_objs(mtmp);
|
||||
migrate_to_level(mtmp, ledger_no(&u.uz), MIGR_APPROX_XY, (coord *) 0);
|
||||
migrate_to_level(mtmp, target_lev, xyloc, (coord *) 0);
|
||||
mtmp->mstate |= MON_MIGRATING;
|
||||
}
|
||||
|
||||
STATIC_OVL boolean
|
||||
ok_to_obliterate(mtmp)
|
||||
struct monst *mtmp;
|
||||
{
|
||||
/*
|
||||
* Add checks for monsters that should not be obliterated
|
||||
* here (return FALSE).
|
||||
*/
|
||||
if (mtmp->data == &mons[PM_WIZARD_OF_YENDOR] || is_rider(mtmp->data)
|
||||
|| has_emin(mtmp) || has_epri(mtmp) || has_eshk(mtmp))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
elemental_clog(mon)
|
||||
struct monst *mon;
|
||||
{
|
||||
int m_lev = 0;
|
||||
static long msgmv = 0L;
|
||||
struct monst *mtmp, *m1, *m2, *m3, *m4, *m5, *zm;
|
||||
|
||||
if (In_endgame(&u.uz)) {
|
||||
m1 = m2 = m3 = m4 = m5 = zm = (struct monst *) 0;
|
||||
if (!msgmv || (g.moves - msgmv) > 200L) {
|
||||
if (!msgmv || rn2(2))
|
||||
You("feel besieged.");
|
||||
msgmv = g.moves;
|
||||
}
|
||||
/*
|
||||
* m1 an elemental from another plane.
|
||||
* m2 an elemental from this plane.
|
||||
* m3 the least powerful monst encountered in loop so far.
|
||||
* m4 some other non-tame monster.
|
||||
* m5 a pet.
|
||||
*/
|
||||
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
|
||||
if (DEADMONSTER(mtmp))
|
||||
continue;
|
||||
if (mtmp->mx == 0 && mtmp->my == 0)
|
||||
continue;
|
||||
if (mon_has_amulet(mtmp) || !ok_to_obliterate(mtmp))
|
||||
continue;
|
||||
if (mtmp->data->mlet == S_ELEMENTAL) {
|
||||
if (!is_home_elemental(mtmp->data)) {
|
||||
if (!m1)
|
||||
m1 = mtmp;
|
||||
} else {
|
||||
if (!m2)
|
||||
m2 = mtmp;
|
||||
}
|
||||
} else {
|
||||
if (!mtmp->mtame) {
|
||||
if (!m_lev || mtmp->m_lev < m_lev) {
|
||||
m_lev = mtmp->m_lev;
|
||||
m3 = mtmp;
|
||||
} else if (!m4) {
|
||||
m4 = mtmp;
|
||||
}
|
||||
} else {
|
||||
if (!m5)
|
||||
m5 = mtmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
mtmp = m1 ? m1 : m2 ? m2 : m3 ? m3 : m4 ? m4 : m5 ? m5 : zm;
|
||||
if (mtmp) {
|
||||
int mx = mtmp->mx, my = mtmp->my;
|
||||
|
||||
mtmp->mstate |= MON_OBLITERATE;
|
||||
mongone(mtmp);
|
||||
mtmp->mx = mtmp->my = 0;
|
||||
rloc_to(mon, mx, my);
|
||||
} else {
|
||||
/* last resort - migrate mon to the next plane */
|
||||
if (Is_waterlevel(&u.uz) || Is_firelevel(&u.uz) || Is_earthlevel(&u.uz)) {
|
||||
/* try sending mon on to the next plane */
|
||||
xchar target_lev = 0, xyloc = 0;
|
||||
struct trap *trap = g.ftrap;
|
||||
|
||||
while (trap) {
|
||||
if (trap->ttyp == MAGIC_PORTAL)
|
||||
break;
|
||||
trap = trap->ntrap;
|
||||
}
|
||||
if (trap) {
|
||||
target_lev = ledger_no(&trap->dst);
|
||||
xyloc = MIGR_RANDOM;
|
||||
}
|
||||
if (target_lev) {
|
||||
mon->mstate |= MON_ENDGAME_MIGR;
|
||||
migrate_mon(mon, target_lev, xyloc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* make monster mtmp next to you (if possible);
|
||||
@@ -2594,8 +2723,7 @@ struct monst *mtmp;
|
||||
}
|
||||
|
||||
if (!enexto(&mm, u.ux, u.uy, mtmp->data) || !isok(mm.x, mm.y)) {
|
||||
debugpline1("mnexto: sending %s into limbo", m_monnam(mtmp));
|
||||
m_into_limbo(mtmp);
|
||||
deal_with_overcrowding(mtmp);
|
||||
return;
|
||||
}
|
||||
rloc_to(mtmp, mm.x, mm.y);
|
||||
@@ -2608,6 +2736,19 @@ struct monst *mtmp;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
deal_with_overcrowding(mtmp)
|
||||
struct monst *mtmp;
|
||||
{
|
||||
if (In_endgame(&u.uz)) {
|
||||
debugpline1("overcrowding: elemental_clog on %s", m_monnam(mtmp));
|
||||
elemental_clog(mtmp);
|
||||
} else {
|
||||
debugpline1("overcrowding: sending %s into limbo", m_monnam(mtmp));
|
||||
m_into_limbo(mtmp);
|
||||
}
|
||||
}
|
||||
|
||||
/* like mnexto() but requires destination to be directly accessible */
|
||||
void
|
||||
maybe_mnexto(mtmp)
|
||||
@@ -2662,6 +2803,7 @@ boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
|
||||
remove_monster(x, y);
|
||||
|
||||
othermon->mx = othermon->my = 0; /* 'othermon' is not on the map */
|
||||
othermon->mstate |= MON_OFFMAP;
|
||||
}
|
||||
|
||||
newx = x;
|
||||
@@ -2671,8 +2813,16 @@ boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
|
||||
* Migrating_mons that need to be placed will cause
|
||||
* no end of trouble.
|
||||
*/
|
||||
if (!enexto(&mm, newx, newy, mtmp->data) || !isok(mm.x, mm.y))
|
||||
if (!enexto(&mm, newx, newy, mtmp->data) || !isok(mm.x, mm.y)) {
|
||||
if (othermon) {
|
||||
/* othermon already had its mx, my set to 0 above
|
||||
* and this would shortly cause a sanity check to fail
|
||||
* if we just return 0 here. The caller only possesses
|
||||
* awareness of mtmp, not othermon. */
|
||||
deal_with_overcrowding(othermon);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
newx = mm.x;
|
||||
newy = mm.y;
|
||||
}
|
||||
@@ -2680,10 +2830,8 @@ boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
|
||||
|
||||
if (move_other && othermon) {
|
||||
res = 2; /* moving another monster out of the way */
|
||||
if (!mnearto(othermon, x, y, FALSE)) { /* no 'move_other' this time */
|
||||
debugpline1("mnearto: sending %s into limbo", m_monnam(othermon));
|
||||
m_into_limbo(othermon);
|
||||
}
|
||||
if (!mnearto(othermon, x, y, FALSE)) /* no 'move_other' this time */
|
||||
deal_with_overcrowding(othermon);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
24
src/steed.c
24
src/steed.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 steed.c $NHDT-Date: 1545441042 2018/12/22 01:10:42 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.62 $ */
|
||||
/* NetHack 3.6 steed.c $NHDT-Date: 1559422254 2019/06/01 20:50:54 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.64 $ */
|
||||
/* Copyright (c) Kevin Hugo, 1998-1999. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -742,23 +742,35 @@ place_monster(mon, x, y)
|
||||
struct monst *mon;
|
||||
int x, y;
|
||||
{
|
||||
char buf[QBUFSZ];
|
||||
|
||||
buf[0] = '\0';
|
||||
/* normal map bounds are <1..COLNO-1,0..ROWNO-1> but sometimes
|
||||
vault guards (either living or dead) are parked at <0,0> */
|
||||
if (!isok(x, y) && (x != 0 || y != 0 || !mon->isgd)) {
|
||||
impossible("trying to place monster at <%d,%d>", x, y);
|
||||
describe_level(buf);
|
||||
impossible("trying to place monster at <%d,%d> mstate:%lx on %s",
|
||||
x, y, mon->mstate, buf);
|
||||
x = y = 0;
|
||||
}
|
||||
if (mon == u.usteed
|
||||
/* special case is for convoluted vault guard handling */
|
||||
|| (DEADMONSTER(mon) && !(mon->isgd && x == 0 && y == 0))) {
|
||||
impossible("placing %s onto map?",
|
||||
(mon == u.usteed) ? "steed" : "defunct monster");
|
||||
describe_level(buf);
|
||||
impossible("placing %s onto map, mstate:%lx, on %s?",
|
||||
(mon == u.usteed) ? "steed" : "defunct monster",
|
||||
mon->mstate, buf);
|
||||
return;
|
||||
}
|
||||
if (g.level.monsters[x][y])
|
||||
impossible("placing monster over another at <%d,%d>?", x, y);
|
||||
if (g.level.monsters[x][y]) {
|
||||
describe_level(buf);
|
||||
impossible("placing monster over another at <%d,%d>, mstates:%lx %lx on %s?",
|
||||
x, y, g.level.monsters[x][y]->mstate, mon->mstate, buf);
|
||||
}
|
||||
mon->mx = x, mon->my = y;
|
||||
g.level.monsters[x][y] = mon;
|
||||
mon->mstate &= ~(MON_OFFMAP | MON_MIGRATING | MON_LIMBO | MON_BUBBLEMOVE
|
||||
| MON_ENDGAME_FREE | MON_ENDGAME_MIGR);
|
||||
}
|
||||
|
||||
/*steed.c*/
|
||||
|
||||
Reference in New Issue
Block a user