-/* NetHack 3.6 region.c $NHDT-Date: 1496087244 2017/05/29 19:47:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.40 $ */
+/* NetHack 3.6 region.c $NHDT-Date: 1573957877 2019/11/17 02:31:17 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.45 $ */
/* Copyright (c) 1996 by Jean-Christophe Collet */
/* NetHack may be freely redistributed. See license for details. */
/* JNetHack Copyright */
/* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
-/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
+/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2022 */
/* JNetHack may be freely redistributed. See license for details. */
#include "hack.h"
if (i == n_regions)
return;
+ /* remove region before potential newsym() calls, but don't free it yet */
+ if (--n_regions != i)
+ regions[i] = regions[n_regions];
+ regions[n_regions] = (NhRegion *) 0;
+
/* Update screen if necessary */
reg->ttl = -2L; /* for visible_region_at */
if (reg->visible)
newsym(x, y);
free_region(reg);
- regions[i] = regions[n_regions - 1];
- regions[n_regions - 1] = (NhRegion *) 0;
- n_regions--;
}
/*
struct monst *mtmp =
find_mid(regions[i]->monsters[j], FM_FMON);
- if (!mtmp || mtmp->mhp <= 0
+ if (!mtmp || DEADMONSTER(mtmp)
|| (*callbacks[f_indx])(regions[i], mtmp)) {
/* The monster died, remove it from list */
k = (regions[i]->n_monst -= 1);
in_out_region(x, y)
xchar x, y;
{
- int i, f_indx;
+ int i, f_indx = 0;
- /* First check if we can do the move */
+ /* First check if hero can do the move */
for (i = 0; i < n_regions; i++) {
- if (inside_region(regions[i], x, y) && !hero_inside(regions[i])
- && !regions[i]->attach_2_u) {
- if ((f_indx = regions[i]->can_enter_f) != NO_CALLBACK)
- if (!(*callbacks[f_indx])(regions[i], (genericptr_t) 0))
- return FALSE;
- } else if (hero_inside(regions[i]) && !inside_region(regions[i], x, y)
- && !regions[i]->attach_2_u) {
- if ((f_indx = regions[i]->can_leave_f) != NO_CALLBACK)
- if (!(*callbacks[f_indx])(regions[i], (genericptr_t) 0))
- return FALSE;
+ if (regions[i]->attach_2_u)
+ continue;
+ if (inside_region(regions[i], x, y)
+ ? (!hero_inside(regions[i])
+ && (f_indx = regions[i]->can_enter_f) != NO_CALLBACK)
+ : (hero_inside(regions[i])
+ && (f_indx = regions[i]->can_leave_f) != NO_CALLBACK)) {
+ if (!(*callbacks[f_indx])(regions[i], (genericptr_t) 0))
+ return FALSE;
}
}
- /* Callbacks for the regions we do leave */
- for (i = 0; i < n_regions; i++)
- if (hero_inside(regions[i]) && !regions[i]->attach_2_u
+ /* Callbacks for the regions hero does leave */
+ for (i = 0; i < n_regions; i++) {
+ if (regions[i]->attach_2_u)
+ continue;
+ if (hero_inside(regions[i])
&& !inside_region(regions[i], x, y)) {
clear_hero_inside(regions[i]);
if (regions[i]->leave_msg != (const char *) 0)
if ((f_indx = regions[i]->leave_f) != NO_CALLBACK)
(void) (*callbacks[f_indx])(regions[i], (genericptr_t) 0);
}
+ }
- /* Callbacks for the regions we do enter */
- for (i = 0; i < n_regions; i++)
- if (!hero_inside(regions[i]) && !regions[i]->attach_2_u
+ /* Callbacks for the regions hero does enter */
+ for (i = 0; i < n_regions; i++) {
+ if (regions[i]->attach_2_u)
+ continue;
+ if (!hero_inside(regions[i])
&& inside_region(regions[i], x, y)) {
set_hero_inside(regions[i]);
if (regions[i]->enter_msg != (const char *) 0)
if ((f_indx = regions[i]->enter_f) != NO_CALLBACK)
(void) (*callbacks[f_indx])(regions[i], (genericptr_t) 0);
}
+ }
+
return TRUE;
}
/*
- * check whether a monster enters/leaves one or more region.
-*/
+ * check whether a monster enters/leaves one or more regions.
+ */
boolean
m_in_out_region(mon, x, y)
struct monst *mon;
xchar x, y;
{
- int i, f_indx;
+ int i, f_indx = 0;
- /* First check if we can do the move */
+ /* First check if mon can do the move */
for (i = 0; i < n_regions; i++) {
- if (inside_region(regions[i], x, y) && !mon_in_region(regions[i], mon)
- && regions[i]->attach_2_m != mon->m_id) {
- if ((f_indx = regions[i]->can_enter_f) != NO_CALLBACK)
- if (!(*callbacks[f_indx])(regions[i], mon))
- return FALSE;
- } else if (mon_in_region(regions[i], mon)
- && !inside_region(regions[i], x, y)
- && regions[i]->attach_2_m != mon->m_id) {
- if ((f_indx = regions[i]->can_leave_f) != NO_CALLBACK)
- if (!(*callbacks[f_indx])(regions[i], mon))
- return FALSE;
+ if (regions[i]->attach_2_m == mon->m_id)
+ continue;
+ if (inside_region(regions[i], x, y)
+ ? (!mon_in_region(regions[i], mon)
+ && (f_indx = regions[i]->can_enter_f) != NO_CALLBACK)
+ : (mon_in_region(regions[i], mon)
+ && (f_indx = regions[i]->can_leave_f) != NO_CALLBACK)) {
+ if (!(*callbacks[f_indx])(regions[i], mon))
+ return FALSE;
}
}
- /* Callbacks for the regions we do leave */
- for (i = 0; i < n_regions; i++)
+ /* Callbacks for the regions mon does leave */
+ for (i = 0; i < n_regions; i++) {
+ if (regions[i]->attach_2_m == mon->m_id)
+ continue;
if (mon_in_region(regions[i], mon)
- && regions[i]->attach_2_m != mon->m_id
&& !inside_region(regions[i], x, y)) {
remove_mon_from_reg(regions[i], mon);
if ((f_indx = regions[i]->leave_f) != NO_CALLBACK)
(void) (*callbacks[f_indx])(regions[i], mon);
}
+ }
- /* Callbacks for the regions we do enter */
- for (i = 0; i < n_regions; i++)
- if (!hero_inside(regions[i]) && !regions[i]->attach_2_u
+ /* Callbacks for the regions mon does enter */
+ for (i = 0; i < n_regions; i++) {
+ if (regions[i]->attach_2_m == mon->m_id)
+ continue;
+ if (!mon_in_region(regions[i], mon)
&& inside_region(regions[i], x, y)) {
add_mon_to_reg(regions[i], mon);
if ((f_indx = regions[i]->enter_f) != NO_CALLBACK)
(void) (*callbacks[f_indx])(regions[i], mon);
}
+ }
+
return TRUE;
}
{
register int i;
- for (i = 0; i < n_regions; i++)
- if (inside_region(regions[i], x, y) && regions[i]->visible
- && regions[i]->ttl != -2L)
+ for (i = 0; i < n_regions; i++) {
+ if (!regions[i]->visible || regions[i]->ttl == -2L)
+ continue;
+ if (inside_region(regions[i], x, y))
return regions[i];
+ }
return (NhRegion *) 0;
}
if (p2 == (genericptr_t) 0) { /* That means the player */
if (!Blind)
- You("bump into %s. Ouch!",
+#if 0 /*JP*/
+ You("bump into %s. Ouch!",
Hallucination ? "an invisible tree"
: "some kind of invisible wall");
+#else
+ You("%s\82É\82Ô\82¿\82 \82½\82Á\82½\81D\82¢\82Ä\82Á\81I",
+ Hallucination ? "\96Ú\82É\8c©\82¦\82È\82¢\96Ø"
+ : "\82È\82ñ\82ç\82©\82Ì\96Ú\82É\8c©\82¦\82È\82¢\95Ç");
+#endif
else
+/*JP
pline("Ouch!");
+*/
+ pline("\82¢\82Ä\82Á\81I");
} else {
mtmp = (struct monst *) p2;
if (canseemon(mtmp))
+/*JP
pline("%s bumps into %s!", Monnam(mtmp), something);
+*/
+ pline("%s\82Í%s\82É\82Ô\82¿\82 \82½\82Á\82½\81I", Monnam(mtmp), something);
}
return FALSE;
}
struct monst *mtmp;
int dam;
+ /*
+ * Gas clouds can't be targetted at water locations, but they can
+ * start next to water and spread over it.
+ */
+
reg = (NhRegion *) p1;
dam = reg->arg.a_int;
if (p2 == (genericptr_t) 0) { /* This means *YOU* Bozo! */
- if (u.uinvulnerable || nonliving(youmonst.data) || Breathless)
+ if (u.uinvulnerable || nonliving(youmonst.data) || Breathless
+ || Underwater)
return FALSE;
if (!Blind) {
/*JP
make_blinded(1L, FALSE);
}
if (!Poison_resistance) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s is burning your %s!", Something,
makeplural(body_part(LUNG)));
#else
adult green dragon is not affected by gas cloud, baby one is */
if (!(nonliving(mtmp->data) || is_vampshifter(mtmp))
&& !breathless(mtmp->data)
+ /* not is_swimmer(); assume that non-fish are swimming on
+ the surface and breathing the air above it periodically
+ unless located at water spot on plane of water */
+ && !((mtmp->data->mlet == S_EEL || Is_waterlevel(&u.uz))
+ && is_pool(mtmp->mx, mtmp->my))
/* exclude monsters with poison gas breath attack:
adult green dragon and Chromatic Dragon (and iron golem,
but nonliving() and breathless() tests also catch that) */
if (resists_poison(mtmp))
return FALSE;
mtmp->mhp -= rnd(dam) + 5;
- if (mtmp->mhp <= 0) {
+ if (DEADMONSTER(mtmp)) {
if (heros_fault(reg))
killed(mtmp);
else
monkilled(mtmp, "gas cloud", AD_DRST);
*/
monkilled(mtmp, "\83K\83X\89_", AD_DRST);
- if (mtmp->mhp <= 0) { /* not lifesaved */
+ if (DEADMONSTER(mtmp)) { /* not lifesaved */
return TRUE;
}
}