Exemplo n.º 1
0
void
stealgold(struct monst *mtmp)
{
	struct gold *gold = g_at(u.ux, u.uy);
	long tmp;

	if(gold && ( !u.ugold || gold->amount > u.ugold || !rn2(5))) {
		mtmp->mgold += gold->amount;
		freegold(gold);
		if(Invisible) newsym(u.ux, u.uy);
		pline("%s quickly snatches some gold from between your feet!",
			Monnam(mtmp));
		if(!u.ugold || !rn2(5)) {
			rloc(mtmp);
			mtmp->mflee = 1;
		}
	} else if(u.ugold) {
		u.ugold -= (tmp = somegold());
		pline("Your purse feels lighter.");
		mtmp->mgold += tmp;
		rloc(mtmp);
		mtmp->mflee = 1;
		flags.botl = 1;
	}
}
Exemplo n.º 2
0
/* 
 * Steal gold coins only.  Leprechauns don't care for lesser coins.
 */
void stealgold(struct monst *mtmp)
{
	struct obj *fgold = gold_at(level, u.ux, u.uy);
	struct obj *ygold;
	long tmp;

        /* skip lesser coins on the floor */        
        while (fgold && fgold->otyp != GOLD_PIECE) fgold = fgold->nexthere; 

        /* Do you have real gold? */
        ygold = findgold(invent);

	if (fgold && ( !ygold || fgold->quan > ygold->quan || !rn2(5))) {
            obj_extract_self(fgold);
	    add_to_minv(mtmp, fgold);
	    newsym(u.ux, u.uy);
	    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(level, mtmp, FALSE);
		monflee(mtmp, 0, FALSE, FALSE);
	    }
	} else if (ygold) {
            const int gold_price = objects[GOLD_PIECE].oc_cost;
	    tmp = (somegold(money_cnt(invent)) + gold_price - 1) / gold_price;
	    tmp = min(tmp, ygold->quan);
            if (tmp < ygold->quan) ygold = splitobj(ygold, tmp);
            freeinv(ygold);
            add_to_minv(mtmp, ygold);
	    pline("Your purse feels lighter.");
	    if (!tele_restrict(mtmp)) rloc(level, mtmp, FALSE);
	    monflee(mtmp, 0, FALSE, FALSE);
	    iflags.botl = 1;
	}
}
Exemplo n.º 3
0
/* create a new shopkeeper in the given room */
static int shkinit ( const struct shclass *shp, struct mkroom *sroom) {
    int sh, sx, sy;
    struct monst *shk;

    /* place the shopkeeper in the given room */
    sh = sroom->fdoor;
    sx = doors[sh].x;
    sy = doors[sh].y;

    /* check that the shopkeeper placement is sane */
    if(sroom->irregular) {
        int rmno = (sroom - rooms) + ROOMOFFSET;
        if (isok(sx-1,sy) && !levl[sx-1][sy].edge &&
                (int) levl[sx-1][sy].roomno == rmno) sx--;
        else if (isok(sx+1,sy) && !levl[sx+1][sy].edge &&
                (int) levl[sx+1][sy].roomno == rmno) sx++;
        else if (isok(sx,sy-1) && !levl[sx][sy-1].edge &&
                (int) levl[sx][sy-1].roomno == rmno) sy--;
        else if (isok(sx,sy+1) && !levl[sx][sy+1].edge &&
                (int) levl[sx][sy+1].roomno == rmno) sx++;
        else goto shk_failed;
    }
    else if(sx == sroom->lx-1) sx++;
    else if(sx == sroom->hx+1) sx--;
    else if(sy == sroom->ly-1) sy++;
    else if(sy == sroom->hy+1) sy--; else {
shk_failed:
        return(-1);
    }

    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)))
        return(-1);
    shk->isshk = shk->mpeaceful = 1;
    set_malign(shk);
    shk->msleeping = 0;
    shk->mtrapseen = ~0;    /* we know all the traps already */
    ESHK(shk)->shoproom = (sroom - rooms) + ROOMOFFSET;
    sroom->resident = shk;
    ESHK(shk)->shoptype = sroom->rtype;
    assign_level(&(ESHK(shk)->shoplevel), &u.uz);
    ESHK(shk)->shd = doors[sh];
    ESHK(shk)->shk.x = sx;
    ESHK(shk)->shk.y = sy;
    ESHK(shk)->robbed = 0L;
    ESHK(shk)->credit = 0L;
    ESHK(shk)->debit = 0L;
    ESHK(shk)->loan = 0L;
    ESHK(shk)->visitct = 0;
    ESHK(shk)->following = 0;
    ESHK(shk)->billct = 0;
    shk->mgold = 1000L + 30L*(long)rnd(100);        /* initial capital */
    if (shp->shknms == shkrings)
        (void) mongets(shk, TOUCHSTONE);
    nameshk(shk, shp->shknms);

    return(sh);
}
Exemplo n.º 4
0
void
mtele_trap(struct monst *mtmp, struct trap *trap, int in_sight)
{
    const char *monname;

    if (tele_restrict(mtmp))
        return;
    if (teleport_pet(mtmp, FALSE)) {
        /* save name with pre-movement visibility */
        monname = Monnam(mtmp);

        /* Note: don't remove the trap if a vault.  Otherwise the monster will
           be stuck there, since the guard isn't going to come for it... */
        if (trap->once)
            mvault_tele(mtmp);
        else
            rloc(mtmp, TRUE);

        if (in_sight) {
            if (canseemon(mtmp))
                pline("%s seems disoriented.", monname);
            else
                pline("%s suddenly disappears!", monname);
            seetrap(trap);
        }
    }
}
Exemplo n.º 5
0
struct monst *
mk_roamer(const struct permonst *ptr, aligntyp alignment, struct level *lev,
          xchar x, xchar y, boolean peaceful, int mm_flags)
{
    struct monst *roamer;
    boolean coaligned = (u.ualign.type == alignment);

    if (ptr != &mons[PM_ALIGNED_PRIEST] && ptr != &mons[PM_ANGEL])
        return NULL;

    if (MON_AT(lev, x, y))
        rloc(m_at(lev, x, y), FALSE);   /* insurance */

    if (!(roamer = makemon(ptr, lev, x, y, mm_flags)))
        return NULL;

    EPRI(roamer)->shralign = alignment;
    if (coaligned && !peaceful)
        EPRI(roamer)->renegade = TRUE;
    /* roamer->ispriest == FALSE naturally */
    roamer->isminion = TRUE;    /* borrowing this bit */
    roamer->mtrapseen = ~0;     /* traps are known */
    msethostility(roamer, !peaceful, TRUE); /* TODO: handle in_mklev */
    roamer->msleeping = 0;

    /* MORE TO COME */
    return roamer;
}
Exemplo n.º 6
0
static int stealarm(void)
{
	struct monst *mtmp;
	struct obj *otmp;

	for (otmp = invent; otmp; otmp = otmp->nobj) {
	    if (otmp->o_id == stealoid) {
		for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
		    if (mtmp->m_id == stealmid) {
			if (DEADMONSTER(mtmp)) warning("stealarm(): dead monster stealing");
			if (!dmgtype(mtmp->data, AD_SITM)) /* polymorphed */
			    goto botm;
			if (otmp->unpaid)
			    subfrombill(otmp, shop_keeper(level, *u.ushops));
			freeinv(otmp);
			pline("%s steals %s!", Monnam(mtmp), doname(otmp));
			mpickobj(mtmp,otmp);	/* may free otmp */
			/* Implies seduction, "you gladly hand over ..."
			   so we don't set mavenge bit here. */
			monflee(mtmp, 0, FALSE, FALSE);
			if (!tele_restrict(mtmp)) rloc(level, mtmp, FALSE);
		        break;
		    }
		}
		break;
	    }
	}
botm:   stealoid = 0;
	return 0;
}
Exemplo n.º 7
0
static int stealarm (void) {
    struct monst *mtmp;
    struct obj *otmp;

    for(otmp = invent; otmp; otmp = otmp->nobj) {
        if(otmp->o_id == stealoid) {
            for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
                if(mtmp->m_id == stealmid) {
                    if(DEADMONSTER(mtmp)) impossible("stealarm(): dead monster stealing");
                    if(!dmgtype(mtmp->data, AD_SITM)) /* polymorphed */
                        goto botm;
                    if(otmp->unpaid)
                        subfrombill(otmp, shop_keeper(*u.ushops));
                    freeinv(otmp);
                    message_monster_object(MSG_M_STEALS_O, mtmp, otmp);
                    mpickobj(mtmp,otmp);     /* may free otmp */
                    /* Implies seduction, "you gladly hand over ..."
                       so we don't set mavenge bit here. */
                    monflee(mtmp, 0, false, false);
                    if (!tele_restrict(mtmp)) (void) rloc(mtmp, false);
                    break;
                }
            }
            break;
        }
    }
botm:   stealoid = 0;
        return 0;
}
Exemplo n.º 8
0
	Engine::Engine(App& app, struct android_app* androidApp) : mRender(androidApp), mApp(app), mAndroidApp(androidApp), mInited(false)
	{
		mAndroidApp->onAppCmd = Engine::handleCmd;

		shared_ptr<ResourceLocator> rloc((ResourceLocator*)new AndroidResourceLocator(mAndroidApp->activity->assetManager));
		mResMgr.addLocator(rloc);
	}
Exemplo n.º 9
0
/* returns 1 if it won't attack. */
int
demon_talk(struct monst *mtmp)
{
    long cash, demand, offer;

    if (uwep && uwep->oartifact == ART_EXCALIBUR) {
        pline("%s looks very angry.", Amonnam(mtmp));
        msethostility(mtmp, TRUE, TRUE);
        return 0;
    }

    /* Slight advantage given. */
    if (is_dprince(mtmp->data) && mtmp->minvis) {
        mtmp->minvis = mtmp->perminvis = 0;
        if (!Blind)
            pline("%s appears before you.", Amonnam(mtmp));
        newsym(mtmp->mx, mtmp->my);
    }
    if (youmonst.data->mlet == S_DEMON) {       /* Won't blackmail their own. */
        pline("%s says, \"Good hunting, %s.\"", Amonnam(mtmp),
              u.ufemale ? "Sister" : "Brother");
        if (!tele_restrict(mtmp))
            rloc(mtmp, TRUE);
        return 1;
    }
    cash = money_cnt(invent);
    /* don't bother with a custom RNG here, too much unpredictability is
       involved */
    demand = (cash * (rnd(80) + 20 * Athome)) /
        (100 * (1 + (sgn(u.ualign.type) == sgn(mtmp->data->maligntyp))));

    if (!demand) {      /* you have no gold */
        msethostility(mtmp, TRUE, TRUE);
        return 0;
    } else {
        /* make sure that the demand is unmeetable if the monster has the
           Amulet, preventing monster from being satisified and removed from
           the game (along with said Amulet...) */
        if (mon_has_amulet(mtmp))
            demand = cash + (long)rn1(1000, 40);

        pline("%s demands %ld %s for safe passage.", Amonnam(mtmp), demand,
              currency(demand));

        if ((offer = bribe(mtmp)) >= demand) {
            pline("%s vanishes, laughing about cowardly %s.", Amonnam(mtmp),
                  makeplural(mortal_or_creature(youmonst.data, FALSE)));
        } else if (offer > 0L && (long)rnd(40) > (demand - offer)) {
            pline("%s scowls at you menacingly, then vanishes.", Amonnam(mtmp));
        } else {
            pline("%s gets angry...", Amonnam(mtmp));
            msethostility(mtmp, TRUE, TRUE);
            return 0;
        }
    }
    mongone(mtmp);
    return 1;
}
Exemplo n.º 10
0
/* you teleport a monster (via wand, spell, or poly'd q.mechanic attack);
   return false iff the attempt fails */
