Source:NetHack 1.3d/wizard.c

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