Exemplo n.º 1
0
struct monst *
christen_monst(struct monst *mtmp, const char *name)
{
    int lth;
    struct monst *mtmp2;
    char buf[PL_PSIZ];

    /* dogname & catname are PL_PSIZ arrays; object names have same limit */
    lth = *name ? (int)(strlen(name) + 1) : 0;
    if (lth > PL_PSIZ) {
        lth = PL_PSIZ;
        name = strncpy(buf, name, PL_PSIZ - 1);
        buf[PL_PSIZ - 1] = '\0';
    }
    if (lth == mtmp->mnamelth) {
        /* don't need to allocate a new monst struct */
        if (lth)
            strcpy(NAME_MUTABLE(mtmp), name);
        return mtmp;
    }
    mtmp2 = newmonst(mtmp->mxtyp, lth);
    *mtmp2 = *mtmp;
    memcpy(mtmp2->mextra, mtmp->mextra, mtmp->mxlth);
    mtmp2->mnamelth = lth;
    if (lth)
        strcpy(NAME_MUTABLE(mtmp2), name);
    replmon(mtmp, mtmp2);
    return mtmp2;
}
Exemplo n.º 2
0
/* Assign a name to a monster, taken from a list of possible names.
   Note that shopkeepers are special and use nameshk instead, partly
   because it contains additional logic peculiar to them and also
   because their name is stored in ESHK because of reasons. */
static void
namemonsterfromlist(struct monst *mon, const char *const *nlist,
                    struct level *lev, boolean unique)
{
    int names_avail, tryct;
    const char *ourname;
    struct monst *mtmp;
    if (!mon) {
        if (wizard)
            impossible("Cannot name a non-existent monster.");
        return;
    }
    if (!nlist[0]) {
        if (wizard)
            impossible("No names available for the %s.", mon_nam(mon));
        return;
    }
    for (names_avail = 0; nlist[names_avail]; names_avail++)
        ;
    for (tryct = 0; tryct < 500; tryct++) {
        ourname = nlist[rn2(names_avail)];
        if (!unique) {
            christen_monst(mon, ourname);
            return;
        }
        for (mtmp = lev->monlist; mtmp; mtmp = mtmp->nmon) {
            if (DEADMONSTER(mtmp) || (mtmp == mon) ||
                !(mtmp->data->mlet == mon->data->mlet))
                continue;
            if (strcmp(NAME_MUTABLE(mtmp), ourname) != 0)
                continue;
            break;
        }
        if (!mtmp) {
            christen_monst(mon, ourname);
            return;
        } 
    }
    /* We're not going to name this monster. */
    if (wizard)
        pline("Failed to find %s name for the %s.",
              (unique ? "an unused" : "a"), mon_nam(mon));
}
Exemplo n.º 3
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; this uses the main RNG because
       realtime effects means that this won't really sync anyway; this also
       calls set_malign (thus there's no need for the caller to call it after
       calling tamedog()) */
    msethostility(mtmp, FALSE, TRUE);
    if (flags.moonphase == FULL_MOON && night() && rn2(6) && obj &&
        mtmp->data->mlet == S_DOG)
        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 (Engulfed)
            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 && CONST_EDOG(mtmp)->hungrytime <= moves))) {
            /* pet will "catch" and eat this thrown food */
            if (canseemon(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 == u.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_MUTABLE(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 */
    }

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