1 /*        $NetBSD: hack.wizard.c,v 1.10 2011/08/07 06:03:45 dholland Exp $      */
2 
3 /*
4  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5  * Amsterdam
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met:
11  *
12  * - Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * - Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  *
19  * - Neither the name of the Stichting Centrum voor Wiskunde en
20  * Informatica, nor the names of its contributors may be used to endorse or
21  * promote products derived from this software without specific prior
22  * written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 /*
38  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39  * All rights reserved.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. The name of the author may not be used to endorse or promote products
50  *    derived from this software without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
55  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62  */
63 
64 #include <sys/cdefs.h>
65 #ifndef lint
66 __RCSID("$NetBSD: hack.wizard.c,v 1.10 2011/08/07 06:03:45 dholland Exp $");
67 #endif                                  /* not lint */
68 
69 /* wizard code - inspired by rogue code from Merlyn Leroy (digi-g!brian) */
70 
71 #include "hack.h"
72 #include "extern.h"
73 
74 #define   WIZSHOT       6               /* one chance in WIZSHOT that wizard will try
75                                          * magic */
76 #define   BOLT_LIM    8                 /* from this distance D and 1 will try to hit
77                                          * you */
78 
79 static const char wizapp[] = "@DNPTUVXcemntx";
80 
81 static void aggravate(void);
82 static void clonewiz(struct monst *);
83 
84 
85 /* If he has found the Amulet, make the wizard appear after some time */
86 void
amulet(void)87 amulet(void)
88 {
89           struct obj     *otmp;
90           struct monst   *mtmp;
91 
92           if (!flags.made_amulet || !flags.no_of_wizards)
93                     return;
94           /* find wizard, and wake him if necessary */
95           for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
96                     if (mtmp->data->mlet == '1' && mtmp->msleep && !rn2(40))
97                               for (otmp = invent; otmp; otmp = otmp->nobj)
98                                         if (otmp->olet == AMULET_SYM && !otmp->spe) {
99                                                   mtmp->msleep = 0;
100                                                   if (dist(mtmp->mx, mtmp->my) > 2)
101                                                             pline(
102                                                                   "You get the creepy feeling that somebody noticed your taking the Amulet."
103                                                                       );
104                                                   return;
105                                         }
106 }
107 
108 int
wiz_hit(struct monst * mtmp)109 wiz_hit(struct monst *mtmp)
110 {
111           /* if we have stolen or found the amulet, we disappear */
112           if (mtmp->minvent && mtmp->minvent->olet == AMULET_SYM &&
113               mtmp->minvent->spe == 0) {
114                     /* vanish -- very primitive */
115                     fall_down(mtmp);
116                     return (1);
117           }
118           /* if it is lying around someplace, we teleport to it */
119           if (!carrying(AMULET_OF_YENDOR)) {
120                     struct obj     *otmp;
121 
122                     for (otmp = fobj; otmp; otmp = otmp->nobj)
123                               if (otmp->olet == AMULET_SYM && !otmp->spe) {
124                                         if ((u.ux != otmp->ox || u.uy != otmp->oy) &&
125                                             !m_at(otmp->ox, otmp->oy)) {
126 
127                                                   /* teleport to it and pick it up */
128                                                   mtmp->mx = otmp->ox;
129                                                   mtmp->my = otmp->oy;
130                                                   freeobj(otmp);
131                                                   mpickobj(mtmp, otmp);
132                                                   pmon(mtmp);
133                                                   return (0);
134                                         }
135                                         goto hithim;
136                               }
137                     return (0);         /* we don't know where it is */
138           }
139 hithim:
140           if (rn2(2)) {                 /* hit - perhaps steal */
141 
142                     /*
143                      * if hit 1/20 chance of stealing amulet & vanish - amulet is
144                      * on level 26 again.
145                      */
146                     if (hitu(mtmp, d(mtmp->data->damn, mtmp->data->damd))
147                         && !rn2(20) && stealamulet(mtmp)) {
148                               /* nothing */
149                     }
150           } else
151                     inrange(mtmp);      /* try magic */
152           return (0);
153 }
154 
155 void
inrange(struct monst * mtmp)156 inrange(struct monst *mtmp)
157 {
158           schar           tx, ty;
159 
160           /* do nothing if cancelled (but make '1' say something) */
161           if (mtmp->data->mlet != '1' && mtmp->mcan)
162                     return;
163 
164           /* spit fire only when both in a room or both in a corridor */
165           if (inroom(u.ux, u.uy) != inroom(mtmp->mx, mtmp->my))
166                     return;
167           tx = u.ux - mtmp->mx;
168           ty = u.uy - mtmp->my;
169           if ((!tx && abs(ty) < BOLT_LIM) || (!ty && abs(tx) < BOLT_LIM)
170               || (abs(tx) == abs(ty) && abs(tx) < BOLT_LIM)) {
171                     switch (mtmp->data->mlet) {
172                     case 'D':
173                               /* spit fire in the direction of @ (not nec. hitting) */
174                               buzz(-1, mtmp->mx, mtmp->my, sgn(tx), sgn(ty));
175                               break;
176                     case '1':
177                               if (rn2(WIZSHOT))
178                                         break;
179                               /*
180                                * if you zapped wizard with wand of cancellation, he
181                                * has to shake off the effects before he can throw
182                                * spells successfully.  1/2 the time they fail
183                                * anyway
184                                */
185                               if (mtmp->mcan || rn2(2)) {
186                                         if (canseemon(mtmp))
187                                                   pline("%s makes a gesture, then curses.",
188                                                         Monnam(mtmp));
189                                         else
190                                                   pline("You hear mumbled cursing.");
191                                         if (!rn2(3)) {
192                                                   mtmp->mspeed = 0;
193                                                   mtmp->minvis = 0;
194                                         }
195                                         if (!rn2(3))
196                                                   mtmp->mcan = 0;
197                               } else {
198                                         if (canseemon(mtmp)) {
199                                                   if (!rn2(6) && !Invis) {
200                                                             pline("%s hypnotizes you.", Monnam(mtmp));
201                                                             nomul(rn2(3) + 3);
202                                                             break;
203                                                   } else
204                                                             pline("%s chants an incantation.",
205                                                                   Monnam(mtmp));
206                                         } else
207                                                   pline("You hear a mumbled incantation.");
208                                         switch (rn2(Invis ? 5 : 6)) {
209                                         case 0:
210                                                   /*
211                                                    * create a nasty monster from a deep
212                                                    * level
213                                                    */
214                                                   /*
215                                                    * (for the moment, 'nasty' is not
216                                                    * implemented)
217                                                    */
218                                                   (void) makemon((struct permonst *) 0, u.ux, u.uy);
219                                                   break;
220                                         case 1:
221                                                   pline("\"Destroy the thief, my pets!\"");
222                                                   aggravate();        /* aggravate all the
223                                                                        * monsters */
224                                                   /* FALLTHROUGH */
225                                         case 2:
226                                                   if (flags.no_of_wizards == 1 && rnd(5) == 0)
227                                                             /*
228                                                              * if only 1 wizard, clone
229                                                              * himself
230                                                              */
231                                                             clonewiz(mtmp);
232                                                   break;
233                                         case 3:
234                                                   if (mtmp->mspeed == MSLOW)
235                                                             mtmp->mspeed = 0;
236                                                   else
237                                                             mtmp->mspeed = MFAST;
238                                                   break;
239                                         case 4:
240                                                   mtmp->minvis = 1;
241                                                   break;
242                                         case 5:
243                                                   /* Only if not Invisible */
244                                                   pline("You hear a clap of thunder!");
245                                                   /*
246                                                    * shoot a bolt of fire or cold, or a
247                                                    * sleep ray
248                                                    */
249                                                   buzz(-rnd(3), mtmp->mx, mtmp->my, sgn(tx), sgn(ty));
250                                                   break;
251                                         }
252                               }
253                     }
254                     if (u.uhp < 1)
255                               done_in_by(mtmp);
256           }
257 }
258 
259 void
aggravate(void)260 aggravate(void)
261 {
262           struct monst   *mtmp;
263 
264           for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
265                     mtmp->msleep = 0;
266                     if (mtmp->mfroz && !rn2(5))
267                               mtmp->mfroz = 0;
268           }
269 }
270 
271 void
clonewiz(struct monst * mtmp)272 clonewiz(struct monst *mtmp)
273 {
274           struct monst   *mtmp2;
275 
276           if ((mtmp2 = makemon(PM_WIZARD, mtmp->mx, mtmp->my)) != NULL) {
277                     flags.no_of_wizards = 2;
278                     unpmon(mtmp2);
279                     mtmp2->mappearance = wizapp[rn2(sizeof(wizapp) - 1)];
280                     pmon(mtmp);
281           }
282 }
283