Source:NetHack 3.2.0/wizard.c
(Redirected from NetHack 3.2.0/wizard.c)
Jump to navigation
Jump to search
Below is the full text to wizard.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/wizard.c#line123]], for example.
Warning! This is the source code from an old release. For the latest release, see Source code
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
1. /* SCCS Id: @(#)wizard.c 3.2 95/11/18 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 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. /* - dewimped and given some maledictions. -3. */ 8. /* - generalized for 3.1 (mike@bullns.on01.bull.ca) */ 9. 10. #include "hack.h" 11. #include "qtext.h" 12. 13. #ifdef OVLB 14. 15. static short FDECL(which_arti, (int)); 16. static boolean FDECL(mon_has_arti, (struct monst *,SHORT_P)); 17. static struct monst *FDECL(other_mon_has_arti, (struct monst *,SHORT_P)); 18. static struct obj *FDECL(on_ground, (SHORT_P)); 19. static boolean FDECL(you_have, (int)); 20. static long FDECL(target_on, (int,struct monst *)); 21. static long FDECL(strategy, (struct monst *)); 22. 23. static NEARDATA const int nasties[] = { 24. PM_COCKATRICE, PM_ETTIN, PM_STALKER, PM_MINOTAUR, PM_RED_DRAGON, 25. PM_BLACK_DRAGON, PM_GREEN_DRAGON, PM_OWLBEAR, PM_PURPLE_WORM, 26. PM_ROCK_TROLL, PM_XAN, PM_GREMLIN, PM_UMBER_HULK, PM_VAMPIRE_LORD, 27. PM_XORN, PM_ZRUTY, PM_ELF_LORD, PM_ELVENKING, PM_YELLOW_DRAGON, 28. PM_LEOCROTTA, PM_BALUCHITHERIUM, PM_CARNIVOROUS_APE, PM_FIRE_GIANT, 29. PM_COUATL, PM_CAPTAIN, PM_WINGED_GARGOYLE, PM_MIND_FLAYER, 30. PM_FIRE_ELEMENTAL, PM_JABBERWOCK, PM_MASTER_LICH, PM_OGRE_KING, 31. PM_OLOG_HAI, PM_IRON_GOLEM, PM_OCHRE_JELLY 32. }; 33. 34. static NEARDATA const unsigned wizapp[] = { 35. PM_HUMAN, PM_WATER_DEMON, PM_VAMPIRE, 36. PM_RED_DRAGON, PM_TROLL, PM_UMBER_HULK, 37. PM_XORN, PM_XAN, PM_COCKATRICE, 38. PM_FLOATING_EYE, 39. PM_GUARDIAN_NAGA, 40. PM_TRAPPER 41. }; 42. 43. #endif /* OVLB */ 44. #ifdef OVL0 45. 46. /* If you've found the Amulet, make the Wizard appear after some time */ 47. /* Also, give hints about portal locations, if amulet is worn/wielded -dlc */ 48. void 49. amulet() 50. { 51. struct monst *mtmp; 52. struct trap *ttmp; 53. struct obj *amu; 54. 55. #if 0 /* caller takes care of this check */ 56. if (!u.uhave.amulet) 57. return; 58. #endif 59. if ((((amu = uamul) != 0 && amu->otyp == AMULET_OF_YENDOR) || 60. ((amu = uwep) != 0 && amu->otyp == AMULET_OF_YENDOR)) 61. && !rn2(15)) { 62. for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) { 63. if(ttmp->ttyp == MAGIC_PORTAL) { 64. int du = distu(ttmp->tx, ttmp->ty); 65. if (du <= 9) 66. pline("%s feels hot!", The(xname(amu))); 67. else if (du <= 64) 68. pline("%s feels very warm.", The(xname(amu))); 69. else if (du <= 144) 70. pline("%s feels warm.", The(xname(amu))); 71. /* else, the amulet feels normal */ 72. break; 73. } 74. } 75. } 76. 77. if (!flags.no_of_wizards) 78. return; 79. /* find Wizard, and wake him if necessary */ 80. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 81. if(mtmp->iswiz && mtmp->msleep && !rn2(40)) { 82. mtmp->msleep = 0; 83. if (distu(mtmp->mx,mtmp->my) > 2) 84. You( 85. "get the creepy feeling that somebody noticed your taking the Amulet." 86. ); 87. return; 88. } 89. } 90. 91. #endif /* OVL0 */ 92. #ifdef OVLB 93. 94. int 95. mon_has_amulet(mtmp) 96. register struct monst *mtmp; 97. { 98. register struct obj *otmp; 99. 100. for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj) 101. if(otmp->otyp == AMULET_OF_YENDOR) return(1); 102. return(0); 103. } 104. 105. int 106. mon_has_special(mtmp) 107. register struct monst *mtmp; 108. { 109. register struct obj *otmp; 110. 111. for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj) 112. if(otmp->otyp == AMULET_OF_YENDOR || 113. is_quest_artifact(otmp) || 114. otmp->otyp == BELL_OF_OPENING || 115. otmp->otyp == CANDELABRUM_OF_INVOCATION || 116. otmp->otyp == SPE_BOOK_OF_THE_DEAD) return(1); 117. return(0); 118. } 119. 120. /* 121. * New for 3.1 Strategy / Tactics for the wiz, as well as other 122. * monsters that are "after" something (defined via mflag3). 123. * 124. * The strategy section decides *what* the monster is going 125. * to attempt, the tactics section implements the decision. 126. */ 127. #define STRAT(w, x, y, typ) (w | ((long)(x)<<16) | ((long)(y)<<8) | (long)typ) 128. 129. #define M_Wants(mask) (mtmp->data->mflags3 & (mask)) 130. 131. static short 132. which_arti(mask) 133. register int mask; 134. { 135. switch(mask) { 136. case M3_WANTSAMUL: return(AMULET_OF_YENDOR); 137. case M3_WANTSBELL: return(BELL_OF_OPENING); 138. case M3_WANTSCAND: return(CANDELABRUM_OF_INVOCATION); 139. case M3_WANTSBOOK: return(SPE_BOOK_OF_THE_DEAD); 140. default: break; /* 0 signifies quest artifact */ 141. } 142. return(0); 143. } 144. 145. /* 146. * If "otyp" is zero, it triggers a check for the quest_artifact, 147. * since bell, book, candle, and amulet are all objects, not really 148. * artifacts right now. [MRS] 149. */ 150. static boolean 151. mon_has_arti(mtmp, otyp) 152. register struct monst *mtmp; 153. register short otyp; 154. { 155. register struct obj *otmp; 156. 157. for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj) { 158. if(otyp) { 159. if(otmp->otyp == otyp) 160. return(1); 161. } 162. else if(is_quest_artifact(otmp)) return(1); 163. } 164. return(0); 165. 166. } 167. 168. static struct monst * 169. other_mon_has_arti(mtmp, otyp) 170. register struct monst *mtmp; 171. register short otyp; 172. { 173. register struct monst *mtmp2; 174. 175. for(mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon) 176. if(mtmp2 != mtmp) 177. if(mon_has_arti(mtmp2, otyp)) return(mtmp2); 178. 179. return((struct monst *)0); 180. } 181. 182. static struct obj * 183. on_ground(otyp) 184. register short otyp; 185. { 186. register struct obj *otmp; 187. 188. for (otmp = fobj; otmp; otmp = otmp->nobj) 189. if (otyp) { 190. if (otmp->otyp == otyp) 191. return(otmp); 192. } else if (is_quest_artifact(otmp)) 193. return(otmp); 194. return((struct obj *)0); 195. } 196. 197. static boolean 198. you_have(mask) 199. register int mask; 200. { 201. switch(mask) { 202. case M3_WANTSAMUL: return(boolean)(u.uhave.amulet); 203. case M3_WANTSBELL: return(boolean)(u.uhave.bell); 204. case M3_WANTSCAND: return(boolean)(u.uhave.menorah); 205. case M3_WANTSBOOK: return(boolean)(u.uhave.book); 206. case M3_WANTSARTI: return(boolean)(u.uhave.questart); 207. default: break; 208. } 209. return(0); 210. } 211. 212. static long 213. target_on(mask, mtmp) 214. register int mask; 215. register struct monst *mtmp; 216. { 217. register short otyp; 218. register struct obj *otmp; 219. register struct monst *mtmp2; 220. 221. if(!M_Wants(mask)) return(STRAT_NONE); 222. 223. otyp = which_arti(mask); 224. if(!mon_has_arti(mtmp, otyp)) { 225. if(you_have(mask)) 226. return(STRAT(STRAT_PLAYER, u.ux, u.uy, mask)); 227. else if((otmp = on_ground(otyp))) 228. return(STRAT(STRAT_GROUND, otmp->ox, otmp->oy, mask)); 229. else if((mtmp2 = other_mon_has_arti(mtmp, otyp))) 230. return(STRAT(STRAT_MONSTR, mtmp2->mx, mtmp2->my, mask)); 231. } 232. return(STRAT_NONE); 233. } 234. 235. static long 236. strategy(mtmp) 237. register struct monst *mtmp; 238. { 239. long strat, dstrat; 240. 241. if(!is_covetous(mtmp->data)) return(STRAT_NONE); 242. 243. switch((mtmp->mhp*3)/mtmp->mhpmax) { /* 0-3 */ 244. 245. default: 246. case 0: /* panic time - mtmp is almost snuffed */ 247. return(STRAT_HEAL); 248. 249. case 1: /* the wiz is less cautious */ 250. if(mtmp->data != &mons[PM_WIZARD_OF_YENDOR]) 251. return(STRAT_HEAL); 252. /* else fall through */ 253. 254. case 2: dstrat = STRAT_HEAL; 255. break; 256. 257. case 3: dstrat = STRAT_NONE; 258. break; 259. } 260. 261. if(flags.made_amulet) 262. if((strat = target_on(M3_WANTSAMUL, mtmp)) != STRAT_NONE) 263. return(strat); 264. 265. if(u.uevent.invoked) { /* priorities change once gate opened */ 266. 267. if((strat = target_on(M3_WANTSARTI, mtmp)) != STRAT_NONE) 268. return(strat); 269. if((strat = target_on(M3_WANTSBOOK, mtmp)) != STRAT_NONE) 270. return(strat); 271. if((strat = target_on(M3_WANTSBELL, mtmp)) != STRAT_NONE) 272. return(strat); 273. if((strat = target_on(M3_WANTSCAND, mtmp)) != STRAT_NONE) 274. return(strat); 275. } else { 276. 277. if((strat = target_on(M3_WANTSBOOK, mtmp)) != STRAT_NONE) 278. return(strat); 279. if((strat = target_on(M3_WANTSBELL, mtmp)) != STRAT_NONE) 280. return(strat); 281. if((strat = target_on(M3_WANTSCAND, mtmp)) != STRAT_NONE) 282. return(strat); 283. if((strat = target_on(M3_WANTSARTI, mtmp)) != STRAT_NONE) 284. return(strat); 285. } 286. return(dstrat); 287. } 288. 289. int 290. tactics(mtmp) 291. register struct monst *mtmp; 292. { 293. long strat = strategy(mtmp); 294. 295. mtmp->mstrategy = (mtmp->mstrategy & STRAT_WAITMASK) | strat; 296. 297. switch (strat) { 298. case STRAT_HEAL: /* hide and recover */ 299. /* if wounded, hole up on or near the stairs (to block them) */ 300. /* unless, of course, there are no stairs (e.g. endlevel) */ 301. if (In_W_tower(mtmp->mx, mtmp->my, &u.uz) || 302. (mtmp->iswiz && !xupstair && !mon_has_amulet(mtmp))) { 303. if (!rn2(3 + mtmp->mhp/10)) rloc(mtmp); 304. } else if (xupstair && 305. (mtmp->mx != xupstair || mtmp->my != yupstair)) { 306. (void) mnearto(mtmp, xupstair, yupstair, TRUE); 307. } 308. /* if you're not around, cast healing spells */ 309. if (distu(mtmp->mx,mtmp->my) > (BOLT_LIM * BOLT_LIM)) 310. if(mtmp->mhp <= mtmp->mhpmax - 8) { 311. mtmp->mhp += rnd(8); 312. return(1); 313. } 314. /* fall through :-) */ 315. 316. case STRAT_NONE: /* harrass */ 317. if(!rn2(5)) mnexto(mtmp); 318. return(0); 319. 320. default: /* kill, maim, pillage! */ 321. { 322. long where = (strat & STRAT_STRATMASK); 323. xchar tx = STRAT_GOALX(strat), 324. ty = STRAT_GOALY(strat); 325. int targ = strat & STRAT_GOAL; 326. struct obj *otmp; 327. 328. if(!targ) { /* simply wants you to close */ 329. return(0); 330. } 331. if((u.ux == tx && u.uy == ty) || where == STRAT_PLAYER) { 332. /* player is standing on it (or has it) */ 333. mnexto(mtmp); 334. return(0); 335. } 336. if(where == STRAT_GROUND) { 337. if(!MON_AT(tx, ty) || (mtmp->mx == tx && mtmp->my == ty)) { 338. /* teleport to it and pick it up */ 339. rloc_to(mtmp, tx, ty); /* clean old pos */ 340. 341. if ((otmp = on_ground(which_arti(targ))) != 0) { 342. if (cansee(mtmp->mx, mtmp->my)) 343. pline("%s picks up %s.", 344. Monnam(mtmp), 345. (distu(mtmp->my, mtmp->my) <= 5) ? 346. doname(otmp) : distant_name(otmp, doname)); 347. obj_extract_self(otmp); 348. mpickobj(mtmp, otmp); 349. return(1); 350. } else return(0); 351. } 352. } else { /* a monster has it - 'port beside it. */ 353. (void) mnearto(mtmp, tx, ty, TRUE); 354. return(0); 355. } 356. } 357. } 358. /* NOTREACHED */ 359. return(0); 360. } 361. 362. void 363. aggravate() 364. { 365. register struct monst *mtmp; 366. 367. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { 368. mtmp->msleep = 0; 369. if(!mtmp->mcanmove && !rn2(5)) { 370. mtmp->mfrozen = 0; 371. mtmp->mcanmove = 1; 372. } 373. } 374. } 375. 376. void 377. clonewiz() 378. { 379. register struct monst *mtmp2; 380. 381. if ((mtmp2 = makemon(&mons[PM_WIZARD_OF_YENDOR], u.ux, u.uy)) != 0) { 382. mtmp2->msleep = mtmp2->mtame = mtmp2->mpeaceful = 0; 383. if (!u.uhave.amulet && rn2(2)) { /* give clone a fake */ 384. add_to_minv(mtmp2, mksobj(FAKE_AMULET_OF_YENDOR, TRUE, FALSE)); 385. } 386. mtmp2->m_ap_type = M_AP_MONSTER; 387. mtmp2->mappearance = wizapp[rn2(SIZE(wizapp))]; 388. newsym(mtmp2->mx,mtmp2->my); 389. } 390. } 391. 392. /* create some nasty monsters, aligned or neutral with the caster */ 393. /* a null caster defaults to a chaotic caster (e.g. the wizard) */ 394. void 395. nasty(mcast) 396. struct monst *mcast; 397. { 398. register struct monst *mtmp; 399. register int i, j, tmp; 400. int castalign = (mcast ? mcast->data->maligntyp : -1); 401. 402. if(!rn2(10) && Inhell) msummon(&mons[PM_WIZARD_OF_YENDOR]); 403. else { 404. tmp = (u.ulevel > 3) ? u.ulevel/3 : 1; /* just in case -- rph */ 405. 406. for(i = rnd(tmp); i > 0; --i) 407. for(j=0; j<20; j++) { 408. if((mtmp = makemon(&mons[nasties[rn2(SIZE(nasties))]], 409. u.ux, u.uy))) { 410. mtmp->msleep = mtmp->mpeaceful = mtmp->mtame = 0; 411. set_malign(mtmp); 412. } else /* GENOD? */ 413. mtmp = makemon((struct permonst *)0, u.ux, u.uy); 414. if(mtmp && (mtmp->data->maligntyp == 0 || 415. sgn(mtmp->data->maligntyp) == sgn(castalign)) ) 416. break; 417. } 418. } 419. return; 420. } 421. 422. /* Let's resurrect the wizard, for some unexpected fun. */ 423. void 424. resurrect() 425. { 426. struct monst *mtmp, **mmtmp; 427. long elapsed; 428. const char *verb; 429. 430. if (!flags.no_of_wizards) { 431. /* make a new Wizard */ 432. verb = "kill"; 433. mtmp = makemon(&mons[PM_WIZARD_OF_YENDOR], u.ux, u.uy); 434. } else { 435. /* look for a migrating Wizard */ 436. verb = "elude"; 437. mmtmp = &migrating_mons; 438. while ((mtmp = *mmtmp) != 0) { 439. if (mtmp->iswiz && 440. (elapsed = monstermoves - mtmp->mlstmv) > 0L) { 441. mon_catchup_elapsed_time(mtmp, elapsed); 442. if (elapsed >= LARGEST_INT) elapsed = LARGEST_INT - 1; 443. elapsed /= 50L; 444. if (mtmp->msleep && rn2((int)elapsed + 1)) 445. mtmp->msleep = 0; 446. if (mtmp->mfrozen == 1) /* would unfreeze on next move */ 447. mtmp->mfrozen = 0, mtmp->mcanmove = 1; 448. if (mtmp->mcanmove && !mtmp->msleep) { 449. *mmtmp = mtmp->nmon; 450. mon_arrive(mtmp, TRUE); 451. /* note: there might be a second Wizard; if so, 452. he'll have to wait til the next resurrection */ 453. break; 454. } 455. } 456. mmtmp = &mtmp->nmon; 457. } 458. } 459. 460. if (mtmp) { 461. mtmp->msleep = mtmp->mtame = mtmp->mpeaceful = 0; 462. set_malign(mtmp); 463. pline("A voice booms out..."); 464. verbalize("So thou thought thou couldst %s me, fool.", verb); 465. } 466. 467. } 468. 469. /* Here, we make trouble for the poor shmuck who actually */ 470. /* managed to do in the Wizard. */ 471. void 472. intervene() 473. { 474. int which = Is_astralevel(&u.uz) ? rnd(4) : rn2(6); 475. /* cases 0 and 5 don't apply on the Astral level */ 476. switch (which) { 477. case 0: 478. case 1: You_feel("vaguely nervous."); 479. break; 480. case 2: if (!Blind) 481. You("notice a %s glow surrounding you.", 482. hcolor(Black)); 483. rndcurse(); 484. break; 485. case 3: aggravate(); 486. break; 487. case 4: nasty((struct monst *)0); 488. break; 489. case 5: resurrect(); 490. break; 491. } 492. } 493. 494. void 495. wizdead() 496. { 497. flags.no_of_wizards--; 498. if (!u.uevent.udemigod) { 499. u.uevent.udemigod = TRUE; 500. u.udg_cnt = rn1(250, 50); 501. } 502. } 503. 504. const char *random_insult[] = { 505. "antic", 506. "blackguard", 507. "caitiff", 508. "chucklehead", 509. "coistrel", 510. "craven", 511. "cretin", 512. "cur", 513. "dastard", 514. "demon fodder", 515. "dimwit", 516. "dolt", 517. "fool", 518. "footpad", 519. "imbecile", 520. "knave", 521. "maledict", 522. "miscreant", 523. "niddering", 524. "poltroon", 525. "rattlepate", 526. "reprobate", 527. "scapegrace", 528. "varlet", 529. "villein", /* (sic.) */ 530. "wittol", 531. "worm", 532. "wretch", 533. }; 534. 535. const char *random_malediction[] = { 536. "Hell shall soon claim thy remains,", 537. "I chortle at thee, thou pathetic", 538. "Prepare to die, thou", 539. "Resistance is useless,", 540. "Surrender or die, thou", 541. "There shall be no mercy, thou", 542. "Thou shalt repent of thy cunning,", 543. "Thou art as a flea to me,", 544. "Thou art doomed,", 545. "Thy fate is sealed,", 546. "Verily, thou shalt be one dead" 547. }; 548. 549. /* Insult or intimidate the player */ 550. void 551. cuss(mtmp) 552. register struct monst *mtmp; 553. { 554. if (mtmp->iswiz) { 555. if (!rn2(5)) /* typical bad guy action */ 556. pline("%s laughs fiendishly.", Monnam(mtmp)); 557. else 558. if (u.uhave.amulet && !rn2(SIZE(random_insult))) 559. verbalize("Relinquish the amulet, %s!", 560. random_insult[rn2(SIZE(random_insult))]); 561. else if (u.uhp < 5 && !rn2(2)) /* Panic */ 562. verbalize(rn2(2) ? 563. "Even now thy life force ebbs, %s!" : 564. "Savor thy breath, %s, it be thine last!", 565. random_insult[rn2(SIZE(random_insult))]); 566. else if (mtmp->mhp < 5 && !rn2(2)) /* Parthian shot */ 567. verbalize(rn2(2) ? 568. "I shall return." : 569. "I'll be back."); 570. else 571. verbalize("%s %s!", 572. random_malediction[rn2(SIZE(random_malediction))], 573. random_insult[rn2(SIZE(random_insult))]); 574. } else if(is_lminion(mtmp->data)) { 575. com_pager(rn2(QTN_ANGELIC - 1 + (Hallucination ? 1 : 0)) + 576. QT_ANGELIC); 577. } else { 578. if (!rn2(5)) 579. pline("%s casts aspersions on your ancestry.", Monnam(mtmp)); 580. else 581. com_pager(rn2(QTN_DEMONIC) + QT_DEMONIC); 582. } 583. } 584. 585. #endif /* OVLB */ 586. 587. /*wizard.c*/