boolean u_teleport_mon(struct monst *mtmp, boolean give_feedback)
{
	coord cc;

	if (mtmp->ispriest && *in_rooms(level, mtmp->mx, mtmp->my, TEMPLE)) {
	    if (give_feedback)
		pline("%s resists your magic!", Monnam(mtmp));
	    return FALSE;
	} else if (level->flags.noteleport && u.uswallow && mtmp == u.ustuck) {
	    if (give_feedback)
		pline("You are no longer inside %s!", mon_nam(mtmp));
	    unstuck(mtmp);
	    rloc(mtmp, FALSE);
	} else if (is_rider(mtmp->data) && rn2(13) &&
		   enexto(&cc, level, u.ux, u.uy, mtmp->data))
	    rloc_to(mtmp, cc.x, cc.y);
	else
	    rloc(mtmp, FALSE);
	return TRUE;
}
Exemplo n.º 11
0
static void
mvault_tele(struct monst *mtmp)
{
    struct mkroom *croom = search_special(level, VAULT);
    coord c;

    if (croom && somexy(level, croom, &c) && goodpos(level, c.x, c.y, mtmp, 0)) {
        rloc_to(mtmp, c.x, c.y);
        return;
    }
    rloc(mtmp, FALSE);
}
Exemplo n.º 12
0
/* bhitm: monster mtmp was hit by the effect of wand otmp */
static void
bhitm(struct monst *mtmp, struct obj *otmp)
{
	wakeup(mtmp);
	switch (otmp->otyp) {
	case WAN_STRIKING:
		if (u.uswallow || rnd(20) < 10 + mtmp->data->ac) {
			int tmp = d(2, 12);
			hit("wand", mtmp, exclam(tmp));
			mtmp->mhp -= tmp;
			if (mtmp->mhp < 1)
				killed(mtmp);
		} else
			miss("wand", mtmp);
		break;
	case WAN_SLOW_MONSTER:
		mtmp->mspeed = MSLOW;
		break;
	case WAN_SPEED_MONSTER:
		mtmp->mspeed = MFAST;
		break;
	case WAN_UNDEAD_TURNING:
		if (strchr(UNDEAD, mtmp->data->mlet)) {
			mtmp->mhp -= rnd(8);
			if (mtmp->mhp < 1)
				killed(mtmp);
			else
				mtmp->mflee = 1;
		}
		break;
	case WAN_POLYMORPH:
		if (newcham(mtmp, &mons[rn2(CMNUM)]))
			objects[otmp->otyp].oc_name_known = 1;
		break;
	case WAN_CANCELLATION:
		mtmp->mcan = 1;
		break;
	case WAN_TELEPORTATION:
		rloc(mtmp);
		break;
	case WAN_MAKE_INVISIBLE:
		mtmp->minvis = 1;
		break;
#ifdef WAN_PROBING
	case WAN_PROBING:
		mstatusline(mtmp);
		break;
#endif /* WAN_PROBING */
	default:
		impossible("What an interesting wand (%u)", otmp->otyp);
	}
}
Exemplo n.º 13
0
void stealgold (struct monst *mtmp) {
    struct obj *gold = g_at(u.ux, u.uy);
    long tmp;

    if (gold && ( !u.ugold || gold->quan > u.ugold || !rn2(5))) {
        mtmp->mgold += gold->quan;
        delobj(gold);
        newsym(u.ux, u.uy);
        message_monster(MSG_M_QUICKLY_SNATCHES_GOLD_FROM_BEETWEEN_YOUR_LEGS, mtmp);
        if(!u.ugold || !rn2(5)) {
            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);
        }
    } else if(u.ugold) {
        u.ugold -= (tmp = somegold());
        Your("purse feels lighter.");
        mtmp->mgold += tmp;
        if (!tele_restrict(mtmp)) (void) rloc(mtmp, false);
        mtmp->mavenge = 1;
        monflee(mtmp, 0, false, false);
    }
}
Exemplo n.º 14
0
void
stealamulet(struct monst *mtmp)
{
    struct obj *otmp = NULL;
    int real = 0, fake = 0;

    /* select the artifact to steal */
    if (u.uhave.amulet) {
        real = AMULET_OF_YENDOR;
        fake = FAKE_AMULET_OF_YENDOR;
    } else if (u.uhave.questart) {
        for (otmp = invent; otmp; otmp = otmp->nobj)
            if (is_quest_artifact(otmp))
                break;
        if (!otmp)
            return;     /* should we panic instead? */
    } else if (u.uhave.bell) {
        real = BELL_OF_OPENING;
        fake = BELL;
    } else if (u.uhave.book) {
        real = SPE_BOOK_OF_THE_DEAD;
    } else if (u.uhave.menorah) {
        real = CANDELABRUM_OF_INVOCATION;
    } else
        return; /* you have nothing of special interest */

    if (!otmp) {
        /* If we get here, real and fake have been set up. */
        for (otmp = invent; otmp; otmp = otmp->nobj)
            if (otmp->otyp == real || (otmp->otyp == fake && !mtmp->iswiz))
                break;
    }

    if (otmp) { /* we have something to snatch */
        if (otmp->owornmask)
            remove_worn_item(otmp, TRUE);
        freeinv(otmp);
        /* mpickobj wont merge otmp because none of the above things to steal
           are mergable */
        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, FALSE);
    }
}
Exemplo n.º 15
0
void
losedogs()
{
	struct monst *mtmp;

	while ((mtmp = mydogs)) {
		mydogs = mtmp->nmon;
		mtmp->nmon = fmon;
		fmon = mtmp;
		mnexto(mtmp);
	}
	while ((mtmp = fallen_down) ){
		fallen_down = mtmp->nmon;
		mtmp->nmon = fmon;
		fmon = mtmp;
		rloc(mtmp);
	}
}
Exemplo n.º 16
0
static bool clear_fcorr(struct monst *grd, bool forceshow) {
    int fcx, fcy, fcbeg;
    struct monst *mtmp;

    if (!on_level(&(EGD(grd)->gdlevel), &u.uz))
        return true;

    while ((fcbeg = EGD(grd)->fcbeg) < EGD(grd)->fcend) {
        fcx = EGD(grd)->fakecorr[fcbeg].fx;
        fcy = EGD(grd)->fakecorr[fcbeg].fy;
        if ((grd->mhp <= 0 || !in_fcorridor(grd, u.ux, u.uy)) &&
        EGD(grd)->gddone)
            forceshow = true;
        if ((u.ux == fcx && u.uy == fcy && grd->mhp > 0) || (!forceshow && couldsee(fcx, fcy)) || (Punished && !carried(uball) && uball->ox == fcx && uball->oy == fcy))
            return false;

        if ((mtmp = m_at(fcx, fcy)) != 0) {
            if (mtmp->isgd)
                return (false);
            else if (!in_fcorridor(grd, u.ux, u.uy)) {
                if (mtmp->mtame)
                    yelp(mtmp);
                (void)rloc(mtmp, false);
            }
        }
        levl[fcx][fcy].typ = EGD(grd)->fakecorr[fcbeg].ftyp;
        map_location(fcx, fcy, 1); /* bypass vision */
        if (!ACCESSIBLE(levl[fcx][fcy].typ))
            block_point(fcx, fcy);
        EGD(grd)->fcbeg++;
    }
    if (grd->mhp <= 0) {
        pline_The("corridor disappears.");
        if (IS_ROCK(levl[u.ux][u.uy].typ))
            You("are encased in rock.");
    }
    return (true);
}
Exemplo n.º 17
0
int stealarm(void)
{
    struct monst *mtmp;
    struct obj *otmp;

    for (otmp = invent; otmp; otmp = otmp->nobj)
	if (otmp->o_id == stealoid) {
	    for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
		if (mtmp->m_id == stealmid) {
		    if (dist(mtmp->mx, mtmp->my) < 3) {
			freeinv(otmp);
			pline("%s steals %s!", Monnam(mtmp), doname(otmp));
			mpickobj(mtmp, otmp);
			mtmp->mflee = 1;
			rloc(mtmp);
		    }
		    break;
		}
	    break;
	}
    stealoid = 0;
    return 0;
}
Exemplo n.º 18
0
/* create a new shopkeeper in the given room; uses level creation RNG */
static int
shkinit(const struct shclass *shp, struct level *lev, struct mkroom *sroom)
{
    int sh, sx, sy;
    struct monst *shk;

    /* place the shopkeeper in the given room */
    sh = sroom->fdoor;
    sx = lev->doors[sh].x;
    sy = lev->doors[sh].y;

    /* check that the shopkeeper placement is sane */
    if (sroom->irregular) {
        int rmno = (sroom - lev->rooms) + ROOMOFFSET;

        if (isok(sx - 1, sy) && !lev->locations[sx - 1][sy].edge &&
            (int)lev->locations[sx - 1][sy].roomno == rmno)
            sx--;
        else if (isok(sx + 1, sy) && !lev->locations[sx + 1][sy].edge &&
                 (int)lev->locations[sx + 1][sy].roomno == rmno)
            sx++;
        else if (isok(sx, sy - 1) && !lev->locations[sx][sy - 1].edge &&
                 (int)lev->locations[sx][sy - 1].roomno == rmno)
            sy--;
        else if (isok(sx, sy + 1) && !lev->locations[sx][sy + 1].edge &&
                 (int)lev->locations[sx][sy + 1].roomno == rmno)
            sx++;
        else
            goto shk_failed;
    } else if (sx == sroom->lx - 1)
        sx++;
    else if (sx == sroom->hx + 1)
        sx--;
    else if (sy == sroom->ly - 1)
        sy++;
    else if (sy == sroom->hy + 1)
        sy--;
    else {
    shk_failed:
        return -1;
    }

    if (MON_AT(lev, sx, sy))
        rloc(m_at(lev, sx, sy), FALSE); /* insurance */

    /* now initialize the shopkeeper monster structure */
    if (!(shk = makemon(&mons[PM_SHOPKEEPER], lev, sx, sy, MM_ALLLEVRNG)))
        return -1;
    shk->isshk = 1;
    msethostility(shk, FALSE, TRUE);
    shk->msleeping = 0;
    shk->mtrapseen = ~0;        /* we know all the traps already */
    ESHK(shk)->shoproom = (sroom - lev->rooms) + ROOMOFFSET;
    sroom->resident = shk;
    ESHK(shk)->shoptype = sroom->rtype;
    assign_level(&(ESHK(shk)->shoplevel), &lev->z);
    ESHK(shk)->shd = lev->doors[sh];
    ESHK(shk)->shk.x = sx;
    ESHK(shk)->shk.y = sy;
    ESHK(shk)->robbed = 0L;
    ESHK(shk)->credit = 0L;
    ESHK(shk)->debit = 0L;
    ESHK(shk)->loan = 0L;
    ESHK(shk)->visitct = 0;
    ESHK(shk)->following = 0;
    ESHK(shk)->billct = 0;
    ESHK(shk)->bill_inactive = FALSE;

    /* initial capital */
    mkmonmoney(shk, 1030L + 30L * mklev_rn2(100, lev), rng_for_level(&lev->z));

    if (shp->shknms == shkrings)
        mongets(shk, TOUCHSTONE, rng_for_level(&lev->z));
    nameshk(shk, shp->shknms, lev);

    return sh;
}
Exemplo n.º 19
0
/* Returns 1 if monster died moving, 0 otherwise */
int dochug(struct monst *mtmp)
{
    struct permonst *mdat;
    int tmp = 0;

    if((mtmp->cham != 0) && (rn2(6) == 0)) {
        newcham(mtmp, &mons[(dlevel + 14) + rn2((CMNUM - 14) - dlevel)]);
    }

    mdat = mtmp->data;

    if(mdat->mlevel < 0) {
        panic("bad monster %c (%d)", mdat->mlet, mdat->mlevel);
    }

    if((((moves % 20) == 0) || (index("ViT", mdat->mlet) != 0))
       && (mtmp->mhp < mtmp->orig_hp)) {
        /* Regenerate monsters. */
        ++mtmp->mhp;
    }

    if(mtmp->mfroz != 0) {
        /* Frozen monsters don't do anything. */
        return 0;
    }

    if(mtmp->msleep != 0) {
        /* Wake up a monster, or get out of here. */
        if((cansee(mtmp->mx, mtmp->my) != 0)
	   && (Stealth == 0)
	   && ((index("NL", mdat->mlet) == 0)
	       || (rn2(50) == 0))
	   && ((Aggravate_monster != 0) 
	       || ((rn2(7) == 0) && (mtmp->mimic == 0)))) {
            mtmp->msleep = 0;
        }
        else {
            return 0;
        }
    }

    /* Not frozen or sleeping: wipe out texts written in the dust */
    wipe_engr_at(mtmp->mx, mtmp->my, 1);

    /* Confused monsters get unconfused with small probability */
    if((mtmp->mconf != 0) && (rn2(50) == 0)) {
        mtmp->mconf = 0;
    }

    /* Some monsters teleport */
    if((mtmp->mflee != 0)
       && (index("tNL", mdat->mlet) != 0) 
       && (rn2(40) == 0)) {
        rloc(mtmp);

        return 0;
    }

    if(mdat->mmove < rnd(6)) {
        return 0;
    }

    if((mtmp->mflee != 0)
       || (mtmp->mconf != 0)
       || ((index("BIuy", mdat->mlet) != 0) && (rn2(4) == 0))
       || ((mdat->mlet == 'L') 
           && (u.ugold == 0)
           && ((mtmp->mgold != 0) || (rn2(2) != 0)))
       || (dist(mtmp->mx, mtmp->my) > 2)
       || ((mtmp->mcansee == 0) && (rn2(4) == 0))
       || (mtmp->mpeaceful != 0)) {
        tmp = m_move(mtmp, 0);
        if((tmp != 0) && (mdat->mmove < 12)) {
            if(tmp == 2) {
                return 1;
            }
            else {
                return 0;
            }
        }
    }

    if(tmp == 2) {
        /* Monster died moving */
        return 1;
    }

    if((index("Ea", mdat->mlet) == 0) 
       && (dist(mtmp->mx, mtmp->my) < 3)
       && (mtmp->mpeaceful == 0)
       && (u.uhp > 0)
       && (sengr_at("Elbereth", u.ux, u.uy) == 0)
       && (sobj_at(SCR_SCARE_MONSTER, u.ux, u.uy) == 0)) {
        if(mhitu(mtmp) != 0) {
            /* Monster died (e.g. 'y' or 'F') */
            return 1;
        }   
    }
        
    /* Extra movement for fast monsters */
    if((mdat->mmove - 12) > rnd(12)) {
        tmp = m_move(mtmp, 1);
    }

    if(tmp == 2) {
        return 1;
    }
    else {
        return 0;
    }
}
Exemplo n.º 20
0
/*
 * mhitu: monster hits you
 *	  returns 1 if monster dies (e.g. 'y', 'F'), 0 otherwise
 */
