Source:NetHack 2.2a/wizard.c

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

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

1.   /*	SCCS Id: @(#)wizard.c	2.2	87/11/29 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; 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.  	}  241.  	tmp_at(-1, -1);  242.  }  243.  #endif  244.   245.  /* Return 1 if it's OK for the monster to move as well as (throw, 246.  * zap, etc).  247.   */  248.  inrange(mtmp)  249.  register struct monst *mtmp;  250.  {  251.  	register schar tx,ty;  252.  #ifdef DGKMOD  253.  	struct obj *otmp;  254.  	register xchar x, y;  255.  #endif  256.  	/* do nothing if cancelled (but make '1' say something) */  257.  	if(mtmp->data->mlet != '1' && mtmp->mcan) return(1);  258.   259.  	/* spit fire only when both in a room or both in a corridor */  260.  #ifndef RPH  261.  	if(inroom(u.ux,u.uy) != inroom(mtmp->mx,mtmp->my)) return(1);  262.  #endif  263.  	tx = u.ux - mtmp->mx;  264.  	ty = u.uy - mtmp->my;  265.  #ifdef DGKMOD  266.  	if ((!tx || !ty || abs(tx) == abs(ty))	/* straight line or diagonal */ 267. 		&& movedist(tx, 0,  ty, 0) < BOLT_LIM) {  268.  		/* Check if there are any dead squares between.  If so,  269.  		 * it won't be possible to shoot.  270.  		 */  271.  		for (x = mtmp->mx, y = mtmp->my; x != u.ux || y != u.uy; 272. 				x += sgn(tx), y += sgn(ty))  273.  			if (!ACCESSIBLE(levl[x][y].typ))  274.  				return(1);  275.   276.  		switch(mtmp->data->mlet) {  277.  #ifdef KOPS  278.  		case 'O':  279.  #endif  280.  #ifdef KAA  281.  		case '9':  282.  #endif  283.  		case 'K':  284.  		case 'C':  285.  		/* If you're coming toward the monster, the monster  286.  		 * should try to soften you up with arrows.  If you're  287.  		 * going away, you are probably hurt or running.  Give  288.  		 * chase, but if you're getting too far away, throw.  289.  		 */  290.  		x = mtmp->mx;  291.  		y = mtmp->my;  292.  #ifdef KOPS  293.  		otmp = (mtmp->data->mlet == 'O') ? m_carrying(mtmp, DART)  294.  # ifdef KAA  295.  		       : (mtmp->data->mlet == 'K') ? m_carrying(mtmp, CREAM_PIE)  296.  # endif  297.  #else  298.  		otmp = (mtmp->data->mlet == 'K') ? m_carrying(mtmp, DART)  299.  #endif  300.  #ifdef KAA 301. 			: (mtmp->data->mlet == '9') ? m_carrying(mtmp, ENORMOUS_ROCK) 302. #endif 303. 			: m_carrying(mtmp, CROSSBOW_BOLT); 304. 		if (otmp && (!URETREATING(x,y) 305. 			|| !rn2(BOLT_LIM - movedist(x, u.ux, y, u.uy)))) { 306. 				m_throw(mtmp->mx, mtmp->my, sgn(tx), sgn(ty),  307.  					BOLT_LIM, otmp); 308. 				if (!--otmp->quan ) 309. 					m_useup(mtmp, otmp); 310. 				return(0); 311. 			}  312.  		break; 313. #else 314. 	if((!tx && abs(ty) < BOLT_LIM) || (!ty && abs(tx) < BOLT_LIM)  315.  	    || (abs(tx) == abs(ty) && abs(tx) < BOLT_LIM)){ 316. 	    switch(mtmp->mappearance) { 317. #endif 318. 	    case 'D': 319. 		/* spit fire in the direction of @ (not nec. hitting) */ 320. 		buzz(-1,mtmp->mx,mtmp->my,sgn(tx),sgn(ty)); 321. 		break; 322. #ifdef HARD 323. 	    case '&': 324. 		demon_hit(mtmp); 325. 		break; 326. #endif 327. 	    case '1': 328. 		if(rn2(WIZSHOT)) break; 329. 		/* if you zapped wizard with wand of cancellation, 330. 		he has to shake off the effects before he can throw 331. 		spells successfully. Sometimes they fail anyway */ 332. 		if(mtmp->mcan ||  333.  #ifdef HARD  334.  		   !rn2(10)  335.  #else  336.  		   !rn2(2)  337.  #endif  338.  		   ) { 339. 		    if(canseemon(mtmp)) 340. 				pline("%s makes a gesture, then curses.",  341.  					Monnam(mtmp)); 342. 		    else	pline("You hear mumbled cursing."); 343.  344.  		    if(!rn2(3)) { 345. 			mtmp->mspeed = 0; 346. 			mtmp->minvis = 0; 347. 		    }  348.  		    if(!rn2(3))	mtmp->mcan = 0; 349.  350.  		} else { 351. 		    if(canseemon(mtmp)){ 352. 			if(!rn2(6) && !Invis) { 353. 			    pline("%s hypnotizes you.", Monnam(mtmp)); 354. 			    nomul(-rn2(3) + 3);	/* bug fix by ab@unido */ 355. 			    break; 356. 			} else 357. 			    pline("%s chants an incantation.", Monnam(mtmp)); 358. 		    } else 359. 			    pline("You hear a mumbled incantation."); 360. 		    switch(rn2(Invis ? 5 : 6)) { 361.  		    case 0: 362. 			/* create a nasty monster from a deep level */ 363. 			nasty; 364. 			break; 365. 		    case 1: 366. 			pline("\"Destroy the thief, my pets!\""); 367. #ifdef HARD 368. 			nasty; 369. #endif 370. 			aggravate;	/* aggravate all the monsters */ 371. 			/* fall into next case */ 372. 		    case 2: 373. 			if (flags.no_of_wizards == 1 && !rn2(3)) { 374. 			    /* if only 1 wizard, clone himself */ 375. 			    pline("Double Trouble..."); 376. 			    clonewiz(mtmp); 377. 			}  378.  			break; 379. 		    case 3: 380. 			if(mtmp->mspeed == MSLOW)	mtmp->mspeed = 0; 381. 			else				mtmp->mspeed = MFAST; 382. 			break; 383. 		    case 4: 384. 			mtmp->minvis = 1; 385. 			break; 386. 		    case 5: 387. 			/* Only if not Invisible */ 388. 			pline("You hear a clap of thunder!"); 389. 			/* shoot a bolt of fire or cold, or a sleep ray */ 390. 			buzz(-rnd(3),mtmp->mx,mtmp->my,sgn(tx),sgn(ty)); 391. 			break; 392. 		    }  393.  		}  394.  	    }  395.  	    if(u.uhp < 1) done_in_by(mtmp); 396. 	}  397.  	return(1); 398. }  399.   400.  aggravate 401. {  402.  	register struct monst *mtmp; 403.  404.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { 405. 		mtmp->msleep = 0; 406. 		if(mtmp->mfroz && !rn2(5)) 407. 			mtmp->mfroz = 0; 408. 	}  409.  }  410.   411.  clonewiz(mtmp) 412. register struct monst *mtmp; 413. {  414.  	register struct monst *mtmp2; 415.  416.  	if(mtmp2 = makemon(PM_WIZARD, u.ux, u.uy)) { 417. 		flags.no_of_wizards = 2; 418. 		mtmp2->mtame = mtmp2->mpeaceful = 0; 419. 		unpmon(mtmp2); 420. 		mtmp2->mappearance = wizapp[rn2(sizeof(wizapp)-1)]; 421. 		pmon(mtmp2); 422. 	}  423.  }  424.   425.  nasty { 426.  427.  #ifdef HARD 428. 	register struct monst	*mtmp; 429. 	struct monst	*mkmon_at; 430. 	register int	i, nastynum, tmp; 431.  432.  	nastynum = sizeof(nasties) - 1; 433. 	tmp = (u.ulevel > 3) ? u.ulevel/3 : 1;	/* just in case -- rph */ 434.  435.  	for(i = rnd(tmp); i > 0; --i) 436. 	    if((mtmp = mkmon_at(nasties[rn2(nastynum)], u.ux, u.uy)))  { 437.  438.  		mtmp->msleep = 0; 439. 		mtmp->mpeaceful = 0; 440. 	    }  441.  #else 442. 	(void) makemon((struct permonst *)0, u.ux, u.uy); 443. #endif 444. 	return(0); 445. }  446.   447.  #ifdef HARD 448. /*	Here, we make trouble for the poor shmuck who actually	*/ 449. /*	managed to do in the Wizard. */ 450.  intervene { 451.  452.  	switch(rn2(6)) { 453.  454.  	    case 0: 455. 	    case 1:	pline("You feel vaguely nervous."); 456. 			break; 457. 	    case 2:	pline("You notice a black glow surrounding you."); 458. 			rndcurse; 459. 			break; 460. 	    case 3:	aggravate; 461. 			break; 462. 	    case 4:	nasty; 463. 			break; 464. 	    case 5:	resurrect; 465. 			break; 466. 	}  467.  }  468.   469.  wizdead(mtmp) 470. register struct monst	*mtmp; 471. {  472.  	flags.no_of_wizards--; 473. 	if(! u.udemigod)  { 474.  475.  		u.udemigod = TRUE; 476. 		u.udg_cnt = rn1(250, 50); 477.  478.  	/*  Make the wizard meaner the next time he appears  */ 479. 		mtmp->data->mlevel++; 480. 		mtmp->data->ac--; 481. 	} else 482. 		mtmp->data->mlevel++; 483. }  484.   485.   486.  /*	Let's resurrect the wizard, for some unexpected fun. */ 487.  resurrect { 488. register struct monst	*mtmp; 489.  490.  	    if(mtmp = makemon(PM_WIZARD, u.ux, u.uy)) { 491.  492.  		mtmp->msleep = mtmp->mtame = mtmp->mpeaceful = 0; 493. 		flags.no_of_wizards++; 494. 		pline("A voice booms out..."); 495. 		pline("\"So you thought you could kill me, fool.\""); 496. 	    }  497.   498.  }  499.  #endif /* HARD /**/