Source:NetHack 2.3e/wizard.c

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

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 /**/