int tamedog(struct monst *mtmp, struct obj *obj) { struct monst *mtmp2; if(flags.moonphase == FULL_MOON && night() && rn2(6)) return(0); /* If we cannot tame him, at least he's no longer afraid. */ mtmp->mflee = 0; mtmp->mfleetim = 0; if(mtmp->mtame || mtmp->mfroz || #ifndef NOWORM mtmp->wormno || #endif /* NOWORM */ mtmp->isshk || mtmp->isgd || strchr(" &@12", mtmp->data->mlet)) return(0); /* no tame long worms? */ if(obj) { if(dogfood(obj) >= MANFOOD) return(0); if(cansee(mtmp->mx,mtmp->my)){ pline("%s devours the %s.", Monnam(mtmp), objects[obj->otyp].oc_name); } obfree(obj, (struct obj *) 0); } mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth); *mtmp2 = *mtmp; mtmp2->mxlth = sizeof(struct edog); if(mtmp->mnamelth) (void) strlcpy(NAME(mtmp2), NAME(mtmp), mtmp2->mnamelth); initedog(mtmp2); replmon(mtmp,mtmp2); return(1); }
void makedog() { struct monst *mtmp = makemon(&li_dog,u.ux,u.uy); if(!mtmp) return; /* dogs were genocided */ initedog(mtmp); }
/* * This function is only called from newgame, so we know: * - pets aren't genocided so makemon will always work * - the petname has not been used yet * This is called very late in the newgame sequence, and so can safely clobber * the charstats RNGs. */ struct monst * makedog(struct newgame_options *ngo) { struct monst *mtmp; struct obj *otmp; const char *petname; int pettype; if (ngo->preferred_pet == 'n') return NULL; pettype = pet_type(ngo); if (pettype == PM_LITTLE_DOG) petname = ngo->dogname; else if (pettype == PM_PONY) petname = ngo->horsename; else petname = ngo->catname; /* default pet names */ if (!*petname && pettype == PM_LITTLE_DOG) { /* All of these names were for dogs. */ if (Role_if(PM_CAVEMAN)) petname = "Slasher"; /* The Warrior */ if (Role_if(PM_SAMURAI)) petname = "Hachi"; /* Shibuya Station */ if (Role_if(PM_BARBARIAN)) petname = "Idefix"; /* Obelix */ if (Role_if(PM_RANGER)) petname = "Sirius"; /* Orion's dog */ } /* ideally we'd use rng_charstats_role for this, but... */ mtmp = makemon(&mons[pettype], level, u.ux, u.uy, MM_EDOG); /* Horses already wear a saddle */ if (pettype == PM_PONY && ((otmp = mksobj(level, SADDLE, TRUE, FALSE, rng_charstats_role)))) { if (mpickobj(mtmp, otmp)) panic("merged saddle?"); mtmp->misc_worn_check |= W_MASK(os_saddle); otmp->dknown = otmp->bknown = otmp->rknown = 1; otmp->owornmask = W_MASK(os_saddle); otmp->leashmon = mtmp->m_id; update_mon_intrinsics(mtmp, otmp, TRUE, TRUE); } if (*petname) mtmp = christen_monst(mtmp, petname); initedog(mtmp); return mtmp; }
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; }
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; }
/* this function is only called from newgame, so we know: * - pets aren't genocided so makemon will always work * - the petname has not been used yet */ struct monst *makedog(void) { struct monst *mtmp; struct obj *otmp; const char *petname; int pettype; if (preferred_pet == 'n') return NULL; pettype = pet_type(); if (pettype == PM_LITTLE_DOG) petname = dogname; else if (pettype == PM_PONY) petname = horsename; else if (pettype == PM_MONKEY) petname = monkeyname; else if (pettype == PM_WOLF || pettype == PM_WINTER_WOLF_CUB) petname = wolfname; else if (pettype == PM_BABY_CROCODILE) petname = crocname; else if (pettype == PM_SEWER_RAT) petname = ratname; else petname = catname; /* default pet names */ if (!*petname) { if (pettype == PM_LITTLE_DOG) { /* All of these names were for dogs. */ if (Role_if(PM_CAVEMAN)) petname = "Slasher"; /* The Warrior */ if (Role_if(PM_SAMURAI)) petname = "Hachi"; /* Shibuya Station */ if (Role_if(PM_BARBARIAN)) petname = "Idefix"; /* Obelix */ if (Role_if(PM_RANGER)) petname = "Sirius"; /* Orion's dog */ } else if (pettype == PM_SEWER_RAT) { if (Role_if(PM_CONVICT)) petname = "Nicodemus"; /* Rats of NIMH */ } } mtmp = makemon(&mons[pettype], level, u.ux, u.uy, MM_EDOG); /* Keep the exotic pets from being higher-level than normal starting * pets. (makedog is only called once, during game setup, so this * is the place to put it.) */ if (pettype == PM_WOLF || pettype == PM_WINTER_WOLF_CUB || pettype == PM_MONKEY || pettype == PM_BABY_CROCODILE) { mtmp->m_lev = 1; mtmp->mhpmax = mtmp->mhp = dice(1,8); } /* Horses already wear a saddle */ if (pettype == PM_PONY && !!(otmp = mksobj(level, SADDLE, TRUE, FALSE))) { if (mpickobj(mtmp, otmp)) panic("merged saddle?"); mtmp->misc_worn_check |= W_SADDLE; otmp->dknown = otmp->bknown = otmp->rknown = 1; otmp->owornmask = W_SADDLE; otmp->leashmon = mtmp->m_id; update_mon_intrinsics(level, mtmp, otmp, TRUE, TRUE); } if (!*petname && pettype == PM_KITTEN && !rn2(100)) { if (mtmp->female) petname = "Shiva"; /* PM: RIP 1 Oct 1998 - 6 Sep 2009 */ else petname = "Kali"; /* PM: RIP 1 May 2000 - 22 Oct 2012 */ } if (*petname) mtmp = christen_monst(mtmp, petname); initedog(mtmp); return mtmp; }