missing fountain tag in minend-3
do not pacify shopkeeper when the hero enters a shop if that hero previously
angered the shopkeeper without ever visibly entering the shop
+attempting to place migrating monsters onto a monster-saturated level no
+ longer triggers impossible()
Platform- and/or Interface-Specific Fixes
E void FDECL(tele_trap, (struct trap *));
E void FDECL(level_tele_trap, (struct trap *));
E void FDECL(rloc_to, (struct monst *,int,int));
-E void FDECL(rloc, (struct monst *));
+E boolean FDECL(rloc, (struct monst *, BOOLEAN_P));
E boolean FDECL(tele_restrict, (struct monst *));
E void FDECL(mtele_trap, (struct monst *, struct trap *,int));
E int FDECL(mlevel_tele_trap, (struct monst *, struct trap *,BOOLEAN_P,int));
setnotworn(obj); /* in case mirror was wielded */
freeinv(obj);
(void) mpickobj(mtmp,obj);
- if (!tele_restrict(mtmp)) rloc(mtmp);
+ if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
} else if (!is_unicorn(mtmp->data) && !humanoid(mtmp->data) &&
(!mtmp->minvis || perceives(mtmp->data)) && rn2(5)) {
if (vis)
#if defined(__BORLANDC__) && !defined(_WIN32)
extern void FDECL(show_borlandc_stats, (winid));
#endif
+#ifdef DEBUG_MIGRATING_MONS
+STATIC_PTR int NDECL(wiz_migrate_mons);
+#endif
STATIC_DCL void FDECL(count_obj, (struct obj *, long *, long *, BOOLEAN_P, BOOLEAN_P));
STATIC_DCL void FDECL(obj_chain, (winid, const char *, struct obj *, long *, long *));
STATIC_DCL void FDECL(mon_invent_chain, (winid, const char *, struct monst *, long *, long *));
*/
{(char *)0, (char *)0, donull, TRUE},
{(char *)0, (char *)0, donull, TRUE},
+#ifdef DEBUG_MIGRATING_MONS
+ {(char *)0, (char *)0, donull, TRUE},
+#endif
{(char *)0, (char *)0, donull, TRUE},
{(char *)0, (char *)0, donull, TRUE},
{(char *)0, (char *)0, donull, TRUE},
static const struct ext_func_tab debug_extcmdlist[] = {
{"levelchange", "change experience level", wiz_level_change, TRUE},
{"lightsources", "show mobile light sources", wiz_light_sources, TRUE},
+#ifdef DEBUG_MIGRATING_MONS
+ {"migratemons", "migrate n random monsters", wiz_migrate_mons, TRUE},
+#endif
{"monpolycontrol", "control monster polymorphs", wiz_mon_polycontrol, TRUE},
{"panic", "test panic routine (fatal to game)", wiz_panic, TRUE},
{"polyself", "polymorph self", wiz_polyself, TRUE},
timer_sanity_check();
}
+#ifdef DEBUG_MIGRATING_MONS
+static int
+wiz_migrate_mons()
+{
+ int mcount = 0;
+ char inbuf[BUFSZ];
+ struct permonst *ptr;
+ struct monst *mtmp;
+ d_level tolevel;
+ getlin("How many random monsters to migrate? [0]", inbuf);
+ if (*inbuf == '\033') return 0;
+ mcount = atoi(inbuf);
+ if (mcount < 0 || mcount > (COLNO * ROWNO) || Is_botlevel(&u.uz))
+ return 0;
+ while (mcount > 0) {
+ if (Is_stronghold(&u.uz))
+ assign_level(&tolevel, &valley_level);
+ else
+ get_level(&tolevel, depth(&u.uz) + 1);
+ ptr = rndmonst();
+ mtmp = makemon(ptr, 0, 0, NO_MM_FLAGS);
+ if (mtmp) migrate_to_level(mtmp, ledger_no(&tolevel),
+ MIGR_RANDOM, (coord *)0);
+ mcount--;
+ }
+ return 0;
+}
+#endif
+
#endif /* WIZARD */
#define unctrl(c) ((c) <= C('z') ? (0x60 | (c)) : (c))
if(IS_ROCK(lev->typ)) return;
if(t_at(x, y)) return; /* don't cover the portal */
if ((mtmp = m_at(x, y)) != 0) /* make sure crucial monsters survive */
- if(!passes_walls(mtmp->data)) rloc(mtmp);
+ if(!passes_walls(mtmp->data)) (void) rloc(mtmp, FALSE);
} else if(lev->typ == ROOM) return;
unblock_point(x,y); /* make sure vision knows this location is open */
if ((mtmp = m_at(u.ux, u.uy)) != 0) {
impossible("mnexto failed (do.c)?");
- rloc(mtmp);
+ (void) rloc(mtmp, FALSE);
}
}
mtmp->my = xyflags;
if (xlocale)
(void) mnearto(mtmp, xlocale, ylocale, FALSE);
- else
- rloc(mtmp);
+ else {
+ if (!rloc(mtmp,TRUE)) {
+ /*
+ * Failed to place migrating monster,
+ * probably because the level is full.
+ * Dump the monster's cargo and leave the monster dead.
+ */
+ struct obj *obj, *corpse;
+ while ((obj = mtmp->minvent) != 0) {
+ obj_extract_self(obj);
+ obj_no_longer_held(obj);
+ if (obj->owornmask & W_WEP)
+ setmnotwielded(mtmp,obj);
+ obj->owornmask = 0L;
+ if (xlocale && ylocale)
+ place_object(obj, xlocale, ylocale);
+ else {
+ rloco(obj);
+ get_obj_location(obj, &xlocale, &ylocale, 0);
+ }
+ }
+ corpse = mkcorpstat(CORPSE, (struct monst *)0, mtmp->data,
+ xlocale, ylocale, FALSE);
+#ifndef GOLDOBJ
+ if (mtmp->mgold) {
+ if (xlocale == 0 && ylocale == 0 && corpse) {
+ (void) get_obj_location(corpse, &xlocale, &ylocale, 0);
+ (void) mkgold(mtmp->mgold, xlocale, ylocale);
+ }
+ mtmp->mgold = 0L;
+ }
+#endif
+ mongone(mtmp);
+ }
+ }
}
/* heal monster for time spent elsewhere */
nopick:
if(!Blind) pline("%s", buf);
- if (!tele_restrict(mon)) rloc(mon);
+ if (!tele_restrict(mon)) (void) rloc(mon, FALSE);
return(ret);
}
we'll get "it" in the suddenly disappears message */
if (vis) Strcpy(mdef_Monnam, Monnam(mdef));
mdef->mstrategy &= ~STRAT_WAITFORU;
- rloc(mdef);
+ (void) rloc(mdef, FALSE);
if (vis && !canspotmon(mdef)
#ifdef STEED
&& mdef != u.usteed
pline("%s steals some gold from %s.", buf, mon_nam(mdef));
}
if (!tele_restrict(magr)) {
- rloc(magr);
+ (void) rloc(magr, FALSE);
if (vis && !canspotmon(magr))
pline("%s suddenly disappears!", buf);
}
0 : MM_AGR_DIED));
if (magr->data->mlet == S_NYMPH &&
!tele_restrict(magr)) {
- rloc(magr);
+ (void) rloc(magr, FALSE);
if (vis && !canspotmon(magr))
pline("%s suddenly disappears!", buf);
}
pline("%s %s.", Monnam(mtmp), mtmp->minvent ?
"brags about the goods some dungeon explorer provided" :
"makes some remarks about how difficult theft is lately");
- if (!tele_restrict(mtmp)) rloc(mtmp);
+ if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
return 3;
} else if (mtmp->mcan) {
if (!Blind) {
flags.female ? "unaffected" : "uninterested");
}
if(rn2(3)) {
- if (!tele_restrict(mtmp)) rloc(mtmp);
+ if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
return 3;
}
break;
break;
default:
if (!is_animal(mtmp->data) && !tele_restrict(mtmp))
- rloc(mtmp);
+ (void) rloc(mtmp, FALSE);
if (is_animal(mtmp->data) && *buf) {
if (canseemon(mtmp))
pline("%s tries to %s away with %s.",
mongone(mtmp);
return 2;
} else if (!rn2(33)) {
- if (!tele_restrict(mtmp)) rloc(mtmp);
+ if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
monflee(mtmp, d(3, 6), TRUE, FALSE);
return 3;
}
if (uarm || uarmc) {
verbalize("You're such a %s; I wish...",
flags.female ? "sweet lady" : "nice guy");
- if (!tele_restrict(mon)) rloc(mon);
+ if (!tele_restrict(mon)) (void) rloc(mon, FALSE);
return 1;
}
if (u.ualign.type == A_CHAOTIC)
#endif
}
if (!rn2(25)) mon->mcan = 1; /* monster is worn out */
- if (!tele_restrict(mon)) rloc(mon);
+ if (!tele_restrict(mon)) (void) rloc(mon, FALSE);
return 1;
}
if (youmonst.data->mlet == S_DEMON) { /* Won't blackmail their own. */
pline("%s says, \"Good hunting, %s.\"",
Amonnam(mtmp), flags.female ? "Sister" : "Brother");
- if (!tele_restrict(mtmp)) rloc(mtmp);
+ if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
return(1);
}
#ifndef GOLDOBJ
/* "something" means the player in this case */
if(MON_AT(x, y)) {
/* move the monster if no choice, or just try again */
- if(oneshot) rloc(m_at(x,y));
+ if(oneshot) (void) rloc(m_at(x,y), FALSE);
else return(FALSE);
}
u_on_newpos(x, y);
if (objtype != CORPSE && objtype != STATUE)
impossible("making corpstat type %d", objtype);
- otmp = mksobj_at(objtype, x, y, init, FALSE);
+ if (x == 0 && y == 0) { /* special case - random placement */
+ otmp = mksobj(objtype, init, FALSE);
+ if (otmp) rloco(otmp);
+ } else
+ otmp = mksobj_at(objtype, x, y, init, FALSE);
if (otmp) {
if (mtmp) {
struct obj *otmp2;
if (mtmp->mhp > 0) {
(void) fire_damage(mtmp->minvent, FALSE, FALSE,
mtmp->mx, mtmp->my);
- rloc(mtmp);
+ (void) rloc(mtmp, FALSE);
return 0;
}
return (1);
}
mondead(mtmp);
if (mtmp->mhp > 0) {
- rloc(mtmp);
+ (void) rloc(mtmp, FALSE);
water_damage(mtmp->minvent, FALSE, FALSE);
return 0;
}
/* some monsters teleport */
if (mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz &&
!level.flags.noteleport) {
- rloc(mtmp);
+ (void) rloc(mtmp, FALSE);
return(0);
}
if (mdat->msound == MS_SHRIEK && !um_dist(mtmp->mx, mtmp->my, 1))
if (is_demon(youmonst.data)) {
/* "Good hunting, brother" */
- if (!tele_restrict(mtmp)) rloc(mtmp);
+ if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
} else {
mtmp->minvis = mtmp->perminvis = 0;
/* Why? For the same reason in real demon talk */
if(ptr == &mons[PM_TENGU] && !rn2(5) && !mtmp->mcan &&
!tele_restrict(mtmp)) {
if(mtmp->mhp < 7 || mtmp->mpeaceful || rn2(2))
- rloc(mtmp);
+ (void) rloc(mtmp, FALSE);
else
mnexto(mtmp);
mmoved = 1;
if (mtmp->wormno) worm_move(mtmp);
} else {
if(is_unicorn(ptr) && rn2(2) && !tele_restrict(mtmp)) {
- rloc(mtmp);
+ (void) rloc(mtmp, FALSE);
return(1);
}
if(mtmp->wormno) worm_nomove(mtmp);
return((struct monst *)0);
if(MON_AT(x, y))
- rloc(m_at(x, y)); /* insurance */
+ (void) rloc(m_at(x, y), FALSE); /* insurance */
if(!In_endgame(&u.uz)) special = FALSE;
return 2;
}
if (oseen && how) makeknown(how);
- rloc(mtmp);
+ (void) rloc(mtmp, FALSE);
return 2;
case MUSE_WAN_TELEPORTATION:
zap_oseen = oseen;
mtmp->msleeping = 0;
if(mtmp->m_ap_type) seemimic(mtmp);
} else if (!tele_restrict(mtmp))
- rloc(mtmp);
+ (void) rloc(mtmp, FALSE);
}
break;
case WAN_CANCELLATION:
int cnt;
if(MON_AT(sx+1, sy))
- rloc(m_at(sx+1, sy)); /* insurance */
+ (void) rloc(m_at(sx+1, sy), FALSE); /* insurance */
priest = makemon(&mons[sanctum ? PM_HIGH_PRIEST : PM_ALIGNED_PRIEST],
sx + 1, sy, NO_MM_FLAGS);
if (ptr != &mons[PM_ALIGNED_PRIEST] && ptr != &mons[PM_ANGEL])
return((struct monst *)0);
- if (MON_AT(x, y)) rloc(m_at(x, y)); /* insurance */
+ if (MON_AT(x, y)) (void) rloc(m_at(x, y), FALSE); /* insurance */
if (!(roamer = makemon(ptr, x, y, NO_MM_FLAGS)))
return((struct monst *)0);
return(-1);
}
- if(MON_AT(sx, sy)) rloc(m_at(sx, sy)); /* insurance */
+ if(MON_AT(sx, sy)) (void) rloc(m_at(sx, sy), FALSE); /* insurance */
/* now initialize the shopkeeper monster structure */
if(!(shk = makemon(&mons[PM_SHOPKEEPER], sx, sy, NO_MM_FLAGS)))
pline("%s quickly snatches some gold from between your %s!",
Monnam(mtmp), makeplural(body_part(FOOT)));
if(!u.ugold || !rn2(5)) {
- if (!tele_restrict(mtmp)) rloc(mtmp);
+ if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
/* do not set mtmp->mavenge here; gold on the floor is fair game */
monflee(mtmp, 0, FALSE, FALSE);
}
u.ugold -= (tmp = somegold());
Your("purse feels lighter.");
mtmp->mgold += tmp;
- if (!tele_restrict(mtmp)) rloc(mtmp);
+ if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
mtmp->mavenge = 1;
monflee(mtmp, 0, FALSE, FALSE);
flags.botl = 1;
pline("%s quickly snatches some gold from between your %s!",
Monnam(mtmp), makeplural(body_part(FOOT)));
if(!ygold || !rn2(5)) {
- if (!tele_restrict(mtmp)) rloc(mtmp);
+ if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
monflee(mtmp, 0, FALSE, FALSE);
}
} else if(ygold) {
freeinv(ygold);
add_to_minv(mtmp, ygold);
Your("purse feels lighter.");
- if (!tele_restrict(mtmp)) rloc(mtmp);
+ if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
monflee(mtmp, 0, FALSE, FALSE);
flags.botl = 1;
}
/* Implies seduction, "you gladly hand over ..."
so we don't set mavenge bit here. */
monflee(mtmp, 0, FALSE, FALSE);
- if (!tele_restrict(mtmp)) rloc(mtmp);
+ if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
break;
}
}
(void) mpickobj(mtmp,otmp); /* may merge and free otmp */
pline("%s stole %s!", Monnam(mtmp), doname(otmp));
if (can_teleport(mtmp->data) && !tele_restrict(mtmp))
- rloc(mtmp);
+ (void) rloc(mtmp, FALSE);
}
}
if (enexto(&cc, u.ux, u.uy, mtmp->data))
rloc_to(mtmp, cc.x, cc.y);
else /* evidently no room nearby; move steed elsewhere */
- rloc(mtmp);
+ (void) rloc(mtmp, FALSE);
return;
}
if (!DEADMONSTER(mtmp)) {
}
/* place a monster at a random location, typically due to teleport */
-void
-rloc(mtmp)
+/* return TRUE if successful, FALSE if not */
+boolean
+rloc(mtmp, suppress_impossible)
struct monst *mtmp; /* mx==0 implies migrating monster arrival */
+boolean suppress_impossible;
{
register int x, y, trycount;
#ifdef STEED
if (mtmp == u.usteed) {
tele();
- return;
+ return TRUE;
}
#endif
goto found_xy;
/* level either full of monsters or somehow faulty */
- impossible("rloc(): couldn't relocate monster");
- return;
+ if (!suppress_impossible)
+ impossible("rloc(): couldn't relocate monster");
+ return FALSE;
found_xy:
rloc_to(mtmp, x, y);
+ return TRUE;
}
STATIC_OVL void
rloc_to(mtmp, c.x, c.y);
return;
}
- rloc(mtmp);
+ (void) rloc(mtmp, FALSE);
}
boolean
* the guard isn't going to come for it...
*/
if (trap->once) mvault_tele(mtmp);
- else rloc(mtmp);
+ else (void) rloc(mtmp, FALSE);
if (in_sight) {
if (canseemon(mtmp))
if (give_feedback)
You("are no longer inside %s!", mon_nam(mtmp));
unstuck(mtmp);
- rloc(mtmp);
+ (void) rloc(mtmp, FALSE);
} else if (is_rider(mtmp->data) && rn2(13) &&
enexto(&cc, u.ux, u.uy, mtmp->data))
rloc_to(mtmp, cc.x, cc.y);
else
- rloc(mtmp);
+ (void) rloc(mtmp, FALSE);
return TRUE;
}
if(mtmp->isgd) return(FALSE);
else if(!in_fcorridor(grd, u.ux, u.uy)) {
if(mtmp->mtame) yelp(mtmp);
- rloc(mtmp);
+ (void) rloc(mtmp, FALSE);
}
}
levl[fcx][fcy].typ = EGD(grd)->fakecorr[fcbeg].ftyp;
if (!IS_WALL(levl[x][y].typ) && !in_fcorridor(grd, x, y)) {
if ((mon = m_at(x, y)) != 0 && mon != grd) {
if (mon->mtame) yelp(mon);
- rloc(mon);
+ (void) rloc(mon, FALSE);
}
if ((gold = g_at(x, y)) != 0) {
move_gold(gold, EGD(grd)->vroom);
(grd_in_vault ||
(in_fcorridor(grd, grd->mx, grd->my) &&
!in_fcorridor(grd, u.ux, u.uy)))) {
- rloc(grd);
+ (void) rloc(grd, FALSE);
wallify_vault(grd);
(void) clear_fcorr(grd, TRUE);
goto letknow;
if (u_carry_gold) { /* player teleported */
m = grd->mx;
n = grd->my;
- rloc(grd);
+ (void) rloc(grd, FALSE);
levl[m][n].typ = egrd->fakecorr[0].ftyp;
newsym(m,n);
grd->mpeaceful = 0;
/* just for insurance... */
if (MON_AT(m, n) && m != grd->mx && n != grd->my) {
verbalize("Out of my way, scum!");
- rloc(m_at(m, n));
+ (void) rloc(m_at(m, n), FALSE);
}
remove_monster(grd->mx, grd->my);
newsym(grd->mx, grd->my);
mtmp->mavenge = 1; /* covetous monsters attack while fleeing */
if (In_W_tower(mtmp->mx, mtmp->my, &u.uz) ||
(mtmp->iswiz && !xupstair && !mon_has_amulet(mtmp))) {
- if (!rn2(3 + mtmp->mhp/10)) rloc(mtmp);
+ if (!rn2(3 + mtmp->mhp/10)) (void) rloc(mtmp, FALSE);
} else if (xupstair &&
(mtmp->mx != xupstair || mtmp->my != yupstair)) {
(void) mnearto(mtmp, xupstair, yupstair, TRUE);