Source:NetHack 2.2a/wizard.c
Revision as of 03:00, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 2.2a/wizard.c moved to Source:NetHack 2.2a/wizard.c: Robot: moved page)
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
Screenshots and source code from Hack are used under the CWI license.
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 /**/