xref: /netbsd/games/hack/hack.wizard.c (revision bf9ec67e)
1 /*	$NetBSD: hack.wizard.c,v 1.5 2001/03/25 20:44:04 jsm Exp $	*/
2 
3 /*
4  * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
5  */
6 
7 #include <sys/cdefs.h>
8 #ifndef lint
9 __RCSID("$NetBSD: hack.wizard.c,v 1.5 2001/03/25 20:44:04 jsm Exp $");
10 #endif				/* not lint */
11 
12 /* wizard code - inspired by rogue code from Merlyn Leroy (digi-g!brian) */
13 
14 #include "hack.h"
15 #include "extern.h"
16 
17 #define	WIZSHOT	    6		/* one chance in WIZSHOT that wizard will try
18 				 * magic */
19 #define	BOLT_LIM    8		/* from this distance D and 1 will try to hit
20 				 * you */
21 
22 const char            wizapp[] = "@DNPTUVXcemntx";
23 
24 /* If he has found the Amulet, make the wizard appear after some time */
25 void
26 amulet()
27 {
28 	struct obj     *otmp;
29 	struct monst   *mtmp;
30 
31 	if (!flags.made_amulet || !flags.no_of_wizards)
32 		return;
33 	/* find wizard, and wake him if necessary */
34 	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
35 		if (mtmp->data->mlet == '1' && mtmp->msleep && !rn2(40))
36 			for (otmp = invent; otmp; otmp = otmp->nobj)
37 				if (otmp->olet == AMULET_SYM && !otmp->spe) {
38 					mtmp->msleep = 0;
39 					if (dist(mtmp->mx, mtmp->my) > 2)
40 						pline(
41 						      "You get the creepy feeling that somebody noticed your taking the Amulet."
42 							);
43 					return;
44 				}
45 }
46 
47 int
48 wiz_hit(mtmp)
49 	struct monst   *mtmp;
50 {
51 	/* if we have stolen or found the amulet, we disappear */
52 	if (mtmp->minvent && mtmp->minvent->olet == AMULET_SYM &&
53 	    mtmp->minvent->spe == 0) {
54 		/* vanish -- very primitive */
55 		fall_down(mtmp);
56 		return (1);
57 	}
58 	/* if it is lying around someplace, we teleport to it */
59 	if (!carrying(AMULET_OF_YENDOR)) {
60 		struct obj     *otmp;
61 
62 		for (otmp = fobj; otmp; otmp = otmp->nobj)
63 			if (otmp->olet == AMULET_SYM && !otmp->spe) {
64 				if ((u.ux != otmp->ox || u.uy != otmp->oy) &&
65 				    !m_at(otmp->ox, otmp->oy)) {
66 
67 					/* teleport to it and pick it up */
68 					mtmp->mx = otmp->ox;
69 					mtmp->my = otmp->oy;
70 					freeobj(otmp);
71 					mpickobj(mtmp, otmp);
72 					pmon(mtmp);
73 					return (0);
74 				}
75 				goto hithim;
76 			}
77 		return (0);	/* we don't know where it is */
78 	}
79 hithim:
80 	if (rn2(2)) {		/* hit - perhaps steal */
81 
82 		/*
83 		 * if hit 1/20 chance of stealing amulet & vanish - amulet is
84 		 * on level 26 again.
85 		 */
86 		if (hitu(mtmp, d(mtmp->data->damn, mtmp->data->damd))
87 		    && !rn2(20) && stealamulet(mtmp));
88 	} else
89 		inrange(mtmp);	/* try magic */
90 	return (0);
91 }
92 
93 void
94 inrange(mtmp)
95 	struct monst   *mtmp;
96 {
97 	schar           tx, ty;
98 
99 	/* do nothing if cancelled (but make '1' say something) */
100 	if (mtmp->data->mlet != '1' && mtmp->mcan)
101 		return;
102 
103 	/* spit fire only when both in a room or both in a corridor */
104 	if (inroom(u.ux, u.uy) != inroom(mtmp->mx, mtmp->my))
105 		return;
106 	tx = u.ux - mtmp->mx;
107 	ty = u.uy - mtmp->my;
108 	if ((!tx && abs(ty) < BOLT_LIM) || (!ty && abs(tx) < BOLT_LIM)
109 	    || (abs(tx) == abs(ty) && abs(tx) < BOLT_LIM)) {
110 		switch (mtmp->data->mlet) {
111 		case 'D':
112 			/* spit fire in the direction of @ (not nec. hitting) */
113 			buzz(-1, mtmp->mx, mtmp->my, sgn(tx), sgn(ty));
114 			break;
115 		case '1':
116 			if (rn2(WIZSHOT))
117 				break;
118 			/*
119 			 * if you zapped wizard with wand of cancellation, he
120 			 * has to shake off the effects before he can throw
121 			 * spells successfully.  1/2 the time they fail
122 			 * anyway
123 			 */
124 			if (mtmp->mcan || rn2(2)) {
125 				if (canseemon(mtmp))
126 					pline("%s makes a gesture, then curses.",
127 					      Monnam(mtmp));
128 				else
129 					pline("You hear mumbled cursing.");
130 				if (!rn2(3)) {
131 					mtmp->mspeed = 0;
132 					mtmp->minvis = 0;
133 				}
134 				if (!rn2(3))
135 					mtmp->mcan = 0;
136 			} else {
137 				if (canseemon(mtmp)) {
138 					if (!rn2(6) && !Invis) {
139 						pline("%s hypnotizes you.", Monnam(mtmp));
140 						nomul(rn2(3) + 3);
141 						break;
142 					} else
143 						pline("%s chants an incantation.",
144 						      Monnam(mtmp));
145 				} else
146 					pline("You hear a mumbled incantation.");
147 				switch (rn2(Invis ? 5 : 6)) {
148 				case 0:
149 					/*
150 					 * create a nasty monster from a deep
151 					 * level
152 					 */
153 					/*
154 					 * (for the moment, 'nasty' is not
155 					 * implemented)
156 					 */
157 					(void) makemon((struct permonst *) 0, u.ux, u.uy);
158 					break;
159 				case 1:
160 					pline("\"Destroy the thief, my pets!\"");
161 					aggravate();	/* aggravate all the
162 							 * monsters */
163 					/* fall into next case */
164 				case 2:
165 					if (flags.no_of_wizards == 1 && rnd(5) == 0)
166 						/*
167 						 * if only 1 wizard, clone
168 						 * himself
169 						 */
170 						clonewiz(mtmp);
171 					break;
172 				case 3:
173 					if (mtmp->mspeed == MSLOW)
174 						mtmp->mspeed = 0;
175 					else
176 						mtmp->mspeed = MFAST;
177 					break;
178 				case 4:
179 					mtmp->minvis = 1;
180 					break;
181 				case 5:
182 					/* Only if not Invisible */
183 					pline("You hear a clap of thunder!");
184 					/*
185 					 * shoot a bolt of fire or cold, or a
186 					 * sleep ray
187 					 */
188 					buzz(-rnd(3), mtmp->mx, mtmp->my, sgn(tx), sgn(ty));
189 					break;
190 				}
191 			}
192 		}
193 		if (u.uhp < 1)
194 			done_in_by(mtmp);
195 	}
196 }
197 
198 void
199 aggravate()
200 {
201 	struct monst   *mtmp;
202 
203 	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
204 		mtmp->msleep = 0;
205 		if (mtmp->mfroz && !rn2(5))
206 			mtmp->mfroz = 0;
207 	}
208 }
209 
210 void
211 clonewiz(mtmp)
212 	struct monst   *mtmp;
213 {
214 	struct monst   *mtmp2;
215 
216 	if ((mtmp2 = makemon(PM_WIZARD, mtmp->mx, mtmp->my)) != NULL) {
217 		flags.no_of_wizards = 2;
218 		unpmon(mtmp2);
219 		mtmp2->mappearance = wizapp[rn2(sizeof(wizapp) - 1)];
220 		pmon(mtmp);
221 	}
222 }
223