Beispiel #1
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);
}
Beispiel #2
0
void initedog(struct monst *mtmp)
{
	mtmp->mtame = is_domestic(mtmp->data) ? 10 : 5;
	mtmp->mpeaceful = 1;
	mtmp->mavenge = 0;
	set_malign(mtmp); /* recalc alignment now that it's tamed */
	mtmp->mleashed = 0;
	mtmp->meating = 0;
	EDOG(mtmp)->droptime = 0;
	EDOG(mtmp)->dropdist = 10000;
	EDOG(mtmp)->apport = 10;
	EDOG(mtmp)->whistletime = 0;
	EDOG(mtmp)->hungrytime = 1000 + moves;
	EDOG(mtmp)->ogoal.x = -1;	/* force error if used before set */
	EDOG(mtmp)->ogoal.y = -1;
	EDOG(mtmp)->abuse = 0;
	EDOG(mtmp)->revivals = 0;
	EDOG(mtmp)->mhpmax_penalty = 0;
	EDOG(mtmp)->killed_by_u = 0;
}
Beispiel #3
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));
        mtmp->mpeaceful = mtmp->mtame = 0;
        set_malign(mtmp);
        newsym(mtmp->mx, mtmp->my);
        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),
              flags.female ? "Sister" : "Brother");
        if (!tele_restrict(mtmp))
            rloc(mtmp, FALSE);
        return 1;
    }
    cash = money_cnt(invent);
    demand =
        (cash * (rnd(80) + 20 * Athome)) / (100 *
                                            (1 +
                                             (sgn(u.ualign.type) ==
                                              sgn(mtmp->data->maligntyp))));

    if (!demand) {      /* you have no gold */
        mtmp->mpeaceful = 0;
        set_malign(mtmp);
        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 mortals.",
                  Amonnam(mtmp));
        } 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));
            mtmp->mpeaceful = 0;
            set_malign(mtmp);
            return 0;
        }
    }
    mongone(mtmp);
    return 1;
}
Beispiel #4
0
void
fill_zoo (struct mkroom *sroom)
{
        struct monst *mon;
        int sx,sy,i;
        int sh, tx, ty, goldlim, type = sroom->rtype;
        int rmno = (sroom - rooms) + ROOMOFFSET;
        coord mm;


        sh = sroom->fdoor;
        switch(type) {
            case COURT:
                if(level.flags.is_maze_lev) {
                    for(tx = sroom->lx; tx <= sroom->hx; tx++)
                        for(ty = sroom->ly; ty <= sroom->hy; ty++)
                            if(IS_THRONE(levl[tx][ty].typ))
                                goto throne_placed;
                }
                i = 100;
                do {    /* don't place throne on top of stairs */
                        (void) somexy(sroom, &mm);
                        tx = mm.x; ty = mm.y;
                } while (occupied((signed char)tx, (signed char)ty) && --i > 0);
            throne_placed:
                /* TODO: try to ensure the enthroned monster is an M2_PRINCE */
                break;
            case BEEHIVE:
                tx = sroom->lx + (sroom->hx - sroom->lx + 1)/2;
                ty = sroom->ly + (sroom->hy - sroom->ly + 1)/2;
                if(sroom->irregular) {
                    /* center might not be valid, so put queen elsewhere */
                    if ((int) levl[tx][ty].roomno != rmno ||
                            levl[tx][ty].edge) {
                        (void) somexy(sroom, &mm);
                        tx = mm.x; ty = mm.y;
                    }
                }
                break;
            case ZOO:
            case LEPREHALL:
                goldlim = 500 * level_difficulty();
                break;
        }
        for(sx = sroom->lx; sx <= sroom->hx; sx++)
            for(sy = sroom->ly; sy <= sroom->hy; sy++) {
                if(sroom->irregular) {
                    if ((int) levl[sx][sy].roomno != rmno ||
                          levl[sx][sy].edge ||
                          (sroom->doorct &&
                           distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1))
                        continue;
                } else if(!SPACE_POS(levl[sx][sy].typ) ||
                          (sroom->doorct &&
                           ((sx == sroom->lx && doors[sh].x == sx-1) ||
                            (sx == sroom->hx && doors[sh].x == sx+1) ||
                            (sy == sroom->ly && doors[sh].y == sy-1) ||
                            (sy == sroom->hy && doors[sh].y == sy+1))))
                    continue;
                /* don't place monster on explicitly placed throne */
                if(type == COURT && IS_THRONE(levl[sx][sy].typ))
                    continue;
                mon = makemon(
                    (type == COURT) ? courtmon() :
                    (type == BARRACKS) ? squadmon() :
                    (type == MORGUE) ? morguemon() :
                    (type == BEEHIVE) ?
                        (sx == tx && sy == ty ? &mons[PM_QUEEN_BEE] :
                         &mons[PM_KILLER_BEE]) :
                    (type == LEPREHALL) ? &mons[PM_LEPRECHAUN] :
                    (type == COCKNEST) ? &mons[PM_COCKATRICE] :
                    (type == ANTHOLE) ? antholemon() :
                    (struct permonst *) 0,
                   sx, sy, NO_MM_FLAGS);
                if(mon) {
                        mon->msleeping = 1;
                        if (type==COURT && mon->mpeaceful) {
                                mon->mpeaceful = 0;
                                set_malign(mon);
                        }
                }
                switch(type) {
                    case ZOO:
                    case LEPREHALL:
                        if(sroom->doorct)
                        {
                            int distval = dist2(sx,sy,doors[sh].x,doors[sh].y);
                            i = sq(distval);
                        }
                        else
                            i = goldlim;
                        if(i >= goldlim) i = 5*level_difficulty();
                        goldlim -= i;
                        (void) mkgold((long) rn1(i, 10), sx, sy);
                        break;
                    case MORGUE:
                        if(!rn2(5))
                            (void) mk_tt_object(CORPSE, sx, sy);
                        if(!rn2(10))    /* lots of treasure buried with dead */
                            (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST,
                                             sx, sy, true, false);
                        if (!rn2(5))
                            make_grave(sx, sy, (char *)0);
                        break;
                    case BEEHIVE:
                        if(!rn2(3))
                            (void) mksobj_at(LUMP_OF_ROYAL_JELLY,
                                             sx, sy, true, false);
                        break;
                    case BARRACKS:
                        if(!rn2(20))    /* the payroll and some loot */
                            (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST,
                                             sx, sy, true, false);
                        break;
                    case COCKNEST:
                        if(!rn2(3)) {
                            struct obj *sobj = mk_tt_object(STATUE, sx, sy);

                            if (sobj) {
                                for (i = rn2(5); i; i--)
                                    (void) add_to_container(sobj,
                                                mkobj(RANDOM_CLASS, false));
                                sobj->owt = weight(sobj);
                            }
                        }
                        break;
                    case ANTHOLE:
                        if(!rn2(3))
                            (void) mkobj_at(FOOD_CLASS, sx, sy, false);
                        break;
                }
            }
        switch (type) {
              case COURT:
                {
                  struct obj *chest;
                  levl[tx][ty].typ = THRONE;
                  (void) somexy(sroom, &mm);
                  (void) mkgold((long) rn1(50 * level_difficulty(),10), mm.x, mm.y);
                  /* the royal coffers */
                  chest = mksobj_at(CHEST, mm.x, mm.y, true, false);
                  chest->spe = 2; /* so it can be found later */
                  level.flags.has_court = 1;
                  break;
                }
              case BARRACKS:
                  level.flags.has_barracks = 1;
                  break;
              case ZOO:
                  level.flags.has_zoo = 1;
                  break;
              case MORGUE:
                  level.flags.has_morgue = 1;
                  break;
              case SWAMP:
                  level.flags.has_swamp = 1;
                  break;
              case BEEHIVE:
                  level.flags.has_beehive = 1;
                  break;
        }
}
Beispiel #5
0
static int dochat(void)
{
    struct monst *mtmp;
    int tx, ty;
    struct obj *otmp;
    schar dx, dy, dz;
    int mdx, mdy, mon_count;

    if (is_silent(youmonst.data)) {
	pline("As %s, you cannot speak.", an(mons_mname(youmonst.data)));
	return 0;
    }
    if (Strangled) {
	pline("You can't speak.  You're choking!");
	return 0;
    }
    if (u.uswallow) {
	pline("They won't hear you out there.");
	return 0;
    }
    if (Underwater) {
	pline("Your speech is unintelligible underwater.");
	return 0;
    }

    if (!Blind && (otmp = shop_object(u.ux, u.uy)) != NULL) {
	/* standing on something in a shop and chatting causes the shopkeeper
	   to describe the price(s).  This can inhibit other chatting inside
	   a shop, but that shouldn't matter much.  shop_object() returns an
	   object iff inside a shop and the shopkeeper is present and willing
	   (not angry) and able (not asleep) to speak and the position contains
	   any objects other than just gold.
	*/
	price_quote(otmp);
	return 1;
    }

    /* count the monsters around the player */
    mon_count = 0;
    for (mdx = -1; mdx <= 1; mdx++) {
	for (mdy = -1; mdy <= 1; mdy++) {
	    if (mdx == 0 && mdy == 0) {
		/* account for steed */
		if (u.usteed) {
		    mon_count++;
		    dx = 0;
		    dy = 0;
		    dz = 1;
		}
		continue;
	    }

	    mtmp = m_at(level, u.ux + mdx, u.uy + mdy);
	    if (mtmp && canspotmon(level, mtmp)) {
		mon_count++;
		dx = mdx;
		dy = mdy;
		dz = 0;
	    }
	}
    }

    /* don't ask for a direction if there's only one monster around */
    if ((mon_count != 1 || iflags.paranoid_chat) &&
	!getdir("Talk to whom? (in what direction)", &dx, &dy, &dz)) {
	/* decided not to chat */
	return 0;
    }

    if (u.usteed && dz > 0) {
	if (!u.usteed->mcanmove || u.usteed->msleeping) {
	    pline("Your steed remains silent...");
	    return 0;
	}
	return domonnoise(u.usteed);
    }
    if (dz) {
	pline("They won't hear you %s there.", dz < 0 ? "up" : "down");
	return 0;
    }

    if (dx == 0 && dy == 0) {
/*
 * Let's not include this.  It raises all sorts of questions: can you wear
 * 2 helmets, 2 amulets, 3 pairs of gloves or 6 rings as a marilith,
 * etc...  --KAA
	if (u.umonnum == PM_ETTIN) {
	    pline("You discover that your other head makes boring conversation.");
	    return 1;
	}
*/
	pline("Talking to yourself is a bad habit for a dungeoneer.");
	return 0;
    }

    tx = u.ux + dx;
    ty = u.uy + dy;
    mtmp = m_at(level, tx, ty);

    if (!mtmp || mtmp->mundetected ||
		mtmp->m_ap_type == M_AP_FURNITURE ||
		mtmp->m_ap_type == M_AP_OBJECT)
	return 0;

    /* sleeping monsters won't talk, except priests (who wake up) */
    if ((!mtmp->mcanmove || mtmp->msleeping) && !mtmp->ispriest) {
	/* If it is unseen, the player can't tell the difference between
	   not noticing him and just not existing, so skip the message. */
	if (canspotmon(level, mtmp))
	    pline("%s seems not to notice you.", Monnam(mtmp));
	return 0;
    }

    /* if this monster is waiting for something, prod it into action */
    mtmp->mstrategy &= ~STRAT_WAITMASK;

    if (mtmp->mtame && mtmp->meating) {
	if (!canspotmon(level, mtmp))
	    map_invisible(mtmp->mx, mtmp->my);
	pline("%s is eating noisily.", Monnam(mtmp));
	return 0;
    }

    if (Role_if(PM_CONVICT) && is_rat(mtmp->data) &&
	!mtmp->mpeaceful && !mtmp->mtame) {
	int soothe_roll = rnl(10);
	pline("You attempt to soothe the %s with chittering sounds.",
	      l_monnam(mtmp));
	if (soothe_roll < 2) {
	    tamedog(mtmp, NULL);
	} else if (soothe_roll > 8) {
	    pline("%s unfortunately ignores your overtures.", Monnam(mtmp));
	} else {
	    mtmp->mpeaceful = 1;
	    set_malign(mtmp);
	}
	return 1;
    }

    return domonnoise(mtmp);
}
Beispiel #6
0
static int domonnoise(struct monst *mtmp)
{
    const char *pline_msg = 0,	/* Monnam(mtmp) will be prepended */
			*verbl_msg = 0;	/* verbalize() */
    const struct permonst *ptr = mtmp->data;
    char verbuf[BUFSZ];

    /* presumably nearness and sleep checks have already been made */
    if (!flags.soundok) return 0;
    if (is_silent(ptr)) return 0;

    /* Make sure its your role's quest quardian; adjust if not */
    if (ptr->msound == MS_GUARDIAN && ptr != &pm_guardian) {
	int mndx = monsndx(ptr);
	ptr = &mons[genus(mndx,1)];
    }

    /* be sure to do this before talking; the monster might teleport away, in
     * which case we want to check its pre-teleport position
     */
    if (!canspotmon(level, mtmp))
	map_invisible(mtmp->mx, mtmp->my);

    switch (ptr->msound) {
	case MS_ORACLE:
	    return doconsult(mtmp);
	case MS_PRIEST:
	    priest_talk(mtmp);
	    break;
	case MS_LEADER:
	case MS_NEMESIS:
	case MS_GUARDIAN:
	    quest_chat(mtmp);
	    break;
	case MS_SELL: /* pitch, pay, total */
	    shk_chat(mtmp);
	    break;
	case MS_VAMPIRE:
	    {
	    /* vampire messages are varied by tameness, peacefulness, and time of night */
		boolean isnight = night();
		boolean kindred = maybe_polyd(u.umonnum == PM_VAMPIRE ||
					      u.umonnum == PM_VAMPIRE_LORD,
					      Race_if(PM_VAMPIRE));
		boolean nightchild = (Upolyd && (u.umonnum == PM_WOLF ||
				       u.umonnum == PM_WINTER_WOLF ||
				       u.umonnum == PM_WINTER_WOLF_CUB));
		const char *racenoun = (flags.female && urace.individual.f) ?
					urace.individual.f : (urace.individual.m) ?
					urace.individual.m : urace.noun;

		if (mtmp->mtame) {
			if (kindred) {
				sprintf(verbuf, "Good %s to you Master%s",
					isnight ? "evening" : "day",
					isnight ? "!" : ".  Why do we not rest?");
				verbl_msg = verbuf;
		    	} else {
		    	    sprintf(verbuf,"%s%s",
				nightchild ? "Child of the night, " : "",
				midnight() ?
					"I can stand this craving no longer!" :
				isnight ?
					"I beg you, help me satisfy this growing craving!" :
					"I find myself growing a little weary.");
				verbl_msg = verbuf;
			}
		} else if (mtmp->mpeaceful) {
			if (kindred && isnight) {
				sprintf(verbuf, "Good feeding %s!",
	    				flags.female ? "sister" : "brother");
				verbl_msg = verbuf;
 			} else if (nightchild && isnight) {
				sprintf(verbuf,
				    "How nice to hear you, child of the night!");
				verbl_msg = verbuf;
	    		} else
		    		verbl_msg = "I only drink... potions.";
    	        } else {
			int vampindex;
	    		static const char * const vampmsg[] = {
			       /* These first two (0 and 1) are specially handled below */
	    			"I vant to suck your %s!",
	    			"I vill come after %s without regret!",
		    	       /* other famous vampire quotes can follow here if desired */
	    		};
			if (kindred)
			    verbl_msg = "This is my hunting ground that you dare to prowl!";
			else if (youmonst.data == &mons[PM_SILVER_DRAGON] ||
				 youmonst.data == &mons[PM_BABY_SILVER_DRAGON]) {
			    /* Silver dragons are silver in color, not made of silver */
			    sprintf(verbuf, "%s! Your silver sheen does not frighten me!",
					youmonst.data == &mons[PM_SILVER_DRAGON] ?
					"Fool" : "Young Fool");
			    verbl_msg = verbuf; 
			} else {
			    vampindex = rn2(SIZE(vampmsg));
			    if (vampindex == 0) {
				sprintf(verbuf, vampmsg[vampindex], body_part(BLOOD));
	    			verbl_msg = verbuf;
			    } else if (vampindex == 1) {
				sprintf(verbuf, vampmsg[vampindex],
					Upolyd ? an(mons_mname(&mons[u.umonnum])) : an(racenoun));
	    			verbl_msg = verbuf;
		    	    } else
			    	verbl_msg = vampmsg[vampindex];
			}
	        }
	    }
	    break;
	case MS_WERE:
	    if (flags.moonphase == FULL_MOON && (night() ^ !rn2(13))) {
		pline("%s throws back %s head and lets out a blood curdling %s!",
		      Monnam(mtmp), mhis(level, mtmp),
		      ptr == &mons[PM_HUMAN_WERERAT] ? "shriek" : "howl");
		wake_nearto(mtmp->mx, mtmp->my, 11*11);
	    } else
		pline_msg =
		     "whispers inaudibly.  All you can make out is \"moon\".";
	    break;
	case MS_BARK:
	    if (flags.moonphase == FULL_MOON && night()) {
		pline_msg = "howls.";
	    } else if (mtmp->mpeaceful) {
		if (mtmp->mtame &&
			(mtmp->mconf || mtmp->mflee || mtmp->mtrapped ||
			 moves > EDOG(mtmp)->hungrytime || mtmp->mtame < 5))
		    pline_msg = "whines.";
		else if (mtmp->mtame && EDOG(mtmp)->hungrytime > moves + 1000)
		    pline_msg = "yips.";
		else {
		    if (mtmp->data != &mons[PM_DINGO])	/* dingos do not actually bark */
			    pline_msg = "barks.";
		}
	    } else {
		pline_msg = "growls.";
	    }
	    break;
	case MS_MEW:
	    if (mtmp->mtame) {
		if (mtmp->mconf || mtmp->mflee || mtmp->mtrapped ||
			mtmp->mtame < 5)
		    pline_msg = "yowls.";
		else if (moves > EDOG(mtmp)->hungrytime)
		    pline_msg = "meows.";
		else if (EDOG(mtmp)->hungrytime > moves + 1000)
		    pline_msg = "purrs.";
		else
		    pline_msg = "mews.";
		break;
	    } /* else FALLTHRU */
	case MS_GROWL:
	    if (mtmp->mtame &&
		(mtmp->data == &mons[PM_MONKEY] ||
		 mtmp->data == &mons[PM_APE] ||
		 mtmp->data == &mons[PM_CARNIVOROUS_APE])) {
		if (mtmp->mconf || mtmp->mflee || mtmp->mtrapped ||
		    moves > EDOG(mtmp)->hungrytime || mtmp->mtame < 5) {
		    pline_msg = "shrieks.";
		    wake_nearto(mtmp->mx, mtmp->my, 8*8);
		} else if (EDOG(mtmp)->hungrytime > moves + 1000) {
		    pline_msg = "chatters.";
		} else {
		    pline_msg = "hoots.";
		}
	    } else {
		pline_msg = mtmp->mpeaceful ? "snarls." : "growls!";
	    }
	    break;
	case MS_ROAR:
	    pline_msg = mtmp->mpeaceful ? "snarls." : "roars!";
	    break;
	case MS_SQEEK:
	    pline_msg = "squeaks.";
	    break;
	case MS_SQAWK:
	    if (ptr == &mons[PM_RAVEN] && !mtmp->mpeaceful)
	    	verbl_msg = "Nevermore!";
	    else
	    	pline_msg = "squawks.";
	    break;
	case MS_HISS:
	    if (!mtmp->mpeaceful)
		pline_msg = "hisses!";
	    else return 0;	/* no sound */
	    break;
	case MS_BUZZ:
	    pline_msg = mtmp->mpeaceful ? "drones." : "buzzes angrily.";
	    break;
	case MS_GRUNT:
	    pline_msg = "grunts.";
	    break;
	case MS_NEIGH:
	    if (mtmp->mtame < 5)
		pline_msg = "neighs.";
	    else if (moves > EDOG(mtmp)->hungrytime)
		pline_msg = "whinnies.";
	    else
		pline_msg = "whickers.";
	    break;
	case MS_WAIL:
	    pline_msg = "wails mournfully.";
	    break;
	case MS_GURGLE:
	    pline_msg = "gurgles.";
	    break;
	case MS_BURBLE:
	    pline_msg = "burbles.";
	    break;
	case MS_SHRIEK:
	    pline_msg = "shrieks.";
	    aggravate();
	    break;
	case MS_IMITATE:
	    pline_msg = "imitates you.";
	    break;
	case MS_BONES:
	    pline("%s rattles noisily.", Monnam(mtmp));
	    pline("You freeze for a moment.");
	    nomul(-2, "scared by rattling");
	    break;
	case MS_LAUGH:
	    {
		static const char * const laugh_msg[4] = {
		    "giggles.", "chuckles.", "snickers.", "laughs.",
		};
		pline_msg = laugh_msg[rn2(4)];
	    }
	    break;
	case MS_MUMBLE:
	    pline_msg = "mumbles incomprehensibly.";
	    break;
	case MS_DJINNI:
	    if (mtmp->mtame) {
		verbl_msg = "Sorry, I'm all out of wishes.";
	    } else if (mtmp->mpeaceful) {
		if (ptr == &mons[PM_WATER_DEMON])
		    pline_msg = "gurgles.";
		else
		    verbl_msg = "I'm free!";
	    } else verbl_msg = "This will teach you not to disturb me!";
	    break;
	case MS_BOAST:	/* giants */
	    if (!mtmp->mpeaceful) {
		switch (rn2(4)) {
		case 0: pline("%s boasts about %s gem collection.",
			      Monnam(mtmp), mhis(level, mtmp));
			break;
		case 1: pline_msg = "complains about a diet of mutton.";
			break;
	       default: pline_msg = "shouts \"Fee Fie Foe Foo!\" and guffaws.";
			wake_nearto(mtmp->mx, mtmp->my, 7*7);
			break;
		}
		break;
	    }
	    /* else FALLTHRU */
	case MS_HUMANOID:
	    if (!mtmp->mpeaceful) {
		if (In_endgame(&u.uz) && is_mplayer(ptr)) {
		    mplayer_talk(mtmp);
		    break;
		} else return 0;	/* no sound */
	    }
	    /* Generic peaceful humanoid behaviour. */
	    if (mtmp->mflee)
		pline_msg = "wants nothing to do with you.";
	    else if (mtmp->mhp < mtmp->mhpmax/4)
		pline_msg = "moans.";
	    else if (mtmp->mconf || mtmp->mstun)
		verbl_msg = !rn2(3) ? "Huh?" : rn2(2) ? "What?" : "Eh?";
	    else if (!mtmp->mcansee)
		verbl_msg = "I can't see!";
	    else if (mtmp->mtrapped) {
		struct trap *t = t_at(level, mtmp->mx, mtmp->my);

		if (t) t->tseen = 1;
		verbl_msg = "I'm trapped!";
	    } else if (mtmp->mhp < mtmp->mhpmax/2)
		pline_msg = "asks for a potion of healing.";
	    else if (mtmp->mtame && !mtmp->isminion &&
						moves > EDOG(mtmp)->hungrytime)
		verbl_msg = "I'm hungry.";
	    /* Specific monsters' interests */
	    else if (is_elf(ptr))
		pline_msg = "curses orcs.";
	    else if (is_dwarf(ptr))
		pline_msg = "talks about mining.";
	    else if (likes_magic(ptr))
		pline_msg = "talks about spellcraft.";
	    else if (ptr->mlet == S_CENTAUR)
		pline_msg = "discusses hunting.";
	    else switch (monsndx(ptr)) {
		case PM_HOBBIT:
		    pline_msg = (mtmp->mhpmax - mtmp->mhp >= 10) ?
				"complains about unpleasant dungeon conditions."
				: "asks you about the One Ring.";
		    break;
		case PM_ARCHEOLOGIST:
    pline_msg = "describes a recent article in \"Spelunker Today\" magazine.";
		    break;
		case PM_TOURIST:
		    verbl_msg = "Aloha.";
		    break;
		default:
		    pline_msg = "discusses dungeon exploration.";
		    break;
	    }
	    break;
	case MS_SEDUCE:
	    if (ptr->mlet != S_NYMPH && flags.seduce_enabled &&
		could_seduce(mtmp, &youmonst, NULL) == 1) {
			doseduce(mtmp);
			break;
	    }
	    
	    switch ((poly_gender() != (int) mtmp->female) ? rn2(3) : 0)
	    {
		case 2:
			verbl_msg = "Hello, sailor.";
			break;
		case 1:
			pline_msg = "comes on to you.";
			break;
		default:
			pline_msg = "cajoles you.";
	    }
	    break;
	case MS_ARREST:
	    if (mtmp->mpeaceful)
		verbalize("Just the facts, %s.",
		      flags.female ? "Ma'am" : "Sir");
	    else {
		static const char * const arrest_msg[3] = {
		    "Anything you say can be used against you.",
		    "You're under arrest!",
		    "Stop in the name of the Law!",
		};
		verbl_msg = arrest_msg[rn2(3)];
	    }
	    break;
	case MS_BRIBE:
	    if (monsndx(ptr) == PM_PRISON_GUARD) {
		long gdemand = 500 * u.ulevel;
		long goffer = 0;

		if (!mtmp->mpeaceful && !mtmp->mtame) {
		    pline("%s demands %ld %s to avoid re-arrest.",
			  Amonnam(mtmp), gdemand, currency(gdemand));
		    if ((goffer = bribe(mtmp)) >= gdemand) {
			verbl_msg = "Good.  Now beat it, scum!";
			mtmp->mpeaceful = 1;
			set_malign(mtmp);
		    } else {
			verbalize("I said %ld!", gdemand);
			mtmp->mspec_used = 1000;
		    }
		} else {
		    verbl_msg = "Out of my way, scum!"; /* still a jerk */
		}
		break;
	    } else if (mtmp->mpeaceful && !mtmp->mtame) {
		demon_talk(mtmp);
		break;
	    }
	    /* fall through */
	case MS_CUSS:
	    if (!mtmp->mpeaceful)
		cuss(mtmp);
	    break;
	case MS_SPELL:
	    /* deliberately vague, since it's not actually casting any spell */
	    pline_msg = "seems to mutter a cantrip.";
	    break;
	case MS_NURSE:
	    if (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep)))
		verbl_msg = "Put that weapon away before you hurt someone!";
	    else if (uarmc || uarm || uarmh || uarms || uarmg || uarmf)
		verbl_msg = Role_if (PM_HEALER) ?
			  "Doc, I can't help you unless you cooperate." :
			  "Please undress so I can examine you.";
	    else if (uarmu)
		verbl_msg = "Take off your shirt, please.";
	    else
		verbl_msg = "Relax, this won't hurt a bit.";
	    break;
	case MS_GUARD:
	    if (money_cnt(invent))
		verbl_msg = "Please drop that gold and follow me.";
	    else
		verbl_msg = "Please follow me.";
	    break;
	case MS_SOLDIER:
	    {
		static const char * const soldier_foe_msg[3] = {
		    "Resistance is useless!",
		    "You're dog meat!",
		    "Surrender!",
		},		  * const soldier_pax_msg[3] = {
		    "What lousy pay we're getting here!",
		    "The food's not fit for Orcs!",
		    "My feet hurt, I've been on them all day!",
		};
		verbl_msg = mtmp->mpeaceful ? soldier_pax_msg[rn2(3)]
					    : soldier_foe_msg[rn2(3)];
	    }
	    break;
	case MS_RIDER:
	    if (ptr == &mons[PM_DEATH] && !rn2(10))
		pline_msg = "is busy reading a copy of Sandman #8.";
	    else
		verbl_msg = (ptr == &mons[PM_DEATH]) ?
			 "WHO DO YOU THINK YOU ARE, WAR?" :
			 "Who do you think you are, War?";
	    break;
    }

    if (pline_msg) pline("%s %s", Monnam(mtmp), pline_msg);
    else if (verbl_msg) verbalize(verbl_msg);
    return 1;
}
Beispiel #7
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);
        }
    }
}
Beispiel #8
0
static void cast_cleric_spell(struct monst *mtmp, int dmg, int spellnum)
{
    if (dmg == 0 && !is_undirected_spell(AD_CLRC, spellnum)) {
	impossible("cast directed cleric spell (%d) with dmg=0?", spellnum);
	return;
    }

    switch (spellnum) {
    case CLC_GEYSER:
	/* this is physical damage, not magical damage */
	pline("A sudden geyser slams into you from nowhere!");
	dmg = dice(8, 6);
	if (Half_physical_damage) dmg = (dmg + 1) / 2;
	break;
    case CLC_FIRE_PILLAR:
	pline("A pillar of fire strikes all around you!");
	if (Fire_resistance) {
	    shieldeff(u.ux, u.uy);
	    dmg = 0;
	} else
	    dmg = dice(8, 6);
	if (Half_spell_damage) dmg = (dmg + 1) / 2;
	burn_away_slime();
	burnarmor(&youmonst);
	destroy_item(SCROLL_CLASS, AD_FIRE);
	destroy_item(POTION_CLASS, AD_FIRE);
	destroy_item(SPBOOK_CLASS, AD_FIRE);
	burn_floor_paper(u.ux, u.uy, TRUE, FALSE);
	break;
    case CLC_LIGHTNING:
    {
	boolean reflects;

	pline("A bolt of lightning strikes down at you from above!");
	reflects = ureflects("It bounces off your %s%s.", "");
	if (reflects || Shock_resistance) {
	    shieldeff(u.ux, u.uy);
	    dmg = 0;
	    if (reflects)
		break;
	} else
	    dmg = dice(8, 6);
	if (Half_spell_damage) dmg = (dmg + 1) / 2;
	destroy_item(WAND_CLASS, AD_ELEC);
	destroy_item(RING_CLASS, AD_ELEC);
	break;
    }
    case CLC_CURSE_ITEMS:
	pline("You feel as if you need some help.");
	rndcurse();
	dmg = 0;
	break;
    case CLC_INSECTS:
      {
	/* Try for insects, and if there are none
	   left, go for (sticks to) snakes.  -3. */
	const struct permonst *pm = mkclass(&u.uz, S_ANT,0);
	struct monst *mtmp2 = NULL;
	char let = (pm ? S_ANT : S_SNAKE);
	boolean success;
	int i;
	coord bypos;
	int quan;

	quan = (mtmp->m_lev < 2) ? 1 : rnd((int)mtmp->m_lev / 2);
	if (quan < 3) quan = 3;
	success = pm ? TRUE : FALSE;
	for (i = 0; i <= quan; i++) {
	    if (!enexto(&bypos, level, mtmp->mux, mtmp->muy, mtmp->data))
		break;
	    if ((pm = mkclass(&u.uz, let,0)) != 0 &&
		    (mtmp2 = makemon(pm, level, bypos.x, bypos.y, NO_MM_FLAGS)) != 0) {
		success = TRUE;
		mtmp2->msleeping = mtmp2->mpeaceful = mtmp2->mtame = 0;
		set_malign(mtmp2);
	    }
	}
	/* Not quite right:
         * -- message doesn't always make sense for unseen caster (particularly
	 *    the first message)
         * -- message assumes plural monsters summoned (non-plural should be
         *    very rare, unlike in nasty())
         * -- message assumes plural monsters seen
         */
	if (!success)
	    pline("%s casts at a clump of sticks, but nothing happens.",
		Monnam(mtmp));
	else if (let == S_SNAKE)
	    pline("%s transforms a clump of sticks into snakes!",
		Monnam(mtmp));
	else if (Invisible && !perceives(mtmp->data) &&
				(mtmp->mux != u.ux || mtmp->muy != u.uy))
	    pline("%s summons insects around a spot near you!",
		Monnam(mtmp));
	else if (Displaced && (mtmp->mux != u.ux || mtmp->muy != u.uy))
	    pline("%s summons insects around your displaced image!",
		Monnam(mtmp));
	else
	    pline("%s summons insects!", Monnam(mtmp));
	dmg = 0;
	break;
      }
    case CLC_BLIND_YOU:
	/* note: resists_blnd() doesn't apply here */
	if (!Blinded) {
	    int num_eyes = eyecount(youmonst.data);
	    pline("Scales cover your %s!",
		  (num_eyes == 1) ?
		  body_part(EYE) : makeplural(body_part(EYE)));
	    make_blinded(Half_spell_damage ? 100L : 200L, FALSE);
	    if (!Blind) pline("Your vision quickly clears.");
	    dmg = 0;
	} else
	    impossible("no reason for monster to cast blindness spell?");
	break;
    case CLC_PARALYZE:
	if (Antimagic || Free_action) {
	    shieldeff(u.ux, u.uy);
	    if (multi >= 0)
		pline("You stiffen briefly.");
	    nomul(-1, "paralyzed by a monster");
	} else {
	    if (multi >= 0)
		pline("You are frozen in place!");
	    dmg = 4 + (int)mtmp->m_lev;
	    if (Half_spell_damage) dmg = (dmg + 1) / 2;
	    nomul(-dmg, "paralyzed by a monster");
	}
	dmg = 0;
	break;
    case CLC_CONFUSE_YOU:
	if (Antimagic) {
	    shieldeff(u.ux, u.uy);
	    pline("You feel momentarily dizzy.");
	} else {
	    boolean oldprop = !!Confusion;

	    dmg = (int)mtmp->m_lev;
	    if (Half_spell_damage) dmg = (dmg + 1) / 2;
	    make_confused(HConfusion + dmg, TRUE);
	    if (Hallucination)
		pline("You feel %s!", oldprop ? "trippier" : "trippy");
	    else
		pline("You feel %sconfused!", oldprop ? "more " : "");
	}
	dmg = 0;
	break;
    case CLC_CURE_SELF:
	if (mtmp->mhp < mtmp->mhpmax) {
	    if (canseemon(mtmp))
		pline("%s looks better.", Monnam(mtmp));
	    /* note: player healing does 6d4; this used to do 1d8 */
	    if ((mtmp->mhp += dice(3,6)) > mtmp->mhpmax)
		mtmp->mhp = mtmp->mhpmax;
	    dmg = 0;
	}
	break;
    case CLC_OPEN_WOUNDS:
	if (Antimagic) {
	    shieldeff(u.ux, u.uy);
	    dmg = (dmg + 1) / 2;
	}
	if (dmg <= 5)
	    pline("Your skin itches badly for a moment.");
	else if (dmg <= 10)
	    pline("Wounds appear on your body!");
	else if (dmg <= 20)
	    pline("Severe wounds appear on your body!");
	else
	    pline("Your body is covered with painful wounds!");
	break;
    default:
	impossible("mcastu: invalid clerical spell (%d)", spellnum);
	dmg = 0;
	break;
    }

    if (dmg) mdamageu(mtmp, dmg);
}
Beispiel #9
0
void invault(void) {
    struct monst *guard;
    int trycount, vaultroom = (int)vault_occupied(u.urooms);

    if (!vaultroom) {
        u.uinvault = 0;
        return;
    }

    vaultroom -= ROOMOFFSET;

    guard = findgd();
    if (++u.uinvault % 30 == 0 && !guard) { /* if time ok and no guard now. */
        char buf[BUFSZ];
        int x, y, dd, gx, gy;
        int lx = 0, ly = 0;
        /* first find the goal for the guard */
        for (dd = 2; (dd < ROWNO || dd < COLNO); dd++) {
            for (y = u.uy - dd; y <= u.uy + dd; ly = y, y++) {
                if (y < 0 || y > ROWNO - 1)
                    continue;
                for (x = u.ux - dd; x <= u.ux + dd; lx = x, x++) {
                    if (y != u.uy - dd && y != u.uy + dd && x != u.ux - dd)
                        x = u.ux + dd;
                    if (x < 1 || x > COLNO - 1)
                        continue;
                    if (levl[x][y].typ == CORR) {
                        if (x < u.ux)
                            lx = x + 1;
                        else if (x > u.ux)
                            lx = x - 1;
                        else
                            lx = x;
                        if (y < u.uy)
                            ly = y + 1;
                        else if (y > u.uy)
                            ly = y - 1;
                        else
                            ly = y;
                        if (levl[lx][ly].typ != STONE && levl[lx][ly].typ != CORR)
                            goto incr_radius;
                        goto fnd;
                    }
                }
            }
            incr_radius: ;
        }
        impossible("Not a single corridor on this level??");
        tele();
        return;
        fnd: gx = x;
        gy = y;

        /* next find a good place for a door in the wall */
        x = u.ux;
        y = u.uy;
        if (levl[x][y].typ != ROOM) { /* player dug a door and is in it */
            if (levl[x + 1][y].typ == ROOM)
                x = x + 1;
            else if (levl[x][y + 1].typ == ROOM)
                y = y + 1;
            else if (levl[x - 1][y].typ == ROOM)
                x = x - 1;
            else if (levl[x][y - 1].typ == ROOM)
                y = y - 1;
            else if (levl[x + 1][y + 1].typ == ROOM) {
                x = x + 1;
                y = y + 1;
            } else if (levl[x - 1][y - 1].typ == ROOM) {
                x = x - 1;
                y = y - 1;
            } else if (levl[x + 1][y - 1].typ == ROOM) {
                x = x + 1;
                y = y - 1;
            } else if (levl[x - 1][y + 1].typ == ROOM) {
                x = x - 1;
                y = y + 1;
            }
        }
        while (levl[x][y].typ == ROOM) {
            int dx, dy;

            dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
            dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
            if (abs(gx - x) >= abs(gy - y))
                x += dx;
            else
                y += dy;
        }
        if (x == u.ux && y == u.uy) {
            if (levl[x + 1][y].typ == HWALL || levl[x + 1][y].typ == DOOR)
                x = x + 1;
            else if (levl[x - 1][y].typ == HWALL || levl[x - 1][y].typ == DOOR)
                x = x - 1;
            else if (levl[x][y + 1].typ == VWALL || levl[x][y + 1].typ == DOOR)
                y = y + 1;
            else if (levl[x][y - 1].typ == VWALL || levl[x][y - 1].typ == DOOR)
                y = y - 1;
            else
                return;
        }

        /* make something interesting happen */
        if (!(guard = makemon(&mons[PM_GUARD], x, y, NO_MM_FLAGS)))
            return;
        guard->isgd = 1;
        guard->mpeaceful = 1;
        set_malign(guard);
        EGD(guard)->gddone = 0;
        EGD(guard)->ogx = x;
        EGD(guard)->ogy = y;
        assign_level(&(EGD(guard)->gdlevel), &u.uz);
        EGD(guard)->vroom = vaultroom;
        EGD(guard)->warncnt = 0;

        reset_faint(); /* if fainted - wake up */
        if (canspotmon(guard)) {
            char name[BUFSZ];
            g_monnam(name, BUFSZ, guard);
            pline("Suddenly one of the Vault's %s enters!", makeplural(name));
        } else {
            pline("Someone else has entered the Vault.");
        }
        newsym(guard->mx, guard->my);
        if (youmonst.m_ap_type == M_AP_OBJECT || u.uundetected) {
            if (youmonst.m_ap_type == M_AP_OBJECT && youmonst.mappearance != GOLD_PIECE)
                verbalize("Hey! Who left that %s in here?", mimic_obj_name(&youmonst));
            /* You're mimicking some object or you're hidden. */
            pline("Puzzled, %s turns around and leaves.", mhe(guard));
            mongone(guard);
            return;
        }
        if (Strangled|| is_silent(youmonst.data) || multi < 0) {
            /* [we ought to record whether this this message has already
             been given in order to vary it upon repeat visits, but
             discarding the monster and its egd data renders that hard] */
            verbalize("I'll be back when you're ready to speak to me!");
            mongone(guard);
            return;
        }

        stop_occupation(); /* if occupied, stop it *now* */
        trycount = 5;
        do {
            getlin("\"Hello stranger, who are you?\" -", buf);
            (void)mungspaces(buf);
        } while (!letter(buf[0]) && --trycount > 0);

        if (u.ualign.type == A_LAWFUL &&
        /* ignore trailing text, in case player includes character's rank */
        strncmpi(buf, plname, (int)strlen(plname)) != 0) {
            adjalign(-1); /* Liar! */
        }

        if (!strcmpi(buf, "Croesus") || !strcmpi(buf, "Kroisos") || !strcmpi(buf, "Creosote")) {
            if (!mvitals[PM_CROESUS].died) {
                verbalize("Oh, yes, of course.  Sorry to have disturbed you.");
                mongone(guard);
            } else {
                setmangry(guard);
                verbalize("Back from the dead, are you?  I'll remedy that!");
                /* don't want guard to waste next turn wielding a weapon */
                if (!MON_WEP(guard)) {
                    guard->weapon_check = NEED_HTH_WEAPON;
                    (void)mon_wield_item(guard);
                }
            }
            return;
        }
        verbalize("I don't know you.");
        if (!u.ugold && !hidden_gold())
            verbalize("Please follow me.");
        else {
            if (!u.ugold)
                verbalize("You have hidden gold.");
            verbalize("Most likely all your gold was stolen from this vault.");
            verbalize("Please drop that gold and follow me.");
        }
        EGD(guard)->gdx = gx;
        EGD(guard)->gdy = gy;
        EGD(guard)->fcbeg = 0;
        EGD(guard)->fakecorr[0].fx = x;
        EGD(guard)->fakecorr[0].fy = y;
        if (IS_WALL(levl[x][y].typ))
            EGD(guard)->fakecorr[0].ftyp = levl[x][y].typ;
        else { /* the initial guard location is a dug door */
            int vlt = EGD(guard)->vroom;
            signed char lowx = rooms[vlt].lx, hix = rooms[vlt].hx;
            signed char lowy = rooms[vlt].ly, hiy = rooms[vlt].hy;

            if (x == lowx - 1 && y == lowy - 1)
                EGD(guard)->fakecorr[0].ftyp = TLCORNER;
            else if (x == hix + 1 && y == lowy - 1)
                EGD(guard)->fakecorr[0].ftyp = TRCORNER;
            else if (x == lowx - 1 && y == hiy + 1)
                EGD(guard)->fakecorr[0].ftyp = BLCORNER;
            else if (x == hix + 1 && y == hiy + 1)
                EGD(guard)->fakecorr[0].ftyp = BRCORNER;
            else if (y == lowy - 1 || y == hiy + 1)
                EGD(guard)->fakecorr[0].ftyp = HWALL;
            else if (x == lowx - 1 || x == hix + 1)
                EGD(guard)->fakecorr[0].ftyp = VWALL;
        }
        levl[x][y].typ = DOOR;
        levl[x][y].flags = D_NODOOR;
        unblock_point(x, y); /* doesn't block light */
        EGD(guard)->fcend = 1;
        EGD(guard)->warncnt = 1;
    }
}
Beispiel #10
0
struct monst *
make_familiar(struct obj *otmp, xchar x, xchar y, boolean quietly)
{
    const struct permonst *pm;
    struct monst *mtmp = 0;
    int chance, trycnt = 100;

    do {
        if (otmp) {     /* figurine; otherwise spell */
            int mndx = otmp->corpsenm;

            pm = &mons[mndx];
            /* activating a figurine provides one way to exceed the maximum
               number of the target critter created--unless it has a special
               limit (erinys, Nazgul) */
            if ((mvitals[mndx].mvflags & G_EXTINCT) &&
                mbirth_limit(mndx) != MAXMONNO) {
                if (!quietly)
                    /* have just been given "You <do something with> the
                       figurine and it transforms." message */
                    pline("... into a pile of dust.");
                break;  /* mtmp is null */
            }
        } else if (!rn2(3)) {
            pm = &mons[pet_type(NULL)];
        } else {
            pm = rndmonst(&u.uz, rng_t_create_monster);
            if (!pm) {
                if (!quietly)
                    pline
                        ("There seems to be nothing available for a familiar.");
                break;
            }
        }

        mtmp = makemon(pm, level, x, y, MM_EDOG | MM_IGNOREWATER |
                       (otmp ? 0 : (MM_CREATEMONSTER | MM_CMONSTER_T)));
        if (otmp && !mtmp) {    /* monster was genocided or square occupied */
            if (!quietly)
                pline("The figurine writhes and then shatters into pieces!");
            break;
        }
    } while (!mtmp && --trycnt > 0);

    if (!mtmp)
        return NULL;

    if (is_pool(level, mtmp->mx, mtmp->my) && minliquid(mtmp))
        return NULL;

    initedog(mtmp);
    mtmp->msleeping = 0;
    if (otmp) { /* figurine; resulting monster might not become a pet */
        chance = rn2_on_rng(10, rng_figurine_effect);
        /* 0: tame, 1: peaceful, 2: hostile, 3+: matching BCU; this gives
           an 80% chance of the desired effect, 10% of each other effect */
        if (chance > 2)
            chance = otmp->blessed ? 0 : !otmp->cursed ? 1 : 2;
        if (chance > 0) {
            mtmp->mtame = 0;    /* not tame after all */
            if (chance == 2) {  /* hostile (cursed figurine) */
                if (!quietly)
                    pline("You get a bad feeling about this.");
                msethostility(mtmp, TRUE, TRUE);
            }
        }
        /* if figurine has been named, give same name to the monster */
        if (otmp->onamelth)
            mtmp = christen_monst(mtmp, ONAME(otmp));
    }
    set_malign(mtmp);   /* more alignment changes */
    newsym(mtmp->mx, mtmp->my);

    /* must wield weapon immediately since pets will otherwise drop it */
    if (mtmp->mtame && attacktype(mtmp->data, AT_WEAP)) {
        mtmp->weapon_check = NEED_HTH_WEAPON;
        mon_wield_item(mtmp);
    }
    return mtmp;
}
Beispiel #11
0
struct monst *tamedog(struct monst *mtmp, struct obj *obj)
{
	struct monst *mtmp2;