bool
mhitu(struct monst *mtmp)
{
	struct permonst *mdat = mtmp->data;
	int tmp, ctmp;

	nomul(0);

	/* If swallowed, can only be affected by hissers and by u.ustuck */
	if (u.uswallow) {
		if (mtmp != u.ustuck) {
			if (mdat->mlet == 'c' && !rn2(13)) {
				pline("Outside, you hear %s's hissing!",
				      monnam(mtmp));
				pline("%s gets turned to stone!",
				      Monnam(u.ustuck));
				pline("And the same fate befalls you.");
				done_in_by(mtmp);
				/* "notreached": not return(1); */
			}
			return (0);
		}
		switch (mdat->mlet) {	/* now mtmp == u.ustuck */
		case ',':
			youswld(mtmp, (u.uac > 0) ? u.uac + 4 : 4,
				5, "The trapper");
			break;
		case '\'':
			youswld(mtmp, rnd(6), 7, "The lurker above");
			break;
		case 'P':
			youswld(mtmp, d(2, 4), 12, "The purple worm");
			break;
		default:
			/* This is not impossible! */
			pline("The mysterious monster totally digests you.");
			u.uhp = 0;
		}
		if (u.uhp < 1)
			done_in_by(mtmp);
		return (0);
	}

	if (mdat->mlet == 'c' && Stoned)
		return (0);

	/* make eels visible the moment they hit/miss us */
	if (mdat->mlet == ';' && mtmp->minvis && cansee(mtmp->mx, mtmp->my)) {
		mtmp->minvis = 0;
		pmon(mtmp);
	}
	if (!strchr("1&DuxynNF", mdat->mlet))
		tmp = hitu(mtmp, d(mdat->damn, mdat->damd));
	else
		tmp = 0;
	if (strchr(UNDEAD, mdat->mlet) && midnight())
		tmp += hitu(mtmp, d(mdat->damn, mdat->damd));

	ctmp = tmp && !mtmp->mcan &&
	    (!uarm || objects[uarm->otyp].a_can < rnd(3) || !rn2(50));
	switch (mdat->mlet) {
	case '1':
		if (wiz_hit(mtmp))	/* he disappeared */
			return (1);
		break;
	case '&':
		if (!mtmp->cham && !mtmp->mcan && !rn2(13)) {
			makemon(PM_DEMON, u.ux, u.uy);
		} else {
			hitu(mtmp, d(2, 6));
			hitu(mtmp, d(2, 6));
			hitu(mtmp, rnd(3));
			hitu(mtmp, rnd(3));
			hitu(mtmp, rn1(4, 2));
		}
		break;
	case ',':
		if (tmp)
			justswld(mtmp, "The trapper");
		break;
	case '\'':
		if (tmp)
			justswld(mtmp, "The lurker above");
		break;
	case ';':
		if (ctmp) {
			if (!u.ustuck && !rn2(10)) {
				pline("%s swings itself around you!",
				      Monnam(mtmp));
				u.ustuck = mtmp;
			} else if (u.ustuck == mtmp &&
				   levl[mtmp->mx][mtmp->my].typ == POOL) {
				pline("%s drowns you ...", Monnam(mtmp));
				done("drowned");
			}
		}
		break;
	case 'A':
		if (ctmp && rn2(2)) {
			if (Poison_resistance)
				pline("The sting doesn't seem to affect you.");
			else {
				pline("You feel weaker!");
				losestr(1);
			}
		}
		break;
	case 'C':
		hitu(mtmp, rnd(6));
		break;
	case 'c':
		if (!rn2(5)) {
			pline("You hear %s's hissing!", monnam(mtmp));
			if (ctmp || !rn2(20) || (flags.moonphase == NEW_MOON
			    && !carrying(DEAD_LIZARD)))
				Stoned = 5;
		}
		break;
	case 'D':
		if (rn2(6) || mtmp->mcan) {
			hitu(mtmp, d(3, 10));
			hitu(mtmp, rnd(8));
			hitu(mtmp, rnd(8));
			break;
		}
		kludge("%s breathes fire!", "The dragon");
		buzz(-1, mtmp->mx, mtmp->my, u.ux - mtmp->mx, u.uy - mtmp->my);
		break;
	case 'd':
		hitu(mtmp, d(2, (flags.moonphase == FULL_MOON) ? 3 : 4));
		break;
	case 'e':
		hitu(mtmp, d(3, 6));
		break;
	case 'F':
		if (mtmp->mcan)
			break;
		kludge("%s explodes!", "The freezing sphere");
		if (Cold_resistance)
			pline("You don't seem affected by it.");
		else {
			xchar dn;
			if (17 - (u.ulevel / 2) > rnd(20)) {
				pline("You get blasted!");
				dn = 6;
			} else {
				pline("You duck the blast...");
				dn = 3;
			}
			losehp_m(d(dn, 6), mtmp);
		}
		mondead(mtmp);
		return (1);
	case 'g':
		if (ctmp && multi >= 0 && !rn2(3)) {
			kludge("You are frozen by %ss juices", "the cube'");
			nomul(-rnd(10));
		}
		break;
	case 'h':
		if (ctmp && multi >= 0 && !rn2(5)) {
			nomul(-rnd(10));
			kludge("You are put to sleep by %ss bite!",
			       "the homunculus'");
		}
		break;
	case 'j':
		tmp = hitu(mtmp, rnd(3));
		tmp &= hitu(mtmp, rnd(3));
		if (tmp) {
			hitu(mtmp, rnd(4));
			hitu(mtmp, rnd(4));
		}
		break;
	case 'k':
		if ((hitu(mtmp, rnd(4)) || !rn2(3)) && ctmp)
			poisoned("bee's sting", mdat->mname);
		break;
	case 'L':
		if (tmp)
			stealgold(mtmp);
		break;
	case 'N':
		if (mtmp->mcan && !Blind) {
			pline("%s tries to seduce you, but you seem not interested.",
			    Amonnam(mtmp, "plain"));
			if (rn2(3))
				rloc(mtmp);
		} else if (steal(mtmp)) {
			rloc(mtmp);
			mtmp->mflee = 1;
		}
		break;
	case 'n':
		if (!uwep && !uarm && !uarmh && !uarms && !uarmg) {
			pline("%s hits! (I hope you don't mind)",
			      Monnam(mtmp));
			u.uhp += rnd(7);
			if (!rn2(7))
				u.uhpmax++;
			if (u.uhp > u.uhpmax)
				u.uhp = u.uhpmax;
			flags.botl = 1;
			if (!rn2(50))
				rloc(mtmp);
		} else {
			hitu(mtmp, d(2, 6));
			hitu(mtmp, d(2, 6));
		}
		break;
	case 'o':
		tmp = hitu(mtmp, rnd(6));
		if (hitu(mtmp, rnd(6)) && tmp &&	/* hits with both paws */
		    !u.ustuck && rn2(2)) {
			u.ustuck = mtmp;
			kludge("%s has grabbed you!", "The owlbear");
			u.uhp -= d(2, 8);
		} else if (u.ustuck == mtmp) {
			u.uhp -= d(2, 8);
			pline("You are being crushed.");
		}
		break;
	case 'P':
		if (ctmp && !rn2(4))
			justswld(mtmp, "The purple worm");
		else
			hitu(mtmp, d(2, 4));
		break;
	case 'Q':
		hitu(mtmp, rnd(2));
		hitu(mtmp, rnd(2));
		break;
	case 'R':
		if (tmp && uarmh && !uarmh->rustfree &&
		    (int)uarmh->spe >= -1) {
			pline("Your helmet rusts!");
			uarmh->spe--;
		} else if (ctmp && uarm && !uarm->rustfree &&	/* Mike Newton */
		    uarm->otyp < STUDDED_LEATHER_ARMOR &&
		    (int)uarm->spe >= -1) {
			pline("Your armor rusts!");
			uarm->spe--;
		}
		break;
	case 'S':
		if (ctmp && !rn2(8))
			poisoned("snake's bite", mdat->mname);
		break;
	case 's':
		if (tmp && !rn2(8))
			poisoned("scorpion's sting", mdat->mname);
		hitu(mtmp, rnd(8));
		hitu(mtmp, rnd(8));
		break;
	case 'T':
		hitu(mtmp, rnd(6));
		hitu(mtmp, rnd(6));
		break;
	case 't':
		if (!rn2(5))
			rloc(mtmp);
		break;
	case 'u':
		mtmp->mflee = 1;
		break;
	case 'U':
		hitu(mtmp, d(3, 4));
		hitu(mtmp, d(3, 4));
		break;
	case 'v':
		if (ctmp && !u.ustuck)
			u.ustuck = mtmp;
		break;
	case 'V':
		if (tmp)
			u.uhp -= 4;
		if (ctmp)
			losexp();
		break;
	case 'W':
		if (ctmp)
			losexp();
		break;
#ifndef NOWORM
	case 'w':
		if (tmp)
			wormhit(mtmp);
#endif /* NOWORM */
		break;
	case 'X':
		hitu(mtmp, rnd(5));
		hitu(mtmp, rnd(5));
		hitu(mtmp, rnd(5));
		break;
	case 'x':
		{
			long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
			pline("%s pricks in your %s leg!",
			    Monnam(mtmp), (side == RIGHT_SIDE) ? "right" : "left");
			set_wounded_legs(side, rnd(50));
			losehp_m(2, mtmp);
			break;
		}
	case 'y':
		if (mtmp->mcan)
			break;
		mondead(mtmp);
		if (!Blind) {
			pline("You are blinded by a blast of light!");
			Blind = d(4, 12);
			seeoff(0);
		}
		return (1);
	case 'Y':
		hitu(mtmp, rnd(6));
		break;
	}
	if (u.uhp < 1)
		done_in_by(mtmp);
	return (0);
}
Exemplo n.º 21
0
/* Stop riding the current steed */
void
dismount_steed(int reason)
{
    struct monst *mtmp;
    struct obj *otmp;
    coord cc;
    const char *verb = "fall";
    boolean repair_leg_damage = TRUE;
    unsigned save_utrap = u.utrap;
    boolean have_spot = landing_spot(&cc, reason, 0);

    mtmp = u.usteed;    /* make a copy of steed pointer */
    /* Sanity check */
    if (!mtmp)  /* Just return silently */
        return;

    /* Check the reason for dismounting */
    otmp = which_armor(mtmp, os_saddle);
    switch (reason) {
    case DISMOUNT_THROWN:
        verb = "are thrown";
    case DISMOUNT_FELL:
        pline("You %s off of %s!", verb, mon_nam(mtmp));
        if (!have_spot)
            have_spot = landing_spot(&cc, reason, 1);
        losehp(rn1(10, 10), "killed in a riding accident");
        set_wounded_legs(LEFT_SIDE, (int)LWounded_legs + rn1(5, 5));
        set_wounded_legs(RIGHT_SIDE, (int)RWounded_legs + rn1(5, 5));
        repair_leg_damage = FALSE;
        break;
    case DISMOUNT_POLY:
        pline("You can no longer ride %s.", mon_nam(u.usteed));
        if (!have_spot)
            have_spot = landing_spot(&cc, reason, 1);
        break;
    case DISMOUNT_ENGULFED:
        /* caller displays message */
        break;
    case DISMOUNT_BONES:
        /* hero has just died... */
        break;
    case DISMOUNT_GENERIC:
        /* no messages, just make it so */
        break;
    case DISMOUNT_BYCHOICE:
    default:
        if (otmp && otmp->cursed) {
            pline("You can't.  The saddle %s cursed.",
                  otmp->bknown ? "is" : "seems to be");
            otmp->bknown = TRUE;
            return;
        }
        if (!have_spot) {
            pline("You can't. There isn't anywhere for you to stand.");
            return;
        }
        if (!mtmp->mnamelth) {
            pline("You've been through the dungeon on %s with no name.",
                  an(mtmp->data->mname));
            if (Hallucination)
                pline("It felt good to get out of the rain.");
        } else
            pline("You dismount %s.", mon_nam(mtmp));
    }
    /* While riding these refer to the steed's legs so after dismounting they
       refer to the player's legs once again. */
    if (repair_leg_damage)
        LWounded_legs = RWounded_legs = 0;

    /* Release the steed and saddle */
    u.usteed = 0;
    u.ugallop = 0L;

    /* Set player and steed's position.  Try moving the player first unless
       we're in the midst of creating a bones file. */
    if (reason == DISMOUNT_BONES) {
        /* move the steed to an adjacent square */
        if (enexto(&cc, level, u.ux, u.uy, mtmp->data))
            rloc_to(mtmp, cc.x, cc.y);
        else    /* evidently no room nearby; move steed elsewhere */
            rloc(mtmp, FALSE);
        return;
    }
    if (!DEADMONSTER(mtmp)) {
        place_monster(mtmp, u.ux, u.uy);
        if (!Engulfed && !u.ustuck && have_spot) {
            const struct permonst *mdat = mtmp->data;

            /* The steed may drop into water/lava */
            if (!is_flyer(mdat) && !is_floater(mdat) && !is_clinger(mdat)) {
                if (is_pool(level, u.ux, u.uy)) {
                    if (!Underwater)
                        pline("%s falls into the %s!", Monnam(mtmp),
                              surface(u.ux, u.uy));
                    if (!is_swimmer(mdat) && !amphibious(mdat)) {
                        killed(mtmp);
                        adjalign(-1);
                    }
                } else if (is_lava(level, u.ux, u.uy)) {
                    pline("%s is pulled into the lava!", Monnam(mtmp));
                    if (!likes_lava(mdat)) {
                        killed(mtmp);
                        adjalign(-1);
                    }
                }
            }
            /* Steed dismounting consists of two steps: being moved to another
               square, and descending to the floor.  We have functions to do
               each of these activities, but they're normally called
               individually and include an attempt to look at or pick up the
               objects on the floor: teleds() --> spoteffects() --> pickup()
               float_down() --> pickup() We use this kludge to make sure there
               is only one such attempt. Clearly this is not the best way to do
               it.  A full fix would involve having these functions not call
               pickup() at all, instead calling them first and calling pickup()
               afterwards.  But it would take a lot of work to keep this change
               from having any unforseen side effects (for instance, you would
               no longer be able to walk onto a square with a hole, and
               autopickup before falling into the hole). */
            /* [ALI] No need to move the player if the steed died. */
            if (!DEADMONSTER(mtmp)) {
                /* Keep steed here, move the player to cc; teleds() clears
                   u.utrap */
                in_steed_dismounting = TRUE;
                teleds(cc.x, cc.y, TRUE);
                in_steed_dismounting = FALSE;

                /* Put your steed in your trap */
                if (save_utrap)
                    mintrap(mtmp);
            }
            /* Couldn't... try placing the steed */
        } else if (enexto(&cc, level, u.ux, u.uy, mtmp->data)) {
            /* Keep player here, move the steed to cc */
            rloc_to(mtmp, cc.x, cc.y);
            /* Player stays put */
            /* Otherwise, kill the steed */
        } else {
            killed(mtmp);
            adjalign(-1);
        }
    }

    /* Return the player to the floor */
    if (reason != DISMOUNT_ENGULFED) {
        in_steed_dismounting = TRUE;
        float_down(0L);
        in_steed_dismounting = FALSE;
        encumber_msg();
        turnstate.vision_full_recalc = TRUE;
    } else
        /* polearms behave differently when not mounted */
        if (uwep && is_pole(uwep))
            u.bashmsg = FALSE;
    return;
}
Exemplo n.º 22
0
static void wallify_vault(struct monst *grd) {
    int x, y, typ;
    int vlt = EGD(grd)->vroom;
    char tmp_viz;
    signed char lox = rooms[vlt].lx - 1, hix = rooms[vlt].hx + 1, loy = rooms[vlt].ly - 1, hiy = rooms[vlt].hy + 1;
    struct monst *mon;
    struct obj *gold;
    struct trap *trap;
    bool fixed = false;
    bool movedgold = false;

    for (x = lox; x <= hix; x++) {
        for (y = loy; y <= hiy; y++) {
            /* if not on the room boundary, skip ahead */
            if (x != lox && x != hix && y != loy && y != hiy)
                continue;

            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);
                    (void)rloc(mon, false);
                }
                if ((gold = g_at(x, y)) != 0) {
                    move_gold(gold, EGD(grd)->vroom);
                    movedgold = true;
                }
                if ((trap = t_at(x, y)) != 0)
                    deltrap(trap);
                if (x == lox)
                    typ = (y == loy) ? TLCORNER : (y == hiy) ? BLCORNER : VWALL;
                else if (x == hix)
                    typ = (y == loy) ? TRCORNER : (y == hiy) ? BRCORNER : VWALL;
                else
                    /* not left or right side, must be top or bottom */
                    typ = HWALL;
                levl[x][y].typ = typ;
                levl[x][y].flags = 0;
                /*
                 * hack: player knows walls are restored because of the
                 * message, below, so show this on the screen.
                 */
                tmp_viz = viz_array[y][x];
                viz_array[y][x] = IN_SIGHT | COULD_SEE;
                newsym(x, y);
                viz_array[y][x] = tmp_viz;
                block_point(x, y);
                fixed = true;
            }
        }
    }

    if (movedgold || fixed) {
        if (in_fcorridor(grd, grd->mx, grd->my) || cansee(grd->mx, grd->my)) {
            char name[BUFSZ];
            g_monnam(name, BUFSZ, grd);
            pline_The("%s whispers an incantation.", name);
        } else {
            You_hear("a distant chant.");
        }
        if (movedgold)
            pline("A mysterious force moves the gold into the vault.");
        if (fixed)
            pline_The("damaged vault's walls are magically restored!");
    }
}
Exemplo n.º 23
0
/* called from resurrect() in addition to losedogs() */
void
mon_arrive(struct monst *mtmp, boolean with_you)
{
    struct trap *t;
    struct obj *otmp;
    xchar xlocale, ylocale, xyloc, xyflags, wander;
    int num_segs;

    mtmp->dlevel = level;
    mtmp->nmon = level->monlist;
    level->monlist = mtmp;
    if (mtmp->isshk)
        set_residency(mtmp, FALSE);

    num_segs = mtmp->wormno;
    /* baby long worms have no tail so don't use is_longworm() */
    if ((mtmp->data == &mons[PM_LONG_WORM]) &&
        (mtmp->wormno = get_wormno(mtmp->dlevel)) != 0) {
        initworm(mtmp, num_segs);
        /* tail segs are not yet initialized or displayed */
    } else
        mtmp->wormno = 0;

    /* some monsters might need to do something special upon arrival _after_
       the current level has been fully set up; see dochug() */
    mtmp->mstrategy |= STRAT_ARRIVE;

    xyloc = mtmp->xyloc;
    xyflags = mtmp->xyflags;
    xlocale = mtmp->xlocale;
    ylocale = mtmp->ylocale;

    for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
        set_obj_level(mtmp->dlevel, otmp);

    if (mtmp == u.usteed)
        return; /* don't place steed on the map */
    if (with_you) {
        /* When a monster accompanies you, sometimes it will arrive at your
           intended destination and you'll end up next to that spot.  This code
           doesn't control the final outcome; goto_level(do.c) decides who ends
           up at your target spot when there is a monster there too. */
        if (!MON_AT(level, u.ux, u.uy) &&
            !rn2(mtmp->mtame ? 10 : mtmp->mpeaceful ? 5 : 2))
            rloc_to(mtmp, u.ux, u.uy);
        else
            mnexto(mtmp);
        return;
    }
    /*
     * The monster arrived on this level independently of the player.
     * Its coordinate fields were overloaded for use as flags that
     * specify its final destination.
     */

    if (mtmp->mlstmv < moves - 1L) {
        /* heal monster for time spent in limbo */
        long nmv = moves - 1L - mtmp->mlstmv;

        mon_catchup_elapsed_time(mtmp, nmv);
        mtmp->mlstmv = moves - 1L;

        /* let monster move a bit on new level (see placement code below) */
        wander = (xchar) min(nmv, 8);
    } else
        wander = 0;

    switch (xyloc) {
    case MIGR_APPROX_XY:       /* {x,y}locale set above */
        break;
    case MIGR_EXACT_XY:
        wander = 0;
        break;
    case MIGR_NEAR_PLAYER:
        xlocale = u.ux, ylocale = u.uy;
        break;
    case MIGR_STAIRS_UP:
        xlocale = level->upstair.sx, ylocale = level->upstair.sy;
        break;
    case MIGR_STAIRS_DOWN:
        xlocale = level->dnstair.sx, ylocale = level->dnstair.sy;
        break;
    case MIGR_LADDER_UP:
        xlocale = level->upladder.sx, ylocale = level->upladder.sy;
        break;
    case MIGR_LADDER_DOWN:
        xlocale = level->dnladder.sx, ylocale = level->dnladder.sy;
        break;
    case MIGR_SSTAIRS:
        xlocale = level->sstairs.sx, ylocale = level->sstairs.sy;
        break;
    case MIGR_PORTAL:
        if (In_endgame(&u.uz)) {
            /* there is no arrival portal for endgame levels */
            /* BUG[?]: for simplicity, this code relies on the fact that we
               know that the current endgame levels always build upwards and
               never have any exclusion subregion inside their TELEPORT_REGION
               settings. */
            xlocale =
                rn1(level->updest.hx - level->updest.lx + 1, level->updest.lx);
            ylocale =
                rn1(level->updest.hy - level->updest.ly + 1, level->updest.ly);
            break;
        }
        /* find the arrival portal */
        for (t = level->lev_traps; t; t = t->ntrap)
            if (t->ttyp == MAGIC_PORTAL)
                break;
        if (t) {
            xlocale = t->tx, ylocale = t->ty;
            break;
        } else {
            impossible("mon_arrive: no corresponding portal?");
        }
     /*FALLTHRU*/ default:
    case MIGR_RANDOM:
        xlocale = COLNO;
        ylocale = ROWNO;
        break;
    }

    if ((xlocale != COLNO) && wander) {
        /* monster moved a bit; pick a nearby location */
        /* mnearto() deals w/stone, et al */
        char *r = in_rooms(level, xlocale, ylocale, 0);

        if (r && *r) {
            coord c;

            /* somexy() handles irregular level->rooms */
            if (somexy(level, &level->rooms[*r - ROOMOFFSET], &c, rng_main))
                xlocale = c.x, ylocale = c.y;
            else {
                xlocale = COLNO;
                ylocale = ROWNO;
            }
        } else {        /* not in a room */
            int i, j;

            i = max(0, xlocale - wander);
            j = min(COLNO - 1, xlocale + wander);
            xlocale = rn1(j - i, i);
            i = max(0, ylocale - wander);
            j = min(ROWNO - 1, ylocale + wander);
            ylocale = rn1(j - i, i);
        }
    }
    /* moved a bit */
    mtmp->mx = COLNO;       /* (already is 0) */
    mtmp->my = xyflags;
    if (xlocale != COLNO)
        mnearto(mtmp, xlocale, ylocale, FALSE);
    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;

            while ((obj = mtmp->minvent) != 0) {
                obj_extract_self(obj);
                obj_no_longer_held(obj);
                if (obj->owornmask & W_MASK(os_wep))
                    setmnotwielded(mtmp, obj);
                obj->owornmask = 0L;
                if (xlocale != COLNO && ylocale != ROWNO)
                    place_object(obj, level, xlocale, ylocale);
                else {
                    rloco(obj);
                    get_obj_location(obj, &xlocale, &ylocale, 0);
                }
            }
            mkcorpstat(CORPSE, NULL, mtmp->data, level, xlocale, ylocale,
                       FALSE, rng_main);
            mongone(mtmp);
        }
    }

    mtmp->mux = COLNO;
    mtmp->muy = ROWNO;
}
Exemplo n.º 24
0
/*
 * return  1: guard moved,  0: guard didn't,  -1: let m_move do it,  -2: died
 */
