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. */
12 STATIC_DCL
int pet_type(void);
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 */
22 set_malign(mtmp
); /* recalc alignment now that it's tamed */
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 */
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;
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 */
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
))
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
))
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
))
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
))
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
))
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
))
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
))
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
))
162 case 1: return (PM_OXYGEN_GOLEM
);
163 case 2: return (PM_SULFUR_GOLEM
);
165 else if (preferred_pet
== 'c')
167 else if (preferred_pet
== 'd')
168 return (PM_LITTLE_DOG
);
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
);
178 make_familiar(otmp
,x
,y
,quietly
,startpet
)
179 register struct obj
*otmp
;
182 int startpet
; /* 0 = maybe, 1 = always, 2 = never */
185 struct monst
*mtmp
= 0;
186 int chance
, trycnt
= 100;
189 if (otmp
) { /* figurine; otherwise spell */
190 int mndx
= otmp
->corpsenm
;
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
) {
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()];
209 There("seems to be nothing available for a familiar.");
214 mtmp
= makemon(pm
, x
, y
, MM_EDOG
|MM_IGNOREWATER
|MM_NOSPECIALS
);
215 if (otmp
&& !mtmp
) { /* monster was genocided or square occupied */
217 pline_The("figurine writhes and then shatters into pieces!");
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;
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 */
238 mtmp
->mtame
= 0; /* not tame after all */
239 if (chance
== 2) { /* hostile (cursed figurine) */
241 You(FunnyHallu
? "shiver." : "get a bad feeling about this.");
246 /* if figurine has been named, give same name to the monster */
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
);
265 make_helper(mnum
,x
,y
)
270 struct monst
*mtmp
= 0;
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 */
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
);
300 register struct monst
*mtmp
;
301 register struct obj
*otmp
;
302 register const char *petname
;
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
)
320 else if (petsym
== S_ZOMBIE
)
322 else if (pettype
== PM_PONY
|| pettype
== PM_GREEN_NIGHTMARE
|| pettype
== PM_DARK_NIGHTMARE
|| pettype
== PM_SPEEDHORSE
)
324 else if (pettype
== PM_SEWER_RAT
)
327 else if (petsym
== S_BAT
)
329 else if (petsym
== S_SNAKE
)
331 else if (petsym
== S_RODENT
)
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
;
340 else if (petsym
== S_DOG
)
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
)
350 else if (pettype
== PM_NINJA_BOY
|| pettype
== PM_LITTLE_BOY
)
352 else if (pettype
== PM_RAVEN
)
354 else if (petsym
== S_FELINE
)
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 */
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 */
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
);
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 */
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
;
581 register struct monst
*mtmp
, *mtmp0
= 0, *mtmp2
;
583 while ((mtmp
= mydogs
) != 0) {
585 mon_arrive(mtmp
, TRUE
);
588 for(mtmp
= migrating_mons
; mtmp
; mtmp
= mtmp2
) {
590 if (mtmp
->mux
== u
.uz
.dnum
&& mtmp
->muy
== u
.uz
.dlevel
) {
591 if(mtmp
== migrating_mons
)
592 migrating_mons
= mtmp
->nmon
;
594 mtmp0
->nmon
= mtmp
->nmon
;
595 mon_arrive(mtmp
, FALSE
);
601 /* called from resurrect() in addition to losedogs() */
603 mon_arrive(mtmp
, with_you
)
608 xchar xlocale
, ylocale
, xyloc
, xyflags
, wander
;
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
]) &&
620 (mtmp
->wormno
= get_wormno(), mtmp
->wormno
!= 0))
622 (mtmp
->wormno
= get_wormno()) != 0)
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 */
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
);
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);
676 case MIGR_APPROX_XY
: /* {x,y}locale set above */
678 case MIGR_EXACT_XY
: wander
= 0;
680 case MIGR_NEAR_PLAYER
: xlocale
= u
.ux
, ylocale
= u
.uy
;
682 case MIGR_STAIRS_UP
: xlocale
= xupstair
, ylocale
= yupstair
;
684 case MIGR_STAIRS_DOWN
: xlocale
= xdnstair
, ylocale
= ydnstair
;
686 case MIGR_LADDER_UP
: xlocale
= xupladder
, ylocale
= yupladder
;
688 case MIGR_LADDER_DOWN
: xlocale
= xdnladder
, ylocale
= ydnladder
;
690 case MIGR_SSTAIRS
: xlocale
= sstairs
.sx
, ylocale
= sstairs
.sy
;
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
);
703 /* find the arrival portal */
704 for (t
= ftrap
; t
; t
= t
->ntrap
)
705 if (t
->ttyp
== MAGIC_PORTAL
) break;
707 xlocale
= t
->tx
, ylocale
= t
->ty
;
709 } else impossible("mon_arrive: no corresponding portal?");
712 case MIGR_RANDOM
: xlocale
= ylocale
= 0;
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);
722 /* somexy() handles irregular rooms */
723 if (somexy(&rooms
[*r
- ROOMOFFSET
], &c
))
724 xlocale
= c
.x
, ylocale
= c
.y
;
726 xlocale
= ylocale
= 0;
727 } else { /* not in a room */
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
);
738 mtmp
->mx
= 0; /*(already is 0)*/
741 (void) mnearto(mtmp
, xlocale
, ylocale
, FALSE
);
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
);
756 if (xlocale
&& ylocale
)
757 place_object(obj
, xlocale
, ylocale
);
760 get_obj_location(obj
, &xlocale
, &ylocale
, 0);
763 corpse
= mkcorpstat(CORPSE
, (struct monst
*)0, mtmp
->data
,
764 xlocale
, ylocale
, FALSE
);
767 if (xlocale
== 0 && ylocale
== 0 && corpse
) {
768 (void) get_obj_location(corpse
, &xlocale
, &ylocale
, 0);
769 (void) mkgold(mtmp
->mgold
, xlocale
, ylocale
);
779 /* heal monster for time spent elsewhere */
781 mon_catchup_elapsed_time(mtmp
, nmv
)
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?");
795 } else if (nmv
== 0L) { /* safe, but should'nt happen */
796 impossible("catchup from now?");
799 if (nmv
>= LARGEST_INT
) /* paranoia */
800 imv
= LARGEST_INT
- 1;
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
;
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;
840 * M2_WERE |-- These types will go ferral
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
) )
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
;
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
;
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
;
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
;
921 if (bmwride(ART_DRESSING_EM
)) {
922 if (mtmp
->mhp
+ 1 >= mtmp
->mhpmax
)
923 mtmp
->mhp
= mtmp
->mhpmax
;
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
;
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
;
943 if (powerfulimplants() && uimplant
&& uimplant
->oartifact
== ART_READY_FOR_A_RIDE
) {
944 if (mtmp
->mhp
+ 2 >= mtmp
->mhpmax
)
945 mtmp
->mhp
= mtmp
->mhpmax
;
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
;
953 if (powerfulimplants() && uimplant
&& uimplant
->oartifact
== ART_READY_FOR_A_RIDE
) {
954 if (mtmp
->mhp
+ 3 >= mtmp
->mhpmax
)
955 mtmp
->mhp
= mtmp
->mhpmax
;
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
;
963 if (powerfulimplants() && uimplant
&& uimplant
->oartifact
== ART_READY_FOR_A_RIDE
) {
964 if (mtmp
->mhp
+ 4 >= mtmp
->mhpmax
)
965 mtmp
->mhp
= mtmp
->mhpmax
;
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
;
973 if (powerfulimplants() && uimplant
&& uimplant
->oartifact
== ART_READY_FOR_A_RIDE
) {
974 if (mtmp
->mhp
+ 5 >= mtmp
->mhpmax
)
975 mtmp
->mhp
= mtmp
->mhpmax
;
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
;
984 if (powerfulimplants() && uimplant
&& uimplant
->oartifact
== ART_READY_FOR_A_RIDE
) {
985 if (mtmp
->mhp
+ 6 >= mtmp
->mhpmax
)
986 mtmp
->mhp
= mtmp
->mhpmax
;
999 /* called when you move to another level */
1002 boolean pets_only
; /* true for ascension or final escape */
1004 register struct monst
*mtmp
, *mtmp2
;
1005 register struct obj
*obj
;
1007 boolean stay_behind
;
1008 extern d_level new_dlevel
; /* in do.c */
1009 int extraradius
= 0;
1011 boolean qbufdefined
= 0; /* fail safe */
1013 if (!(PlayerCannotUseSkills
)) {
1014 switch (P_SKILL(P_PETKEEPING
)) {
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
) {
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
);
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
));
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");
1068 } else if (mon_has_amulet(mtmp
)) {
1069 if (canseemon(mtmp
))
1070 pline("%s seems very disoriented for a moment.",
1073 } else if (mtmp
->mtame
&& mtmp
->mtrapped
) {
1074 if (canseemon(mtmp
))
1075 pline("%s is still trapped.", Monnam(mtmp
));
1078 if (mtmp
== u
.usteed
) stay_behind
= FALSE
;
1080 if (mtmp
->mleashed
) {
1081 pline("%s leash suddenly comes loose.",
1082 humanoid(mtmp
->data
)
1083 ? (mtmp
->female
? "Her" : "His")
1085 m_unleash(mtmp
, FALSE
);
1090 set_residency(mtmp
, TRUE
);
1094 /* NOTE: worm is truncated to # segs = max wormno size */
1095 cnt
= count_wsegs(mtmp
);
1096 num_segs
= min(cnt
, MAX_NUM_WORMS
- 1);
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 */
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
;
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
);
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
;
1142 int num_segs
= 0; /* count of worm segments */
1145 set_residency(mtmp
, TRUE
);
1149 /* **** NOTE: worm is truncated to # segs = max wormno size **** */
1150 cnt
= count_wsegs(mtmp
);
1151 num_segs
= min(cnt
, MAX_NUM_WORMS
- 1);
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 */
1162 if (mtmp
->mleashed
) {
1164 m_unleash(mtmp
, TRUE
);
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 */
1190 makedoghungry(mon
, 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;
1208 /* return quality of food; the lower the better */
1209 /* fungi will eat even tainted food */
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
];
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
) {
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 */
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
) ?
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
) ?
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
) {
1266 case HUGE_CHUNK_OF_MEAT
:
1267 return (carni
? DOGFOOD
: MANFOOD
);
1269 if (touch_petrifies(&mons
[obj
->corpsenm
]) && obj
->corpsenm
!= PM_PLAYERMON
&& !resists_ston(mon
))
1271 return (carni
? CADAVER
: MANFOOD
);
1273 /* WAC add don't eat own class*/
1274 if (mons
[obj
->corpsenm
].mlet
== mon
->data
->mlet
)
1275 return (starving
&& carni
? ACCFOOD
: TABU
);
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
)))
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
));
1291 return ( (metallivorous(mon
->data
) || mon
->egotype_metallivore
) ? ACCFOOD
: MANFOOD
);
1294 return (herbi
? DOGFOOD
: starving
? ACCFOOD
: MANFOOD
);
1296 return ((mon
->data
->mlet
== S_YETI
) ? DOGFOOD
:
1297 ((herbi
|| starving
) ? ACCFOOD
: MANFOOD
));
1299 if (starving
) return ACCFOOD
;
1300 return (obj
->otyp
> SLIME_MOLD
?
1301 (carni
? ACCFOOD
: MANFOOD
) :
1302 (herbi
? ACCFOOD
: MANFOOD
));
1305 if (obj
->otyp
== AMULET_OF_STRANGULATION
||
1306 obj
->otyp
== RIN_SLOW_DIGESTION
|| obj
->otyp
== RIN_INDIGESTION
)
1308 if (hates_silver(mon
->data
) &&
1309 objects
[obj
->otyp
].oc_material
== MT_SILVER
)
1311 if (hates_copper(mon
->data
) &&
1312 objects
[obj
->otyp
].oc_material
== MT_COPPER
)
1314 if (hates_platinum(mon
->data
) &&
1315 objects
[obj
->otyp
].oc_material
== MT_PLATINUM
)
1317 if (hates_cursed(mon
->data
) && obj
->cursed
)
1319 if (hates_viva(mon
->data
) &&
1320 objects
[obj
->otyp
].oc_material
== MT_VIVA
)
1322 if (hates_inka(mon
->data
) &&
1323 objects
[obj
->otyp
].oc_material
== MT_INKA
)
1325 /* KMH -- Taz likes organics, too! */
1326 if ((organivorous(mon
->data
) || mon
->egotype_organivore
) && is_organic(obj
))
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
:
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
)
1341 /* fall into next case */
1343 if ( (lithivorous(mon
->data
) || mon
->egotype_lithivore
) && is_lithic(obj
) ) return( DOGFOOD
);
1352 tamedog(mtmp
, obj
, guaranteed
)
1353 register struct monst
*mtmp
;
1354 register struct obj
*obj
;
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
)) {
1386 pline("You're an undead slayer, not an undead tamer! %s refuses to be tamed!", Monnam(mtmp
));
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);
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. */
1422 /* make grabber let go now, whether it becomes tame or not */
1423 if (mtmp
== u
.ustuck
) {
1425 expels(mtmp
, mtmp
->data
, TRUE
);
1426 else if (!(Upolyd
&& sticks(youmonst
.data
)))
1430 /* feeding it treats makes it tamer */
1431 if (mtmp
->mtame
&& obj
) {
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 */
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 */
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
);
1505 mtmp2
->mxlth
= sizeof(struct edog
);
1506 if (mtmp
->mnamelth
) strcpy(NAME(mtmp2
), NAME(mtmp
));
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
)) {
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
);
1560 int make_pet_minion(mnum
,alignment
)
1564 register struct monst
*mon
;
1565 register struct monst
*mtmp2
;
1566 mon
= makemon(&mons
[mnum
], u
.ux
, u
.uy
, MM_NOSPECIALS
);
1568 /* now tame that puppy... */
1569 mtmp2
= newmonst(sizeof(struct edog
) + mon
->mnamelth
);
1571 mtmp2
->mxlth
= sizeof(struct edog
);
1572 if(mon
->mnamelth
) strcpy(NAME(mtmp2
), NAME(mon
));
1575 newsym(mtmp2
->mx
, mtmp2
->my
);
1576 mtmp2
->mpeaceful
= 1;
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
;
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.
1598 wary_dog(mtmp
, was_dead
)
1603 boolean quietly
= was_dead
;
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.",
1626 mtmp
->mpeaceful
? "seems unable" :
1630 pline("%s avoids your gaze.",
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;
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
) {
1650 edog
->killed_by_u
= 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;
1660 edog
->droptime
= 0L;
1661 edog
->dropdist
= 10000;
1662 edog
->whistletime
= 0L;
1664 } /* else lifesaved, so retain current values */
1669 befriend_with_obj(ptr
, obj
)
1670 struct permonst
*ptr
;
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
;
1702 if (!mtmp
->mtame
) return;
1704 if (Aggravate_monster
|| Conflict
) mtmp
->mtame
/=2;
1707 if (mtmp
->mtame
&& !mtmp
->isminion
&& !(Role_if(PM_SLAVE_MASTER
) && rn2(5)) )
1708 EDOG(mtmp
)->abuse
++;
1710 if (Role_if(PM_CRUEL_ABUSER
)) {
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
);