	/* The Wiz, Medusa and the quest nemeses aren't even made peaceful. */
	if (mtmp->iswiz || mtmp->data == &mons[PM_MEDUSA]
				|| (mtmp->data->mflags3 & M3_WANTSARTI))
		return NULL;

	/* worst case, at least it'll be peaceful. */
	mtmp->mpeaceful = 1;
	set_malign(mtmp);
	if (flags.moonphase == FULL_MOON && night() && rn2(6) && obj
						&& mtmp->data->mlet == S_DOG)
		return NULL;

	/* Domestic animals are wary of the Convict. */
	if (Role_if(PM_CONVICT) && is_domestic(mtmp->data) && obj) {
	    pline("%s still seems wary of you.", Monnam(mtmp));
	    return NULL;
	}

	/* If we cannot tame it, at least it's no longer afraid. */
	mtmp->mflee = 0;
	mtmp->mfleetim = 0;

	/* make grabber let go now, whether it becomes tame or not */
	if (mtmp == u.ustuck) {
	    if (u.uswallow)
		expels(mtmp, mtmp->data, TRUE);
	    else if (!(Upolyd && sticks(youmonst.data)))
		unstuck(mtmp);
	}

	/* feeding it treats makes it tamer */
	if (mtmp->mtame && obj) {
	    int tasty;

	    if (mtmp->mcanmove && !mtmp->mconf && !mtmp->meating &&
		((tasty = dogfood(mtmp, obj)) == DOGFOOD ||
		 (tasty <= ACCFOOD && EDOG(mtmp)->hungrytime <= moves))) {
		/* pet will "catch" and eat this thrown food */
		if (canseemon(level, mtmp)) {
		    boolean big_corpse = (obj->otyp == CORPSE &&
					  obj->corpsenm >= LOW_PM &&
				mons[obj->corpsenm].msize > mtmp->data->msize);
		    pline("%s catches %s%s",
			  Monnam(mtmp), the(xname(obj)),
			  !big_corpse ? "." : ", or vice versa!");
		} else if (cansee(mtmp->mx,mtmp->my))
		    pline("%s.", Tobjnam(obj, "stop"));
		/* dog_eat expects a floor object */
		place_object(obj, level, mtmp->mx, mtmp->my);
		dog_eat(mtmp, obj, mtmp->mx, mtmp->my, FALSE);
		/* eating might have killed it, but that doesn't matter here;
		   a non-null result suppresses "miss" message for thrown
		   food and also implies that the object has been deleted */
		return mtmp;
	    } else
		return NULL;
	}