int gd_move(struct monst *grd) {
    int x, y, nx, ny, m, n;
    int dx, dy, gx, gy, fci;
    unsigned char typ;
    struct fakecorridor *fcp;
    struct egd *egrd = EGD(grd);
    struct rm *crm;
    bool goldincorridor = false, u_in_vault = vault_occupied(u.urooms) ? true : false, grd_in_vault = *in_rooms(grd->mx, grd->my, VAULT) ?
    true :
                                                                                                                                           false;
    bool disappear_msg_seen = false, semi_dead = (grd->mhp <= 0);
    bool u_carry_gold = ((u.ugold + hidden_gold()) > 0L);
    bool see_guard;

    if (!on_level(&(egrd->gdlevel), &u.uz))
        return (-1);
    nx = ny = m = n = 0;
    if (!u_in_vault && !grd_in_vault)
        wallify_vault(grd);
    if (!grd->mpeaceful) {
        if (semi_dead) {
            egrd->gddone = 1;
            goto newpos;
        }
        if (!u_in_vault && (grd_in_vault || (in_fcorridor(grd, grd->mx, grd->my) && !in_fcorridor(grd, u.ux, u.uy)))) {
            (void)rloc(grd, false);
            wallify_vault(grd);
            (void)clear_fcorr(grd, true);
            goto letknow;
        }
        if (!in_fcorridor(grd, grd->mx, grd->my))
            (void)clear_fcorr(grd, true);
        return (-1);
    }
    if (abs(egrd->ogx - grd->mx) > 1 || abs(egrd->ogy - grd->my) > 1)
        return (-1); /* teleported guard - treat as monster */
    if (egrd->fcend == 1) {
        if (u_in_vault && (u_carry_gold || um_dist(grd->mx, grd->my, 1))) {
            if (egrd->warncnt == 3)
                verbalize("I repeat, %sfollow me!", u_carry_gold ? (!u.ugold ? "drop that hidden gold and " : "drop that gold and ") : "");
            if (egrd->warncnt == 7) {
                m = grd->mx;
                n = grd->my;
                verbalize("You've been warned, knave!");
                mnexto(grd);
                levl[m][n].typ = egrd->fakecorr[0].ftyp;
                newsym(m, n);
                grd->mpeaceful = 0;
                return (-1);
            }
            /* not fair to get mad when (s)he's fainted or paralyzed */
            if (!is_fainted() && multi >= 0)
                egrd->warncnt++;
            return (0);
        }

        if (!u_in_vault) {
            if (u_carry_gold) { /* player teleported */
                m = grd->mx;
                n = grd->my;
                (void)rloc(grd, false);
                levl[m][n].typ = egrd->fakecorr[0].ftyp;
                newsym(m, n);
                grd->mpeaceful = 0;
                letknow: if (!cansee(grd->mx, grd->my) || !mon_visible(grd)) {
                    You_hear("the shrill sound of a guard's whistle.");
                } else {
                    const char * fmt = um_dist(grd->mx, grd->my, 2) ? "see an angry %s approaching." : "are confronted by an angry %s.";
                    char name[BUFSZ];
                    g_monnam(name, BUFSZ, grd);
                    You(fmt, name);
                }
                return (-1);
            } else {
                verbalize("Well, begone.");
                wallify_vault(grd);
                egrd->gddone = 1;
                goto cleanup;
            }
        }
    }

    if (egrd->fcend > 1) {
        if (egrd->fcend > 2 && in_fcorridor(grd, grd->mx, grd->my) && !egrd->gddone && !in_fcorridor(grd, u.ux, u.uy) &&
        levl[egrd->fakecorr[0].fx][egrd->fakecorr[0].fy].typ == egrd->fakecorr[0].ftyp) {
            char name[BUFSZ];
            g_monnam(name, BUFSZ, grd);
            pline_The("%s, confused, disappears.", name);
            disappear_msg_seen = true;
            goto cleanup;
        }
        if (u_carry_gold && (in_fcorridor(grd, u.ux, u.uy) ||
        /* cover a 'blind' spot */
        (egrd->fcend > 1 && u_in_vault))) {
            if (!grd->mx) {
                restfakecorr(grd);
                return (-2);
            }
            if (egrd->warncnt < 6) {
                egrd->warncnt = 6;
                verbalize("Drop all your gold, scoundrel!");
                return (0);
            } else {
                verbalize("So be it, rogue!");
                grd->mpeaceful = 0;
                return (-1);
            }
        }
    }
    for (fci = egrd->fcbeg; fci < egrd->fcend; fci++)
        if (g_at(egrd->fakecorr[fci].fx, egrd->fakecorr[fci].fy)) {
            m = egrd->fakecorr[fci].fx;
            n = egrd->fakecorr[fci].fy;
            goldincorridor = true;
        }
    if (goldincorridor && !egrd->gddone) {
        x = grd->mx;
        y = grd->my;
        if (m == u.ux && n == u.uy) {
            struct obj *gold = g_at(m, n);
            /* Grab the gold from between the hero's feet.  */
            grd->mgold += gold->quan;
            delobj(gold);
            newsym(m, n);
        } else if (m == x && n == y) {
            mpickgold(grd); /* does a newsym */
        } else {
            /* just for insurance... */
            if (MON_AT(m, n) && m != grd->mx && n != grd->my) {
                verbalize("Out of my way, scum!");
                (void)rloc(m_at(m, n), false);
            }
            remove_monster(grd->mx, grd->my);
            newsym(grd->mx, grd->my);
            place_monster(grd, m, n);
            mpickgold(grd); /* does a newsym */
        }
        if (cansee(m, n)) {
            char name[BUFSZ];
            Monnam(name, BUFSZ, grd);
            pline("%s%s picks up the gold.", name, grd->mpeaceful ? " calms down and" : "");
        }
        if (x != grd->mx || y != grd->my) {
            remove_monster(grd->mx, grd->my);
            newsym(grd->mx, grd->my);
            place_monster(grd, x, y);
            newsym(x, y);
        }
        if (!grd->mpeaceful)
            return (-1);
        else {
            egrd->warncnt = 5;
            return (0);
        }
    }
    if (um_dist(grd->mx, grd->my, 1) || egrd->gddone) {
        if (!egrd->gddone && !rn2(10))
            verbalize("Move along!");
        restfakecorr(grd);
        return (0); /* didn't move */
    }
    x = grd->mx;
    y = grd->my;

    if (u_in_vault)
        goto nextpos;

    /* look around (hor & vert only) for accessible places */
    for (nx = x - 1; nx <= x + 1; nx++) {
        for (ny = y - 1; ny <= y + 1; ny++) {
            if ((nx == x || ny == y) && (nx != x || ny != y) && isok(nx, ny)) {

                typ = (crm = &levl[nx][ny])->typ;
                if (!IS_STWALL(typ) && !IS_POOL(typ)) {

                    if (in_fcorridor(grd, nx, ny))
                        goto nextnxy;

                    if (*in_rooms(nx, ny, VAULT))
                        continue;

                    /* seems we found a good place to leave him alone */
                    egrd->gddone = 1;
                    if (ACCESSIBLE(typ))
                        goto newpos;
                    crm->typ = (typ == SCORR) ? CORR : DOOR;
                    if (crm->typ == DOOR)
                        crm->flags = D_NODOOR;
                    goto proceed;
                }
            }
            nextnxy: ;
        }
    }
    nextpos: nx = x;
    ny = y;
    gx = egrd->gdx;
    gy = egrd->gdy;
    dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
    dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
    if (abs(gx - x) >= abs(gy - y))
        nx += dx;
    else
        ny += dy;

    while ((typ = (crm = &levl[nx][ny])->typ) != 0) {
        /* in view of the above we must have IS_WALL(typ) or typ == POOL */
        /* must be a wall here */
        if (isok(nx + nx - x, ny + ny - y) && !IS_POOL(typ) && IS_ROOM(levl[nx+nx-x][ny+ny-y].typ)) {
            crm->typ = DOOR;
            crm->flags = D_NODOOR;
            goto proceed;
        }
        if (dy && nx != x) {
            nx = x;
            ny = y + dy;
            continue;
        }
        if (dx && ny != y) {
            ny = y;
            nx = x + dx;
            dy = 0;
            continue;
        }
        /* I don't like this, but ... */
        if (IS_ROOM(typ)) {
            crm->typ = DOOR;
            crm->flags = D_NODOOR;
            goto proceed;
        }
        break;
    }
    crm->typ = CORR;
    proceed: unblock_point(nx, ny); /* doesn't block light */
    if (cansee(nx, ny))
        newsym(nx, ny);

    fcp = &(egrd->fakecorr[egrd->fcend]);
    if (egrd->fcend++ == FCSIZ)
        impossible("fakecorr overflow");
    fcp->fx = nx;
    fcp->fy = ny;
    fcp->ftyp = typ;
    newpos: if (egrd->gddone) {
        /* The following is a kludge.  We need to keep    */
        /* the guard around in order to be able to make   */
        /* the fake corridor disappear as the player      */
        /* moves out of it, but we also need the guard    */
        /* out of the way.  We send the guard to never-   */
        /* never land.  We set ogx ogy to mx my in order  */
        /* to avoid a check at the top of this function.  */
        /* At the end of the process, the guard is killed */
        /* in restfakecorr().                             */
        cleanup: x = grd->mx;
        y = grd->my;

        see_guard = canspotmon(grd);
        wallify_vault(grd);
        remove_monster(grd->mx, grd->my);
        newsym(grd->mx, grd->my);
        place_monster(grd, 0, 0);
        egrd->ogx = grd->mx;
        egrd->ogy = grd->my;
        restfakecorr(grd);
        if (!semi_dead && (in_fcorridor(grd, u.ux, u.uy) || cansee(x, y))) {
            if (!disappear_msg_seen && see_guard) {
                char name[BUFSZ];
                g_monnam(name, BUFSZ, grd);
                pline("Suddenly, the %s disappears.", name);
            }
            return (1);
        }
        return (-2);
    }
    egrd->ogx = grd->mx; /* update old positions */
    egrd->ogy = grd->my;
    remove_monster(grd->mx, grd->my);
    place_monster(grd, nx, ny);
    newsym(grd->mx, grd->my);
    restfakecorr(grd);
    return (1);
}
Exemplo n.º 25
0
/* exclusively for mktemple(); uses level creation RNG */
void
priestini(struct level *lev, struct mkroom *sroom, int sx, int sy,
          boolean sanctum)
{       /* is it the seat of the high priest? */
    struct monst *priest = NULL;
    struct obj *otmp;
    int cnt;

    coord *priest_pos, pos_array[] = {
        { sx + 1, sy },
        { sx - 1, sy },
        { sx, sy + 1 },
        { sx, sy - 1 },
        { sx, sy },
        { COLNO, ROWNO },
    };

    /* Search for a good position for the priest. The -1 in the array bound is
     * to ensure that we stop on the { COLNO, ROWNO } entry which is not ok. Do
     * not pass a monster to goodpos(), because we will move any monster later.
     */
    for (priest_pos = pos_array;
         !goodpos(lev, priest_pos->x, priest_pos->y, NULL, 0) &&
         (priest_pos < pos_array + ARRAY_SIZE(pos_array) - 1);
         ++priest_pos)
         {}
    
    if (!isok(priest_pos->x, priest_pos->y)) {
        impossible("Unable to find location for priest in shrine");
    } else {
        if (MON_AT(lev, priest_pos->x, priest_pos->y))
            rloc(m_at(lev, priest_pos->x, priest_pos->y), FALSE);

        priest = makemon(&mons[sanctum ? PM_HIGH_PRIEST : PM_ALIGNED_PRIEST],
                         lev, priest_pos->x, priest_pos->y, MM_ALLLEVRNG);
    }

    if (priest) {
        EPRI(priest)->shroom = (sroom - lev->rooms) + ROOMOFFSET;
        EPRI(priest)->shralign = Amask2align(lev->locations[sx][sy].altarmask);
        EPRI(priest)->shrpos.x = sx;
        EPRI(priest)->shrpos.y = sy;
        assign_level(&(EPRI(priest)->shrlevel), &lev->z);
        priest->mtrapseen = ~0; /* traps are known */
        priest->mpeaceful = 1;
        priest->ispriest = 1;
        priest->msleeping = 0;
        set_malign(priest);     /* mpeaceful may have changed */

        /* now his/her goodies... */
        if (sanctum && CONST_EPRI(priest)->shralign == A_NONE &&
            on_level(&sanctum_level, &lev->z)) {
            mongets(priest, AMULET_OF_YENDOR, rng_for_level(&lev->z));
        }
        /* 2 to 4 spellbooks */
        for (cnt = rn1(3, 2); cnt > 0; --cnt) {
            mpickobj(priest, mkobj(level, SPBOOK_CLASS, FALSE,
                                   rng_for_level(&lev->z)));
        }
        /* robe [via makemon()] */
        if (mklev_rn2(2, lev) && (otmp = which_armor(priest, os_armc)) != 0) {
            if (p_coaligned(priest))
                uncurse(otmp);
            else
                curse(otmp);
        }
    }
}
Exemplo n.º 26
0
//
// called with [x,y] = coordinates;
//      [0,0] means anyplace
//      [_u.ux,_u.uy] means: call mnexto (if !in_mklev)
//
//      In case we make an Orc or killer bee, we make an entire horde (swarm);
//      note that in this case we return only one of them (the one at [x,y]).
struct monst* makemon (const struct permonst* ptr, int x, int y)
{
    if (x != 0 || y != 0)
	if (m_at(x, y))
	    return NULL;
    bool anything = false;
    if (!ptr) {
	anything = true;
	unsigned mi = rn2 (CMNUM*_u.dlevel/24+7);
	if (mi+4 < _u.dlevel)
	    mi = rn2 (CMNUM*_u.dlevel/24+12);
	if (mi >= CMNUM)
	    mi = rn1 (CMNUM-CMNUM/2, CMNUM/2);
	while (mi < CMNUM && is_monster_genocided (c_Monsters[mi].mlet))
	    ++mi;
	if (mi >= CMNUM)
	    return NULL;	// all monsters genocided
	ptr = &c_Monsters[mi];
    } else if (is_monster_genocided (ptr->mlet))
	return NULL;
    struct monst* mtmp = newmonst(ptr->pxlth);
    mtmp->nmon = _level->monsters;
    _level->monsters = mtmp;
    mtmp->m_id = _wflags.ident++;
    mtmp->data = ptr;
    mtmp->mxlth = ptr->pxlth;
    if (ptr->mlet == 'D')
	mtmp->mhpmax = mtmp->mhp = 80;
    else if (!ptr->mlevel)
	mtmp->mhpmax = mtmp->mhp = rnd(4);
    else
	mtmp->mhpmax = mtmp->mhp = d(ptr->mlevel, 8);
    mtmp->mx = x;
    mtmp->my = y;
    mtmp->mcansee = 1;
    if (!in_mklev) {
	if (x == _u.ux && y == _u.uy && ptr->mlet != ' ')
	    mnexto(mtmp);
	if (x == 0 && y == 0)
	    rloc(mtmp);
    }
    if (ptr->mlet == 's' || ptr->mlet == 'S') {
	mtmp->mhide = mtmp->mundetected = 1;
	if (in_mklev)
	    if (mtmp->mx && mtmp->my)
		mkobj_at(0, mtmp->mx, mtmp->my);
    }
    if (ptr->mlet == 'I' || ptr->mlet == ';')
	mtmp->minvis = 1;
    if (ptr->mlet == 'L' || ptr->mlet == 'N' || (in_mklev && strchr("&w;", ptr->mlet) && rn2(5))
	)
	mtmp->msleep = 1;

