xref: /openbsd-src/games/hack/hack.wizard.c (revision aed906e4b20d9afbda31247cdb6acf6f29da8819)
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