Blindfold removal fix
[slashemextended.git] / src / dog.c
blobb6f9ddff20897d03b0448fd47dda33d4f4a8bee8
1 /* SCCS Id: @(#)dog.c 3.4 2002/09/08 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
6 #include "edog.h"
7 #include "emin.h"
8 #include "epri.h"
10 #ifdef OVLB
12 STATIC_DCL int pet_type(void);
14 void
15 initedog(mtmp)
16 register struct monst *mtmp;
18 mtmp->mtame = is_domestic(mtmp->data) ? 10 : 5;
19 mtmp->wastame = 1; /* this should stay even if the monster later becomes untamed */
20 mtmp->mpeaceful = 1;
21 mtmp->mavenge = 0;
22 set_malign(mtmp); /* recalc alignment now that it's tamed */
23 mtmp->mleashed = 0;
24 mtmp->meating = 0;
25 EDOG(mtmp)->droptime = 0;
26 EDOG(mtmp)->dropdist = 10000;
27 EDOG(mtmp)->apport = 10;
28 EDOG(mtmp)->whistletime = 0;
29 EDOG(mtmp)->hungrytime = 1000 + monstermoves;
30 if (PetstarveEffect || u.uprops[PETSTARVE_EFFECT].extrinsic || have_petstarvestone()) {
31 EDOG(mtmp)->hungrytime = 50 + monstermoves;
33 EDOG(mtmp)->ogoal.x = -1; /* force error if used before set */
34 EDOG(mtmp)->ogoal.y = -1;
35 EDOG(mtmp)->abuse = 0;
36 EDOG(mtmp)->revivals = 0;
37 EDOG(mtmp)->mhpmax_penalty = 0;
38 EDOG(mtmp)->abouttostarve = 0;
39 EDOG(mtmp)->killed_by_u = 0;
41 /* if the pet has a weapon, we want it to wield, not drop it! --Amy */
42 if (mtmp->mtame && attacktype(mtmp->data, AT_WEAP)) {
43 mtmp->weapon_check = NEED_HTH_WEAPON;
44 (void) mon_wield_item(mtmp);
48 /* do the player's missiles, beams etc. pass through a pet instead of hitting it? --Amy
49 * meant to depend on the player's petkeeping skill; control magic in/extrinsic affects it too */
50 boolean
51 control_magic_works()
54 /* petkeeping skill - only if it's turned on (which it is by default, can change via #monster) */
55 if (!PlayerCannotUseSkills && u.controlmiguc) {
56 int contmagchance = 0;
57 switch (P_SKILL(P_PETKEEPING)) {
58 case P_BASIC: contmagchance = 10; break;
59 case P_SKILLED: contmagchance = 20; break;
60 case P_EXPERT: contmagchance = 30; break;
61 case P_MASTER: contmagchance = 40; break;
62 case P_GRAND_MASTER: contmagchance = 50; break;
63 case P_SUPREME_MASTER: contmagchance = 60; break;
64 default: break;
67 if (rn2(100) < contmagchance) return TRUE;
70 /* control magic trinsic cannot be "turned off"; if it annoys you, have to unequip the item or use a gremlin */
71 if (ControlMagic && rn2(5)) return TRUE;
72 if (StrongControlMagic && rn2(5)) return TRUE;
74 return FALSE; /* catchall */
77 STATIC_OVL int
78 pet_type()
80 if (urole.petnum != NON_PM)
81 return (urole.petnum);
82 else if (Role_if(PM_PIRATE))
83 return (rn2(2) ? PM_AIRBORNE_PARROT : PM_MONKEY);
84 else if (Role_if(PM_GOFF))
85 return (rn2(2) ? PM_NINJA_BOY : PM_NINJA_GIRL);
86 else if (Role_if(PM_KORSAIR))
87 switch (rnd(5)) {
88 case 1: return (PM_LITTLE_DOG);
89 case 2: return (PM_KITTEN);
90 case 3: return (PM_SEWER_RAT);
91 case 4: return (PM_MONKEY);
92 case 5: return (PM_BABY_CROCODILE);
94 else if (Role_if(PM_LUNATIC))
95 switch (rnd(7)) {
96 case 1: return (PM_WOLF);
97 case 2: return (PM_JACKAL);
98 case 3: return (PM_SEWER_RAT);
99 case 4: return (PM_PANTHER);
100 case 5: return (PM_TIGER);
101 case 6: return (PM_VIPER);
102 case 7: return (PM_GIANT_SPIDER);
104 else if (Role_if(PM_CHEVALIER))
105 switch (rnd(11)) {
106 case 1: return (PM_BABY_YELLOW_DRAGON);
107 case 2: return (PM_BABY_GREEN_DRAGON);
108 case 3: return (PM_BABY_BLUE_DRAGON);
109 case 4: return (PM_BABY_BLACK_DRAGON);
110 case 5: return (PM_BABY_ORANGE_DRAGON);
111 case 6: return (PM_BABY_WHITE_DRAGON);
112 case 7: return (PM_BABY_RED_DRAGON);
113 case 8: return (PM_BABY_DEEP_DRAGON);
114 case 9: return (PM_BABY_SHIMMERING_DRAGON);
115 case 10: return (PM_BABY_SILVER_DRAGON);
116 case 11: return (PM_BABY_GRAY_DRAGON);
118 else if (Role_if(PM_DRAGONMASTER))
119 switch (rnd(11)) {
120 case 1: return (PM_BABY_YELLOW_DRAGON);
121 case 2: return (PM_BABY_GREEN_DRAGON);
122 case 3: return (PM_BABY_BLUE_DRAGON);
123 case 4: return (PM_BABY_BLACK_DRAGON);
124 case 5: return (PM_BABY_ORANGE_DRAGON);
125 case 6: return (PM_BABY_WHITE_DRAGON);
126 case 7: return (PM_BABY_RED_DRAGON);
127 case 8: return (PM_BABY_DEEP_DRAGON);
128 case 9: return (PM_BABY_SHIMMERING_DRAGON);
129 case 10: return (PM_BABY_SILVER_DRAGON);
130 case 11: return (PM_BABY_GRAY_DRAGON);
132 else if (Role_if(PM_MEDIUM)) {
133 switch (u.ualign.type) {
134 case A_LAWFUL: return (PM_WHITE_UNICORN_FOAL);
135 case A_NEUTRAL: return (PM_GRAY_UNICORN_FOAL);
136 case A_CHAOTIC: return (PM_BLACK_UNICORN_FOAL);
137 default: return (PM_GRAY_UNICORN_FOAL);
140 else if (Role_if(PM_TRANSVESTITE) || Role_if(PM_TRANSSYLVANIAN) )
141 return ( !rn2(5) ? PM_ASIAN_GIRL : !rn2(10) ? PM_ESTRELLA_GIRL : rn2(2) ? PM_LITTLE_GIRL : PM_LITTLE_BOY);
142 else if (Role_if(PM_TOPMODEL))
143 switch (rnd(3)) {
144 case 1: return (PM_DARK_GIRL);
145 case 2: return (PM_REDGUARD_GIRL);
146 case 3: return (PM_THIEVING_GIRL);
148 else if (Role_if(PM_FAILED_EXISTENCE))
149 switch (rnd(3)) {
150 case 1: return (PM_DARK_GIRL);
151 case 2: return (PM_REDGUARD_GIRL);
152 case 3: return (PM_THIEVING_GIRL);
154 else if (Role_if(PM_LADIESMAN))
155 switch (rnd(3)) {
156 case 1: return (PM_DARK_GIRL);
157 case 2: return (PM_REDGUARD_GIRL);
158 case 3: return (PM_THIEVING_GIRL);
160 else if (Role_if(PM_PRACTICANT))
161 switch (rnd(2)) {
162 case 1: return (PM_OXYGEN_GOLEM);
163 case 2: return (PM_SULFUR_GOLEM);
165 else if (preferred_pet == 'c')
166 return (PM_KITTEN);
167 else if (preferred_pet == 'd')
168 return (PM_LITTLE_DOG);
169 else
170 return (rn2(2) ? PM_KITTEN : PM_LITTLE_DOG);
172 /* the compiler doesn't want this last return to be only in the else block...
173 * we shouldn't have a valueless return here, but better safe than sorry --Amy */
174 return (rn2(2) ? PM_KITTEN : PM_LITTLE_DOG);
177 struct monst *
178 make_familiar(otmp,x,y,quietly,startpet)
179 register struct obj *otmp;
180 xchar x, y;
181 boolean quietly;
182 int startpet; /* 0 = maybe, 1 = always, 2 = never */
184 struct permonst *pm;
185 struct monst *mtmp = 0;
186 int chance, trycnt = 100;
188 do {
189 if (otmp) { /* figurine; otherwise spell */
190 int mndx = otmp->corpsenm;
191 pm = &mons[mndx];
192 /* activating a figurine provides one way to exceed the
193 maximum number of the target critter created--unless
194 it has a special limit (erinys, Nazgul) */
195 if ((mvitals[mndx].mvflags & G_EXTINCT) &&
196 mbirth_limit(mndx) != MAXMONNO) {
197 if (!quietly)
198 /* have just been given "You <do something with>
199 the figurine and it transforms." message */
200 pline(FunnyHallu ? "... into a pile of garbage. Even you know that that's of no use." : "... into a pile of dust.");
201 break; /* mtmp is null */
203 } else if ((startpet == 1) || (!rn2(3) && !startpet) ) {
204 pm = &mons[pet_type()];
205 } else {
206 pm = rndmonst();
207 if (!pm) {
208 if (!quietly)
209 There("seems to be nothing available for a familiar.");
210 break;
214 mtmp = makemon(pm, x, y, MM_EDOG|MM_IGNOREWATER|MM_NOSPECIALS);
215 if (otmp && !mtmp) { /* monster was genocided or square occupied */
216 if (!quietly)
217 pline_The("figurine writhes and then shatters into pieces!");
218 break;
220 } while (!mtmp && --trycnt > 0);
222 if (!mtmp) return (struct monst *)0;
224 if ((is_waterypool(mtmp->mx, mtmp->my) || is_watertunnel(mtmp->mx, mtmp->my)) && minliquid(mtmp))
225 return (struct monst *)0;
227 initedog(mtmp);
228 mtmp->msleeping = 0;
229 if (otmp) { /* figurine; resulting monster might not become a pet */
230 chance = rn2(5); /* 0==tame, 1==peaceful, 2==hostile */
231 if (chance > 2) chance = otmp->blessed ? 0 : !otmp->cursed ? 1 : 2;
232 if ((rnd(30 - ACURR(A_CHA))) < 4) chance = 0;
233 if (otmp && otmp->oartifact == ART_GUARANTEED_SPECIAL_PET) chance = 0;
234 if (otmp && otmp->oartifact == ART_HOSTILITAWN) chance = 2;
235 if (otmp && otmp->oartifact == ART_NEUTRALNESS_NEUTERED) chance = 1;
236 /* 0,1,2: b=60%,20,20; nc=20%,60,20; c=20%,20,60 */
237 if (chance > 0) {
238 mtmp->mtame = 0; /* not tame after all */
239 if (chance == 2) { /* hostile (cursed figurine) */
240 if (!quietly)
241 You(FunnyHallu ? "shiver." : "get a bad feeling about this.");
242 mtmp->mpeaceful = 0;
243 set_malign(mtmp);
246 /* if figurine has been named, give same name to the monster */
247 if (otmp->onamelth)
248 mtmp = christen_monst(mtmp, ONAME(otmp));
250 set_malign(mtmp); /* more alignment changes */
251 newsym(mtmp->mx, mtmp->my);
253 if (mtmp && mtmp->mtame && FunnyHallu) verbalize("wassup fam");
255 /* must wield weapon immediately since pets will otherwise drop it */
256 if (mtmp->mtame && attacktype(mtmp->data, AT_WEAP)) {
257 mtmp->weapon_check = NEED_HTH_WEAPON;
258 (void) mon_wield_item(mtmp);
260 return mtmp;
264 struct monst *
265 make_helper(mnum,x,y)
266 int mnum;
267 xchar x, y;
269 struct permonst *pm;
270 struct monst *mtmp = 0;
271 int trycnt = 100;
273 do {
274 pm = &mons[mnum];
276 pm->pxlth += sizeof (struct edog);
277 mtmp = makemon(pm, x, y, NO_MINVENT|MM_NOSPECIALS);
278 pm->pxlth -= sizeof (struct edog);
279 } while (!mtmp && --trycnt > 0);
281 if(!mtmp) return((struct monst *) 0); /* genocided */
283 initedog(mtmp);
284 mtmp->msleeping = 0;
285 set_malign(mtmp); /* more alignment changes */
286 newsym(mtmp->mx, mtmp->my);
288 /* must wield weapon immediately since pets will otherwise drop it */
289 if (mtmp->mtame && attacktype(mtmp->data, AT_WEAP)) {
290 mtmp->weapon_check = NEED_HTH_WEAPON;
291 (void) mon_wield_item(mtmp);
293 return (mtmp);
297 struct monst *
298 makedog()
300 register struct monst *mtmp;
301 register struct obj *otmp;
302 register const char *petname;
303 int pettype, petsym;
304 static int petname_used = 0;
306 /* some roles should be forced to start with a pet because they get a detrimental one :P keyword "newroles" --Amy */
307 if (!Role_if(PM_KURWA) && !Role_if(PM_SHOE_FETISHIST) && !Role_if(PM_JANITOR) && !Role_if(PM_YAUTJA) && !Role_if(PM_GRENADONIN) && !Role_if(PM_PSYKER) && !Role_if(PM_MILL_SWALLOWER) && !Role_if(PM_CHAOS_SORCEROR) && (preferred_pet == 'n')) return((struct monst *) 0);
309 /* Gang scholars are supposed to start without a pet. However, every once in a blue moon they do get one --Amy */
310 if (Role_if(PM_GANG_SCHOLAR) && rn2(100)) return((struct monst *) 0);
312 pettype = pet_type();
314 /* In Soviet Russia, people don't like exotic pets. Even interesting ones like Green-elves or animated wedge sandals they despise for some reason, and want them to be "normalized" into being dogs or cats. Of course, for other races there's no such communist normalization, so they will get their actual pets. --Amy */
315 if (issoviet) pettype = rn2(2) ? PM_LITTLE_DOG : PM_KITTEN;
317 petsym = mons[pettype].mlet;
318 if (pettype == PM_WINTER_WOLF_CUB || pettype == PM_WOLF)
319 petname = wolfname;
320 else if (petsym == S_ZOMBIE)
321 petname = ghoulname;
322 else if (pettype == PM_PONY || pettype == PM_GREEN_NIGHTMARE || pettype == PM_DARK_NIGHTMARE || pettype == PM_SPEEDHORSE)
323 petname = horsename;
324 else if (pettype == PM_SEWER_RAT)
325 petname = ratname;
326 #if 0
327 else if (petsym == S_BAT)
328 petname = batname;
329 else if (petsym == S_SNAKE)
330 petname = snakename;
331 else if (petsym == S_RODENT)
332 petname = ratname;
333 else if (pettype == PM_GIANT_BADGER)
334 petname = badgername;
335 else if (pettype == PM_BABY_RED_DRAGON)
336 petname = reddragonname;
337 else if (pettype == PM_BABY_WHITE_DRAGON)
338 petname = whitedragonname;
339 #endif
340 else if (petsym == S_DOG)
341 petname = dogname;
342 else if (petsym == S_DRAGON)
343 petname = dragonname;
344 else if (pettype == PM_MONKEY)
345 petname = monkeyname;
346 else if (pettype == PM_AIRBORNE_PARROT || pettype == PM_PARROT)
347 petname = parrotname;
348 else if (pettype == PM_BLOCK_HEELED_GIRL || pettype == PM_KICKBOXING_GIRL || pettype == PM_NINJA_GIRL || pettype == PM_GOODWIFE || pettype == PM_DANCING_GIRL || pettype == PM_LITTLE_GIRL || pettype == PM_ASIAN_GIRL || pettype == PM_ESTRELLA_GIRL || pettype == PM_DARK_GIRL || pettype == PM_REDGUARD_GIRL || pettype == PM_THIEVING_GIRL || pettype == PM_SEXY_GIRL)
349 petname = girlname;
350 else if (pettype == PM_NINJA_BOY || pettype == PM_LITTLE_BOY)
351 petname = boyname;
352 else if (pettype == PM_RAVEN)
353 petname = ravenname;
354 else if (petsym == S_FELINE)
355 petname = catname;
356 else
357 goto maeney;
359 /* default pet names */
360 if (!*petname && pettype == PM_LITTLE_DOG) {
361 /* All of these names were for dogs. */
362 if(Role_if(PM_CAVEMAN)) petname = "Slasher"; /* The Warrior */
363 if(Role_if(PM_SAMURAI)) petname = "Hachi"; /* Shibuya Station */
364 if(Role_if(PM_BARBARIAN)) petname = "Idefix"; /* Obelix */
365 if(Role_if(PM_RANGER)) petname = "Sirius"; /* Orion's dog */
367 if (!*petname && pettype == PM_SEWER_RAT) {
368 if(Role_if(PM_CONVICT)) petname = "Nicodemus"; /* Rats of NIMH */
370 if (!*petname) {
371 maeney:
372 if (pettype == PM_MONKEY) petname = "Ugga-Ugga";
373 if (pettype == PM_AIRBORNE_PARROT) petname = "Squawks";
374 if (pettype == PM_SPEEDHORSE) petname = "Harley Davidson";
375 if (pettype == PM_BABY_CROCODILE) petname = "Snappy"; /* in Germany it would be called Schnappi */
376 if (pettype == PM_EEVEE) petname = "HUSI";
377 if (pettype == PM_WHITE_UNICORN_FOAL) petname = "Rastafari"; /* creature of peace */
378 if (pettype == PM_GRAY_UNICORN_FOAL) petname = "Balance of Neutrality";
379 if (pettype == PM_BLACK_UNICORN_FOAL) petname = "Orderly Chaos";
381 if (pettype == PM_ROGUE_HIRELING) petname = "Aliza";
383 if (pettype == PM_SESSILICHEN) petname = "Sessilium";
384 if (pettype == PM_PILE_OF_COPPER_COINS) petname = "Counterfeit";
385 if (pettype == PM_BLOCK_HEELED_GIRL) petname = "Dora";
387 if (pettype == PM_GRIMER) petname = "BADEB";
388 if (pettype == PM_DARK_NIGHTMARE) petname = "Opel Manta";
389 if (pettype == PM_SUPERSCHOOL_SPEAKER) petname = "Walt";
390 if (pettype == PM_BRAIN_EATING_GHOUL) petname = "Barnotis";
391 if (pettype == PM_BRAIN_GOLEM) petname = "Roald Amundsen";
393 if (pettype == PM_ARVOGENIC_TOPMODEL) petname = "Cara";
395 if (pettype == PM_VENOM_FUNGUS) petname = "This Is A BioHazard";
396 if (pettype == PM_MARTTI_IHRASAARI) petname = "Martti Ihrasaari";
397 if (pettype == PM_ELIF) petname = "Elif";
398 if (pettype == PM_JENNIFER) petname = "Jennifer";
399 if (pettype == PM_JESSICA) petname = "Jessica";
401 if (pettype == PM_BUST_SUPERSECRET_ADVICE_RIFLING_UNVERIFIED_BOSOMING) petname = "Boris";
402 if (pettype == PM_KATI_S_STRIPED_SNEAKER) petname = "Sweet Kati";
404 if (pettype == PM_KICKBOXING_GIRL) petname = "Marija";
406 if (pettype == PM_NINJA_BOY) petname = "Cornelia Fuck"; /* My Immortal fanfic */
407 if (pettype == PM_NINJA_GIRL) petname = "Doris Rumbridge";
409 if (pettype == PM_DRAGONBALL_KID) petname = "Android Nr. 17"; /* don't know the real name, but it was something like this --Amy */
411 if (pettype == PM_GREEN_ELF) petname = "Dray Harp";
412 if (pettype == PM_BARD) petname = "Michael Jackson";
413 if (pettype == PM_DROW) petname = "Roflth"; /* Lolth */
414 if (pettype == PM_OFFICER) petname = "Officer O'Brian";
415 if (pettype == PM_SOLDIER) petname = "Lieutenant Surge"; /* Pokemon Yellow */
416 if (pettype == PM_VALKYRIE) petname = "Rue"; /* hunger games */
417 if (pettype == PM_PLATYPUS) petname = "Donald Duck";
418 if (pettype == PM_OFFICER_JENNY) petname = "Jenny";
419 if (pettype == PM_FEMALE_SAMURAI) petname = "Miss Grenade";
420 if (pettype == PM_ORDINATOR) petname = "Andragil";
421 if (pettype == PM_ROTHE) petname = "Rambo";
422 if (pettype == PM_GEEK) petname = "Tacitus";
423 if (pettype == PM_SOFTWARE_BUG) petname = "Signal 11";
424 if (pettype == PM_ROOMBA) petname = "Asshole Vacuum Cleaner";
425 if (pettype == PM_CUNTGUN_TROOPER) petname = "Sergeant McShithead";
426 if (pettype == PM_DRATINI) petname = "DRAGO";
427 if (pettype == PM_ROBOT) petname = "Meliha";
428 if (pettype == PM_MISTER_HEAD) petname = "Mister Head";
429 if (pettype == PM_QUADRENNIAL_SODDEN_RATCHET) petname = "Randomized Script Monster";
430 if (pettype == PM_NURSE) petname = "Klara";
431 if (pettype == PM_ELVEN_MAGE) petname = "Keytu Framer";
432 if (pettype == PM_SCHINDA) petname = "Tragic Past On Crack";
433 if (pettype == PM_UFO) petname = "Flying Saucer";
434 if (pettype == PM_DENRYU) petname = "Ryu Hayabusa";
435 if (pettype == PM_CHRISTINE) petname = "Christine";
436 if (pettype == PM_BIRSEN) petname = "Birsen";
437 if (pettype == PM_ISABEL) petname = "Isabel";
438 if (pettype == PM_EROTICLOUDY) petname = "Claudia";
440 if (pettype == PM_FLOATING_EYE) petname = "Gazing Beholder Orb";
442 if (pettype == PM_GOODWIFE) petname = "Patchouli Knowledge";
444 if (pettype == PM_EVASIVE_SNIPER) petname = "Tingsi Major";
446 if (pettype == PM_PRIEST) petname = "Septimus";
448 if (pettype == PM_HUMAN_THIEF) petname = "Wiesbek the Thief"; /* dunno where I originally got that name from --Amy */
450 if (pettype == PM_VAMPIRE) petname = "Cheater";
452 if (pettype == PM_RAVEN) petname = "Nevermore";
454 if (pettype == PM_ANTIMATTER_VORTEX) petname = "Expensive Special Effect";
456 if (pettype == PM_DARK_GRUE) petname = "ZORK!";
457 if (pettype == PM_FRY) petname = "Perry";
459 if (pettype == PM_CLEFAIRY) petname = "Thief Pokemon";
460 if (pettype == PM_CHAMELEON) petname = "The RNG";
461 if (pettype == PM_CHAOS_POLYMORPHER) petname = "Mr. X";
463 if (pettype == PM_PANTHER) petname = "Tomcat Karlo";
464 if (pettype == PM_TIGER) petname = "Simba";
465 if (pettype == PM_VIPER) petname = "Lukas";
466 if (pettype == PM_GIANT_SPIDER) petname = "Andreas";
467 if (pettype == PM_ZUBAT) petname = "Cliff Racer"; /* Morrowind */
468 if (pettype == PM_DANCING_GIRL) petname = "Thaedil"; /* Oblivion, Shivering Esles */
469 if (pettype == PM_THALMOR) petname = "Rulindil"; /* Skyrim */
470 if (pettype == PM_CRUEL_ABUSER) petname = "Ms. Robinson"; /* 50 Shades of Fucked Up */
472 if (pettype == PM_ANIMATED_WEDGE_SANDAL) petname = "Larissa"; /* just a common female first name */
473 if (pettype == PM_GOLD_GOLEM) petname = "Midas"; /* the greedy king who unfortunately lost all his gold :( */
475 if (pettype == PM_JEDI) petname = "Luke Skywalker";
476 if (pettype == PM_SLAVE) petname = "Gob"; /* Fallout 3 */
478 if (pettype == PM_LITTLE_GIRL) petname = "Sarah"; /* just a common female first name */
479 if (pettype == PM_LITTLE_BOY) petname = "Jonas"; /* just a common male first name */
480 if (pettype == PM_ASIAN_GIRL) petname = "Whitney"; /* the Normal-type gym leader in Pokemon Crystal */
481 if (pettype == PM_ESTRELLA_GIRL) petname = "Estrella"; /* uncommon female first name */
483 if (pettype == PM_DARK_GIRL) petname = "Everella"; /* taken from a fanfic */
484 if (pettype == PM_REDGUARD_GIRL) petname = "Jasajeen"; /* taken from a fanfic */
485 if (pettype == PM_THIEVING_GIRL) petname = "Esruth"; /* taken from a fanfic */
487 if (pettype == PM_SEXY_GIRL) petname = "Natalje";
489 if (pettype == PM_FLYING_BLOODFISH) petname = "Kiri";
490 if (pettype == PM_OXYGEN_GOLEM) petname = "Scheele";
491 if (pettype == PM_SULFUR_GOLEM) petname = "Lavoisier";
492 if (pettype == PM_EMERA) petname = "Doctor Faust";
493 if (pettype == PM_TASMANIAN_DEVIL) petname = "Taz";
494 if (pettype == PM_SPIKE_MOLD) petname = "Improv";
495 if (pettype == PM_GENDERSTARIST) petname = "Bariwun";
496 if (pettype == PM_PEGASUS) petname = "Pegasus";
498 if (pettype == PM_ACTIVISTOR) petname = "Helen"; /* yet another common first name */
500 if (pettype == PM_BABY_YELLOW_DRAGON || pettype == PM_BABY_GREEN_DRAGON || pettype == PM_BABY_BLUE_DRAGON || pettype == PM_BABY_RED_DRAGON || pettype == PM_BABY_ORANGE_DRAGON || pettype == PM_BABY_WHITE_DRAGON || pettype == PM_BABY_BLACK_DRAGON || pettype == PM_BABY_DEEP_DRAGON || pettype == PM_BABY_SHIMMERING_DRAGON || pettype == PM_BABY_GRAY_DRAGON || pettype == PM_BABY_SILVER_DRAGON) petname = "Odahviing";
503 if (petname && !(strcmpi(petname, "Glorious Dead") ) ) petname = "Cheating Bastard";
504 if (petname && !(strcmpi(petname, "Satan's Secret Storage") ) ) petname = "Cheating Bastard";
505 if (petname && !(strcmpi(petname, "Main Container") ) ) petname = "Cheating Bastard";
506 if (petname && !(strcmpi(petname, "Arti Lockbox") ) ) petname = "Cheating Bastard";
507 if (petname && !(strcmpi(petname, "Hoards of Treasure") ) ) petname = "Cheating Bastard";
508 if (petname && !(strcmpi(petname, "Emergency Cash") ) ) petname = "Cheating Bastard";
509 if (petname && !(strcmpi(petname, "Whoa-Acid") ) ) petname = "Cheating Bastard";
510 if (petname && !(strcmpi(petname, "Burnup") ) ) petname = "Cheating Bastard";
511 if (petname && !(strcmpi(petname, "Somnus Mortus") ) ) petname = "Cheating Bastard";
512 if (petname && !(strcmpi(petname, "Ylva Blimp") ) ) petname = "Cheating Bastard";
513 if (petname && !(strcmpi(petname, "Veryfirm") ) ) petname = "Cheating Bastard";
514 if (petname && !(strcmpi(petname, "Goodshock") ) ) petname = "Cheating Bastard";
515 if (petname && !(strcmpi(petname, "Emergency Assistance") ) ) petname = "Cheating Bastard";
516 if (petname && !(strcmpi(petname, "Nymphism") ) ) petname = "Cheating Bastard";
517 if (petname && !(strcmpi(petname, "Tengu Shuffle") ) ) petname = "Cheating Bastard";
518 if (petname && !(strcmpi(petname, "Eyes Everywhere") ) ) petname = "Cheating Bastard";
519 if (petname && !(strcmpi(petname, "Radar Up!") ) ) petname = "Cheating Bastard";
520 if (petname && !(strcmpi(petname, "Let's Go On A Hunt") ) ) petname = "Cheating Bastard";
521 if (petname && !(strcmpi(petname, "Stalk-me") ) ) petname = "Cheating Bastard";
522 if (petname && !(strcmpi(petname, "found it.") ) ) petname = "Cheating Bastard";
523 if (petname && !(strcmpi(petname, "Lying Novel Cerium") ) ) petname = "Cheating Bastard";
524 if (petname && !(strcmpi(petname, "Not Gonna Die") ) ) petname = "Cheating Bastard";
525 if (petname && !(strcmpi(petname, "Mysteriumtart") ) ) petname = "Cheating Bastard";
526 if (petname && !(strcmpi(petname, "Feel The Living") ) ) petname = "Cheating Bastard";
527 if (petname && !(strcmpi(petname, "Dueueueueueuei") ) ) petname = "Cheating Bastard";
528 if (petname && !(strcmpi(petname, "Oh, well...") ) ) petname = "Cheating Bastard";
529 if (petname && !(strcmpi(petname, "You Badass Enough?") ) ) petname = "Cheating Bastard";
530 if (petname && !(strcmpi(petname, "Ice Snack") ) ) petname = "Cheating Bastard";
531 if (petname && !(strcmpi(petname, "Redeye") ) ) petname = "Cheating Bastard";
532 if (petname && !(strcmpi(petname, "Luke's Little Snack") ) ) petname = "Cheating Bastard";
533 if (petname && !(strcmpi(petname, "Mindbonuses For You") ) ) petname = "Cheating Bastard";
534 if (petname && !(strcmpi(petname, "Nose-Up") ) ) petname = "Cheating Bastard";
535 if (petname && !(strcmpi(petname, "Blue-blue-blue...") ) ) petname = "Cheating Bastard";
536 if (petname && !(strcmpi(petname, "The 'u' command") ) ) petname = "Cheating Bastard";
537 if (petname && !(strcmpi(petname, "MFer") ) ) petname = "Cheating Bastard";
538 if (petname && !(strcmpi(petname, "Wizardlunch") ) ) petname = "Cheating Bastard";
540 mtmp = makemon(&mons[pettype], u.ux, u.uy, MM_EDOG);
542 if(!mtmp) return((struct monst *) 0); /* pets were genocided */
544 /* Horses already wear a saddle */
545 if ((pettype == PM_PONY || pettype == PM_PEGASUS || pettype == PM_GREEN_NIGHTMARE || pettype == PM_SPEEDHORSE) && !!(otmp = mksobj(Race_if(PM_INKA) ? INKA_SADDLE : LEATHER_SADDLE, TRUE, FALSE, FALSE))) {
546 if (mpickobj(mtmp, otmp, TRUE)) {
547 /*impossible("merged saddle?")*/
548 ; /* do nothing; unlike vanilla, this is something that can happen --Amy */
549 } else {
550 mtmp->misc_worn_check |= W_SADDLE;
551 otmp->dknown = otmp->bknown = otmp->rknown = 1;
552 otmp->owornmask = W_SADDLE;
553 otmp->leashmon = mtmp->m_id;
554 update_mon_intrinsics(mtmp, otmp, TRUE, TRUE);
558 if (!petname_used++ && *petname)
559 mtmp = christen_monst(mtmp, petname);
561 initedog(mtmp);
562 return(mtmp);
565 /* record `last move time' for all monsters prior to level save so that
566 mon_arrive() can catch up for lost time when they're restored later */
567 void
568 update_mlstmv()
570 struct monst *mon;
572 /* monst->mlstmv used to be updated every time `monst' actually moved,
573 but that is no longer the case so we just do a blanket assignment */
574 for (mon = fmon; mon; mon = mon->nmon)
575 if (!DEADMONSTER(mon)) mon->mlstmv = monstermoves;
578 void
579 losedogs()
581 register struct monst *mtmp, *mtmp0 = 0, *mtmp2;
583 while ((mtmp = mydogs) != 0) {
584 mydogs = mtmp->nmon;
585 mon_arrive(mtmp, TRUE);
588 for(mtmp = migrating_mons; mtmp; mtmp = mtmp2) {
589 mtmp2 = mtmp->nmon;
590 if (mtmp->mux == u.uz.dnum && mtmp->muy == u.uz.dlevel) {
591 if(mtmp == migrating_mons)
592 migrating_mons = mtmp->nmon;
593 else
594 mtmp0->nmon = mtmp->nmon;
595 mon_arrive(mtmp, FALSE);
596 } else
597 mtmp0 = mtmp;
601 /* called from resurrect() in addition to losedogs() */
602 void
603 mon_arrive(mtmp, with_you)
604 struct monst *mtmp;
605 boolean with_you;
607 struct trap *t;
608 xchar xlocale, ylocale, xyloc, xyflags, wander;
609 int num_segs;
611 mtmp->nmon = fmon;
612 fmon = mtmp;
613 if (mtmp->isshk)
614 set_residency(mtmp, FALSE);
616 num_segs = mtmp->wormno;
617 /* baby long worms have no tail so don't use is_longworm() */
618 if ((mtmp->data == &mons[PM_LONG_WORM]) &&
619 #ifdef DCC30_BUG
620 (mtmp->wormno = get_wormno(), mtmp->wormno != 0))
621 #else
622 (mtmp->wormno = get_wormno()) != 0)
623 #endif
625 initworm(mtmp, num_segs);
626 /* tail segs are not yet initialized or displayed */
627 } else mtmp->wormno = 0;
629 /* some monsters might need to do something special upon arrival
630 _after_ the current level has been fully set up; see dochug() */
631 mtmp->mstrategy |= STRAT_ARRIVE;
633 /* make sure mnexto(rloc_to(set_apparxy())) doesn't use stale data */
634 mtmp->mux = u.ux, mtmp->muy = u.uy;
635 xyloc = mtmp->mtrack[0].x;
636 xyflags = mtmp->mtrack[0].y;
637 xlocale = mtmp->mtrack[1].x;
638 ylocale = mtmp->mtrack[1].y;
639 mtmp->mtrack[0].x = mtmp->mtrack[0].y = 0;
640 mtmp->mtrack[1].x = mtmp->mtrack[1].y = 0;
642 if (mtmp == u.usteed)
643 return; /* don't place steed on the map */
644 if (with_you) {
645 /* When a monster accompanies you, sometimes it will arrive
646 at your intended destination and you'll end up next to
647 that spot. This code doesn't control the final outcome;
648 goto_level(do.c) decides who ends up at your target spot
649 when there is a monster there too. */
650 if (!MON_AT(u.ux, u.uy) &&
651 !rn2(mtmp->mtame ? 10 : mtmp->mpeaceful ? 5 : 2))
652 rloc_to(mtmp, u.ux, u.uy);
653 else
654 mnexto(mtmp);
655 return;
658 * The monster arrived on this level independently of the player.
659 * Its coordinate fields were overloaded for use as flags that
660 * specify its final destination.
663 if (mtmp->mlstmv < monstermoves - 1L) {
664 /* heal monster for time spent in limbo */
665 long nmv = monstermoves - 1L - mtmp->mlstmv;
667 mon_catchup_elapsed_time(mtmp, nmv);
668 mtmp->mlstmv = monstermoves - 1L;
670 /* let monster move a bit on new level (see placement code below) */
671 wander = (xchar) min(nmv, 8);
672 } else
673 wander = 0;
675 switch (xyloc) {
676 case MIGR_APPROX_XY: /* {x,y}locale set above */
677 break;
678 case MIGR_EXACT_XY: wander = 0;
679 break;
680 case MIGR_NEAR_PLAYER: xlocale = u.ux, ylocale = u.uy;
681 break;
682 case MIGR_STAIRS_UP: xlocale = xupstair, ylocale = yupstair;
683 break;
684 case MIGR_STAIRS_DOWN: xlocale = xdnstair, ylocale = ydnstair;
685 break;
686 case MIGR_LADDER_UP: xlocale = xupladder, ylocale = yupladder;
687 break;
688 case MIGR_LADDER_DOWN: xlocale = xdnladder, ylocale = ydnladder;
689 break;
690 case MIGR_SSTAIRS: xlocale = sstairs.sx, ylocale = sstairs.sy;
691 break;
692 case MIGR_PORTAL:
693 if (In_endgame(&u.uz)) {
694 /* there is no arrival portal for endgame levels */
695 /* BUG[?]: for simplicity, this code relies on the fact
696 that we know that the current endgame levels always
697 build upwards and never have any exclusion subregion
698 inside their TELEPORT_REGION settings. */
699 xlocale = rn1(updest.hx - updest.lx + 1, updest.lx);
700 ylocale = rn1(updest.hy - updest.ly + 1, updest.ly);
701 break;
703 /* find the arrival portal */
704 for (t = ftrap; t; t = t->ntrap)
705 if (t->ttyp == MAGIC_PORTAL) break;
706 if (t) {
707 xlocale = t->tx, ylocale = t->ty;
708 break;
709 } else impossible("mon_arrive: no corresponding portal?");
710 /*FALLTHRU*/
711 default:
712 case MIGR_RANDOM: xlocale = ylocale = 0;
713 break;
716 if (xlocale && wander) {
717 /* monster moved a bit; pick a nearby location */
718 /* mnearto() deals w/stone, et al */
719 char *r = in_rooms(xlocale, ylocale, 0);
720 if (r && *r) {
721 coord c;
722 /* somexy() handles irregular rooms */
723 if (somexy(&rooms[*r - ROOMOFFSET], &c))
724 xlocale = c.x, ylocale = c.y;
725 else
726 xlocale = ylocale = 0;
727 } else { /* not in a room */
728 int i, j;
729 i = max(1, xlocale - wander);
730 j = min(COLNO-1, xlocale + wander);
731 xlocale = rn1(j - i, i);
732 i = max(0, ylocale - wander);
733 j = min(ROWNO-1, ylocale + wander);
734 ylocale = rn1(j - i, i);
736 } /* moved a bit */
738 mtmp->mx = 0; /*(already is 0)*/
739 mtmp->my = xyflags;
740 if (xlocale)
741 (void) mnearto(mtmp, xlocale, ylocale, FALSE);
742 else {
743 if (!rloc(mtmp,TRUE)) {
745 * Failed to place migrating monster,
746 * probably because the level is full.
747 * Dump the monster's cargo and leave the monster dead.
749 struct obj *obj, *corpse;
750 while ((obj = mtmp->minvent) != 0) {
751 obj_extract_self(obj);
752 obj_no_longer_held(obj);
753 if (obj->owornmask & W_WEP)
754 setmnotwielded(mtmp,obj);
755 obj->owornmask = 0L;
756 if (xlocale && ylocale)
757 place_object(obj, xlocale, ylocale);
758 else {
759 rloco(obj);
760 get_obj_location(obj, &xlocale, &ylocale, 0);
763 corpse = mkcorpstat(CORPSE, (struct monst *)0, mtmp->data,
764 xlocale, ylocale, FALSE);
765 #ifndef GOLDOBJ
766 if (mtmp->mgold) {
767 if (xlocale == 0 && ylocale == 0 && corpse) {
768 (void) get_obj_location(corpse, &xlocale, &ylocale, 0);
769 (void) mkgold(mtmp->mgold, xlocale, ylocale);
771 mtmp->mgold = 0L;
773 #endif
774 mongone(mtmp);
779 /* heal monster for time spent elsewhere */
780 void
781 mon_catchup_elapsed_time(mtmp, nmv)
782 struct monst *mtmp;
784 long nmv; /* number of moves */
786 struct edog *edog = EDOG(mtmp);
788 int imv = 0; /* avoid zillions of casts and lint warnings */
790 #if defined(DEBUG) || defined(BETA)
791 if (nmv < 0L) { /* crash likely... */
792 panic("catchup from future time?");
793 /*NOTREACHED*/
794 return;
795 } else if (nmv == 0L) { /* safe, but should'nt happen */
796 impossible("catchup from now?");
797 } else
798 #endif
799 if (nmv >= LARGEST_INT) /* paranoia */
800 imv = LARGEST_INT - 1;
801 else
802 imv = (int)nmv;
804 /* might stop being afraid, blind or frozen */
805 /* set to 1 and allow final decrement in movemon() */
806 if (mtmp->mblinded) {
807 if (imv >= (int) mtmp->mblinded) mtmp->mblinded = 1;
808 else mtmp->mblinded -= imv;
810 if (mtmp->mfrozen) {
811 if (imv >= (int) mtmp->mfrozen) mtmp->mfrozen = 1;
812 else mtmp->mfrozen -= imv;
814 if (mtmp->mfleetim) {
815 if (imv >= (int) mtmp->mfleetim) mtmp->mfleetim = 1;
816 else mtmp->mfleetim -= imv;
819 /* might recover from temporary trouble */
820 if (mtmp->mtrapped && rn2(imv + 1) > 40/2) mtmp->mtrapped = 0;
821 if (mtmp->mconf && rn2(imv + 1) > 50/2) mtmp->mconf = 0;
822 if (mtmp->mstun && rn2(imv + 1) > 10/2) mtmp->mstun = 0;
824 /* might finish eating or be able to use special ability again */
825 if (imv > mtmp->meating) mtmp->meating = 0;
826 else mtmp->meating -= imv;
827 if (imv > mtmp->mspec_used) mtmp->mspec_used = 0;
828 else mtmp->mspec_used -= imv;
830 /* might have been charging a homing lazer */
831 if (mtmp->hominglazer) {
832 mtmp->hominglazer += imv;
833 if (mtmp->hominglazer > 200) mtmp->hominglazer = 0;
838 * M1_MINDLESS __
839 * M2_UNDEAD |
840 * M2_WERE |-- These types will go ferral
841 * M2_DEMON |
842 * M1_ANIMAL --
845 if ((is_animal(mtmp->data) || mindless(mtmp->data) ||
846 is_demon(mtmp->data) || is_undead(mtmp->data) || mtmp->egotype_undead ||
847 is_were(mtmp->data)) && mtmp->mtame && (issoviet || ((monstermoves + 5000) > edog->hungrytime)) ) {
848 /* reduce tameness for every
849 * 150 moves you are away
850 Amy -- edit so that well-satiated pets can be on another level for much longer */
851 /* In Soviet Russia, dogs HATE it if their owners are gone for more than a measly few minutes. They will
852 * assume that their holders are dead, and not recognize them anymore. No matter how well-fed they were.
853 * I'm not sure if my improvements were in SLASHTHEM, but probably not, because if they were, I'd bet actual
854 * money on Soviet reverting it "because the Amy made this change so it must be teh suxx0rz!!!!!111" --Amy */
855 /*struct edog *edog = EDOG(mtmp);*/
857 if (mtmp->mtame > (nmv / (issoviet ? 150 : 1000))) /* increased by Amy */
858 mtmp->mtame -= (nmv / (issoviet ? 150 : 1000));
859 else mtmp->mtame = 0;
861 /* check to see if it would have died as a pet; if so, go wild instead
862 * of dying the next time we call dog_move()
864 if (mtmp->mtame && !mtmp->isminion &&
865 (carnivorous(mtmp->data) || herbivorous(mtmp->data) || metallivorous(mtmp->data) || lithivorous(mtmp->data) || mtmp->egotype_lithivore || mtmp->egotype_metallivore || mtmp->egotype_allivore )) {
867 if ((monstermoves > edog->hungrytime + 500 && mtmp->mhp < 3) ||
868 (monstermoves > edog->hungrytime + 750)) {
870 /* let's make a pet with high tameness resistant to becoming hostile. Give them a chance to be peaceful instead. */
871 if (mtmp->mtame >= 1 && rn2(2) && rn2(mtmp->mtame) )
872 mtmp->mtame = 0;
873 else mtmp->mtame = mtmp->mpeaceful = 0;
878 if (!mtmp->mtame && mtmp->mleashed) {
879 /* leashed monsters should always be with hero, consequently
880 never losing any time to be accounted for later */
881 impossible("catching up for leashed monster?");
882 m_unleash(mtmp, FALSE);
885 if (mtmp->healblock || mtmp->bleedout) goto healingdone;
887 /* recover lost hit points */
888 /* note by Amy: see mon_regen() in monmove.c too and keep that updated! */
890 if (!regenerates(mtmp->data) && (!mtmp->egotype_regeneration) ) imv /= (ishaxor ? 10 : 20);
891 if (mtmp->mhp + imv >= mtmp->mhpmax)
892 mtmp->mhp = mtmp->mhpmax;
893 else mtmp->mhp += imv;
895 if (uwep && uwep->oartifact == ART_MUNZUR_S_CLUBMATE) {
896 if (mtmp->mhp + 1 >= mtmp->mhpmax)
897 mtmp->mhp = mtmp->mhpmax;
898 else mtmp->mhp++;
901 /* recover more depending on charisma --Amy */
902 if ((rnd(30 - ACURR(A_CHA))) < 4) {
903 if (mtmp->mhp + 1 >= mtmp->mhpmax)
904 mtmp->mhp = mtmp->mhpmax;
905 else mtmp->mhp++;
908 if (powerfulimplants() && uimplant && uimplant->oartifact == ART_READY_FOR_A_RIDE && u.usteed && (mtmp == u.usteed)) {
909 if (mtmp->mhp + 1 >= mtmp->mhpmax)
910 mtmp->mhp = mtmp->mhpmax;
911 else mtmp->mhp++;
914 if (u.usteed && mtmp == u.usteed) {
916 if (bmwride(ART_CURE_HASSIA_COURSE)) {
917 if (mtmp->mhp + 1 >= mtmp->mhpmax)
918 mtmp->mhp = mtmp->mhpmax;
919 else mtmp->mhp++;
921 if (bmwride(ART_DRESSING_EM)) {
922 if (mtmp->mhp + 1 >= mtmp->mhpmax)
923 mtmp->mhp = mtmp->mhpmax;
924 else mtmp->mhp++;
928 /* good riding skill gives extra regeneration to ridden monster --Amy */
930 if (!(PlayerCannotUseSkills)) {
932 if (P_SKILL(P_RIDING) == P_BASIC && u.usteed && (mtmp == u.usteed) && !rn2(10) ) {
933 if (powerfulimplants() && uimplant && uimplant->oartifact == ART_READY_FOR_A_RIDE) {
934 if (mtmp->mhp + 1 >= mtmp->mhpmax)
935 mtmp->mhp = mtmp->mhpmax;
936 else mtmp->mhp++;
939 if (P_SKILL(P_RIDING) == P_SKILLED && u.usteed && (mtmp == u.usteed) && !rn2(10) ) {
940 if (mtmp->mhp + 1 >= mtmp->mhpmax)
941 mtmp->mhp = mtmp->mhpmax;
942 else mtmp->mhp++;
943 if (powerfulimplants() && uimplant && uimplant->oartifact == ART_READY_FOR_A_RIDE) {
944 if (mtmp->mhp + 2 >= mtmp->mhpmax)
945 mtmp->mhp = mtmp->mhpmax;
946 else mtmp->mhp++;
949 if (P_SKILL(P_RIDING) == P_EXPERT && u.usteed && (mtmp == u.usteed) && !rn2(5) ) {
950 if (mtmp->mhp + 1 >= mtmp->mhpmax)
951 mtmp->mhp = mtmp->mhpmax;
952 else mtmp->mhp++;
953 if (powerfulimplants() && uimplant && uimplant->oartifact == ART_READY_FOR_A_RIDE) {
954 if (mtmp->mhp + 3 >= mtmp->mhpmax)
955 mtmp->mhp = mtmp->mhpmax;
956 else mtmp->mhp++;
959 if (P_SKILL(P_RIDING) == P_MASTER && u.usteed && (mtmp == u.usteed) && !rn2(3) ) {
960 if (mtmp->mhp + 1 >= mtmp->mhpmax)
961 mtmp->mhp = mtmp->mhpmax;
962 else mtmp->mhp++;
963 if (powerfulimplants() && uimplant && uimplant->oartifact == ART_READY_FOR_A_RIDE) {
964 if (mtmp->mhp + 4 >= mtmp->mhpmax)
965 mtmp->mhp = mtmp->mhpmax;
966 else mtmp->mhp++;
969 if (P_SKILL(P_RIDING) == P_GRAND_MASTER && u.usteed && (mtmp == u.usteed) ) {
970 if (mtmp->mhp + 1 >= mtmp->mhpmax)
971 mtmp->mhp = mtmp->mhpmax;
972 else mtmp->mhp++;
973 if (powerfulimplants() && uimplant && uimplant->oartifact == ART_READY_FOR_A_RIDE) {
974 if (mtmp->mhp + 5 >= mtmp->mhpmax)
975 mtmp->mhp = mtmp->mhpmax;
976 else mtmp->mhp++;
980 if (P_SKILL(P_RIDING) == P_SUPREME_MASTER && u.usteed && (mtmp == u.usteed) ) {
981 if (mtmp->mhp + 1 >= mtmp->mhpmax)
982 mtmp->mhp = mtmp->mhpmax;
983 else mtmp->mhp++;
984 if (powerfulimplants() && uimplant && uimplant->oartifact == ART_READY_FOR_A_RIDE) {
985 if (mtmp->mhp + 6 >= mtmp->mhpmax)
986 mtmp->mhp = mtmp->mhpmax;
987 else mtmp->mhp++;
991 healingdone:
996 #endif /* OVLB */
997 #ifdef OVL2
999 /* called when you move to another level */
1000 void
1001 keepdogs(pets_only)
1002 boolean pets_only; /* true for ascension or final escape */
1004 register struct monst *mtmp, *mtmp2;
1005 register struct obj *obj;
1006 int num_segs;
1007 boolean stay_behind;
1008 extern d_level new_dlevel; /* in do.c */
1009 int extraradius = 0;
1010 char qbuf[QBUFSZ];
1011 boolean qbufdefined = 0; /* fail safe */
1013 if (!(PlayerCannotUseSkills)) {
1014 switch (P_SKILL(P_PETKEEPING)) {
1015 default: break;
1016 case P_BASIC: extraradius = 4; break;
1017 case P_SKILLED: extraradius = 8; break;
1018 case P_EXPERT: extraradius = 12; break;
1019 case P_MASTER: extraradius = 16; break;
1020 case P_GRAND_MASTER: extraradius = 20; break;
1021 case P_SUPREME_MASTER: extraradius = 25; break;
1025 if (uarmu && uarmu->oartifact == ART_HEEEEELEEEEEN) extraradius = 999999;
1027 for (mtmp = fmon; mtmp; mtmp = mtmp2) {
1028 mtmp2 = mtmp->nmon;
1029 if (DEADMONSTER(mtmp)) continue;
1030 if (pets_only && !mtmp->mtame) continue;
1031 if (u.freeplaytransit && !mtmp->mtame) continue;
1033 if (mtmp && !program_state.gameover && !u.freeplaytransit && isok(u.ux, u.uy) && extraradius && mtmp->mtame && levl_follower(mtmp) && (distu(mtmp->mx, mtmp->my) < (4 + extraradius))) {
1034 sprintf(qbuf, "You can take %s (%s) with you. Do it?", noit_mon_nam(mtmp), Hallucination ? "sparkly dood" : sanityrandomname() ? rndmonnam() : mtmp->data->mname);
1035 qbufdefined = 1;
1038 if (((monnear(mtmp, u.ux, u.uy) && levl_follower(mtmp))
1040 /* come on, if you ascend then all tame monsters should ascend with you. --Amy */
1041 || (mtmp->mtame && u.freeplaytransit)
1043 || (mtmp && !(program_state.gameover) && qbufdefined && isok(u.ux, u.uy) && extraradius && mtmp->mtame && levl_follower(mtmp) && (distu(mtmp->mx, mtmp->my) < (4 + extraradius)) && (yn(qbuf) == 'y') ) ||
1044 (mtmp == u.usteed) ||
1045 /* the wiz will level t-port from anywhere to chase
1046 the amulet; if you don't have it, will chase you
1047 only if in range. -3. */
1048 (u.uhave.amulet && mtmp->iswiz))
1049 && ((!mtmp->msleeping && mtmp->mcanmove)
1050 /* eg if level teleport or new trap, steed has no control
1051 to avoid following */
1052 || (mtmp == u.usteed)
1054 /* monster won't follow if it hasn't noticed you yet */
1055 && !(mtmp->mstrategy & STRAT_WAITFORU)) {
1056 stay_behind = FALSE;
1057 if (mtmp->mtame && mtmp->meating) {
1058 if (canseemon(mtmp))
1059 pline("%s is still eating.", Monnam(mtmp));
1060 stay_behind = TRUE;
1061 /* there's a bug where escaping or ascending makes the game think you're going to the black market... --Amy */
1062 } else if (mtmp->mtame && !u.freeplaytransit && !program_state.gameover &&
1063 (Is_blackmarket(&new_dlevel) || Is_blackmarket(&u.uz))) {
1064 pline("%s can't follow you %s.",
1065 Monnam(mtmp), Is_blackmarket(&u.uz) ?
1066 "through the portal" : "into the Black Market");
1067 stay_behind = TRUE;
1068 } else if (mon_has_amulet(mtmp)) {
1069 if (canseemon(mtmp))
1070 pline("%s seems very disoriented for a moment.",
1071 Monnam(mtmp));
1072 stay_behind = TRUE;
1073 } else if (mtmp->mtame && mtmp->mtrapped) {
1074 if (canseemon(mtmp))
1075 pline("%s is still trapped.", Monnam(mtmp));
1076 stay_behind = TRUE;
1078 if (mtmp == u.usteed) stay_behind = FALSE;
1079 if (stay_behind) {
1080 if (mtmp->mleashed) {
1081 pline("%s leash suddenly comes loose.",
1082 humanoid(mtmp->data)
1083 ? (mtmp->female ? "Her" : "His")
1084 : "Its");
1085 m_unleash(mtmp, FALSE);
1087 continue;
1089 if (mtmp->isshk)
1090 set_residency(mtmp, TRUE);
1092 if (mtmp->wormno) {
1093 register int cnt;
1094 /* NOTE: worm is truncated to # segs = max wormno size */
1095 cnt = count_wsegs(mtmp);
1096 num_segs = min(cnt, MAX_NUM_WORMS - 1);
1097 wormgone(mtmp);
1098 } else num_segs = 0;
1100 /* set minvent's obj->no_charge to 0 */
1101 for(obj = mtmp->minvent; obj; obj = obj->nobj) {
1102 if (Has_contents(obj))
1103 picked_container(obj); /* does the right thing */
1104 obj->no_charge = 0;
1107 relmon(mtmp);
1108 newsym(mtmp->mx,mtmp->my);
1109 mtmp->mx = mtmp->my = 0; /* avoid mnexto()/MON_AT() problem */
1110 mtmp->wormno = num_segs;
1111 mtmp->mlstmv = monstermoves;
1112 mtmp->nmon = mydogs;
1113 mydogs = mtmp;
1114 } else if (mtmp->iswiz) {
1115 /* we want to be able to find him when his next resurrection
1116 chance comes up, but have him resume his present location
1117 if player returns to this level before that time */
1118 migrate_to_level(mtmp, ledger_no(&u.uz),
1119 MIGR_EXACT_XY, (coord *)0);
1120 } else if (mtmp->mleashed) {
1121 /* this can happen if your quest leader ejects you from the
1122 "home" level while a leashed pet isn't next to you */
1123 pline("%s leash goes slack.", s_suffix(Monnam(mtmp)));
1124 m_unleash(mtmp, FALSE);
1129 #endif /* OVL2 */
1130 #ifdef OVLB
1132 void
1133 migrate_to_level(mtmp, tolev, xyloc, cc)
1134 register struct monst *mtmp;
1135 xchar tolev; /* destination level */
1136 xchar xyloc; /* MIGR_xxx destination xy location: */
1137 coord *cc; /* optional destination coordinates */
1139 register struct obj *obj;
1140 d_level new_lev;
1141 xchar xyflags;
1142 int num_segs = 0; /* count of worm segments */
1144 if (mtmp->isshk)
1145 set_residency(mtmp, TRUE);
1147 if (mtmp->wormno) {
1148 register int cnt;
1149 /* **** NOTE: worm is truncated to # segs = max wormno size **** */
1150 cnt = count_wsegs(mtmp);
1151 num_segs = min(cnt, MAX_NUM_WORMS - 1);
1152 wormgone(mtmp);
1155 /* set minvent's obj->no_charge to 0 */
1156 for(obj = mtmp->minvent; obj; obj = obj->nobj) {
1157 if (Has_contents(obj))
1158 picked_container(obj); /* does the right thing */
1159 obj->no_charge = 0;
1162 if (mtmp->mleashed) {
1163 mtmp->mtame--;
1164 m_unleash(mtmp, TRUE);
1166 relmon(mtmp);
1167 mtmp->nmon = migrating_mons;
1168 migrating_mons = mtmp;
1169 newsym(mtmp->mx,mtmp->my);
1171 new_lev.dnum = ledger_to_dnum((xchar)tolev);
1172 new_lev.dlevel = ledger_to_dlev((xchar)tolev);
1173 /* overload mtmp->[mx,my], mtmp->[mux,muy], and mtmp->mtrack[] as */
1174 /* destination codes (setup flag bits before altering mx or my) */
1175 xyflags = (depth(&new_lev) < depth(&u.uz)); /* 1 => up */
1176 if (In_W_tower(mtmp->mx, mtmp->my, &u.uz)) xyflags |= 2;
1177 mtmp->wormno = num_segs;
1178 mtmp->mlstmv = monstermoves;
1179 mtmp->mtrack[1].x = cc ? cc->x : mtmp->mx;
1180 mtmp->mtrack[1].y = cc ? cc->y : mtmp->my;
1181 mtmp->mtrack[0].x = xyloc;
1182 mtmp->mtrack[0].y = xyflags;
1183 mtmp->mux = new_lev.dnum;
1184 mtmp->muy = new_lev.dlevel;
1185 mtmp->mx = mtmp->my = 0; /* this implies migration */
1188 /* function that makes your pet more hungry, e.g. because it got hit by a famine attack */
1189 void
1190 makedoghungry(mon, amount)
1191 struct monst *mon;
1192 int amount;
1194 if (!mon->mtame) return;
1196 struct edog *edog = EDOG(mon);
1198 if (edog && edog->hungrytime > 1) {
1199 edog->hungrytime -= amount;
1200 if (edog->hungrytime < 1) edog->hungrytime = 1;
1205 #endif /* OVLB */
1206 #ifdef OVL1
1208 /* return quality of food; the lower the better */
1209 /* fungi will eat even tainted food */
1211 dogfood(mon,obj)
1212 struct monst *mon;
1213 register struct obj *obj;
1215 boolean carni = carnivorous(mon->data);
1216 boolean herbi = (herbivorous(mon->data) || mon->egotype_petty);
1217 struct permonst *fptr = &mons[obj->corpsenm];
1218 boolean starving;
1219 struct monst *potentialpet;
1221 if (is_quest_artifact(obj) || obj_resists(obj, 0, 95))
1222 return (obj->cursed ? TABU : APPORT);
1224 /* KMH -- Koalas can only eat eucalyptus */
1225 if (mon->data == &mons[PM_KOALA])
1226 return (obj->otyp == EUCALYPTUS_LEAF ? DOGFOOD : APPORT);
1227 if (mon->data == &mons[PM_GIANT_KOALA])
1228 return (obj->otyp == EUCALYPTUS_LEAF ? DOGFOOD : APPORT);
1229 if (mon->data->msound == MS_SHOE && Race_if(PM_SHOE) && obj->oclass == FOOD_CLASS) return DOGFOOD;
1231 switch(obj->oclass) {
1232 case FOOD_CLASS:
1233 if (obj->otyp == CORPSE &&
1234 ((touch_petrifies(&mons[obj->corpsenm]) && !resists_ston(mon)) ||
1235 ((((potentialpet = get_mtraits(obj, FALSE)) != (struct monst *)0) ) && !issoviet && potentialpet->mtame)
1236 || is_rider(fptr) || (!issoviet && (fptr->cnutrit < 1)) || is_deadlysin(fptr) || fptr->mlet == S_TROVE )) /* troves are meant for the player --Amy */
1237 return TABU;
1238 /* Ghouls only eat old corpses... yum! */
1239 if (saprovorous(mon->data)) {
1240 return (obj->otyp == CORPSE && !acidic(&mons[obj->corpsenm]) &&
1241 peek_at_iced_corpse_age(obj) + 5*rn1(20,10) <= monstermoves) ?
1242 DOGFOOD : TABU;
1244 /* vampires only "eat" very fresh corpses ...
1245 * Assume meat -> blood
1247 if (is_vampire(mon->data)) {
1248 return (obj->otyp == CORPSE &&
1249 has_blood(&mons[obj->corpsenm]) && !obj->oeaten && !obj->odrained &&
1250 peek_at_iced_corpse_age(obj) + 5 >= monstermoves) ?
1251 DOGFOOD : TABU;
1254 if (!carni && !herbi)
1255 return (obj->cursed ? UNDEF : APPORT);
1257 /* a starving pet will eat almost anything */
1258 starving = (mon->mtame && !mon->isminion &&
1259 EDOG(mon)->mhpmax_penalty);
1261 switch (obj->otyp) {
1262 case TRIPE_RATION:
1263 case MEATBALL:
1264 case MEAT_RING:
1265 case MEAT_STICK:
1266 case HUGE_CHUNK_OF_MEAT:
1267 return (carni ? DOGFOOD : MANFOOD);
1268 case EGG:
1269 if (touch_petrifies(&mons[obj->corpsenm]) && obj->corpsenm != PM_PLAYERMON && !resists_ston(mon))
1270 return POISON;
1271 return (carni ? CADAVER : MANFOOD);
1272 case CORPSE:
1273 /* WAC add don't eat own class*/
1274 if (mons[obj->corpsenm].mlet == mon->data->mlet)
1275 return (starving && carni ? ACCFOOD : TABU);
1276 else
1277 if ((peek_at_iced_corpse_age(obj) + 50L <= monstermoves
1278 && !nocorpsedecay(&mons[obj->corpsenm])
1279 && mon->data->mlet != S_FUNGUS) ||
1280 (acidic(&mons[obj->corpsenm]) && !resists_acid(mon)) ||
1281 (poisonous(&mons[obj->corpsenm]) &&
1282 !resists_poison(mon)))
1283 return POISON;
1284 else if (vegan(fptr))
1285 return (herbi ? CADAVER : MANFOOD);
1286 else return (carni ? CADAVER : MANFOOD);
1287 case CLOVE_OF_GARLIC:
1288 return ( (is_undead(mon->data) || mon->egotype_undead) ? TABU :
1289 ((herbi || starving) ? ACCFOOD : MANFOOD));
1290 case TIN:
1291 return ( (metallivorous(mon->data) || mon->egotype_metallivore) ? ACCFOOD : MANFOOD);
1292 case APPLE:
1293 case CARROT:
1294 return (herbi ? DOGFOOD : starving ? ACCFOOD : MANFOOD);
1295 case BANANA:
1296 return ((mon->data->mlet == S_YETI) ? DOGFOOD :
1297 ((herbi || starving) ? ACCFOOD : MANFOOD));
1298 default:
1299 if (starving) return ACCFOOD;
1300 return (obj->otyp > SLIME_MOLD ?
1301 (carni ? ACCFOOD : MANFOOD) :
1302 (herbi ? ACCFOOD : MANFOOD));
1304 default:
1305 if (obj->otyp == AMULET_OF_STRANGULATION ||
1306 obj->otyp == RIN_SLOW_DIGESTION || obj->otyp == RIN_INDIGESTION)
1307 return TABU;
1308 if (hates_silver(mon->data) &&
1309 objects[obj->otyp].oc_material == MT_SILVER)
1310 return(TABU);
1311 if (hates_copper(mon->data) &&
1312 objects[obj->otyp].oc_material == MT_COPPER)
1313 return(TABU);
1314 if (hates_platinum(mon->data) &&
1315 objects[obj->otyp].oc_material == MT_PLATINUM)
1316 return(TABU);
1317 if (hates_cursed(mon->data) && obj->cursed)
1318 return(TABU);
1319 if (hates_viva(mon->data) &&
1320 objects[obj->otyp].oc_material == MT_VIVA)
1321 return(TABU);
1322 if (hates_inka(mon->data) &&
1323 objects[obj->otyp].oc_material == MT_INKA)
1324 return(TABU);
1325 /* KMH -- Taz likes organics, too! */
1326 if ((organivorous(mon->data) || mon->egotype_organivore) && is_organic(obj))
1327 return(ACCFOOD);
1328 if ( (metallivorous(mon->data) || mon->egotype_metallivore) && is_metallic(obj) ) {
1329 /* Non-rustproofed ferrous based metals are preferred. */
1330 return((is_rustprone(obj) && !obj->oerodeproof) ? DOGFOOD :
1331 ACCFOOD);
1334 if ( (lithivorous(mon->data) || mon->egotype_lithivore) && is_lithic(obj) ) return( DOGFOOD );
1336 /* Lithivores can eat any lithic object. They really like eating such items, too. */
1338 if(!obj->cursed && obj->oclass != BALL_CLASS &&
1339 obj->oclass != CHAIN_CLASS)
1340 return(APPORT);
1341 /* fall into next case */
1342 case ROCK_CLASS:
1343 if ( (lithivorous(mon->data) || mon->egotype_lithivore) && is_lithic(obj) ) return( DOGFOOD );
1344 return(UNDEF);
1348 #endif /* OVL1 */
1349 #ifdef OVLB
1351 struct monst *
1352 tamedog(mtmp, obj, guaranteed)
1353 register struct monst *mtmp;
1354 register struct obj *obj;
1355 boolean guaranteed;
1357 register struct monst *mtmp2;
1359 if (DEADMONSTER(mtmp)) return((struct monst *)0); /* fail safe */
1361 /* The Wiz, Medusa and the quest nemeses aren't even made peaceful. */
1362 if (mtmp->iswiz || mtmp->data == &mons[PM_MEDUSA]
1363 || (mtmp->data->mflags3 & M3_WANTSARTI))
1365 return((struct monst *)0);
1368 if (Aggravate_monster && !rn2(20) && !((rnd(30 - ACURR(A_CHA))) < 4) ) {
1369 if (mtmp->mpeaceful && !mtmp->mtame) {
1370 pline("%s is aggravated!", Monnam(mtmp));
1371 mtmp->mpeaceful = 0;
1372 } else if (!mtmp->mpeaceful && !mtmp->mtame) {
1373 pline("%s is frenzied!", Monnam(mtmp));
1374 mtmp->mfrenzied = 1;
1376 return((struct monst *)0);
1379 if (u.uprops[HATE_TRAP_EFFECT].extrinsic || HateTrapEffect || (uarms && uarms->oartifact == ART_REAL_PSYCHOS_WEAR_PURPLE) || (uarms && uarms->oartifact == ART_REAL_MEN_WEAR_PSYCHOS) || (uarmf && uarmf->oartifact == ART_TOO_MUCH_BRAVERY) || have_hatestone() || autismweaponcheck(ART_POST_OFFICE_COURSE) || (uarmf && uarmf->oartifact == ART_KATIE_MELUA_S_FLEECINESS) || Role_if(PM_GANG_SCHOLAR) ) {
1380 pline("%s hates you too much!", Monnam(mtmp));
1381 return((struct monst *)0);
1384 if (Role_if(PM_UNDEAD_SLAYER) && !mtmp->mtame && is_undead(mtmp->data)) {
1385 if (rn2(10)) {
1386 pline("You're an undead slayer, not an undead tamer! %s refuses to be tamed!", Monnam(mtmp));
1387 if (!rn2(10)) {
1388 mtmp->mtame = 0;
1389 mtmp->mpeaceful = 0;
1390 mtmp->mfrenzied = 1;
1391 pline("%s is very annoyed by your attempt, and enters a state of frenzy!", Monnam(mtmp));
1393 return((struct monst *)0);
1397 /* worst case, at least it'll be peaceful. */
1398 if (!mtmp->mfrenzied) {
1399 mtmp->mpeaceful = 1;
1400 mtmp->mtraitor = 0; /* No longer a traitor */
1402 if (mtmp->mfrenzied) {
1403 return((struct monst *)0);
1405 set_malign(mtmp);
1406 if(flags.moonphase == FULL_MOON && night() && rn2(6) && obj
1407 && mtmp->data->mlet == S_DOG)
1409 return((struct monst *)0);
1412 if ( (Role_if(PM_CONVICT) || Role_if(PM_MURDERER)) && (is_domestic(mtmp->data) && obj)) {
1413 /* Domestic animals are wary of the Convict */
1414 pline("%s still looks wary of you.", Monnam(mtmp));
1415 return((struct monst *)0);
1418 /* If we cannot tame it, at least it's no longer afraid. */
1419 mtmp->mflee = 0;
1420 mtmp->mfleetim = 0;
1422 /* make grabber let go now, whether it becomes tame or not */
1423 if (mtmp == u.ustuck) {
1424 if (u.uswallow)
1425 expels(mtmp, mtmp->data, TRUE);
1426 else if (!(Upolyd && sticks(youmonst.data)))
1427 unstuck(mtmp);
1430 /* feeding it treats makes it tamer */
1431 if (mtmp->mtame && obj) {
1432 int tasty;
1434 if (mtmp->mcanmove && (!mtmp->mconf || (EDOG(mtmp)->hungrytime <= monstermoves)) && !mtmp->meating &&
1435 ((tasty = dogfood(mtmp, obj)) == DOGFOOD ||
1436 (tasty <= ACCFOOD && EDOG(mtmp)->hungrytime <= monstermoves))) {
1437 /* pet will "catch" and eat this thrown food
1438 * Amy edit: since pets that are about to starve get confused, but they might have gotten very hungry due
1439 * to a hunger-inducing attack, they have to be able to catch the food anyway */
1440 if (canseemon(mtmp)) {
1441 boolean big_corpse = (obj->otyp == CORPSE &&
1442 obj->corpsenm >= LOW_PM &&
1443 mons[obj->corpsenm].msize > mtmp->data->msize);
1444 pline("%s catches %s%s",
1445 Monnam(mtmp), the(xname(obj)),
1446 !big_corpse ? "." : ", or vice versa!");
1447 } else if (cansee(mtmp->mx,mtmp->my))
1448 pline("%s.", Tobjnam(obj, "stop"));
1450 /* since there's no way to say sorry if you accidentally hit your pet, feeding has a similar effect --Amy */
1451 if (!rn2(5) && !mtmp->isminion && EDOG(mtmp)->abuse) EDOG(mtmp)->abuse--;
1453 /* dog_eat expects a floor object */
1454 place_object(obj, mtmp->mx, mtmp->my);
1455 (void) dog_eat(mtmp, obj, mtmp->mx, mtmp->my, FALSE);
1456 /* eating might have killed it, but that doesn't matter here;
1457 a non-null result suppresses "miss" message for thrown
1458 food and also implies that the object has been deleted */
1459 return mtmp;
1460 } else {
1462 if (!is_domestic(mtmp->data) && !is_petty(mtmp->data)) return (struct monst *)0;
1467 if (mtmp->mtame || !mtmp->mcanmove ||
1468 /* monsters with conflicting structures cannot be tamed */
1469 mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion ||
1470 /* KMH -- Added gypsy */
1471 mtmp->isgyp ||
1472 (is_covetous(mtmp->data) && (issoviet || rn2(50) ) ) || (is_human(mtmp->data) && (issoviet || rn2(4) ) ) ||
1473 (is_demon(mtmp->data) && !is_demon(youmonst.data) && !(uarmf && uarmf->oartifact == ART_AMPERSAND_HAREM) && !Race_if(PM_HUMANOID_DEVIL) && !Race_if(PM_GAVIL) && !(Race_if(PM_PLAYER_SHEEP) && u.ulevel >= 20) && (issoviet || rn2(10) ) ) ||
1474 /* Mik -- New flag to indicate which things cannot be tamed... */
1475 cannot_be_tamed(mtmp->data) || mtmp->mfrenzied ||
1476 (obj && dogfood(mtmp, obj) >= MANFOOD && !(Race_if(PM_CELTIC) && mtmp->data->mlet == S_GOLEM) )) {
1478 /* In Soviet Russia, people only know dogs, cats and maybe horses. Everything else cannot be tamed, and variety
1479 * is also something that absolutely no one likes. Communism means everyone gets the same, so you can't have an
1480 * exotic pet! If you do then you'll "vanish" silently, like all the other lawbreakers. --Amy */
1482 /* Attire charm technique and certain other methods set the guaranteed flag,
1483 * which allows players to tame humans and certain other monsters. --Amy */
1485 if (!is_domestic(mtmp->data) && !is_petty(mtmp->data) && !(guaranteed) )
1486 return (struct monst *)0;
1488 if (!(guaranteed) && obj && dogfood(mtmp, obj) >= MANFOOD)
1489 return (struct monst *)0;
1493 /* failsafe for things that REALLY cannot be tamed --Amy */
1494 if (cannot_be_tamed(mtmp->data) || (mtmp->cham == CHAM_ZRUTINATOR) || mtmp->mfrenzied || mtmp->mtame || mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion || mtmp->isgyp)
1495 return (struct monst *)0;
1497 if (mtmp->m_id == quest_status.leader_m_id)
1499 return((struct monst *)0);
1502 /* make a new monster which has the pet extension */
1503 mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
1504 *mtmp2 = *mtmp;
1505 mtmp2->mxlth = sizeof(struct edog);
1506 if (mtmp->mnamelth) strcpy(NAME(mtmp2), NAME(mtmp));
1507 initedog(mtmp2);
1508 replmon(mtmp, mtmp2);
1510 /* `mtmp' is now obsolete */
1512 /* high skill, especially coupled with high charisma, means they don't start with anemic health --Amy */
1513 if (!PlayerCannotUseSkills) {
1515 int minimumhealth = 0;
1517 switch (P_SKILL(P_PETKEEPING)) {
1518 default: break;
1519 case P_BASIC: minimumhealth = 10; break;
1520 case P_SKILLED: minimumhealth = 20; break;
1521 case P_EXPERT: minimumhealth = 30; break;
1522 case P_MASTER: minimumhealth = 50; break;
1523 case P_GRAND_MASTER: minimumhealth = 70; break;
1524 case P_SUPREME_MASTER: minimumhealth = 100; break;
1527 if (ACURR(A_CHA) > 9) {
1528 minimumhealth *= (100 + ( (ACURR(A_CHA) - 9) * 3) );
1529 minimumhealth /= 100;
1532 if (mtmp2->mhpmax < minimumhealth) {
1533 int hpdifference = (minimumhealth - mtmp2->mhpmax);
1534 mtmp2->mhpmax = minimumhealth;
1535 mtmp2->mhp += hpdifference;
1536 if (mtmp2->mhp > mtmp2->mhpmax) mtmp2->mhp = mtmp2->mhpmax;
1539 /* this can mean that a 5HP little dog is suddenly boosted to 100HP... but since you usually don't have grand master
1540 * petkeeping skill on dungeon level 2 with your XL3 char, this should still be balanced, and means that freshly
1541 * tamed pets in gehennom will no longer die immediately late into the game when ancient red dragons and everything * are roaming freely, although you still need good petkeeping and charisma for this boost --Amy */
1543 if (obj) { /* thrown food */
1544 /* defer eating until the edog extension has been set up */
1545 place_object(obj, mtmp2->mx, mtmp2->my); /* put on floor */
1546 /* devour the food (might grow into larger, genocided monster) */
1547 if (dog_eat(mtmp2, obj, mtmp2->mx, mtmp2->my, TRUE) == 2)
1548 return mtmp2; /* oops, it died... */
1549 /* `obj' is now obsolete */
1552 newsym(mtmp2->mx, mtmp2->my);
1553 if (attacktype(mtmp2->data, AT_WEAP)) {
1554 mtmp2->weapon_check = NEED_HTH_WEAPON;
1555 (void) mon_wield_item(mtmp2);
1557 return(mtmp2);
1560 int make_pet_minion(mnum,alignment)
1561 int mnum;
1562 aligntyp alignment;
1564 register struct monst *mon;
1565 register struct monst *mtmp2;
1566 mon = makemon(&mons[mnum], u.ux, u.uy, MM_NOSPECIALS);
1567 if (!mon) return 0;
1568 /* now tame that puppy... */
1569 mtmp2 = newmonst(sizeof(struct edog) + mon->mnamelth);
1570 *mtmp2 = *mon;
1571 mtmp2->mxlth = sizeof(struct edog);
1572 if(mon->mnamelth) strcpy(NAME(mtmp2), NAME(mon));
1573 initedog(mtmp2);
1574 replmon(mon,mtmp2);
1575 newsym(mtmp2->mx, mtmp2->my);
1576 mtmp2->mpeaceful = 1;
1577 set_malign(mtmp2);
1578 mtmp2->mtame = 10;
1579 /* this section names the creature "of ______" */
1580 if (mons[mnum].pxlth == 0) {
1581 mtmp2->isminion = TRUE;
1582 EMIN(mtmp2)->min_align = alignment;
1583 } else if (mnum == PM_ANGEL) {
1584 mtmp2->isminion = TRUE;
1585 EPRI(mtmp2)->shralign = alignment;
1587 return 1;
1591 * Called during pet revival or pet life-saving.
1592 * If you killed the pet, it revives wild.
1593 * If you abused the pet a lot while alive, it revives wild.
1594 * If you abused the pet at all while alive, it revives untame.
1595 * If the pet wasn't abused and was very tame, it might revive tame.
1597 void
1598 wary_dog(mtmp, was_dead)
1599 struct monst *mtmp;
1600 boolean was_dead;
1602 struct edog *edog;
1603 boolean quietly = was_dead;
1605 mtmp->meating = 0;
1606 if (!mtmp->mtame) return;
1607 edog = !mtmp->isminion ? EDOG(mtmp) : 0;
1609 /* if monster was starving when it died, undo that now */
1610 if (edog && edog->mhpmax_penalty) {
1611 mtmp->mhpmax += edog->mhpmax_penalty;
1612 mtmp->mhp += edog->mhpmax_penalty; /* heal it */
1613 edog->mhpmax_penalty = 0;
1615 if (edog && edog->abouttostarve) edog->abouttostarve = 0;
1617 if (edog && (edog->killed_by_u == 1 || edog->abuse > 2)) {
1618 mtmp->mpeaceful = mtmp->mtame = 0;
1619 if (edog->abuse >= 0 && edog->abuse < 10)
1620 if (!rn2(edog->abuse + 1) && !mtmp->mfrenzied) mtmp->mpeaceful = 1;
1621 if(!quietly && cansee(mtmp->mx, mtmp->my)) {
1622 if (haseyes(youmonst.data)) {
1623 if (haseyes(mtmp->data))
1624 pline("%s %s to look you in the %s.",
1625 Monnam(mtmp),
1626 mtmp->mpeaceful ? "seems unable" :
1627 "refuses",
1628 body_part(EYE));
1629 else
1630 pline("%s avoids your gaze.",
1631 Monnam(mtmp));
1634 } else {
1635 /* chance it goes wild anyway - Pet Semetary */
1636 if (!rn2(mtmp->mtame) && !((rnd(30 - ACURR(A_CHA))) < 4) ) {
1637 mtmp->mpeaceful = mtmp->mtame = 0;
1640 if (!mtmp->mtame) {
1641 newsym(mtmp->mx, mtmp->my);
1642 /* a life-saved monster might be leashed;
1643 don't leave it that way if it's no longer tame */
1644 if (mtmp->mleashed) m_unleash(mtmp, TRUE);
1647 /* if its still a pet, start a clean pet-slate now */
1648 if (edog && mtmp->mtame) {
1649 edog->revivals++;
1650 edog->killed_by_u = 0;
1651 edog->abuse = 0;
1652 edog->ogoal.x = edog->ogoal.y = -1;
1653 if (was_dead || edog->hungrytime < monstermoves + 500L) {
1654 edog->hungrytime = monstermoves + 500L;
1655 if (PetstarveEffect || u.uprops[PETSTARVE_EFFECT].extrinsic || have_petstarvestone()) {
1656 EDOG(mtmp)->hungrytime = monstermoves + 50L;
1659 if (was_dead) {
1660 edog->droptime = 0L;
1661 edog->dropdist = 10000;
1662 edog->whistletime = 0L;
1663 edog->apport = 5;
1664 } /* else lifesaved, so retain current values */
1668 boolean
1669 befriend_with_obj(ptr, obj)
1670 struct permonst *ptr;
1671 struct obj *obj;
1673 if (obj->oclass == FOOD_CLASS) {
1674 if (is_domestic(ptr)) return TRUE;
1675 if (Race_if(PM_HUMANLIKE_DRAGON) && ptr->mlet == S_DRAGON) return TRUE;
1676 if (Role_if(PM_DRAGONMASTER) && ptr->mlet == S_DRAGON) return TRUE;
1677 if (uarmc && uarmc->oartifact == ART_NAME_RESCUE && ptr->mlet == S_FELINE) return TRUE;
1678 if (is_animal(ptr) && Race_if(PM_HUMANOID_CENTAUR) && !((ptr)->geno & G_UNIQ)) return TRUE;
1679 if (is_rat(ptr) && Role_if(PM_CONVICT)) return TRUE;
1680 /* [Tom] Dorothy wants more pets... */
1681 if (obj->otyp == CHEESE && is_rat(ptr)) return TRUE;
1682 if (obj->otyp == ORANGE && (ptr) == &mons[PM_MANDARUCK]) return TRUE;
1683 if (ptr->msound == MS_SHOE && Race_if(PM_SHOE)) return TRUE;
1684 if (obj->otyp == KELP_FROND && (ptr->mflags3 & M3_PETTY)) return TRUE;
1685 if (obj->otyp == BANANA && herbivorous(ptr) && ptr->mlet == S_YETI) return TRUE;
1688 /* Amy edit: metallivores etc. should also be capable of being domestic */
1689 if (is_metallic(obj) && is_domestic(ptr) && metallivorous(ptr)) return TRUE;
1690 if (is_lithic(obj) && is_domestic(ptr) && lithivorous(ptr)) return TRUE;
1691 if (is_organic(obj) && is_domestic(ptr) && organivorous(ptr)) return TRUE;
1693 if (Race_if(PM_CELTIC) && is_metallic(obj) && ptr->mlet == S_GOLEM) return TRUE;
1695 return FALSE;
1698 void
1699 abuse_dog(mtmp)
1700 struct monst *mtmp;
1702 if (!mtmp->mtame) return;
1704 if (Aggravate_monster || Conflict) mtmp->mtame /=2;
1705 else mtmp->mtame--;
1707 if (mtmp->mtame && !mtmp->isminion && !(Role_if(PM_SLAVE_MASTER) && rn2(5)) )
1708 EDOG(mtmp)->abuse++;
1710 if (Role_if(PM_CRUEL_ABUSER)) {
1711 adjalign(5);
1712 pline(FunnyHallu ? "Let's whip that bitch some more!" : "You feel empowered."); /* Christian Grey likes to be needlessly cruel */
1715 if (!mtmp->mtame && mtmp->mleashed)
1716 m_unleash(mtmp, TRUE);
1718 /* don't make a sound if pet is in the middle of leaving the level */
1719 /* newsym isn't necessary in this case either */
1720 if (mtmp->mx != 0) {
1721 if (mtmp->mtame && rn2(mtmp->mtame)) yelp(mtmp);
1722 else growl(mtmp); /* give them a moment's worry */
1724 /* Give monster a chance to betray you now */
1725 if (mtmp->mtame) betrayed(mtmp);
1727 if (!mtmp->mtame) newsym(mtmp->mx, mtmp->my);
1731 #endif /* OVLB */
1733 /*dog.c*/