    if (anything)
	if (ptr->mlet == 'O' || ptr->mlet == 'k') {
	    struct coord mm;
	    int cnt = rnd(10);
	    mm.x = x;
	    mm.y = y;
	    while (cnt--) {
		mm = enexto(mm.x, mm.y);
		makemon(ptr, mm.x, mm.y);
	    }
	}
    return mtmp;
}
Exemplo n.º 27
0
int
dothrow()
{
	struct obj *obj;
	struct monst *mon;
	int tmp;

	obj = getobj("#)", "throw");   /* it is also possible to throw food */
				       /* (or jewels, or iron balls ... ) */
	if(!obj || !getdir(1))	       /* ask "in what direction?" */
		return(0);
	if(obj->owornmask & (W_ARMOR | W_RING)){
		pline("You can't throw something you are wearing.");
		return(0);
	}

	u_wipe_engr(2);

	if(obj == uwep){
		if(obj->cursed){
			pline("Your weapon is welded to your hand.");
			return(1);
		}
		if(obj->quan > 1)
			setuwep(splitobj(obj, 1));
		else
			setuwep((struct obj *) 0);
	}
	else if(obj->quan > 1)
		(void) splitobj(obj, 1);
	freeinv(obj);
	if(u.uswallow) {
		mon = u.ustuck;
		bhitpos.x = mon->mx;
		bhitpos.y = mon->my;
	} else if(u.dz) {
	  if(u.dz < 0) {
	    pline("%s hits the ceiling, then falls back on top of your head.",
		Doname(obj));		/* note: obj->quan == 1 */
	    if(obj->olet == POTION_SYM)
		potionhit(&youmonst, obj);
	    else {
		if(uarmh) pline("Fortunately, you are wearing a helmet!");
		losehp(uarmh ? 1 : rnd((int)(obj->owt)), "falling object");
		dropy(obj);
	    }
	  } else {
	    pline("%s hits the floor.", Doname(obj));
	    if(obj->otyp == EXPENSIVE_CAMERA) {
		pline("It is shattered in a thousand pieces!");
		obfree(obj, Null(obj));
	    } else if(obj->otyp == EGG) {
		pline("\"Splash!\"");
		obfree(obj, Null(obj));
	    } else if(obj->olet == POTION_SYM) {
		pline("The flask breaks, and you smell a peculiar odor ...");
		potionbreathe(obj);
		obfree(obj, Null(obj));
	    } else {
		dropy(obj);
	    }
	  }
	  return(1);
	} else if(obj->otyp == BOOMERANG) {
		mon = boomhit(u.dx, u.dy);
		if(mon == &youmonst) {		/* the thing was caught */
			(void) addinv(obj);
			return(1);
		}
	} else {
		if(obj->otyp == PICK_AXE && shkcatch(obj))
		    return(1);

		mon = bhit(u.dx, u.dy, (obj->otyp == ICE_BOX) ? 1 :
			(!Punished || obj != uball) ? 8 : !u.ustuck ? 5 : 1,
			obj->olet, NULL, NULL, obj);
	}
	if(mon) {
		/* awake monster if sleeping */
		wakeup(mon);

		if(obj->olet == WEAPON_SYM) {
			tmp = -1+u.ulevel+mon->data->ac+abon();
			if(obj->otyp < ROCK) {
				if(!uwep ||
				    uwep->otyp != obj->otyp+(BOW-ARROW))
					tmp -= 4;
				else {
					tmp += uwep->spe;
				}
			} else
			if(obj->otyp == BOOMERANG) tmp += 4;
			tmp += obj->spe;
			if(u.uswallow || tmp >= rnd(20)) {
				if(hmon(mon,obj,1) == TRUE){
				  /* mon still alive */
#ifndef NOWORM
				  cutworm(mon,bhitpos.x,bhitpos.y,obj->otyp);
#endif /* NOWORM */
				} else mon = 0;
				/* weapons thrown disappear sometimes */
				if(obj->otyp < BOOMERANG && rn2(3)) {
					/* check bill; free */
					obfree(obj, (struct obj *) 0);
					return(1);
				}
			} else miss(objects[obj->otyp].oc_name, mon);
		} else if(obj->otyp == HEAVY_IRON_BALL) {
			tmp = -1+u.ulevel+mon->data->ac+abon();
			if(!Punished || obj != uball) tmp += 2;
			if(u.utrap) tmp -= 2;
			if(u.uswallow || tmp >= rnd(20)) {
				if(hmon(mon,obj,1) == FALSE)
					mon = 0;	/* he died */
			} else miss("iron ball", mon);
		} else if(obj->olet == POTION_SYM && u.ulevel > rn2(15)) {
			potionhit(mon, obj);
			return(1);
		} else {
			if(cansee(bhitpos.x,bhitpos.y))
				pline("You miss %s.",monnam(mon));
			else pline("You miss it.");
			if(obj->olet == FOOD_SYM && mon->data->mlet == 'd')
				if(tamedog(mon,obj)) return(1);
			if(obj->olet == GEM_SYM && mon->data->mlet == 'u' &&
				!mon->mtame){
			 if(obj->dknown && objects[obj->otyp].oc_name_known){
			  if(objects[obj->otyp].g_val > 0){
			    u.uluck += 5;
			    goto valuable;
			  } else {
			    pline("%s is not interested in your junk.",
				Monnam(mon));
			  }
			 } else { /* value unknown to @ */
			    u.uluck++;
			valuable:
			    if(u.uluck > LUCKMAX)	/* dan@ut-ngp */
				u.uluck = LUCKMAX;
			    pline("%s graciously accepts your gift.",
				Monnam(mon));
			    mpickobj(mon, obj);
			    rloc(mon);
			    return(1);
			 }
			}
		}
	}
		/* the code following might become part of dropy() */
	if(obj->otyp == CRYSKNIFE)
		obj->otyp = WORM_TOOTH;
	obj->ox = bhitpos.x;
	obj->oy = bhitpos.y;
	obj->nobj = fobj;
	fobj = obj;
	/* prevent him from throwing articles to the exit and escaping */
	/* subfrombill(obj); */
	stackobj(obj);
	if(Punished && obj == uball &&
		(bhitpos.x != u.ux || bhitpos.y != u.uy)){
		freeobj(uchain);
		unpobj(uchain);
		if(u.utrap){
			if(u.utraptype == TT_PIT)
				pline("The ball pulls you out of the pit!");
			else {
			    long side =
				rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
			    pline("The ball pulls you out of the bear trap.");
			    pline("Your %s leg is severely damaged.",
				(side == LEFT_SIDE) ? "left" : "right");
			    set_wounded_legs(side, 500+rn2(1000));
			    losehp(2, "thrown ball");
			}
			u.utrap = 0;
		}
		unsee();
		uchain->nobj = fobj;
		fobj = uchain;
		u.ux = uchain->ox = bhitpos.x - u.dx;
		u.uy = uchain->oy = bhitpos.y - u.dy;
		setsee();
		(void) inshop();
	}
	if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y);
	return(1);
}
Exemplo n.º 28
0
int m_move(struct monst *mtmp, int after)
{
    struct monst *mtmp2;
    int nx = 0;
    int ny = 0;
    int omx;
    int omy;
    int appr;
    int nearer;
    int cnt;
    int i;
    int j;
    xchar gx;
    xchar gy;
    xchar nix;
    xchar niy;
    xchar chcnt;
    schar chi;
    boolean likegold = 0;
    boolean likegems = 0;
    boolean likeobjs = 0;

    /* Not strictly necessary: chi >= 0 will do */
    schar mmoved = 0;
    coord poss[9];
    int info[9];

    if(mtmp->mtrapped != 0) {
        i = mintrap(mtmp);

        if(i == 2) {
            /* He died */
            return 2;
        }

        if(i == 1) {
            /* Still in trap so didn't move */
            return 0;
        }
    }

    if((mtmp->mhide != 0)
       && (o_at(mtmp->mx, mtmp->my) != NULL)
       && (rn2(10) != 0)) {
        /* Do not leave hiding place */
        return 0;
    }

    /* My dog gets a special treatment */
    if(mtmp->mtame != 0) {
        return dog_move(mtmp, after);
    }

    /* Likewise for shopkeeper */
    if(mtmp->isshk != 0) {
        mmoved = shk_move();

        if(mmoved == 1) {
            if(mintrap(mtmp) == 2) {
                /* He died */
                return 2;
            }

            if(likegold != 0) {
                mpickgold(mtmp);
            }
            
            if(likegems != 0) {
                mpickgems(mtmp);
            }

            if(mtmp->mhide != 0) {
                mtmp->mundetected = 1;
            }
        }

        return mmoved;
    }

    /* And for the guard */
    if(mtmp->isgd != 0) {
        mmoved = gd_move();

        if(mmoved == 1) {
            if(mintrap(mtmp) == 2) {
                /* He died */
                return 2;
            }

            if(likegold != 0) {
                mpickgold(mtmp);
            }

            if(likegems != 0) {
                mpickgems(mtmp);
            }

            if(mtmp->mhide != 0) {
                mtmp->mundetected = 1;
            }
        }

        return mmoved;
    }

    if((mtmp->data->mlet == 't') && (rn2(5) == 0)) {
        if(rn2(2) != 0) {
            mnexto(mtmp);
        }
        else {
            rloc(mtmp);
        }

        mmoved = 1;

        if(mmoved == 1) {
            if(mintrap(mtmp) == 2) {
                /* He died */
                return 2;
            }

            if(likegold != 0) {
                mpickgold(mtmp);
            }

            if(likegems != 0) {
                mpickgems(mtmp);
            }

            if(mtmp->mhide != 0) {
                mtmp->mundetected = 1;
            }
        }

        return mmoved;
    }

    if((mtmp->data->mlet == 'D') && (mtmp->mcan == 0)) {
        inrange(mtmp);
    }

    if((Blind == 0)
       && (Confusion == 0) 
       && (mtmp->data->mlet == 'U') 
       && (mtmp->mcan == 0)
       && (cansee(mtmp->mx, mtmp->my) != 0)
       && (rn2(5) != 0)) {
        pline("%s's gaze has confused you!", Monnam(mtmp));

        if(rn2(5) != 0) {
            mtmp->mcan = 1;
        }

        /* Timeout */
        Confusion = d(3, 4);
    }

    if((mtmp->mflee == 0) && (u.uswallow != 0) && (u.ustuck != mtmp)) {
        return 1;
    }

    appr = 1;

    if(mtmp->mflee != 0) {
        appr = -1;
    }

    if((mtmp->mconf != 0)
       || (Invis != 0)
       || (mtmp->mcansee == 0)
       || ((index("Biy", mtmp->data->mlet) != 0) && (rn2(3) == 0))) {
        appr = 0;
    }

    omx = mtmp->mx;
    omy = mtmp->my;
    gx = u.ux;
    gy = u.uy;

    if((mtmp->data->mlet == 'L') && (appr == 1) && (mtmp->mgold > u.ugold)) {
        appr = -1;
    }

#ifdef TRACK
    /*
     * Random criterion for 'smell'
     * should use mtmp->msmell
     */
    if(('a' <= mtmp->data->mlet) && (mtmp->data->mlet <= 'z')) {
        coord *cp;
        schar mroom;

        mroom = inroom(omx, omy);
        if((mroom < 0) || (mroom != inroom(u.ux, u.uy))) {
            cp = gettrack(omx, omy);

            if(cp != 0) {
                gx = cp->x;
                gy = cp->y;
            }
        }
    }
#endif

    /* Look for gold or jewels nearby */
    if(index("LOD", mtmp->data->mlet) != NULL) {
        likegold = 1;
    }
    else {
        likegold = 0;
    }

    if(index("ODu", mtmp->data->mlet) != NULL) {
        likegems = 1;
    }
    else {
        likegems = 0;
    }

    likeobjs = mtmp->mhide;

#define SRCHRADIUS 25
    /* Not too far away */
    xchar mind = SRCHRADIUS;
    int dd;

    if(likegold != 0) {
        struct gen *gold;

        for(gold = fgold; gold != NULL; gold = gold->ngen) {
            dd = DIST(omx, omy, gold->gx, gold->gy);
            if(dd < mind) {
                mind = dd;
                gx = gold->gx;
                gy = gold->gy;
            }
        }
    }

    if((likegems != 0) || (likeobjs != 0)) {
        struct obj *otmp;
        
        for(otmp = fobj; otmp != NULL; otmp = otmp->nobj) {
            if((likeobjs != 0) || (otmp->olet == GEM_SYM)) {
                if((mtmp->data->mlet != 'u')
                   || (objects[otmp->otyp].g_val != 0)) {
                    dd = DIST(omx, omy, otmp->ox, otmp->oy);
                    if(dd < mind) {
                        mind = dd;
                        gx = otmp->ox;
                        gy = otmp->oy;
                    }
                }
            }
        }
    }

    if((mind < SRCHRADIUS) && (appr == -1)) {
        if(dist(omx, omy) < 10) {
            gx = u.ux;
            gy = u.uy;
        }
        else {
            appr = 1;
        }
    }

    nix = omx;
    niy = omy;
    
    if(mtmp->data->mlet == 'u') {
        cnt = mfndpos(mtmp, poss, info, NOTONL);
    }
    else {
        if(index(" VWZ", mtmp->data->mlet) != 0) {
            cnt = mfndpos(mtmp, poss, info, NOGARLIC);
        }
        else {
            cnt = mfndpos(mtmp, poss, info, ALLOW_TRAPS);
        }
    }

    /* ALLOW_ROCK for some monsters? */
    chcnt = 0;
    chi = -1;

    for(i = 0; i < cnt; ++i) {
        nx = poss[i].x;
        nx = poss[i].y;

        for(j = 0; (j < MTSZ) && (j < (cnt - 1)); ++j) {
            if((nx == mtmp->mtrack[j].x) && (ny == mtmp->mtrack[j].y)) {
                if(rn2(4 * (cnt - j)) == 0) {
#ifdef STUPID
                    /* Some stupid compilers thing that is is too complicated */
                    int d1 = DIST(nx, ny, gx, gy);
                    int d2 = DIST(nix, niy, gx, gy);
                    
                    if(d1 < d2) {
                        nearer = 1;
                    }
                    else {
                        nearer = 0;
                    }
#else
		    if(DIST(nx, ny, gx, gy) < DIST(nix, niy, gx, gy)) {
			nearer = 1;
		    }
		    else {
			nearer = 0;
		    }
#endif
		    
                    if(((appr == 1) && (nearer != 0))
                       || ((appr == -1) && (nearer == 0))
                       || (mmoved == 0)) {
                        nix = nx;
                        niy = ny;
                        chi = i;
                        mmoved = 1;
                    }
                    else {
                        if(appr == 0) {
                            if(rn2(chcnt) == 0) {
                                ++chcnt;
                                nix = nx;
                                niy = ny;
                                chi = i;
                                mmoved = 1;
                            }
                            else {
                                ++chcnt;
                            }
                        }
                    }
                }
            }
        }
    }

    if(mmoved != 0) {
        if((info[(int)chi] & ALLOW_M) != 0) {
            mtmp2 = m_at(nix, niy);

            if((hitmm(mtmp, mtmp2) == 1)
               && (rn2(4) != 0) 
               && (hitmm(mtmp2, mtmp) == 2)) {
                return 2;
            }

            return 0;
        }

        if((info[(int)chi] & ALLOW_U) != 0) {
            hitu(mtmp, d(mtmp->data->damn, mtmp->data->damd) + 1);
        
            return 0;
        }

        mtmp->mx = nix;
        mtmp->my = niy;

        for(j = MTSZ - 1; j > 0; --j) {
            mtmp->mtrack[j] = mtmp->mtrack[j - 1];
        }

        mtmp->mtrack[0].x = omx;
        mtmp->mtrack[0].y = omy;

#ifndef NOWORM
        if(mtmp->wormno != 0) {
            worm_move(mtmp);
        }
#endif
    }
    else {
        if((mtmp->data->mlet == 'u') && (rn2(2) != 0)) {
            rloc(mtmp);
        
            return 0;
        }

#ifndef NOWORM
        if(mtmp->wormno != 0) {
            worm_nomove(mtmp);
        }
#endif
    }

    if(mmoved == 1) {
        if(mintrap(mtmp) == 2) {
            /* He died */
            return 2;
        }

        if(likegold != 0) {
            mpickgold(mtmp);
        }

        if(likegems != 0) {
            mpickgems(mtmp);
        }

        if(mtmp->mhide != 0) {
            mtmp->mundetected = 1;
        }
    }

    pmon(mtmp);

    return mmoved;
}
Exemplo n.º 29
0
/*
 * called with [x,y] = coordinates;
 *	[0,0] means anyplace
 *	[u.ux,u.uy] means: call mnexto (if !in_mklev)
 *
 *	In case we make an Orc or killer bee, we make an entire horde (swarm);
 *	note that in this case we return only one of them (the one at [x,y]).
 */
