Source:NetHack 2.3e/wizard.c

From NetHackWiki
Revision as of 04:11, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 2.3e/wizard.c moved to Source:NetHack 2.3e/wizard.c: Robot: moved page)
Jump to navigation Jump to search

Below is the full text to wizard.c from the source code of NetHack 2.3e. To link to a particular line, write [[NetHack 2.3e/wizard.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

Screenshots and source code from Hack are used under the CWI license.

1.    /*	SCCS Id: @(#)wizard.c	2.3	88/02/11
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    
4.    /* wizard code - inspired by rogue code from Merlyn Leroy (digi-g!brian) */
5.    /*	       - heavily modified to give the wiz balls.  (genat!mike)   */
6.    
7.    #include "hack.h"
8.    extern struct permonst pm_wizard;
9.    extern struct monst *makemon();
10.   extern struct obj *carrying(), *mksobj_at();
11.   
12.   #if defined(HARD) || defined(DGKMOD)
13.   # ifdef SAC
14.   char	nasties[] = "cdDeImoPTUVwxXz3&,:;";
15.   # else
16.   char	nasties[] = "cdDeImoPTUVwxXz&,:;";
17.   # endif
18.   #define WIZSHOT	    2
19.   #else
20.   #define	WIZSHOT	    6	/* one chance in WIZSHOT that wizard will try magic */
21.   #endif
22.   
23.   #define	BOLT_LIM    8	/* from this distance D and 1 will try to hit you */
24.   
25.   char wizapp[] = "@&DNPTUVXcemntx";
26.   
27.   #ifdef DGKMOD
28.   #define URETREATING(x,y) (movedist(u.ux,u.uy,x,y) > movedist(u.ux0,u.uy0,x,y))
29.   extern char mlarge[];
30.   
31.   movedist(x0, x1, y0, y1)
32.   {
33.   	register int absdx, absdy;
34.   
35.   	absdx = abs(x1 - x0);
36.   	absdy = abs(y1 - y0);
37.   
38.   	return (absdx + absdy - min(absdx, absdy));
39.   }
40.   #endif
41.   
42.   /* If he has found the Amulet, make the wizard appear after some time */
43.   amulet(){
44.   	register struct obj *otmp;
45.   	register struct monst *mtmp;
46.   
47.   	if(!flags.made_amulet || !flags.no_of_wizards)
48.   		return;
49.   	/* find wizard, and wake him if necessary */
50.   	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
51.   	    if(mtmp->data->mlet == '1' && mtmp->msleep && !rn2(40))
52.   		for(otmp = invent; otmp; otmp = otmp->nobj)
53.   		    if(otmp->olet == AMULET_SYM && !otmp->spe) {
54.   			mtmp->msleep = 0;
55.   			if(dist(mtmp->mx,mtmp->my) > 2)
56.   			    pline(
57.       "You get the creepy feeling that somebody noticed your taking the Amulet."
58.   			    );
59.   			return;
60.   		    }
61.   }
62.   
63.   wiz_hit(mtmp)
64.   register struct monst *mtmp;
65.   {
66.   	/* if we have stolen or found the amulet, we disappear */
67.   	if(mtmp->minvent && mtmp->minvent->olet == AMULET_SYM &&
68.   	    mtmp->minvent->spe == 0) {
69.   		/* vanish -- very primitive */
70.   		fall_down(mtmp);
71.   		return(1);
72.   	}
73.   
74.   	/* if it is lying around someplace, we teleport to it */
75.   	if(!carrying(AMULET_SYM)) {
76.   	    register struct obj *otmp;
77.   
78.   	    for(otmp = fobj; otmp; otmp = otmp->nobj)
79.   		if(otmp->olet == AMULET_SYM && !otmp->spe) {
80.   		    if((u.ux != otmp->ox || u.uy != otmp->oy) &&
81.   		       !m_at(otmp->ox, otmp->oy)) {
82.   
83.   			/* teleport to it and pick it up */
84.   			mtmp->mx = otmp->ox;
85.   			mtmp->my = otmp->oy;
86.   			freeobj(otmp);
87.   			mpickobj(mtmp, otmp);
88.   			pmon(mtmp);
89.   			return(0);
90.   		    }
91.   		    goto hithim;
92.   		}
93.   	    return(0);				/* we don't know where it is */
94.   	}
95.   hithim:
96.   	if(rn2(2)) {				/* hit - perhaps steal */
97.   
98.   	    /* if hit 1/20 chance of stealing amulet & vanish
99.   		- amulet is on level 26 again. */
100.  	    if(hitu(mtmp, d(mtmp->data->damn,mtmp->data->damd))
101.  		&& !rn2(20) && stealamulet(mtmp))
102.  		;
103.  	}
104.  	else    inrange(mtmp);			/* try magic */
105.  	return(0);
106.  }
107.  
108.  #ifdef DGKMOD
109.  /* Check if a monster is carrying a particular item.
110.   */
111.  struct obj *
112.  m_carrying(mtmp, type)
113.  struct monst *mtmp;
114.  int type;
115.  {
116.  	register struct obj *otmp;
117.  
118.  	for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
119.  		if(otmp->otyp == type)
120.  			return(otmp);
121.  	return((struct obj *) 0);
122.  }
123.  
124.  /* Remove an item from the monster's inventory.
125.   */
126.  m_useup(mon, obj)
127.  struct monst *mon;
128.  struct obj *obj;
129.  {
130.  	struct obj *otmp, *prev;
131.  
132.  	prev = ((struct obj *) 0);
133.  	for (otmp = mon->minvent; otmp; otmp = otmp->nobj) {
134.  		if (otmp == obj) {
135.  			if (prev)
136.  				prev->nobj = obj->nobj;
137.  			else
138.  				mon->minvent = obj->nobj;
139.  			free((char *) obj);
140.  			break;
141.  		}
142.  		prev = otmp;
143.  	}
144.  }
145.  
146.  m_throw(x, y, dx, dy, range, obj)
147.  register int x,y,dx,dy,range;		/* direction and range */
148.  register struct obj *obj;
149.  {
150.  	register struct monst *mtmp;
151.  	struct objclass *oclass = &objects[obj->otyp];
152.  	char sym = obj->olet;
153.  	int damage;
154.  	extern char *exclam();
155.  
156.  	bhitpos.x = x;
157.  	bhitpos.y = y;
158.  
159.  	if(sym) tmp_at(-1, sym);	/* open call */
160.  	while(range-- > 0) {
161.  		bhitpos.x += dx;
162.  		bhitpos.y += dy;
163.  		if(mtmp = m_at(bhitpos.x,bhitpos.y)) {
164.  			damage = index(mlarge, mtmp->data->mlet)
165.  				? oclass->wldam
166.  				: oclass->wsdam;
167.  #ifdef KAA
168.  # ifdef KOPS
169.  			if(obj->otyp == CREAM_PIE) damage = 0;
170.  # endif
171.  			if(mtmp->data->ac + 8 <= rnd(20))
172.  				miss(oclass->oc_name, mtmp);
173.  			else {
174.  #endif
175.  				hit(oclass->oc_name, mtmp, exclam(damage));
176.  				mtmp->mhp -= damage;
177.  				if(mtmp->mhp < 1) {
178.  					pline("%s is killed!", (Blind) ? "It" : Monnam(mtmp));
179.  					mondied(mtmp);
180.  				}
181.  				range = 0;
182.  #ifdef KAA
183.  # ifdef KOPS
184.  				if(obj->otyp == CREAM_PIE) {
185.  
186.  					pline("%s is blinded by the pie.", (Blind) ? "It" : Monnam(mtmp));
187.  					if(mtmp->msleep) mtmp->msleep = 0;
188.  					setmangry(mtmp);
189.  					mtmp->mcansee = 0;
190.  					mtmp->mblinded += rnd(25);
191.  					if (mtmp->mblinded <= 0)
192.  						mtmp->mblinded = 127;
193.  				} else
194.  # endif
195.  				    if(obj->otyp == ENORMOUS_ROCK) {
196.  					mksobj_at(ENORMOUS_ROCK, bhitpos.x, bhitpos.y);
197.  					fobj->quan=1;
198.  					stackobj(fobj);
199.  				}
200.  			}
201.  #endif
202.  		}
203.  		if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
204.  			if (multi)
205.  				nomul(0);
206.  #ifdef KAA
207.  /* For giants throwing rocks, the rock which hits you shouldn't disappear. */
208.  # ifdef KOPS
209.  /* Cream pies must disappear if they hit or miss. */
210.  			{ int hit, blindinc, thitu();
211.  			 if (!(hit = thitu(8, (obj->otyp != CREAM_PIE) ? rnd(oclass->wldam) : 0, oclass->oc_name))
212.  			    && obj->otyp != CREAM_PIE
213.  # else
214.  			 if (!thitu(8, rnd(oclass->wldam), oclass->oc_name)
215.  # endif /* KOPS /**/
216.  			    || obj->otyp == ENORMOUS_ROCK) {
217.  #else
218.  			 if (!thitu(8, rnd(oclass->wldam), oclass->oc_name)) {
219.  #endif /* KAA /**/
220.  				mksobj_at(obj->otyp, u.ux, u.uy);
221.  				fobj->quan = 1;
222.  				stackobj(fobj);
223.  			 }
224.  #if defined(KAA) && defined(KOPS)
225.  			 if(hit && obj->otyp == CREAM_PIE) {
226.  			    if(!Blind)	pline("Yeech! You've been creamed.");
227.  			    else	pline("There's something sticky all over your face.");
228.  			    /* blindfold keeps pie filling out of your eyes */
229.  			    if (!Blindfolded) {
230.  				u.ucreamed += (blindinc = rnd(25));
231.  				Blinded += blindinc;
232.  				seeoff(0);
233.  			    }
234.  			 }
235.  			}
236.  #endif
237.  			range = 0;
238.  		}
239.  		tmp_at(bhitpos.x, bhitpos.y);
240.  #ifdef SINKS
241.  		if(IS_SINK(levl[bhitpos.x][bhitpos.y].typ))
242.  			break;	/* thrown objects fall on sink */
243.  #endif
244.  	}
245.  	tmp_at(-1, -1);
246.  }
247.  #endif
248.  
249.  /* Return 1 if it's OK for the monster to move as well as (throw,
250.   * zap, etc).
251.   */
252.  inrange(mtmp)
253.  register struct monst *mtmp;
254.  {
255.  	register schar tx,ty;
256.  #ifdef DGKMOD
257.  	struct obj *otmp;
258.  	register xchar x, y;
259.  #endif
260.  	/* do nothing if cancelled (but make '1' say something) */
261.  	if(mtmp->data->mlet != '1' && mtmp->mcan) return(1);
262.  
263.  	/* spit fire only when both in a room or both in a corridor */
264.  #ifndef RPH
265.  	if(inroom(u.ux,u.uy) != inroom(mtmp->mx,mtmp->my)) return(1);
266.  #endif
267.  	tx = u.ux - mtmp->mx;
268.  	ty = u.uy - mtmp->my;
269.  #ifdef DGKMOD
270.  	if ((!tx || !ty || abs(tx) == abs(ty))	/* straight line or diagonal */
271.  		&& movedist(tx, 0,  ty, 0) < BOLT_LIM) {
272.  		/* Check if there are any dead squares between.  If so,
273.  		 * it won't be possible to shoot.
274.  		 */
275.  		for (x = mtmp->mx, y = mtmp->my; x != u.ux || y != u.uy;
276.  				x += sgn(tx), y += sgn(ty))
277.  			if (!ACCESSIBLE(levl[x][y].typ))
278.  				return(1);
279.  
280.  		switch(mtmp->data->mlet) {
281.  #ifdef KOPS
282.  		case 'O':
283.  #endif
284.  #ifdef KAA
285.  		case '9':
286.  #endif
287.  		case 'K':
288.  		case 'C':
289.  		/* If you're coming toward the monster, the monster
290.  		 * should try to soften you up with arrows.  If you're
291.  		 * going away, you are probably hurt or running.  Give
292.  		 * chase, but if you're getting too far away, throw.
293.  		 */
294.  		x = mtmp->mx;
295.  		y = mtmp->my;
296.  #ifdef KOPS
297.  		otmp = (mtmp->data->mlet == 'O') ? m_carrying(mtmp, DART)
298.  # ifdef KAA
299.  		       : (mtmp->data->mlet == 'K') ? m_carrying(mtmp, CREAM_PIE)
300.  # endif
301.  #else
302.  		otmp = (mtmp->data->mlet == 'K') ? m_carrying(mtmp, DART)
303.  #endif
304.  #ifdef KAA
305.  			: (mtmp->data->mlet == '9') ? m_carrying(mtmp, ENORMOUS_ROCK)
306.  #endif
307.  			: m_carrying(mtmp, CROSSBOW_BOLT);
308.  		if (otmp && (!URETREATING(x,y)
309.  			|| !rn2(BOLT_LIM - movedist(x, u.ux, y, u.uy)))) {
310.  				m_throw(mtmp->mx, mtmp->my, sgn(tx), sgn(ty),
311.  					BOLT_LIM, otmp);
312.  				if (!--otmp->quan )
313.  					m_useup(mtmp, otmp);
314.  				return(0);
315.  			}
316.  		break;
317.  #else
318.  	if((!tx && abs(ty) < BOLT_LIM) || (!ty && abs(tx) < BOLT_LIM)
319.  	    || (abs(tx) == abs(ty) && abs(tx) < BOLT_LIM)){
320.  	    switch(mtmp->mappearance) {
321.  #endif
322.  	    case 'D':
323.  		/* spit fire in the direction of @ (not nec. hitting) */
324.  		buzz((int) - 10 - (mtmp->dragon),
325.  			mtmp->mx,mtmp->my,sgn(tx),sgn(ty));
326.  		break;
327.  #ifdef HARD
328.  	    case '&':
329.  		demon_hit(mtmp);
330.  		break;
331.  #endif
332.  	    case '1':
333.  		if(rn2(WIZSHOT)) break;
334.  		/* if you zapped wizard with wand of cancellation,
335.  		he has to shake off the effects before he can throw
336.  		spells successfully.  Sometimes they fail anyway */
337.  		if(mtmp->mcan ||
338.  #ifdef HARD
339.  		   !rn2(10)
340.  #else
341.  		   !rn2(2)
342.  #endif
343.  		   ) {
344.  		    if(canseemon(mtmp))
345.  				pline("%s makes a gesture, then curses.",
346.  					Monnam(mtmp));
347.  		    else	pline("You hear mumbled cursing.");
348.  
349.  		    if(!rn2(3)) {
350.  			mtmp->mspeed = 0;
351.  			mtmp->minvis = 0;
352.  		    }
353.  		    if(!rn2(3))	mtmp->mcan = 0;
354.  
355.  		} else {
356.  		    if(canseemon(mtmp)){
357.  			if(!rn2(6) && !Invis) {
358.  			    pline("%s hypnotizes you.", Monnam(mtmp));
359.  			    nomul(-rn2(3) + 3);	/* bug fix by ab@unido */
360.  			    break;
361.  			} else
362.  			    pline("%s chants an incantation.", Monnam(mtmp));
363.  		    } else
364.  			    pline("You hear a mumbled incantation.");
365.  		    switch(rn2(Invis ? 5 : 6)) {
366.  		    case 0:
367.  			/* create a nasty monster from a deep level */
368.  			nasty();
369.  			break;
370.  		    case 1:
371.  			pline("\"Destroy the thief, my pets!\"");
372.  #ifdef HARD
373.  			nasty();
374.  #endif
375.  			aggravate();	/* aggravate all the monsters */
376.  			/* fall into next case */
377.  		    case 2:
378.  			if (flags.no_of_wizards == 1 && !rn2(3)) {
379.  			    /* if only 1 wizard, clone himself */
380.  			    pline("Double Trouble...");
381.  			    clonewiz(mtmp);
382.  			}
383.  			break;
384.  		    case 3:
385.  			if(mtmp->mspeed == MSLOW)	mtmp->mspeed = 0;
386.  			else				mtmp->mspeed = MFAST;
387.  			break;
388.  		    case 4:
389.  			mtmp->minvis = 1;
390.  			break;
391.  		    case 5:
392.  			/* Only if not Invisible */
393.  			pline("You hear a clap of thunder!");
394.  			/* shoot a bolt of fire or cold, or a sleep ray */
395.  			/* or death, or lightning, but not  magic missile */
396.  			buzz(-rnd(5),mtmp->mx,mtmp->my,sgn(tx),sgn(ty));
397.  			break;
398.  		    }
399.  		}
400.  	    }
401.  	    if(u.uhp < 1) done_in_by(mtmp);
402.  	}
403.  	return(1);
404.  }
405.  
406.  aggravate()
407.  {
408.  	register struct monst *mtmp;
409.  
410.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
411.  		mtmp->msleep = 0;
412.  		if(mtmp->mfroz && !rn2(5))
413.  			mtmp->mfroz = 0;
414.  	}
415.  }
416.  
417.  clonewiz(mtmp)
418.  register struct monst *mtmp;
419.  {
420.  	register struct monst *mtmp2;
421.  
422.  	if(mtmp2 = makemon(PM_WIZARD, u.ux, u.uy)) {
423.  		flags.no_of_wizards = 2;
424.  		mtmp2->mtame = mtmp2->mpeaceful = 0;
425.  		unpmon(mtmp2);
426.  		mtmp2->mappearance = wizapp[rn2(sizeof(wizapp)-1)];
427.  		pmon(mtmp2);
428.  	}
429.  }
430.  
431.  nasty() {
432.  
433.  #ifdef HARD
434.  	register struct monst	*mtmp;
435.  	struct monst	*mkmon_at();
436.  	register int	i, nastynum, tmp;
437.  
438.  	nastynum = sizeof(nasties) - 1;
439.  	tmp = (u.ulevel > 3) ? u.ulevel/3 : 1;	/* just in case -- rph */
440.  
441.  	for(i = rnd(tmp); i > 0; --i)
442.  	    if((mtmp = mkmon_at(nasties[rn2(nastynum)], u.ux, u.uy)))  {
443.  
444.  		mtmp->msleep = 0;
445.  		mtmp->mpeaceful = 0;
446.  	    }
447.  #else
448.  	(void) makemon((struct permonst *)0, u.ux, u.uy);
449.  #endif
450.  	return(0);
451.  }
452.  
453.  #ifdef HARD
454.  /*	Here, we make trouble for the poor shmuck who actually	*/
455.  /*	managed to do in the Wizard.				*/
456.  intervene() {
457.  
458.  	switch(rn2(6)) {
459.  
460.  	    case 0:
461.  	    case 1:	pline("You feel vaguely nervous.");
462.  			break;
463.  	    case 2:	pline("You notice a black glow surrounding you.");
464.  			rndcurse();
465.  			break;
466.  	    case 3:	aggravate();
467.  			break;
468.  	    case 4:	nasty();
469.  			break;
470.  	    case 5:	resurrect();
471.  			break;
472.  	}
473.  }
474.  
475.  wizdead(mtmp)
476.  register struct monst	*mtmp;
477.  {
478.  	flags.no_of_wizards--;
479.  	if(! u.udemigod)  {
480.  
481.  		u.udemigod = TRUE;
482.  		u.udg_cnt = rn1(250, 50);
483.  
484.  	/*  Make the wizard meaner the next time he appears  */
485.  		mtmp->data->mlevel++;
486.  		mtmp->data->ac--;
487.  	} else  
488.  		mtmp->data->mlevel++;
489.  }
490.  
491.  
492.  /*	Let's resurrect the wizard, for some unexpected fun.	*/
493.  resurrect() {
494.  register struct monst	*mtmp;
495.  
496.  	    if(mtmp = makemon(PM_WIZARD, u.ux, u.uy)) {
497.  
498.  		mtmp->msleep = mtmp->mtame = mtmp->mpeaceful = 0;
499.  		flags.no_of_wizards++;
500.  		pline("A voice booms out...");
501.  		pline("\"So you thought you could kill me, fool.\"");
502.  	    }
503.  
504.  }
505.  #endif /* HARD /**/