-/* NetHack 3.6 region.c $NHDT-Date: 1446892454 2015/11/07 10:34:14 $ $NHDT-Branch: master $:$NHDT-Revision: 1.36 $ */
+/* 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-2022 */
+/* JNetHack may be freely redistributed. See license for details. */
+
#include "hack.h"
#include "lev.h"
NhRegion *reg;
reg = (NhRegion *) alloc(sizeof(NhRegion));
+ (void) memset((genericptr_t)reg, 0, sizeof(NhRegion));
/* Determines bounding box */
if (nrect > 0) {
reg->bounding_box = rects[0];
} else {
- reg->bounding_box.lx = 99;
- reg->bounding_box.ly = 99;
- reg->bounding_box.hx = 0;
+ reg->bounding_box.lx = COLNO;
+ reg->bounding_box.ly = ROWNO;
+ reg->bounding_box.hx = 0; /* 1 */
reg->bounding_box.hy = 0;
}
reg->nrects = nrect;
- reg->rects =
- nrect > 0 ? (NhRect *) alloc((sizeof(NhRect)) * nrect) : (NhRect *) 0;
+ reg->rects = (nrect > 0) ? (NhRect *) alloc(nrect * sizeof (NhRect)) : 0;
for (i = 0; i < nrect; i++) {
if (rects[i].lx < reg->bounding_box.lx)
reg->bounding_box.lx = rects[i].lx;
{
NhRect *tmp_rect;
- tmp_rect = (NhRect *) alloc(sizeof(NhRect) * (reg->nrects + 1));
+ tmp_rect = (NhRect *) alloc((reg->nrects + 1) * sizeof (NhRect));
if (reg->nrects > 0) {
(void) memcpy((genericptr_t) tmp_rect, (genericptr_t) reg->rects,
- (sizeof(NhRect) * reg->nrects));
+ reg->nrects * sizeof (NhRect));
free((genericptr_t) reg->rects);
}
tmp_rect[reg->nrects] = *rect;
unsigned *tmp_m;
if (reg->max_monst <= reg->n_monst) {
- tmp_m = (unsigned *) alloc(sizeof(unsigned)
+ tmp_m = (unsigned *) alloc(sizeof (unsigned)
* (reg->max_monst + MONST_INC));
if (reg->max_monst > 0) {
for (i = 0; i < reg->max_monst; i++)
if (max_regions <= n_regions) {
tmp_reg = regions;
regions =
- (NhRegion **) alloc(sizeof(NhRegion *) * (max_regions + 10));
+ (NhRegion **) alloc((max_regions + 10) * sizeof (NhRegion *));
if (max_regions > 0) {
(void) memcpy((genericptr_t) regions, (genericptr_t) tmp_reg,
- max_regions * sizeof(NhRegion *));
+ max_regions * sizeof (NhRegion *));
free((genericptr_t) tmp_reg);
}
max_regions += 10;
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;
}
reset_region_mids(regions[i]);
}
+/* to support '#stats' wizard-mode command */
+void
+region_stats(hdrfmt, hdrbuf, count, size)
+const char *hdrfmt;
+char *hdrbuf;
+long *count, *size;
+{
+ NhRegion *rg;
+ int i;
+
+ /* other stats formats take one parameter; this takes two */
+ Sprintf(hdrbuf, hdrfmt, (long) sizeof (NhRegion), (long) sizeof (NhRect));
+ *count = (long) n_regions; /* might be 0 even though max_regions isn't */
+ *size = (long) max_regions * (long) sizeof (NhRegion);
+ for (i = 0; i < n_regions; ++i) {
+ rg = regions[i];
+ *size += (long) rg->nrects * (long) sizeof (NhRect);
+ if (rg->enter_msg)
+ *size += (long) (strlen(rg->enter_msg) + 1);
+ if (rg->leave_msg)
+ *size += (long) (strlen(rg->leave_msg) + 1);
+ *size += (long) rg->max_monst * (long) sizeof *rg->monsters;
+ }
+ /* ? */
+}
+
/* update monster IDs for region being loaded from bones; `ghostly' implied */
STATIC_OVL void
reset_region_mids(reg)
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
Your("%s sting.", makeplural(body_part(EYE)));
+*/
+ Your("%s\82ª\83`\83N\83`\83N\82µ\82½\81D", body_part(EYE));
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
} else { /* A monster is inside the cloud */
mtmp = (struct monst *) p2;
- /* Non living and non breathing monsters are not concerned */
+ /* Non living and non breathing monsters are not concerned;
+ adult green dragon is not affected by gas cloud, baby one is */
if (!(nonliving(mtmp->data) || is_vampshifter(mtmp))
- && !breathless(mtmp->data)) {
+ && !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) */
+ && !(attacktype_fordmg(mtmp->data, AT_BREA, AD_DRST)
+ || attacktype_fordmg(mtmp->data, AT_BREA, AD_RBRE))) {
if (cansee(mtmp->mx, mtmp->my))
/*JP
pline("%s coughs!", Monnam(mtmp));
*/
pline("%s\82Í\8aP\82«\82±\82ñ\82¾\81I", Monnam(mtmp));
if (heros_fault(reg))
- setmangry(mtmp);
+ setmangry(mtmp, TRUE);
if (haseyes(mtmp->data) && mtmp->mcansee) {
mtmp->mblinded = 1;
mtmp->mcansee = 0;
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;
}
}
safe_teleds(FALSE);
} else if (r) {
remove_region(r);
+/*JP
pline_The("gas cloud enveloping you dissipates.");
+*/
+ pline("\82 \82È\82½\82ð\95ï\82ñ\82Å\82¢\82½\83K\83X\89_\82Í\8fÁ\82¦\82½\81D");
} else {
/* cloud dissipated on its own, so nothing needs to be done */
+/*JP
pline_The("gas cloud has dissipated.");
+*/
+ pline("\83K\83X\89_\82Í\8fÁ\82¦\82½\81D");
}
/* maybe cure blindness too */
if ((Blinded & TIMEOUT) == 1L)