struct monst *
makemon(struct permonst *ptr, int x, int y)
{
	struct monst *mtmp;
	int tmp, ct;
	boolean anything = (!ptr);
	extern boolean in_mklev;

	if(x != 0 || y != 0) if(m_at(x,y)) return((struct monst *) 0);
	if(ptr){
		if(strchr(fut_geno, ptr->mlet)) return((struct monst *) 0);
	} else {
		ct = CMNUM - strlen(fut_geno);
		if(strchr(fut_geno, 'm')) ct++;  /* make only 1 minotaur */
		if(strchr(fut_geno, '@')) ct++;
		if(ct <= 0) return(0); 		  /* no more monsters! */
		tmp = rn2(ct*dlevel/24 + 7);
		if(tmp < dlevel - 4) tmp = rn2(ct*dlevel/24 + 12);
		if(tmp >= ct) tmp = rn1(ct - ct/2, ct/2);
		for(ct = 0; ct < CMNUM; ct++){
			ptr = &mons[ct];
			if(strchr(fut_geno, ptr->mlet))
				continue;
			if(!tmp--) goto gotmon;
		}
		panic("makemon?");
	}
gotmon:
	mtmp = newmonst(ptr->pxlth);
	*mtmp = zeromonst;	/* clear all entries in structure */
	for(ct = 0; ct < ptr->pxlth; ct++)
		((char *) &(mtmp->mextra[0]))[ct] = 0;
	mtmp->nmon = fmon;
	fmon = mtmp;
	mtmp->m_id = flags.ident++;
	mtmp->data = ptr;
	mtmp->mxlth = ptr->pxlth;
	if(ptr->mlet == 'D') mtmp->mhpmax = mtmp->mhp = 80;
	else if(!ptr->mlevel) mtmp->mhpmax = mtmp->mhp = rnd(4);
	else mtmp->mhpmax = mtmp->mhp = d(ptr->mlevel, 8);
	mtmp->mx = x;
	mtmp->my = y;
	mtmp->mcansee = 1;
	if(ptr->mlet == 'M'){
		mtmp->mimic = 1;
		mtmp->mappearance = ']';
	}
	if(!in_mklev) {
		if(x == u.ux && y == u.uy && ptr->mlet != ' ')
			mnexto(mtmp);
		if(x == 0 && y == 0)
			rloc(mtmp);
	}
	if(ptr->mlet == 's' || ptr->mlet == 'S') {
		mtmp->mhide = mtmp->mundetected = 1;
		if(in_mklev)
		if(mtmp->mx && mtmp->my)
			(void) mkobj_at(0, mtmp->mx, mtmp->my);
	}
	if(ptr->mlet == ':') {
		mtmp->cham = 1;
		(void) newcham(mtmp, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]);
	}
	if(ptr->mlet == 'I' || ptr->mlet == ';')
		mtmp->minvis = 1;
	if(ptr->mlet == 'L' || ptr->mlet == 'N'
	    || (in_mklev && strchr("&w;", ptr->mlet) && rn2(5))
	) mtmp->msleep = 1;