	if (mtmp->mtame || !mtmp->mcanmove ||
	    /* monsters with conflicting structures cannot be tamed */
	    mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion ||
	    is_covetous(mtmp->data) || is_human(mtmp->data) ||
	    (is_demon(mtmp->data) && !is_demon(youmonst.data)) ||
	    (obj && dogfood(mtmp, obj) >= MANFOOD)) return NULL;

	if (mtmp->m_id == quest_status.leader_m_id)
	    return NULL;

	/* make a new monster which has the pet extension */
	mtmp2 = newmonst(MX_EDOG, mtmp->mnamelth);
	*mtmp2 = *mtmp;
	mtmp2->mxtyp = MX_EDOG;
	mtmp2->mxlth = sizeof(struct edog);
	if (mtmp->mnamelth) strcpy(NAME(mtmp2), NAME(mtmp));
	initedog(mtmp2);
	replmon(mtmp, mtmp2);
	/* `mtmp' is now obsolete */

	if (obj) {		/* thrown food */
	    /* defer eating until the edog extension has been set up */
	    place_object(obj, level, mtmp2->mx, mtmp2->my);	/* put on floor */
	    /* devour the food (might grow into larger, genocided monster) */
	    if (dog_eat(mtmp2, obj, mtmp2->mx, mtmp2->my, TRUE) == 2)
		return mtmp2;		/* oops, it died... */
	    /* `obj' is now obsolete */
	}

	newsym(mtmp2->mx, mtmp2->my);
	if (attacktype(mtmp2->data, AT_WEAP)) {
		mtmp2->weapon_check = NEED_HTH_WEAPON;
		mon_wield_item(mtmp2);
	}
	return mtmp2;
}