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