#ifndef NOWORM
	if(ptr->mlet == 'w' && getwn(mtmp))
		initworm(mtmp);
#endif /* NOWORM */

	if(anything) if(ptr->mlet == 'O' || ptr->mlet == 'k') {
		coord mm;
		int cnt = rnd(10);
		mm.x = x;
		mm.y = y;
		while(cnt--) {
			mm = enexto(mm.x, mm.y);
			(void) makemon(ptr, mm.x, mm.y);
		}
	}

	return(mtmp);
}
Exemplo n.º 30
0
Short mon_in_trap(monst_t *mtmp) // was mintrap
{
  trap_t *trap = trap_at(mtmp->mx, mtmp->my);
  Boolean wasintrap = (mtmp->bitflags & M_IS_TRAPPED);

  if (!trap) {
    mtmp->bitflags &= ~M_IS_TRAPPED;	/* perhaps teleported? */
  } else if (wasintrap) {
    if (!rund(40)) mtmp->bitflags &= ~M_IS_TRAPPED;
  } else {
    Short tt = get_trap_type(trap->trap_info);
    Short in_sight = cansee(mtmp->mx, mtmp->my);

    if (mtmp->mtraps_seen & (1 << tt)) {
      /* he has been in such a trap - perhaps he escapes */
      if (rund(4)) return 0;
    }
    mtmp->mtraps_seen |= (1 << tt);
    switch (tt) {
    case BEAR_TRAP:
      if (StrChr(mlarge, mtmp->data->mlet)) {
	if (in_sight) {
	  StrPrintF(ScratchBuffer,"%s is caught in a bear trap!",Monnam(mtmp));
	  message(ScratchBuffer);
	} else
	  if (mtmp->data->mlet == 'o')
	    message("You hear the roaring of an angry bear!");
	mtmp->bitflags |= M_IS_TRAPPED;
      }
      break;
    case PIT:
      /* there should be a mtmp/data -> floating */
      if (!StrChr("EywBfk'& ", mtmp->data->mlet)) { /* ab */
	mtmp->bitflags |= M_IS_TRAPPED;
	if (in_sight) {
	  StrPrintF(ScratchBuffer, "%s falls in a pit!", Monnam(mtmp));
	  message(ScratchBuffer);
	}
      }
      break;
    case SLP_GAS_TRAP:
      if (!(mtmp->bitflags & (M_IS_ASLEEP | M_IS_FROZEN))) {
	mtmp->bitflags |= M_IS_ASLEEP;
	if (in_sight) {
	  StrPrintF(ScratchBuffer, "%s suddenly falls asleep!", Monnam(mtmp));
	  message(ScratchBuffer);
	}
      }
      break;
    case TELEP_TRAP:
      rloc(mtmp);
      if (in_sight && !cansee(mtmp->mx,mtmp->my)) {
	StrPrintF(ScratchBuffer, "%s suddenly disappears!", Monnam(mtmp));
	  message(ScratchBuffer);
      }
      break;
    case ARROW_TRAP:
      if (in_sight) {
	StrPrintF(ScratchBuffer, "%s is hit by an arrow!", Monnam(mtmp));
	message(ScratchBuffer);
      }
      mtmp->mhp -= 3;
      break;
    case DART_TRAP:
      if (in_sight) {
	StrPrintF(ScratchBuffer, "%s is hit by a dart!", Monnam(mtmp));
	message(ScratchBuffer);
      }
      mtmp->mhp -= 2;
      /* not mondied here !! */
      break;
    case TRAPDOOR:
      if (!xdnstair) {
	mtmp->mhp -= 10;
	if (in_sight) {
	  StrPrintF(ScratchBuffer,
		    "A trap door in the ceiling opens and a rock hits %s!",
		    monnam(mtmp));
	  message(ScratchBuffer);
	}
	break;
      }
      if (mtmp->data->mlet != 'w') {
	fall_down(mtmp);
	if (in_sight) {
	  StrPrintF(ScratchBuffer, "Suddenly, %s disappears out of sight.",
		    monnam(mtmp));
	  message(ScratchBuffer);
	}
	return 2;	/* no longer on this level */
      }
      break;
    case PIERC:
      break;
    default:
      message("BUG: Some monster encountered a strange trap.");
    }
  }
  return ((mtmp->bitflags & M_IS_TRAPPED) != 0);
}