1 /* NetHack 3.6 read.c $NHDT-Date: 1450577673 2015/12/20 02:14:33 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.131 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
7 #define Your_Own_Role(mndx) \
8 ((mndx) == urole.malenum \
9 || (urole.femalenum != NON_PM && (mndx) == urole.femalenum))
10 #define Your_Own_Race(mndx) \
11 ((mndx) == urace.malenum \
12 || (urace.femalenum != NON_PM && (mndx) == urace.femalenum))
16 static NEARDATA
const char readable
[] = { ALL_CLASSES
, SCROLL_CLASS
,
18 static const char all_count
[] = { ALLOW_COUNT
, ALL_CLASSES
, 0 };
20 STATIC_DCL boolean
FDECL(learnscrolltyp
, (SHORT_P
));
21 STATIC_DCL
char * FDECL(erode_obj_text
, (struct obj
*, char *));
22 STATIC_DCL
void NDECL(do_class_genocide
);
23 STATIC_DCL
void FDECL(stripspe
, (struct obj
*));
24 STATIC_DCL
void FDECL(p_glow1
, (struct obj
*));
25 STATIC_DCL
void FDECL(p_glow2
, (struct obj
*, const char *));
26 STATIC_DCL
void FDECL(randomize
, (int *, int));
27 STATIC_DCL
void FDECL(forget_single_object
, (int));
28 STATIC_DCL
void FDECL(forget
, (int));
29 STATIC_DCL
int FDECL(maybe_tame
, (struct monst
*, struct obj
*));
30 STATIC_DCL boolean
FDECL(is_valid_stinking_cloud_pos
, (int, int, BOOLEAN_P
));
31 STATIC_DCL
void FDECL(display_stinking_cloud_positions
, (int));
32 STATIC_PTR
void FDECL(set_lit
, (int, int, genericptr
));
35 learnscrolltyp(scrolltyp
)
38 if (!objects
[scrolltyp
].oc_name_known
) {
40 more_experienced(0, 10);
46 /* also called from teleport.c for scroll of teleportation */
51 /* it's implied that sobj->dknown is set;
52 we couldn't be reading this scroll otherwise */
53 if (sobj
->oclass
!= SPBOOK_CLASS
)
54 (void) learnscrolltyp(sobj
->otyp
);
58 erode_obj_text(otmp
, buf
)
62 int erosion
= greatest_erosion(otmp
);
64 wipeout_text(buf
, (int) (strlen(buf
) * erosion
/ (2 * MAX_ERODE
)),
65 otmp
->o_id
^ (unsigned) ubirthday
);
70 tshirt_text(tshirt
, buf
)
74 static const char *shirt_msgs
[] = {
76 "I explored the Dungeons of Doom and all I got was this lousy T-shirt!",
77 "Is that Mjollnir in your pocket or are you just happy to see me?",
78 "It's not the size of your sword, it's how #enhance'd you are with it.",
79 "Madame Elvira's House O' Succubi Lifetime Customer",
80 "Madame Elvira's House O' Succubi Employee of the Month",
81 "Ludios Vault Guards Do It In Small, Dark Rooms",
82 "Yendor Military Soldiers Do It In Large Groups",
83 "I survived Yendor Military Boot Camp",
84 "Ludios Accounting School Intra-Mural Lacrosse Team",
85 "Oracle(TM) Fountains 10th Annual Wet T-Shirt Contest",
86 "Hey, black dragon! Disintegrate THIS!",
87 "I'm With Stupid -->",
88 "Don't blame me, I voted for Izchak!",
89 "Don't Panic", /* HHGTTG */
90 "Furinkan High School Athletic Dept.", /* Ranma 1/2 */
91 "Hel-LOOO, Nurse!", /* Animaniacs */
93 "100% goblin hair - do not wash",
94 "Aberzombie and Fitch",
95 "cK -- Cockatrice touches the Kop",
96 "Don't ask me, I only adventure here",
98 "d, your dog or a killer?",
102 "Hello, my darlings!", /* Charlie Drake */
103 "Hey! Nymphs! Steal This T-Shirt!",
104 "I <3 Dungeon of Doom",
106 "I am a Valkyrie. If you see me running, try to keep up.",
107 "I am not a pack rat - I am a collector",
108 "I bounced off a rubber tree", /* Monkey Island */
109 "Plunder Island Brimstone Beach Club", /* Monkey Island */
110 "If you can read this, I can hit you with my polearm",
112 "I scored with the princess",
113 "I want to live forever or die in the attempt.",
115 "LOST IN THOUGHT - please send search party",
117 "Minetown Better Business Bureau",
119 "Ms. Palm's House of Negotiable Affection -- A Very Reputable House Of Disrepute",
120 "Protection Racketeer",
121 "Real men love Crom",
122 "Somebody stole my Mojo!",
123 "The Hellhound Gang",
125 "They Might Be Storm Giants",
126 "Weapons don't kill people, I kill people",
128 "You're killing me!",
129 "Anhur State University - Home of the Fighting Fire Ants!",
132 "Real men are valkyries",
133 "Young Men's Cavedigging Association",
134 "Occupy Fort Ludios",
135 "I couldn't afford this T-shirt so I stole it!",
137 "I'm not wearing any pants",
138 "Down with the living!",
144 Strcpy(buf
, shirt_msgs
[tshirt
->o_id
% SIZE(shirt_msgs
)]);
145 return erode_obj_text(tshirt
, buf
);
149 apron_text(apron
, buf
)
153 static const char *apron_msgs
[] = {
155 "I'm making SCIENCE!",
156 "Don't mess with the chef",
157 "Don't make me poison you",
158 "Gehennom's Kitchen",
159 "Rat: The other white meat",
160 "If you can't stand the heat, get out of Gehennom!",
161 "If we weren't meant to eat animals, why are they made out of meat?",
162 "If you don't like the food, I'll stab you",
165 Strcpy(buf
, apron_msgs
[apron
->o_id
% SIZE(apron_msgs
)]);
166 return erode_obj_text(apron
, buf
);
172 register struct obj
*scroll
;
173 boolean confused
, nodisappear
;
176 if (check_capacity((char *) 0))
178 scroll
= getobj(readable
, "read");
182 /* outrumor has its own blindness check */
183 if (scroll
->otyp
== FORTUNE_COOKIE
) {
185 You("break up the cookie and throw away the pieces.");
186 outrumor(bcsign(scroll
), BY_COOKIE
);
188 u
.uconduct
.literate
++;
191 } else if (scroll
->otyp
== T_SHIRT
|| scroll
->otyp
== ALCHEMY_SMOCK
) {
194 You_cant("feel any Braille writing.");
197 /* can't read shirt worn under suit (under cloak is ok though) */
198 if (scroll
->otyp
== T_SHIRT
&& uarm
&& scroll
== uarmu
) {
199 pline("%s shirt is obscured by %s%s.",
200 scroll
->unpaid
? "That" : "Your", shk_your(buf
, uarm
),
201 suit_simple_name(uarm
));
204 u
.uconduct
.literate
++;
207 pline("\"%s\"", (scroll
->otyp
== T_SHIRT
) ? tshirt_text(scroll
, buf
)
208 : apron_text(scroll
, buf
));
210 } else if (scroll
->otyp
== CREDIT_CARD
) {
211 static const char *card_msgs
[] = {
212 "Leprechaun Gold Tru$t - Shamrock Card",
213 "Magic Memory Vault Charge Card", "Larn National Bank", /* Larn */
214 "First Bank of Omega", /* Omega */
215 "Bank of Zork - Frobozz Magic Card", /* Zork */
216 "Ankh-Morpork Merchant's Guild Barter Card",
217 "Ankh-Morpork Thieves' Guild Unlimited Transaction Card",
218 "Ransmannsby Moneylenders Association",
219 "Bank of Gehennom - 99% Interest Card",
220 "Yendorian Express - Copper Card",
221 "Yendorian Express - Silver Card",
222 "Yendorian Express - Gold Card",
223 "Yendorian Express - Mithril Card",
224 "Yendorian Express - Platinum Card", /* must be last */
228 You("feel the embossed numbers:");
234 ? card_msgs
[SIZE(card_msgs
) - 1]
235 : card_msgs
[scroll
->o_id
% (SIZE(card_msgs
) - 1)]);
237 /* Make a credit card number */
238 pline("\"%d0%d %d%d1 0%d%d0\"", ((scroll
->o_id
% 89) + 10),
239 (scroll
->o_id
% 4), (((scroll
->o_id
* 499) % 899999) + 100000),
240 (scroll
->o_id
% 10), (!(scroll
->o_id
% 3)),
241 ((scroll
->o_id
* 7) % 10));
242 u
.uconduct
.literate
++;
244 } else if (scroll
->otyp
== CAN_OF_GREASE
) {
245 pline("This %s has no label.", singular(scroll
, xname
));
247 } else if (scroll
->otyp
== MAGIC_MARKER
) {
249 You_cant("feel any Braille writing.");
254 pline("\"Magic Marker(TM) Red Ink Marker Pen. Water Soluble.\"");
255 u
.uconduct
.literate
++;
257 } else if (scroll
->oclass
== COIN_CLASS
) {
259 You("feel the embossed words:");
260 else if (flags
.verbose
)
262 pline("\"1 Zorkmid. 857 GUE. In Frobs We Trust.\"");
263 u
.uconduct
.literate
++;
265 } else if (scroll
->oartifact
== ART_ORB_OF_FATE
) {
267 You("feel the engraved signature:");
269 pline("It is signed:");
271 u
.uconduct
.literate
++;
273 } else if (scroll
->otyp
== CANDY_BAR
) {
274 static const char *wrapper_msgs
[] = {
276 "Moon Crunchy", /* South Park */
277 "Snacky Cake", "Chocolate Nuggie", "The Small Bar",
278 "Crispy Yum Yum", "Nilla Crunchie", "Berry Bar",
279 "Choco Nummer", "Om-nom", /* Cat Macro */
280 "Fruity Oaty", /* Serenity */
281 "Wonka Bar" /* Charlie and the Chocolate Factory */
285 You_cant("feel any Braille writing.");
288 pline("The wrapper reads: \"%s\"",
289 wrapper_msgs
[scroll
->o_id
% SIZE(wrapper_msgs
)]);
290 u
.uconduct
.literate
++;
292 } else if (scroll
->oclass
!= SCROLL_CLASS
293 && scroll
->oclass
!= SPBOOK_CLASS
) {
294 pline(silly_thing_to
, "read");
296 } else if (Blind
&& (scroll
->otyp
!= SPE_BOOK_OF_THE_DEAD
)) {
297 const char *what
= 0;
298 if (scroll
->oclass
== SPBOOK_CLASS
)
299 what
= "mystic runes";
300 else if (!scroll
->dknown
)
301 what
= "formula on the scroll";
303 pline("Being blind, you cannot read the %s.", what
);
308 confused
= (Confusion
!= 0);
310 if (scroll
->otyp
== SCR_MAIL
) {
311 confused
= FALSE
; /* override */
312 /* reading mail is a convenience for the player and takes
313 place outside the game, so shouldn't affect gameplay;
314 on the other hand, it starts by explicitly making the
315 hero actively read something, which is pretty hard
316 to simply ignore; as a compromise, if the player has
317 maintained illiterate conduct so far, and this mail
318 scroll didn't come from bones, ask for confirmation */
319 if (!u
.uconduct
.literate
) {
320 if (!scroll
->spe
&& yn(
321 "Reading mail will violate \"illiterate\" conduct. Read anyway?"
328 /* Actions required to win the game aren't counted towards conduct */
329 /* Novel conduct is handled in read_tribute so exclude it too*/
330 if (scroll
->otyp
!= SPE_BOOK_OF_THE_DEAD
331 && scroll
->otyp
!= SPE_BLANK_PAPER
&& scroll
->otyp
!= SCR_BLANK_PAPER
332 && scroll
->otyp
!= SPE_NOVEL
)
333 u
.uconduct
.literate
++;
335 if (scroll
->oclass
== SPBOOK_CLASS
) {
336 return study_book(scroll
);
338 scroll
->in_use
= TRUE
; /* scroll, not spellbook, now being read */
339 if (scroll
->otyp
!= SCR_BLANK_PAPER
) {
340 /* a few scroll feedback messages describe something happening
341 to the scroll itself, so avoid "it disappears" for those */
342 nodisappear
= (scroll
->otyp
== SCR_FIRE
343 || (scroll
->otyp
== SCR_REMOVE_CURSE
347 ? "You %s the formula on the scroll."
348 : "As you %s the formula on it, the scroll disappears.",
349 is_silent(youmonst
.data
) ? "cogitate" : "pronounce");
351 pline(nodisappear
? "You read the scroll."
352 : "As you read the scroll, it disappears.");
355 pline("Being so trippy, you screw up...");
357 pline("Being confused, you %s the magic words...",
358 is_silent(youmonst
.data
) ? "misunderstand"
362 if (!seffects(scroll
)) {
363 if (!objects
[scroll
->otyp
].oc_name_known
) {
366 else if (!objects
[scroll
->otyp
].oc_uname
)
369 scroll
->in_use
= FALSE
;
370 if (scroll
->otyp
!= SCR_BLANK_PAPER
)
378 register struct obj
*obj
;
380 if (obj
->blessed
|| obj
->spe
<= 0) {
381 pline1(nothing_happens
);
383 /* order matters: message, shop handling, actual transformation */
384 pline("%s briefly.", Yobjnam2(obj
, "vibrate"));
385 costly_alteration(obj
, COST_UNCHRG
);
387 if (obj
->otyp
== OIL_LAMP
|| obj
->otyp
== BRASS_LANTERN
)
394 register struct obj
*otmp
;
396 pline("%s briefly.", Yobjnam2(otmp
, Blind
? "vibrate" : "glow"));
401 register struct obj
*otmp
;
402 register const char *color
;
404 pline("%s%s%s for a moment.", Yobjnam2(otmp
, Blind
? "vibrate" : "glow"),
405 Blind
? "" : " ", Blind
? "" : hcolor(color
));
408 /* Is the object chargeable? For purposes of inventory display; it is
409 possible to be able to charge things for which this returns FALSE. */
414 if (obj
->oclass
== WAND_CLASS
)
416 /* known && !oc_name_known is possible after amnesia/mind flayer */
417 if (obj
->oclass
== RING_CLASS
)
418 return (boolean
) (objects
[obj
->otyp
].oc_charged
421 && objects
[obj
->otyp
].oc_name_known
)));
422 if (is_weptool(obj
)) /* specific check before general tools */
424 if (obj
->oclass
== TOOL_CLASS
)
425 return (boolean
) objects
[obj
->otyp
].oc_charged
;
426 return FALSE
; /* why are weapons/armor considered charged anyway? */
429 /* recharge an object; curse_bless is -1 if the recharging implement
430 was cursed, +1 if blessed, 0 otherwise. */
432 recharge(obj
, curse_bless
)
437 boolean is_cursed
, is_blessed
;
439 is_cursed
= curse_bless
< 0;
440 is_blessed
= curse_bless
> 0;
442 if (obj
->oclass
== WAND_CLASS
) {
443 int lim
= (obj
->otyp
== WAN_WISHING
)
445 : (objects
[obj
->otyp
].oc_dir
!= NODIR
) ? 8 : 15;
447 /* undo any prior cancellation, even when is_cursed */
452 * Recharging might cause wands to explode.
453 * v = number of previous recharges
454 * v = percentage chance to explode on this attempt
455 * v = cumulative odds for exploding
465 n
= (int) obj
->recharged
;
466 if (n
> 0 && (obj
->otyp
== WAN_WISHING
467 || (n
* n
* n
> rn2(7 * 7 * 7)))) { /* recharge_limit */
468 wand_explode(obj
, rnd(lim
));
471 /* didn't explode, so increment the recharge count */
472 obj
->recharged
= (unsigned) (n
+ 1);
474 /* now handle the actual recharging */
478 n
= (lim
== 3) ? 3 : rn1(5, lim
+ 1 - 5);
486 if (obj
->otyp
== WAN_WISHING
&& obj
->spe
> 3) {
487 wand_explode(obj
, 1);
491 p_glow2(obj
, NH_BLUE
);
494 #if 0 /*[shop price doesn't vary by charge count]*/
495 /* update shop bill to reflect new higher price */
501 } else if (obj
->oclass
== RING_CLASS
&& objects
[obj
->otyp
].oc_charged
) {
502 /* charging does not affect ring's curse/bless status */
503 int s
= is_blessed
? rnd(3) : is_cursed
? -rnd(2) : 1;
504 boolean is_on
= (obj
== uleft
|| obj
== uright
);
506 /* destruction depends on current state, not adjustment */
507 if (obj
->spe
> rn2(7) || obj
->spe
<= -5) {
508 pline("%s momentarily, then %s!", Yobjnam2(obj
, "pulsate"),
509 otense(obj
, "explode"));
512 s
= rnd(3 * abs(obj
->spe
)); /* amount of damage */
514 losehp(Maybe_Half_Phys(s
), "exploding ring", KILLED_BY_AN
);
516 long mask
= is_on
? (obj
== uleft
? LEFT_RING
: RIGHT_RING
) : 0L;
518 pline("%s spins %sclockwise for a moment.", Yname2(obj
),
519 s
< 0 ? "counter" : "");
521 costly_alteration(obj
, COST_DECHNT
);
522 /* cause attributes and/or properties to be updated */
525 obj
->spe
+= s
; /* update the ring while it's off */
527 setworn(obj
, mask
), Ring_on(obj
);
528 /* oartifact: if a touch-sensitive artifact ring is
529 ever created the above will need to be revised */
530 /* update shop bill to reflect new higher price */
531 if (s
> 0 && obj
->unpaid
)
535 } else if (obj
->oclass
== TOOL_CLASS
) {
536 int rechrg
= (int) obj
->recharged
;
538 if (objects
[obj
->otyp
].oc_charged
) {
539 /* tools don't have a limit, but the counter used does */
540 if (rechrg
< 7) /* recharge_limit */
544 case BELL_OF_OPENING
:
556 case EXPENSIVE_CAMERA
:
561 == MAGIC_MARKER
) { /* previously recharged */
562 obj
->recharged
= 1; /* override increment done above */
564 Your("marker seems permanently dried out.");
566 pline1(nothing_happens
);
567 } else if (is_blessed
) {
568 n
= rn1(16, 15); /* 15..30 */
569 if (obj
->spe
+ n
<= 50)
571 else if (obj
->spe
+ n
<= 75)
574 int chrg
= (int) obj
->spe
;
575 if ((chrg
+ n
) > 127)
580 p_glow2(obj
, NH_BLUE
);
582 n
= rn1(11, 10); /* 10..20 */
583 if (obj
->spe
+ n
<= 50)
586 int chrg
= (int) obj
->spe
;
587 if ((chrg
+ n
) > 127)
592 p_glow2(obj
, NH_WHITE
);
601 pline("%s out!", Tobjnam(obj
, "go"));
604 } else if (is_blessed
) {
607 p_glow2(obj
, NH_BLUE
);
619 } else if (is_blessed
) {
621 p_glow2(obj
, NH_BLUE
);
627 pline1(nothing_happens
);
635 } else if (is_blessed
) {
637 obj
->spe
+= rn1(10, 6);
639 obj
->spe
+= rn1(5, 6);
642 p_glow2(obj
, NH_BLUE
);
654 case DRUM_OF_EARTHQUAKE
:
657 } else if (is_blessed
) {
661 p_glow2(obj
, NH_BLUE
);
677 You("have a feeling of loss.");
681 /* Forget known information about this object type. */
683 forget_single_object(obj_id
)
686 objects
[obj_id
].oc_name_known
= 0;
687 objects
[obj_id
].oc_pre_discovered
= 0; /* a discovery when relearned */
688 if (objects
[obj_id
].oc_uname
) {
689 free((genericptr_t
) objects
[obj_id
].oc_uname
);
690 objects
[obj_id
].oc_uname
= 0;
692 undiscover_object(obj_id
); /* after clearing oc_name_known */
694 /* clear & free object names from matching inventory items too? */
697 #if 0 /* here if anyone wants it.... */
698 /* Forget everything known about a particular object class. */
700 forget_objclass(oclass
)
705 for (i
= bases
[oclass
];
706 i
< NUM_OBJECTS
&& objects
[i
].oc_class
== oclass
; i
++)
707 forget_single_object(i
);
711 /* randomize the given list of numbers 0 <= i < count */
713 randomize(indices
, count
)
719 for (i
= count
- 1; i
> 0; i
--) {
720 if ((iswap
= rn2(i
+ 1)) == i
)
723 indices
[i
] = indices
[iswap
];
724 indices
[iswap
] = temp
;
728 /* Forget % of known objects. */
730 forget_objects(percent
)
734 int indices
[NUM_OBJECTS
];
738 if (percent
<= 0 || percent
> 100) {
739 impossible("forget_objects: bad percent %d", percent
);
743 indices
[0] = 0; /* lint suppression */
744 for (count
= 0, i
= 1; i
< NUM_OBJECTS
; i
++)
745 if (OBJ_DESCR(objects
[i
])
746 && (objects
[i
].oc_name_known
|| objects
[i
].oc_uname
))
747 indices
[count
++] = i
;
750 randomize(indices
, count
);
752 /* forget first % of randomized indices */
753 count
= ((count
* percent
) + rn2(100)) / 100;
754 for (i
= 0; i
< count
; i
++)
755 forget_single_object(indices
[i
]);
759 /* Forget some or all of map (depends on parameters). */
770 for (zx
= 0; zx
< COLNO
; zx
++)
771 for (zy
= 0; zy
< ROWNO
; zy
++)
772 if (howmuch
& ALL_MAP
|| rn2(7)) {
773 /* Zonk all memory of this location. */
774 levl
[zx
][zy
].seenv
= 0;
775 levl
[zx
][zy
].waslit
= 0;
776 levl
[zx
][zy
].glyph
= cmap_to_glyph(S_stone
);
777 lastseentyp
[zx
][zy
] = STONE
;
779 /* forget overview data for this level */
780 forget_mapseen(ledger_no(&u
.uz
));
783 /* Forget all traps on the level. */
787 register struct trap
*trap
;
789 /* forget all traps (except the one the hero is in :-) */
790 for (trap
= ftrap
; trap
; trap
= trap
->ntrap
)
791 if ((trap
->tx
!= u
.ux
|| trap
->ty
!= u
.uy
) && (trap
->ttyp
!= HOLE
))
796 * Forget given % of all levels that the hero has visited and not forgotten,
800 forget_levels(percent
)
804 xchar maxl
, this_lev
;
805 int indices
[MAXLINFO
];
810 if (percent
<= 0 || percent
> 100) {
811 impossible("forget_levels: bad percent %d", percent
);
815 this_lev
= ledger_no(&u
.uz
);
816 maxl
= maxledgerno();
818 /* count & save indices of non-forgotten visited levels */
819 /* Sokoban levels are pre-mapped for the player, and should stay
820 * so, or they become nearly impossible to solve. But try to
821 * shift the forgetting elsewhere by fiddling with percent
822 * instead of forgetting fewer levels.
824 indices
[0] = 0; /* lint suppression */
825 for (count
= 0, i
= 0; i
<= maxl
; i
++)
826 if ((level_info
[i
].flags
& VISITED
)
827 && !(level_info
[i
].flags
& FORGOTTEN
) && i
!= this_lev
) {
828 if (ledger_to_dnum(i
) == sokoban_dnum
)
831 indices
[count
++] = i
;
838 randomize(indices
, count
);
840 /* forget first % of randomized indices */
841 count
= ((count
* percent
) + 50) / 100;
842 for (i
= 0; i
< count
; i
++) {
843 level_info
[indices
[i
]].flags
|= FORGOTTEN
;
844 forget_mapseen(indices
[i
]);
850 * Forget some things (e.g. after reading a scroll of amnesia). When called,
851 * the following are always forgotten:
852 * - felt ball & chain
854 * - part (6 out of 7) of the map
856 * Other things are subject to flags:
857 * howmuch & ALL_MAP = forget whole map
858 * howmuch & ALL_SPELLS = forget all spells
865 u
.bc_felt
= 0; /* forget felt ball&chain */
870 /* 1 in 3 chance of forgetting some levels */
872 forget_levels(rn2(25));
874 /* 1 in 3 chance of forgetting some objects */
876 forget_objects(rn2(25));
878 if (howmuch
& ALL_SPELLS
)
881 * Make sure that what was seen is restored correctly. To do this,
882 * we need to go blind for an instant --- turn off the display,
883 * then restart it. All this work is needed to correctly handle
884 * walls which are stone on one side and wall on the other. Turning
885 * off the seen bits above will make the wall revert to stone, but
886 * there are cases where we don't want this to happen. The easiest
887 * thing to do is to run it through the vision system again, which
890 docrt(); /* this correctly will reset vision */
893 /* monster is hit by scroll of taming's effect */
895 maybe_tame(mtmp
, sobj
)
899 int was_tame
= mtmp
->mtame
;
900 unsigned was_peaceful
= mtmp
->mpeaceful
;
904 if (was_peaceful
&& !mtmp
->mpeaceful
)
908 make_happy_shk(mtmp
, FALSE
);
909 else if (!resist(mtmp
, sobj
->oclass
, 0, NOTELL
))
910 (void) tamedog(mtmp
, (struct obj
*) 0);
911 if ((!was_peaceful
&& mtmp
->mpeaceful
) || (!was_tame
&& mtmp
->mtame
))
918 is_valid_stinking_cloud_pos(x
, y
, showmsg
)
922 if (!cansee(x
, y
) || !ACCESSIBLE(levl
[x
][y
].typ
) || distu(x
, y
) >= 32) {
924 You("smell rotten eggs.");
931 display_stinking_cloud_positions(state
)
935 tmp_at(DISP_BEAM
, cmap_to_glyph(S_goodpos
));
936 } else if (state
== 1) {
940 for (dx
= -dist
; dx
<= dist
; dx
++)
941 for (dy
= -dist
; dy
<= dist
; dy
++) {
944 if (isok(x
, y
) && is_valid_stinking_cloud_pos(x
, y
, FALSE
))
952 /* scroll effects; return 1 if we use up the scroll and possibly make it
953 become discovered, 0 if caller should take care of those side-effects */
956 struct obj
*sobj
; /* scroll, or fake spellbook object for scroll-like spell */
958 int cval
, otyp
= sobj
->otyp
;
959 boolean confused
= (Confusion
!= 0), sblessed
= sobj
->blessed
,
960 scursed
= sobj
->cursed
, already_known
, old_erodeproof
,
964 if (objects
[otyp
].oc_magic
)
965 exercise(A_WIS
, TRUE
); /* just for trying */
966 already_known
= (sobj
->oclass
== SPBOOK_CLASS
/* spell */
967 || objects
[otyp
].oc_name_known
);
974 /* "stamped scroll" created via magic marker--without a stamp */
975 pline("This scroll is marked \"postage due\".");
977 /* scroll of mail obtained from bones file or from wishing;
978 * note to the puzzled: the game Larn actually sends you junk
982 "This seems to be junk mail addressed to the finder of the Eye of Larn.");
987 case SCR_ENCHANT_ARMOR
: {
989 boolean special_armor
;
992 otmp
= some_armor(&youmonst
);
994 strange_feeling(sobj
, !Blind
995 ? "Your skin glows then fades."
996 : "Your skin feels warm for a moment.");
997 sobj
= 0; /* useup() in strange_feeling() */
998 exercise(A_CON
, !scursed
);
999 exercise(A_STR
, !scursed
);
1003 old_erodeproof
= (otmp
->oerodeproof
!= 0);
1004 new_erodeproof
= !scursed
;
1005 otmp
->oerodeproof
= 0; /* for messages */
1007 otmp
->rknown
= FALSE
;
1008 pline("%s warm for a moment.", Yobjnam2(otmp
, "feel"));
1010 otmp
->rknown
= TRUE
;
1011 pline("%s covered by a %s %s %s!", Yobjnam2(otmp
, "are"),
1012 scursed
? "mottled" : "shimmering",
1013 hcolor(scursed
? NH_BLACK
: NH_GOLDEN
),
1015 : (is_shield(otmp
) ? "layer" : "shield"));
1017 if (new_erodeproof
&& (otmp
->oeroded
|| otmp
->oeroded2
)) {
1018 otmp
->oeroded
= otmp
->oeroded2
= 0;
1019 pline("%s as good as new!",
1020 Yobjnam2(otmp
, Blind
? "feel" : "look"));
1022 if (old_erodeproof
&& !new_erodeproof
) {
1023 /* restore old_erodeproof before shop charges */
1024 otmp
->oerodeproof
= 1;
1025 costly_alteration(otmp
, COST_DEGRD
);
1027 otmp
->oerodeproof
= new_erodeproof
? 1 : 0;
1030 /* elven armor vibrates warningly when enchanted beyond a limit */
1031 special_armor
= is_elven_armor(otmp
)
1032 || (Role_if(PM_WIZARD
) && otmp
->otyp
== CORNUTHAUM
);
1034 same_color
= (otmp
->otyp
== BLACK_DRAGON_SCALE_MAIL
1035 || otmp
->otyp
== BLACK_DRAGON_SCALES
);
1037 same_color
= (otmp
->otyp
== SILVER_DRAGON_SCALE_MAIL
1038 || otmp
->otyp
== SILVER_DRAGON_SCALES
1039 || otmp
->otyp
== SHIELD_OF_REFLECTION
);
1043 /* KMH -- catch underflow */
1044 s
= scursed
? -otmp
->spe
: otmp
->spe
;
1045 if (s
> (special_armor
? 5 : 3) && rn2(s
)) {
1046 otmp
->in_use
= TRUE
;
1047 pline("%s violently %s%s%s for a while, then %s.", Yname2(otmp
),
1048 otense(otmp
, Blind
? "vibrate" : "glow"),
1049 (!Blind
&& !same_color
) ? " " : "",
1050 (Blind
|| same_color
) ? "" : hcolor(scursed
? NH_BLACK
1052 otense(otmp
, "evaporate"));
1053 remove_worn_item(otmp
, FALSE
);
1059 ? (rn2(otmp
->spe
) == 0)
1061 ? rnd(3 - otmp
->spe
/ 3)
1063 if (s
>= 0 && Is_dragon_scales(otmp
)) {
1064 /* dragon scales get turned into dragon scale mail */
1065 pline("%s merges and hardens!", Yname2(otmp
));
1066 setworn((struct obj
*) 0, W_ARM
);
1067 /* assumes same order */
1068 otmp
->otyp
+= GRAY_DRAGON_SCALE_MAIL
- GRAY_DRAGON_SCALES
;
1073 } else if (otmp
->cursed
)
1076 setworn(otmp
, W_ARM
);
1078 alter_cost(otmp
, 0L); /* shop bill */
1081 pline("%s %s%s%s%s for a %s.", Yname2(otmp
),
1082 s
== 0 ? "violently " : "",
1083 otense(otmp
, Blind
? "vibrate" : "glow"),
1084 (!Blind
&& !same_color
) ? " " : "",
1085 (Blind
|| same_color
)
1086 ? "" : hcolor(scursed
? NH_BLACK
: NH_SILVER
),
1087 (s
* s
> 1) ? "while" : "moment");
1088 /* [this cost handling will need updating if shop pricing is
1089 ever changed to care about curse/bless status of armor] */
1091 costly_alteration(otmp
, COST_DECHNT
);
1092 if (scursed
&& !otmp
->cursed
)
1094 else if (sblessed
&& !otmp
->blessed
)
1096 else if (!scursed
&& otmp
->cursed
)
1101 known
= otmp
->known
;
1102 /* update shop bill to reflect new higher price */
1103 if (s
> 0 && otmp
->unpaid
)
1104 alter_cost(otmp
, 0L);
1107 if ((otmp
->spe
> (special_armor
? 5 : 3))
1108 && (special_armor
|| !rn2(7)))
1109 pline("%s %s.", Yobjnam2(otmp
, "suddenly vibrate"),
1110 Blind
? "again" : "unexpectedly");
1113 case SCR_DESTROY_ARMOR
: {
1114 otmp
= some_armor(&youmonst
);
1117 strange_feeling(sobj
, "Your bones itch.");
1118 sobj
= 0; /* useup() in strange_feeling() */
1119 exercise(A_STR
, FALSE
);
1120 exercise(A_CON
, FALSE
);
1123 old_erodeproof
= (otmp
->oerodeproof
!= 0);
1124 new_erodeproof
= scursed
;
1125 otmp
->oerodeproof
= 0; /* for messages */
1126 p_glow2(otmp
, NH_PURPLE
);
1127 if (old_erodeproof
&& !new_erodeproof
) {
1128 /* restore old_erodeproof before shop charges */
1129 otmp
->oerodeproof
= 1;
1130 costly_alteration(otmp
, COST_DEGRD
);
1132 otmp
->oerodeproof
= new_erodeproof
? 1 : 0;
1135 if (!scursed
|| !otmp
|| !otmp
->cursed
) {
1136 if (!destroy_arm(otmp
)) {
1137 strange_feeling(sobj
, "Your skin itches.");
1138 sobj
= 0; /* useup() in strange_feeling() */
1139 exercise(A_STR
, FALSE
);
1140 exercise(A_CON
, FALSE
);
1144 } else { /* armor and scroll both cursed */
1145 pline("%s.", Yobjnam2(otmp
, "vibrate"));
1146 if (otmp
->spe
>= -6) {
1150 make_stunned((HStun
& TIMEOUT
) + (long) rn1(10, 10), TRUE
);
1153 case SCR_CONFUSE_MONSTER
:
1154 case SPE_CONFUSE_MONSTER
:
1155 if (youmonst
.data
->mlet
!= S_HUMAN
|| scursed
) {
1157 You_feel("confused.");
1158 make_confused(HConfusion
+ rnd(100), FALSE
);
1159 } else if (confused
) {
1161 Your("%s begin to %s%s.", makeplural(body_part(HAND
)),
1162 Blind
? "tingle" : "glow ",
1163 Blind
? "" : hcolor(NH_PURPLE
));
1164 make_confused(HConfusion
+ rnd(100), FALSE
);
1166 pline("A %s%s surrounds your %s.",
1167 Blind
? "" : hcolor(NH_RED
),
1168 Blind
? "faint buzz" : " glow", body_part(HEAD
));
1169 make_confused(0L, TRUE
);
1173 Your("%s%s %s%s.", makeplural(body_part(HAND
)),
1174 Blind
? "" : " begin to glow",
1175 Blind
? (const char *) "tingle" : hcolor(NH_RED
),
1176 u
.umconf
? " even more" : "");
1180 Your("%s tingle %s sharply.", makeplural(body_part(HAND
)),
1181 u
.umconf
? "even more" : "very");
1183 Your("%s glow a%s brilliant %s.",
1184 makeplural(body_part(HAND
)),
1185 u
.umconf
? "n even more" : "", hcolor(NH_RED
));
1186 /* after a while, repeated uses become less effective */
1190 u
.umconf
+= rn1(8, 2);
1194 case SCR_SCARE_MONSTER
:
1195 case SPE_CAUSE_FEAR
: {
1196 register int ct
= 0;
1197 register struct monst
*mtmp
;
1199 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
1200 if (DEADMONSTER(mtmp
))
1202 if (cansee(mtmp
->mx
, mtmp
->my
)) {
1203 if (confused
|| scursed
) {
1204 mtmp
->mflee
= mtmp
->mfrozen
= mtmp
->msleeping
= 0;
1206 } else if (!resist(mtmp
, sobj
->oclass
, 0, NOTELL
))
1207 monflee(mtmp
, 0, FALSE
, FALSE
);
1209 ct
++; /* pets don't laugh at you */
1212 if (otyp
== SCR_SCARE_MONSTER
|| !ct
)
1213 You_hear("%s %s.", (confused
|| scursed
) ? "sad wailing"
1214 : "maniacal laughter",
1215 !ct
? "in the distance" : "close by");
1218 case SCR_BLANK_PAPER
:
1220 You("don't remember there being any magic words on this scroll.");
1222 pline("This scroll seems to be blank.");
1225 case SCR_REMOVE_CURSE
:
1226 case SPE_REMOVE_CURSE
: {
1227 register struct obj
*obj
;
1229 You_feel(!Hallucination
1230 ? (!confused
? "like someone is helping you."
1231 : "like you need some help.")
1232 : (!confused
? "in touch with the Universal Oneness."
1233 : "the power of the Force against you!"));
1236 pline_The("scroll disintegrates.");
1238 for (obj
= invent
; obj
; obj
= obj
->nobj
) {
1241 /* gold isn't subject to cursing and blessing */
1242 if (obj
->oclass
== COIN_CLASS
)
1244 wornmask
= (obj
->owornmask
& ~(W_BALL
| W_ART
| W_ARTI
));
1245 if (wornmask
&& !sblessed
) {
1246 /* handle a couple of special cases; we don't
1247 allow auxiliary weapon slots to be used to
1248 artificially increase number of worn items */
1249 if (obj
== uswapwep
) {
1252 } else if (obj
== uquiver
) {
1253 if (obj
->oclass
== WEAPON_CLASS
) {
1254 /* mergeable weapon test covers ammo,
1255 missiles, spears, daggers & knives */
1256 if (!objects
[obj
->otyp
].oc_merge
)
1258 } else if (obj
->oclass
== GEM_CLASS
) {
1259 /* possibly ought to check whether
1260 alternate weapon is a sling... */
1264 /* weptools don't merge and aren't
1265 reasonable quivered weapons */
1270 if (sblessed
|| wornmask
|| obj
->otyp
== LOADSTONE
1271 || (obj
->otyp
== LEASH
&& obj
->leashmon
)) {
1272 /* water price varies by curse/bless status */
1273 boolean shop_h2o
= (obj
->unpaid
&& obj
->otyp
== POT_WATER
);
1276 blessorcurse(obj
, 2);
1277 /* lose knowledge of this object's curse/bless
1278 state (even if it didn't actually change) */
1280 /* blessorcurse() only affects uncursed items
1281 so no need to worry about price of water
1282 going down (hence no costly_alteration) */
1283 if (shop_h2o
&& (obj
->cursed
|| obj
->blessed
))
1284 alter_cost(obj
, 0L); /* price goes up */
1285 } else if (obj
->cursed
) {
1287 costly_alteration(obj
, COST_UNCURS
);
1293 if (Punished
&& !confused
)
1295 if (u
.utrap
&& u
.utraptype
== TT_BURIEDBALL
) {
1296 buried_ball_to_freedom();
1297 pline_The("clasp on your %s vanishes.", body_part(LEG
));
1302 case SCR_CREATE_MONSTER
:
1303 case SPE_CREATE_MONSTER
:
1304 if (create_critters(1 + ((confused
|| scursed
) ? 12 : 0)
1305 + ((sblessed
|| rn2(73)) ? 0 : rnd(4)),
1306 confused
? &mons
[PM_ACID_BLOB
]
1307 : (struct permonst
*) 0,
1310 /* no need to flush monsters; we ask for identification only if the
1311 * monsters are not visible
1314 case SCR_ENCHANT_WEAPON
:
1315 if (confused
&& uwep
1316 && (uwep
->oclass
== WEAPON_CLASS
|| is_weptool(uwep
))) {
1317 old_erodeproof
= (uwep
->oerodeproof
!= 0);
1318 new_erodeproof
= !scursed
;
1319 uwep
->oerodeproof
= 0; /* for messages */
1321 uwep
->rknown
= FALSE
;
1322 Your("weapon feels warm for a moment.");
1324 uwep
->rknown
= TRUE
;
1325 pline("%s covered by a %s %s %s!", Yobjnam2(uwep
, "are"),
1326 scursed
? "mottled" : "shimmering",
1327 hcolor(scursed
? NH_PURPLE
: NH_GOLDEN
),
1328 scursed
? "glow" : "shield");
1330 if (new_erodeproof
&& (uwep
->oeroded
|| uwep
->oeroded2
)) {
1331 uwep
->oeroded
= uwep
->oeroded2
= 0;
1332 pline("%s as good as new!",
1333 Yobjnam2(uwep
, Blind
? "feel" : "look"));
1335 if (old_erodeproof
&& !new_erodeproof
) {
1336 /* restore old_erodeproof before shop charges */
1337 uwep
->oerodeproof
= 1;
1338 costly_alteration(uwep
, COST_DEGRD
);
1340 uwep
->oerodeproof
= new_erodeproof
? 1 : 0;
1343 if (!chwepon(sobj
, scursed
? -1
1345 : (uwep
->spe
>= 9) ? !rn2(uwep
->spe
)
1346 : sblessed
? rnd(3 - uwep
->spe
/ 3)
1348 sobj
= 0; /* nothing enchanted: strange_feeling -> useup */
1351 case SPE_CHARM_MONSTER
: {
1352 int candidates
, res
, results
, vis_results
;
1356 results
= vis_results
= maybe_tame(u
.ustuck
, sobj
);
1358 int i
, j
, bd
= confused
? 5 : 1;
1361 /* note: maybe_tame() can return either positive or
1362 negative values, but not both for the same scroll */
1363 candidates
= results
= vis_results
= 0;
1364 for (i
= -bd
; i
<= bd
; i
++)
1365 for (j
= -bd
; j
<= bd
; j
++) {
1366 if (!isok(u
.ux
+ i
, u
.uy
+ j
))
1368 if ((mtmp
= m_at(u
.ux
+ i
, u
.uy
+ j
)) != 0
1369 || (!i
&& !j
&& (mtmp
= u
.usteed
) != 0)) {
1371 res
= maybe_tame(mtmp
, sobj
);
1373 if (canspotmon(mtmp
))
1379 pline("Nothing interesting %s.",
1380 !candidates
? "happens" : "seems to happen");
1382 pline_The("neighborhood %s %sfriendlier.",
1383 vis_results
? "is" : "seems",
1384 (results
< 0) ? "un" : "");
1385 if (vis_results
> 0)
1392 You("have found a scroll of genocide!");
1395 do_class_genocide();
1397 do_genocide(!scursed
| (2 * !!Confusion
));
1400 if (!confused
|| rn2(5)) {
1403 litroom(!confused
&& !scursed
, sobj
);
1404 if (!confused
&& !scursed
) {
1405 if (lightdamage(sobj
, TRUE
, 5))
1409 /* could be scroll of create monster, don't set known ...*/
1410 (void) create_critters(1, !scursed
? &mons
[PM_YELLOW_LIGHT
]
1411 : &mons
[PM_BLACK_LIGHT
],
1413 if (!objects
[sobj
->otyp
].oc_uname
)
1417 case SCR_TELEPORTATION
:
1418 if (confused
|| scursed
) {
1421 known
= scrolltele(sobj
);
1424 case SCR_GOLD_DETECTION
:
1425 if ((confused
|| scursed
) ? trap_detect(sobj
) : gold_detect(sobj
))
1426 sobj
= 0; /* failure: strange_feeling() -> useup() */
1428 case SCR_FOOD_DETECTION
:
1429 case SPE_DETECT_FOOD
:
1430 if (food_detect(sobj
))
1431 sobj
= 0; /* nothing detected: strange_feeling -> useup */
1434 /* known = TRUE; -- handled inline here */
1435 /* use up the scroll first, before makeknown() performs a
1436 perm_invent update; also simplifies empty invent check */
1438 sobj
= 0; /* it's gone */
1440 You("identify this as an identify scroll.");
1441 else if (!already_known
|| !invent
)
1442 /* force feedback now if invent became
1443 empty after using up this scroll */
1444 pline("This is an identify scroll.");
1446 (void) learnscrolltyp(SCR_IDENTIFY
);
1450 if (sblessed
|| (!scursed
&& !rn2(5))) {
1452 /* note: if cval==0, identify all items */
1453 if (cval
== 1 && sblessed
&& Luck
> 0)
1456 if (invent
&& !confused
) {
1457 identify_pack(cval
, !already_known
);
1458 } else if (otyp
== SPE_IDENTIFY
) {
1459 /* when casting a spell we know we're not confused,
1460 so inventory must be empty (another message has
1461 already been given above if reading a scroll) */
1462 pline("You're not carrying anything to be identified.");
1468 You_feel("discharged.");
1471 You_feel("charged up!");
1472 u
.uen
+= d(sblessed
? 6 : 4, 4);
1473 if (u
.uen
> u
.uenmax
) /* if current energy is already at */
1474 u
.uenmax
= u
.uen
; /* or near maximum, increase maximum */
1476 u
.uen
= u
.uenmax
; /* otherwise restore current to max */
1481 /* known = TRUE; -- handled inline here */
1482 if (!already_known
) {
1483 pline("This is a charging scroll.");
1486 /* use it up now to prevent it from showing in the
1487 getobj picklist because the "disappears" message
1488 was already delivered */
1490 sobj
= 0; /* it's gone */
1491 otmp
= getobj(all_count
, "charge");
1493 recharge(otmp
, scursed
? -1 : sblessed
? 1 : 0);
1495 case SCR_MAGIC_MAPPING
:
1496 if (level
.flags
.nommap
) {
1497 Your("mind is filled with crazy lines!");
1499 pline("Wow! Modern art.");
1501 Your("%s spins in bewilderment.", body_part(HEAD
));
1502 make_confused(HConfusion
+ rnd(30), FALSE
);
1508 for (x
= 1; x
< COLNO
; x
++)
1509 for (y
= 0; y
< ROWNO
; y
++)
1510 if (levl
[x
][y
].typ
== SDOOR
)
1511 cvt_sdoor_to_door(&levl
[x
][y
]);
1512 /* do_mapping() already reveals secret passages */
1515 case SPE_MAGIC_MAPPING
:
1516 if (level
.flags
.nommap
) {
1517 Your("%s spins as %s blocks the spell!", body_part(HEAD
),
1519 make_confused(HConfusion
+ rnd(30), FALSE
);
1522 pline("A map coalesces in your mind!");
1523 cval
= (scursed
&& !confused
);
1525 HConfusion
= 1; /* to screw up map */
1528 HConfusion
= 0; /* restore */
1529 pline("Unfortunately, you can't grasp the details.");
1534 forget((!sblessed
? ALL_SPELLS
: 0)
1535 | (!confused
|| scursed
? ALL_MAP
: 0));
1536 if (Hallucination
) /* Ommmmmm! */
1537 Your("mind releases itself from mundane concerns.");
1538 else if (!strncmpi(plname
, "Maud", 4))
1540 "As your mind turns inward on itself, you forget everything else.");
1542 pline("Who was that Maud person anyway?");
1544 pline("Thinking of Maud you forget everything else.");
1545 exercise(A_WIS
, FALSE
);
1548 cval
= bcsign(sobj
);
1550 sobj
= 0; /* it's gone */
1552 (void) learnscrolltyp(SCR_FIRE
);
1554 if (Fire_resistance
) {
1555 shieldeff(u
.ux
, u
.uy
);
1557 pline("Oh, look, what a pretty fire in your %s.",
1558 makeplural(body_part(HAND
)));
1560 You_feel("a pleasant warmth in your %s.",
1561 makeplural(body_part(HAND
)));
1563 pline_The("scroll catches fire and you burn your %s.",
1564 makeplural(body_part(HAND
)));
1565 losehp(1, "scroll of fire", KILLED_BY_AN
);
1570 pline_The("water around you vaporizes violently!");
1572 pline_The("scroll erupts in a tower of flame!");
1573 iflags
.last_msg
= PLNMSG_TOWER_OF_FLAME
; /* for explode() */
1576 explode(u
.ux
, u
.uy
, 11, (2 * (rn1(3, 3) + 2 * cval
) + 1) / 3,
1577 SCROLL_CLASS
, EXPL_FIERY
);
1580 /* TODO: handle steeds */
1581 if (!Is_rogue_level(&u
.uz
) && has_ceiling(&u
.uz
)
1582 && (!In_endgame(&u
.uz
) || Is_earthlevel(&u
.uz
))) {
1586 /* Identify the scroll */
1588 You_hear("rumbling.");
1590 pline_The("%s rumbles %s you!", ceiling(u
.ux
, u
.uy
),
1591 sblessed
? "around" : "above");
1595 /* Loop through the surrounding squares */
1597 for (x
= u
.ux
- 1; x
<= u
.ux
+ 1; x
++) {
1598 for (y
= u
.uy
- 1; y
<= u
.uy
+ 1; y
++) {
1599 /* Is this a suitable spot? */
1600 if (isok(x
, y
) && !closed_door(x
, y
)
1601 && !IS_ROCK(levl
[x
][y
].typ
)
1602 && !IS_AIR(levl
[x
][y
].typ
)
1603 && (x
!= u
.ux
|| y
!= u
.uy
)) {
1605 drop_boulder_on_monster(x
, y
, confused
, TRUE
);
1609 /* Attack the player */
1611 drop_boulder_on_player(confused
, !scursed
, TRUE
, FALSE
);
1612 } else if (!nboulders
)
1613 pline("But nothing else happens.");
1616 case SCR_PUNISHMENT
:
1618 if (confused
|| sblessed
) {
1619 You_feel("guilty.");
1624 case SCR_STINKING_CLOUD
: {
1628 You("have found a scroll of stinking cloud!");
1630 pline("Where do you want to center the %scloud?",
1631 already_known
? "stinking " : "");
1634 getpos_sethilite(display_stinking_cloud_positions
);
1635 if (getpos(&cc
, TRUE
, "the desired position") < 0) {
1639 if (!is_valid_stinking_cloud_pos(cc
.x
, cc
.y
, TRUE
))
1641 (void) create_gas_cloud(cc
.x
, cc
.y
, 3 + bcsign(sobj
),
1642 8 + 4 * bcsign(sobj
));
1646 impossible("What weird effect is this? (%u)", otyp
);
1648 return sobj
? 0 : 1;
1652 drop_boulder_on_player(confused
, helmet_protects
, byu
, skip_uswallow
)
1653 boolean confused
, helmet_protects
, byu
, skip_uswallow
;
1658 /* hit monster if swallowed */
1659 if (u
.uswallow
&& !skip_uswallow
) {
1660 drop_boulder_on_monster(u
.ux
, u
.uy
, confused
, byu
);
1664 otmp2
= mksobj(confused
? ROCK
: BOULDER
, FALSE
, FALSE
);
1667 otmp2
->quan
= confused
? rn1(5, 2) : 1;
1668 otmp2
->owt
= weight(otmp2
);
1669 if (!amorphous(youmonst
.data
) && !Passes_walls
1670 && !noncorporeal(youmonst
.data
) && !unsolid(youmonst
.data
)) {
1671 You("are hit by %s!", doname(otmp2
));
1672 dmg
= dmgval(otmp2
, &youmonst
) * otmp2
->quan
;
1673 if (uarmh
&& helmet_protects
) {
1674 if (is_metallic(uarmh
)) {
1675 pline("Fortunately, you are wearing a hard helmet.");
1678 } else if (flags
.verbose
) {
1679 pline("%s does not protect you.", Yname2(uarmh
));
1684 /* Must be before the losehp(), for bones files */
1685 if (!flooreffects(otmp2
, u
.ux
, u
.uy
, "fall")) {
1686 place_object(otmp2
, u
.ux
, u
.uy
);
1691 losehp(Maybe_Half_Phys(dmg
), "scroll of earth", KILLED_BY_AN
);
1695 drop_boulder_on_monster(x
, y
, confused
, byu
)
1697 boolean confused
, byu
;
1699 register struct obj
*otmp2
;
1700 register struct monst
*mtmp
;
1702 /* Make the object(s) */
1703 otmp2
= mksobj(confused
? ROCK
: BOULDER
, FALSE
, FALSE
);
1705 return FALSE
; /* Shouldn't happen */
1706 otmp2
->quan
= confused
? rn1(5, 2) : 1;
1707 otmp2
->owt
= weight(otmp2
);
1709 /* Find the monster here (won't be player) */
1711 if (mtmp
&& !amorphous(mtmp
->data
) && !passes_walls(mtmp
->data
)
1712 && !noncorporeal(mtmp
->data
) && !unsolid(mtmp
->data
)) {
1713 struct obj
*helmet
= which_armor(mtmp
, W_ARMH
);
1716 if (cansee(mtmp
->mx
, mtmp
->my
)) {
1717 pline("%s is hit by %s!", Monnam(mtmp
), doname(otmp2
));
1718 if (mtmp
->minvis
&& !canspotmon(mtmp
))
1719 map_invisible(mtmp
->mx
, mtmp
->my
);
1720 } else if (u
.uswallow
&& mtmp
== u
.ustuck
)
1721 You_hear("something hit %s %s over your %s!",
1722 s_suffix(mon_nam(mtmp
)), mbodypart(mtmp
, STOMACH
),
1725 mdmg
= dmgval(otmp2
, mtmp
) * otmp2
->quan
;
1727 if (is_metallic(helmet
)) {
1728 if (canspotmon(mtmp
))
1729 pline("Fortunately, %s is wearing a hard helmet.",
1732 You_hear("a clanging sound.");
1736 if (canspotmon(mtmp
))
1737 pline("%s's %s does not protect %s.", Monnam(mtmp
),
1738 xname(helmet
), mhim(mtmp
));
1742 if (mtmp
->mhp
<= 0) {
1746 pline("%s is killed.", Monnam(mtmp
));
1750 } else if (u
.uswallow
&& mtmp
== u
.ustuck
) {
1751 obfree(otmp2
, (struct obj
*) 0);
1752 /* fall through to player */
1753 drop_boulder_on_player(confused
, TRUE
, FALSE
, TRUE
);
1756 /* Drop the rock/boulder to the floor */
1757 if (!flooreffects(otmp2
, x
, y
, "fall")) {
1758 place_object(otmp2
, x
, y
);
1760 newsym(x
, y
); /* map the rock */
1765 /* overcharging any wand or zapping/engraving cursed wand */
1767 wand_explode(obj
, chg
)
1769 int chg
; /* recharging */
1771 const char *expl
= !chg
? "suddenly" : "vibrates violently and";
1774 /* number of damage dice */
1776 chg
= 2; /* zap/engrave adjustment */
1779 n
= 2; /* arbitrary minimum */
1780 /* size of damage dice */
1781 switch (obj
->otyp
) {
1785 case WAN_CANCELLATION
:
1788 case WAN_UNDEAD_TURNING
:
1794 case WAN_MAGIC_MISSILE
:
1804 /* inflict damage and destroy the wand */
1806 obj
->in_use
= TRUE
; /* in case losehp() is fatal (or --More--^C) */
1807 pline("%s %s explodes!", Yname2(obj
), expl
);
1808 losehp(Maybe_Half_Phys(dmg
), "exploding wand", KILLED_BY_AN
);
1810 /* obscure side-effect */
1811 exercise(A_STR
, FALSE
);
1814 /* used to collect gremlins being hit by light so that they can be processed
1815 after vision for the entire lit area has been brought up to date */
1820 STATIC_VAR
struct litmon
*gremlins
= 0;
1823 * Low-level lit-field update routine.
1831 struct litmon
*gremlin
;
1835 if ((mtmp
= m_at(x
, y
)) != 0 && mtmp
->data
== &mons
[PM_GREMLIN
]) {
1836 gremlin
= (struct litmon
*) alloc(sizeof *gremlin
);
1837 gremlin
->mon
= mtmp
;
1838 gremlin
->nxt
= gremlins
;
1843 snuff_light_source(x
, y
);
1849 register boolean on
;
1852 char is_lit
; /* value is irrelevant; we use its address
1853 as a `not null' flag for set_lit() */
1855 /* first produce the text (provided you're not blind) */
1857 register struct obj
*otmp
;
1861 pline("It seems even darker in here than before.");
1863 if (uwep
&& artifact_light(uwep
) && uwep
->lamplit
)
1864 pline("Suddenly, the only light left comes from %s!",
1867 You("are surrounded by darkness!");
1871 /* the magic douses lamps, et al, too */
1872 for (otmp
= invent
; otmp
; otmp
= otmp
->nobj
)
1874 (void) snuff_lit(otmp
);
1879 else if (is_animal(u
.ustuck
->data
))
1880 pline("%s %s is lit.", s_suffix(Monnam(u
.ustuck
)),
1881 mbodypart(u
.ustuck
, STOMACH
));
1882 else if (is_whirly(u
.ustuck
->data
))
1883 pline("%s shines briefly.", Monnam(u
.ustuck
));
1885 pline("%s glistens.", Monnam(u
.ustuck
));
1887 pline("A lit field surrounds you!");
1890 /* No-op when swallowed or in water */
1891 if (u
.uswallow
|| Underwater
|| Is_waterlevel(&u
.uz
))
1894 * If we are darkening the room and the hero is punished but not
1895 * blind, then we have to pick up and replace the ball and chain so
1896 * that we don't remember them if they are out of sight.
1898 if (Punished
&& !on
&& !Blind
)
1899 move_bc(1, 0, uball
->ox
, uball
->oy
, uchain
->ox
, uchain
->oy
);
1901 if (Is_rogue_level(&u
.uz
)) {
1902 /* Can't use do_clear_area because MAX_RADIUS is too small */
1903 /* rogue lighting must light the entire room */
1904 int rnum
= levl
[u
.ux
][u
.uy
].roomno
- ROOMOFFSET
;
1908 for (rx
= rooms
[rnum
].lx
- 1; rx
<= rooms
[rnum
].hx
+ 1; rx
++)
1909 for (ry
= rooms
[rnum
].ly
- 1; ry
<= rooms
[rnum
].hy
+ 1; ry
++)
1911 (genericptr_t
) (on
? &is_lit
: (char *) 0));
1912 rooms
[rnum
].rlit
= on
;
1914 /* hallways remain dark on the rogue level */
1916 do_clear_area(u
.ux
, u
.uy
,
1917 (obj
&& obj
->oclass
== SCROLL_CLASS
&& obj
->blessed
)
1919 set_lit
, (genericptr_t
) (on
? &is_lit
: (char *) 0));
1922 * If we are not blind, then force a redraw on all positions in sight
1923 * by temporarily blinding the hero. The vision recalculation will
1924 * correctly update all previously seen positions *and* correctly
1925 * set the waslit bit [could be messed up from above].
1930 /* replace ball&chain */
1931 if (Punished
&& !on
)
1932 move_bc(0, 0, uball
->ox
, uball
->oy
, uchain
->ox
, uchain
->oy
);
1935 vision_full_recalc
= 1; /* delayed vision recalculation */
1937 struct litmon
*gremlin
;
1939 /* can't delay vision recalc after all */
1941 /* after vision has been updated, monsters who are affected
1942 when hit by light can now be hit by it */
1945 gremlins
= gremlin
->nxt
;
1946 light_hits_gremlin(gremlin
->mon
, rnd(5));
1947 free((genericptr_t
) gremlin
);
1955 int i
, j
, immunecnt
, gonecnt
, goodcnt
, class, feel_dead
= 0;
1957 boolean gameover
= FALSE
; /* true iff killed self */
1961 pline1(thats_enough_tries
);
1965 getlin("What class of monsters do you wish to genocide?", buf
);
1966 (void) mungspaces(buf
);
1968 /* choosing "none" preserves genocideless conduct */
1969 if (*buf
== '\033' || !strcmpi(buf
, "none")
1970 || !strcmpi(buf
, "nothing"))
1973 class = name_to_monclass(buf
, (int *) 0);
1974 if (class == 0 && (i
= name_to_mon(buf
)) != NON_PM
)
1975 class = mons
[i
].mlet
;
1976 immunecnt
= gonecnt
= goodcnt
= 0;
1977 for (i
= LOW_PM
; i
< NUMMONS
; i
++) {
1978 if (mons
[i
].mlet
== class) {
1979 if (!(mons
[i
].geno
& G_GENO
))
1981 else if (mvitals
[i
].mvflags
& G_GENOD
)
1987 if (!goodcnt
&& class != mons
[urole
.malenum
].mlet
1988 && class != mons
[urace
.malenum
].mlet
) {
1990 pline("All such monsters are already nonexistent.");
1991 else if (immunecnt
|| class == S_invisible
)
1992 You("aren't permitted to genocide such monsters.");
1993 else if (wizard
&& buf
[0] == '*') {
1994 register struct monst
*mtmp
, *mtmp2
;
1997 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp2
) {
1999 if (DEADMONSTER(mtmp
))
2004 pline("Eliminated %d monster%s.", gonecnt
, plur(gonecnt
));
2007 pline("That %s does not represent any monster.",
2008 strlen(buf
) == 1 ? "symbol" : "response");
2012 for (i
= LOW_PM
; i
< NUMMONS
; i
++) {
2013 if (mons
[i
].mlet
== class) {
2016 Strcpy(nam
, makeplural(mons
[i
].mname
));
2017 /* Although "genus" is Latin for race, the hero benefits
2018 * from both race and role; thus genocide affects either.
2020 if (Your_Own_Role(i
) || Your_Own_Race(i
)
2021 || ((mons
[i
].geno
& G_GENO
)
2022 && !(mvitals
[i
].mvflags
& G_GENOD
))) {
2023 /* This check must be first since player monsters might
2024 * have G_GENOD or !G_GENO.
2026 mvitals
[i
].mvflags
|= (G_GENOD
| G_NOCORPSE
);
2028 kill_genocided_monsters();
2029 update_inventory(); /* eggs & tins */
2030 pline("Wiped out all %s.", nam
);
2031 if (Upolyd
&& i
== u
.umonnum
) {
2036 /* finish genociding this class of
2037 monsters before ultimately dying */
2042 /* Self-genocide if it matches either your race
2043 or role. Assumption: male and female forms
2044 share same monster class. */
2045 if (i
== urole
.malenum
|| i
== urace
.malenum
) {
2049 You_feel("dead inside.");
2056 } else if (mvitals
[i
].mvflags
& G_GENOD
) {
2058 pline("All %s are already nonexistent.", nam
);
2059 } else if (!gameover
) {
2060 /* suppress feedback about quest beings except
2061 for those applicable to our own role */
2062 if ((mons
[i
].msound
!= MS_LEADER
2063 || quest_info(MS_LEADER
) == i
)
2064 && (mons
[i
].msound
!= MS_NEMESIS
2065 || quest_info(MS_NEMESIS
) == i
)
2066 && (mons
[i
].msound
!= MS_GUARDIAN
2067 || quest_info(MS_GUARDIAN
) == i
)
2068 /* non-leader/nemesis/guardian role-specific monster
2070 && (i
!= PM_NINJA
/* nuisance */
2071 || Role_if(PM_SAMURAI
))) {
2072 boolean named
, uniq
;
2074 named
= type_is_pname(&mons
[i
]) ? TRUE
: FALSE
;
2075 uniq
= (mons
[i
].geno
& G_UNIQ
) ? TRUE
: FALSE
;
2076 /* one special case */
2077 if (i
== PM_HIGH_PRIEST
)
2080 You("aren't permitted to genocide %s%s.",
2081 (uniq
&& !named
) ? "the " : "",
2082 (uniq
|| named
) ? mons
[i
].mname
: nam
);
2087 if (gameover
|| u
.uhp
== -1) {
2088 killer
.format
= KILLED_BY_AN
;
2089 Strcpy(killer
.name
, "scroll of genocide");
2103 /* 0 = no genocide; create monsters (cursed scroll) */
2104 /* 1 = normal genocide */
2105 /* 3 = forced genocide of player */
2106 /* 5 (4 | 1) = normal genocide from throne */
2109 register int i
, killplayer
= 0;
2111 register struct permonst
*ptr
;
2115 mndx
= u
.umonster
; /* non-polymorphed mon num */
2117 Strcpy(buf
, ptr
->mname
);
2122 /* cursed effect => no free pass (unless rndmonst() fails) */
2123 if (!(how
& REALLY
) && (ptr
= rndmonst()) != 0)
2126 pline1(thats_enough_tries
);
2129 getlin("What monster do you want to genocide? [type the name]",
2131 (void) mungspaces(buf
);
2132 /* choosing "none" preserves genocideless conduct */
2133 if (*buf
== '\033' || !strcmpi(buf
, "none")
2134 || !strcmpi(buf
, "nothing")) {
2135 /* ... but no free pass if cursed */
2136 if (!(how
& REALLY
) && (ptr
= rndmonst()) != 0)
2137 break; /* remaining checks don't apply */
2142 mndx
= name_to_mon(buf
);
2143 if (mndx
== NON_PM
|| (mvitals
[mndx
].mvflags
& G_GENOD
)) {
2144 pline("Such creatures %s exist in this world.",
2145 (mndx
== NON_PM
) ? "do not" : "no longer");
2149 /* Although "genus" is Latin for race, the hero benefits
2150 * from both race and role; thus genocide affects either.
2152 if (Your_Own_Role(mndx
) || Your_Own_Race(mndx
)) {
2157 adjalign(-sgn(u
.ualign
.type
));
2159 adjalign(sgn(u
.ualign
.type
));
2161 if (!(ptr
->geno
& G_GENO
)) {
2163 /* FIXME: unconditional "caverns" will be silly in some
2164 * circumstances. Who's speaking? Divine pronouncements
2165 * aren't supposed to be hampered by deafness....
2168 pline("A thunderous voice booms through the caverns:");
2169 verbalize("No, mortal! That will not be done.");
2173 /* KMH -- Unchanging prevents rehumanization */
2174 if (Unchanging
&& ptr
== youmonst
.data
)
2178 mndx
= monsndx(ptr
); /* needed for the 'no free pass' cases */
2182 if (Hallucination
) {
2184 Strcpy(buf
, youmonst
.data
->mname
);
2186 Strcpy(buf
, (flags
.female
&& urole
.name
.f
) ? urole
.name
.f
2188 buf
[0] = lowc(buf
[0]);
2191 Strcpy(buf
, ptr
->mname
); /* make sure we have standard singular */
2192 if ((ptr
->geno
& G_UNIQ
) && ptr
!= &mons
[PM_HIGH_PRIEST
])
2193 which
= !type_is_pname(ptr
) ? "the " : "";
2196 /* setting no-corpse affects wishing and random tin generation */
2197 mvitals
[mndx
].mvflags
|= (G_GENOD
| G_NOCORPSE
);
2198 pline("Wiped out %s%s.", which
,
2199 (*which
!= 'a') ? buf
: makeplural(buf
));
2202 /* might need to wipe out dual role */
2203 if (urole
.femalenum
!= NON_PM
&& mndx
== urole
.malenum
)
2204 mvitals
[urole
.femalenum
].mvflags
|= (G_GENOD
| G_NOCORPSE
);
2205 if (urole
.femalenum
!= NON_PM
&& mndx
== urole
.femalenum
)
2206 mvitals
[urole
.malenum
].mvflags
|= (G_GENOD
| G_NOCORPSE
);
2207 if (urace
.femalenum
!= NON_PM
&& mndx
== urace
.malenum
)
2208 mvitals
[urace
.femalenum
].mvflags
|= (G_GENOD
| G_NOCORPSE
);
2209 if (urace
.femalenum
!= NON_PM
&& mndx
== urace
.femalenum
)
2210 mvitals
[urace
.malenum
].mvflags
|= (G_GENOD
| G_NOCORPSE
);
2214 killer
.format
= KILLED_BY
;
2215 Strcpy(killer
.name
, "genocidal confusion");
2216 } else if (how
& ONTHRONE
) {
2217 /* player selected while on a throne */
2218 killer
.format
= KILLED_BY_AN
;
2219 Strcpy(killer
.name
, "imperious order");
2220 } else { /* selected player deliberately, not confused */
2221 killer
.format
= KILLED_BY_AN
;
2222 Strcpy(killer
.name
, "scroll of genocide");
2225 /* Polymorphed characters will die as soon as they're rehumanized.
2227 /* KMH -- Unchanging prevents rehumanization */
2228 if (Upolyd
&& ptr
!= youmonst
.data
) {
2229 delayed_killer(POLYMORPH
, killer
.format
, killer
.name
);
2230 You_feel("dead inside.");
2233 } else if (ptr
== youmonst
.data
) {
2236 reset_rndmonst(mndx
);
2237 kill_genocided_monsters();
2238 update_inventory(); /* in case identified eggs were affected */
2240 int cnt
= 0, census
= monster_census(FALSE
);
2242 if (!(mons
[mndx
].geno
& G_UNIQ
)
2243 && !(mvitals
[mndx
].mvflags
& (G_GENOD
| G_EXTINCT
)))
2244 for (i
= rn1(3, 4); i
> 0; i
--) {
2245 if (!makemon(ptr
, u
.ux
, u
.uy
, NO_MINVENT
))
2246 break; /* couldn't make one */
2248 if (mvitals
[mndx
].mvflags
& G_EXTINCT
)
2249 break; /* just made last one */
2252 /* accumulated 'cnt' doesn't take groups into account;
2253 assume bringing in new mon(s) didn't remove any old ones */
2254 cnt
= monster_census(FALSE
) - census
;
2255 pline("Sent in %s%s.", (cnt
> 1) ? "some " : "",
2256 (cnt
> 1) ? makeplural(buf
) : an(buf
));
2258 pline1(nothing_happens
);
2266 struct obj
*reuse_ball
= (sobj
&& sobj
->otyp
== HEAVY_IRON_BALL
)
2267 ? sobj
: (struct obj
*) 0;
2269 /* KMH -- Punishment is still okay when you are riding */
2271 You("are being punished for your misbehavior!");
2273 Your("iron ball gets heavier.");
2274 uball
->owt
+= IRON_BALL_W_INCR
* (1 + sobj
->cursed
);
2277 if (amorphous(youmonst
.data
) || is_whirly(youmonst
.data
)
2278 || unsolid(youmonst
.data
)) {
2280 pline("A ball and chain appears, then falls away.");
2281 dropy(mkobj(BALL_CLASS
, TRUE
));
2287 setworn(mkobj(CHAIN_CLASS
, TRUE
), W_CHAIN
);
2289 setworn(mkobj(BALL_CLASS
, TRUE
), W_BALL
);
2291 setworn(reuse_ball
, W_BALL
);
2292 uball
->spe
= 1; /* special ball (see save) */
2295 * Place ball & chain if not swallowed. If swallowed, the ball &
2296 * chain variables will be set at the next call to placebc().
2301 set_bc(1); /* set up ball and chain variables */
2302 newsym(u
.ux
, u
.uy
); /* see ball&chain if can't see self */
2306 /* remove the ball and chain */
2310 struct obj
*savechain
= uchain
;
2312 obj_extract_self(uchain
);
2313 newsym(uchain
->ox
, uchain
->oy
);
2314 setworn((struct obj
*) 0, W_CHAIN
);
2315 dealloc_obj(savechain
);
2317 setworn((struct obj
*) 0, W_BALL
);
2320 /* some creatures have special data structures that only make sense in their
2321 * normal locations -- if the player tries to create one elsewhere, or to
2322 * revive one, the disoriented creature becomes a zombie
2325 cant_revive(mtype
, revival
, from_obj
)
2328 struct obj
*from_obj
;
2330 /* SHOPKEEPERS can be revived now */
2331 if (*mtype
== PM_GUARD
|| (*mtype
== PM_SHOPKEEPER
&& !revival
)
2332 || *mtype
== PM_HIGH_PRIEST
|| *mtype
== PM_ALIGNED_PRIEST
2333 || *mtype
== PM_ANGEL
) {
2334 *mtype
= PM_HUMAN_ZOMBIE
;
2336 } else if (*mtype
== PM_LONG_WORM_TAIL
) { /* for create_particular() */
2337 *mtype
= PM_LONG_WORM
;
2339 } else if (unique_corpstat(&mons
[*mtype
])
2340 && (!from_obj
|| !has_omonst(from_obj
))) {
2341 /* unique corpses (from bones or wizard mode wish) or
2342 statues (bones or any wish) end up as shapechangers */
2343 *mtype
= PM_DOPPELGANGER
;
2350 * Make a new monster with the type controlled by the user.
2352 * Note: when creating a monster by class letter, specifying the
2353 * "strange object" (']') symbol produces a random monster rather
2354 * than a mimic. This behavior quirk is useful so don't "fix" it
2355 * (use 'm'--or "mimic"--to create a random mimic).
2357 * Used in wizard mode only (for ^G command and for scroll or spell
2358 * of create monster). Once upon a time, an earlier incarnation of
2359 * this code was also used for the scroll/spell in explore mode.
2364 char buf
[BUFSZ
], *bufp
, monclass
;
2365 int which
, tryct
, i
, firstchoice
= NON_PM
;
2366 struct permonst
*whichpm
= NULL
;
2368 boolean madeany
= FALSE
;
2369 boolean maketame
, makepeaceful
, makehostile
;
2370 boolean randmonst
= FALSE
;
2374 monclass
= MAXMCLASSES
;
2375 which
= urole
.malenum
; /* an arbitrary index into mons[] */
2376 maketame
= makepeaceful
= makehostile
= FALSE
;
2377 getlin("Create what kind of monster? [type the name or symbol]", buf
);
2378 bufp
= mungspaces(buf
);
2379 if (*bufp
== '\033')
2381 /* allow the initial disposition to be specified */
2382 if (!strncmpi(bufp
, "tame ", 5)) {
2385 } else if (!strncmpi(bufp
, "peaceful ", 9)) {
2387 makepeaceful
= TRUE
;
2388 } else if (!strncmpi(bufp
, "hostile ", 8)) {
2392 /* decide whether a valid monster was chosen */
2393 if (wizard
&& (!strcmp(bufp
, "*") || !strcmp(bufp
, "random"))) {
2397 which
= name_to_mon(bufp
);
2398 if (which
>= LOW_PM
)
2399 break; /* got one */
2400 monclass
= name_to_monclass(bufp
, &which
);
2401 if (which
>= LOW_PM
) {
2402 monclass
= MAXMCLASSES
; /* matters below */
2404 } else if (monclass
> 0) {
2405 which
= urole
.malenum
; /* reset from NON_PM */
2408 /* no good; try again... */
2409 pline("I've never heard of such monsters.");
2410 } while (--tryct
> 0);
2413 pline1(thats_enough_tries
);
2416 firstchoice
= which
;
2417 if (cant_revive(&which
, FALSE
, (struct obj
*) 0)) {
2418 /* wizard mode can override handling of special monsters */
2419 Sprintf(buf
, "Creating %s instead; force %s?",
2420 mons
[which
].mname
, mons
[firstchoice
].mname
);
2422 which
= firstchoice
;
2424 whichpm
= &mons
[which
];
2426 for (i
= 0; i
<= multi
; i
++) {
2427 if (monclass
!= MAXMCLASSES
)
2428 whichpm
= mkclass(monclass
, 0);
2430 whichpm
= rndmonst();
2431 mtmp
= makemon(whichpm
, u
.ux
, u
.uy
, NO_MM_FLAGS
);
2433 /* quit trying if creation failed and is going to repeat */
2434 if (monclass
== MAXMCLASSES
&& !randmonst
)
2436 /* otherwise try again */
2440 (void) tamedog(mtmp
, (struct obj
*) 0);
2441 } else if (makepeaceful
|| makehostile
) {
2442 mtmp
->mtame
= 0; /* sanity precaution */
2443 mtmp
->mpeaceful
= makepeaceful
? 1 : 0;
2447 /* in case we got a doppelganger instead of what was asked
2448 for, make it start out looking like what was asked for */
2449 if (mtmp
->cham
!= NON_PM
&& firstchoice
!= NON_PM
2450 && mtmp
->cham
!= firstchoice
)
2451 (void) newcham(mtmp
, &mons
[firstchoice
], FALSE
, FALSE
);