fight.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393
  1. /* $NetBSD: fight.c,v 1.10 2004/04/11 13:35:06 he Exp $ */
  2. /*
  3. * fight.c Phantasia monster fighting routines
  4. */
  5. #include "include.h"
  6. #undef bool
  7. #include <curses.h>
  8. void
  9. encounter(particular)
  10. int particular;
  11. {
  12. volatile bool firsthit = Player.p_blessing; /* set if player gets
  13. * the first hit */
  14. volatile int flockcnt = 1; /* how many time flocked */
  15. /* let others know what we are doing */
  16. Player.p_status = S_MONSTER;
  17. writerecord(&Player, Fileloc);
  18. #ifdef SYS5
  19. flushinp();
  20. #endif
  21. Shield = 0.0; /* no shield up yet */
  22. if (particular >= 0)
  23. /* monster is specified */
  24. Whichmonster = particular;
  25. else
  26. /* pick random monster */
  27. Whichmonster = pickmonster();
  28. setjmp(Fightenv); /* this is to enable changing fight state */
  29. move(6, 0);
  30. clrtobot(); /* clear bottom area of screen */
  31. Lines = 9;
  32. callmonster(Whichmonster); /* set up monster to fight */
  33. Luckout = FALSE; /* haven't tried to luckout yet */
  34. if (Curmonster.m_type == SM_MORGOTH)
  35. mvprintw(4, 0, "You've encountered %s, Bane of the Council and Valar.\n",
  36. Enemyname);
  37. if (Curmonster.m_type == SM_UNICORN) {
  38. if (Player.p_virgin) {
  39. printw("You just subdued %s, thanks to the virgin.\n", Enemyname);
  40. Player.p_virgin = FALSE;
  41. } else {
  42. printw("You just saw %s running away!\n", Enemyname);
  43. Curmonster.m_experience = 0.0;
  44. Curmonster.m_treasuretype = 0;
  45. }
  46. } else
  47. /* not a special monster */
  48. for (;;)
  49. /* print header, and arbitrate between player and
  50. * monster */
  51. {
  52. mvprintw(6, 0, "You are being attacked by %s, EXP: %.0f (Size: %.0f)\n",
  53. Enemyname, Curmonster.m_experience, Circle);
  54. displaystats();
  55. mvprintw(1, 26, "%20.0f", Player.p_energy + Shield); /* overprint energy */
  56. readmessage();
  57. if (Curmonster.m_type == SM_DARKLORD
  58. && Player.p_blessing
  59. && Player.p_charms > 0)
  60. /* overpower Dark Lord with blessing and charm */
  61. {
  62. mvprintw(7, 0, "You just overpowered %s!", Enemyname);
  63. Lines = 8;
  64. Player.p_blessing = FALSE;
  65. --Player.p_charms;
  66. break;
  67. }
  68. /* allow paralyzed monster to wake up */
  69. Curmonster.m_speed = MIN(Curmonster.m_speed + 1.0, Curmonster.m_maxspeed);
  70. if (drandom() * Curmonster.m_speed > drandom() * Player.p_speed
  71. /* monster is faster */
  72. && Curmonster.m_type != SM_DARKLORD
  73. /* not D. L. */
  74. && Curmonster.m_type != SM_SHRIEKER
  75. /* not mimic */
  76. && !firsthit)
  77. /* monster gets a hit */
  78. monsthits();
  79. else
  80. /* player gets a hit */
  81. {
  82. firsthit = FALSE;
  83. playerhits();
  84. }
  85. refresh();
  86. if (Lines > LINES - 2)
  87. /* near bottom of screen - pause */
  88. {
  89. more(Lines);
  90. move(Lines = 8, 0);
  91. clrtobot();
  92. }
  93. if (Player.p_energy <= 0.0)
  94. /* player died */
  95. {
  96. more(Lines);
  97. death(Enemyname);
  98. cancelmonster();
  99. break; /* fight ends if the player is saved
  100. * from death */
  101. }
  102. if (Curmonster.m_energy <= 0.0)
  103. /* monster died */
  104. break;
  105. }
  106. /* give player credit for killing monster */
  107. Player.p_experience += Curmonster.m_experience;
  108. if (drandom() < Curmonster.m_flock / 100.0)
  109. /* monster flocks */
  110. {
  111. more(Lines);
  112. ++flockcnt;
  113. longjmp(Fightenv, 0);
  114. /* NOTREACHED */
  115. } else
  116. if (Circle > 1.0
  117. && Curmonster.m_treasuretype > 0
  118. && drandom() > 0.2 + pow(0.4, (double) (flockcnt / 3 + Circle / 3.0)))
  119. /* monster has treasure; this takes # of flocks and
  120. * size into account */
  121. {
  122. more(Lines);
  123. awardtreasure();
  124. }
  125. /* pause before returning */
  126. getyx(stdscr, Lines, flockcnt);
  127. more(Lines + 1);
  128. Player.p_ring.ring_inuse = FALSE; /* not using ring */
  129. /* clean up the screen */
  130. move(4, 0);
  131. clrtobot();
  132. }
  133. int
  134. pickmonster()
  135. {
  136. if (Player.p_specialtype == SC_VALAR)
  137. /* even chance of any monster */
  138. return ((int) ROLL(0.0, 100.0));
  139. if (Marsh)
  140. /* water monsters */
  141. return ((int) ROLL(0.0, 15.0));
  142. else
  143. if (Circle > 24)
  144. /* even chance of all non-water monsters */
  145. return ((int) ROLL(14.0, 86.0));
  146. else
  147. if (Circle > 15)
  148. /* chance of all non-water monsters, weighted
  149. * toward middle */
  150. return ((int) (ROLL(0.0, 50.0) + ROLL(14.0, 37.0)));
  151. else
  152. if (Circle > 8)
  153. /* not all non-water monsters,
  154. * weighted toward middle */
  155. return ((int) (ROLL(0.0, 50.0) + ROLL(14.0, 26.0)));
  156. else
  157. if (Circle > 3)
  158. /* even chance of some tamer
  159. * non-water monsters */
  160. return ((int) ROLL(14.0, 50.0));
  161. else
  162. /* even chance of some of the
  163. * tamest non-water monsters */
  164. return ((int) ROLL(14.0, 25.0));
  165. }
  166. void
  167. playerhits()
  168. {
  169. double inflict; /* damage inflicted */
  170. int ch; /* input */
  171. mvaddstr(7, 0, "1:Melee 2:Skirmish 3:Evade 4:Spell 5:Nick ");
  172. if (!Luckout) {
  173. /* haven't tried to luckout yet */
  174. if (Curmonster.m_type == SM_MORGOTH)
  175. /* cannot luckout against Morgoth */
  176. addstr("6:Ally ");
  177. else
  178. addstr("6:Luckout ");
  179. }
  180. if (Player.p_ring.ring_type != R_NONE)
  181. /* player has a ring */
  182. addstr("7:Use Ring ");
  183. else
  184. clrtoeol();
  185. ch = inputoption();
  186. move(8, 0);
  187. clrtobot(); /* clear any messages from before */
  188. Lines = 9;
  189. mvaddstr(4, 0, "\n\n"); /* clear status area */
  190. switch (ch) {
  191. case 'T': /* timeout; lose turn */
  192. break;
  193. case ' ':
  194. case '1': /* melee */
  195. /* melee affects monster's energy and strength */
  196. inflict = ROLL(Player.p_might / 2.0 + 5.0, 1.3 * Player.p_might)
  197. + (Player.p_ring.ring_inuse ? Player.p_might : 0.0);
  198. Curmonster.m_melee += inflict;
  199. Curmonster.m_strength = Curmonster.m_o_strength
  200. - Curmonster.m_melee / Curmonster.m_o_energy
  201. * Curmonster.m_o_strength / 4.0;
  202. hitmonster(inflict);
  203. break;
  204. case '2': /* skirmish */
  205. /* skirmish affects monter's energy and speed */
  206. inflict = ROLL(Player.p_might / 3.0 + 3.0, 1.1 * Player.p_might)
  207. + (Player.p_ring.ring_inuse ? Player.p_might : 0.0);
  208. Curmonster.m_skirmish += inflict;
  209. Curmonster.m_maxspeed = Curmonster.m_o_speed
  210. - Curmonster.m_skirmish / Curmonster.m_o_energy
  211. * Curmonster.m_o_speed / 4.0;
  212. hitmonster(inflict);
  213. break;
  214. case '3': /* evade */
  215. /* use brains and speed to try to evade */
  216. if ((Curmonster.m_type == SM_DARKLORD
  217. || Curmonster.m_type == SM_SHRIEKER
  218. /* can always run from D. L. and shrieker */
  219. || drandom() * Player.p_speed * Player.p_brains
  220. > drandom() * Curmonster.m_speed * Curmonster.m_brains)
  221. && (Curmonster.m_type != SM_MIMIC))
  222. /* cannot run from mimic */
  223. {
  224. mvaddstr(Lines++, 0, "You got away!");
  225. cancelmonster();
  226. altercoordinates(0.0, 0.0, A_NEAR);
  227. } else
  228. mvprintw(Lines++, 0, "%s is still after you!", Enemyname);
  229. break;
  230. case 'M':
  231. case '4': /* magic spell */
  232. throwspell();
  233. break;
  234. case '5': /* nick */
  235. /* hit 1 plus sword; give some experience */
  236. inflict = 1.0 + Player.p_sword;
  237. Player.p_experience += floor(Curmonster.m_experience / 10.0);
  238. Curmonster.m_experience *= 0.92;
  239. /* monster gets meaner */
  240. Curmonster.m_maxspeed += 2.0;
  241. Curmonster.m_speed = (Curmonster.m_speed < 0.0) ? 0.0 : Curmonster.m_speed + 2.0;
  242. if (Curmonster.m_type == SM_DARKLORD)
  243. /* Dark Lord; doesn't like to be nicked */
  244. {
  245. mvprintw(Lines++, 0,
  246. "You hit %s %.0f times, and made him mad!", Enemyname, inflict);
  247. Player.p_quickness /= 2.0;
  248. altercoordinates(0.0, 0.0, A_FAR);
  249. cancelmonster();
  250. } else
  251. hitmonster(inflict);
  252. break;
  253. case 'B':
  254. case '6': /* luckout */
  255. if (Luckout)
  256. mvaddstr(Lines++, 0, "You already tried that.");
  257. else {
  258. Luckout = TRUE;
  259. if (Curmonster.m_type == SM_MORGOTH)
  260. /* Morgoth; ally */
  261. {
  262. if (drandom() < Player.p_sin / 100.0) {
  263. mvprintw(Lines++, 0, "%s accepted!", Enemyname);
  264. cancelmonster();
  265. } else
  266. mvaddstr(Lines++, 0, "Nope, he's not interested.");
  267. } else
  268. /* normal monster; use brains for success */
  269. {
  270. if ((drandom() + 0.333) * Player.p_brains
  271. < (drandom() + 0.333) * Curmonster.m_brains)
  272. mvprintw(Lines++, 0, "You blew it, %s.", Player.p_name);
  273. else {
  274. mvaddstr(Lines++, 0, "You made it!");
  275. Curmonster.m_energy = 0.0;
  276. }
  277. }
  278. }
  279. break;
  280. case '7': /* use ring */
  281. if (Player.p_ring.ring_type != R_NONE) {
  282. mvaddstr(Lines++, 0, "Now using ring.");
  283. Player.p_ring.ring_inuse = TRUE;
  284. if (Player.p_ring.ring_type != R_DLREG)
  285. /* age ring */
  286. --Player.p_ring.ring_duration;
  287. }
  288. break;
  289. }
  290. }
  291. void
  292. monsthits()
  293. {
  294. double inflict; /* damage inflicted */
  295. int ch; /* input */
  296. switch (Curmonster.m_type)
  297. /* may be a special monster */
  298. {
  299. case SM_DARKLORD:
  300. /* hits just enough to kill player */
  301. inflict = (Player.p_energy + Shield) * 1.02;
  302. goto SPECIALHIT;
  303. case SM_SHRIEKER:
  304. /* call a big monster */
  305. mvaddstr(Lines++, 0,
  306. "Shrieeeek!! You scared it, and it called one of its friends.");
  307. more(Lines);
  308. Whichmonster = (int) ROLL(70.0, 30.0);
  309. longjmp(Fightenv, 0);
  310. /* NOTREACHED */
  311. case SM_BALROG:
  312. /* take experience away */
  313. inflict = ROLL(10.0, Curmonster.m_strength);
  314. inflict = MIN(Player.p_experience, inflict);
  315. mvprintw(Lines++, 0,
  316. "%s took away %.0f experience points.", Enemyname, inflict);
  317. Player.p_experience -= inflict;
  318. return;
  319. case SM_FAERIES:
  320. if (Player.p_holywater > 0)
  321. /* holy water kills when monster tries to hit */
  322. {
  323. mvprintw(Lines++, 0, "Your holy water killed it!");
  324. --Player.p_holywater;
  325. Curmonster.m_energy = 0.0;
  326. return;
  327. }
  328. break;
  329. case SM_NONE:
  330. /* normal hit */
  331. break;
  332. default:
  333. if (drandom() > 0.2)
  334. /* normal hit */
  335. break;
  336. /* else special things */
  337. switch (Curmonster.m_type) {
  338. case SM_LEANAN:
  339. /* takes some of the player's strength */
  340. inflict = ROLL(1.0, (Circle - 1.0) / 2.0);
  341. inflict = MIN(Player.p_strength, inflict);
  342. mvprintw(Lines++, 0, "%s sapped %.0f of your strength!",
  343. Enemyname, inflict);
  344. Player.p_strength -= inflict;
  345. Player.p_might -= inflict;
  346. break;
  347. case SM_SARUMAN:
  348. if (Player.p_palantir)
  349. /* take away palantir */
  350. {
  351. mvprintw(Lines++, 0, "Wormtongue stole your palantir!");
  352. Player.p_palantir = FALSE;
  353. } else
  354. if (drandom() > 0.5)
  355. /* gems turn to gold */
  356. {
  357. mvprintw(Lines++, 0,
  358. "%s transformed your gems into gold!", Enemyname);
  359. Player.p_gold += Player.p_gems;
  360. Player.p_gems = 0.0;
  361. } else
  362. /* scramble some stats */
  363. {
  364. mvprintw(Lines++, 0, "%s scrambled your stats!", Enemyname);
  365. scramblestats();
  366. }
  367. break;
  368. case SM_THAUMATURG:
  369. /* transport player */
  370. mvprintw(Lines++, 0, "%s transported you!", Enemyname);
  371. altercoordinates(0.0, 0.0, A_FAR);
  372. cancelmonster();
  373. break;
  374. case SM_VORTEX:
  375. /* suck up some mana */
  376. inflict = ROLL(0, 7.5 * Circle);
  377. inflict = MIN(Player.p_mana, floor(inflict));
  378. mvprintw(Lines++, 0,
  379. "%s sucked up %.0f of your mana!", Enemyname, inflict);
  380. Player.p_mana -= inflict;
  381. break;
  382. case SM_NAZGUL:
  383. /* try to take ring if player has one */
  384. if (Player.p_ring.ring_type != R_NONE)
  385. /* player has a ring */
  386. {
  387. mvaddstr(Lines++, 0, "Will you relinguish your ring ? ");
  388. ch = getanswer("YN", FALSE);
  389. if (ch == 'Y')
  390. /* take ring away */
  391. {
  392. Player.p_ring.ring_type = R_NONE;
  393. Player.p_ring.ring_inuse = FALSE;
  394. cancelmonster();
  395. break;
  396. }
  397. }
  398. /* otherwise, take some brains */
  399. mvprintw(Lines++, 0,
  400. "%s neutralized 1/5 of your brain!", Enemyname);
  401. Player.p_brains *= 0.8;
  402. break;
  403. case SM_TIAMAT:
  404. /* take some gold and gems */
  405. mvprintw(Lines++, 0,
  406. "%s took half your gold and gems and flew off.", Enemyname);
  407. Player.p_gold /= 2.0;
  408. Player.p_gems /= 2.0;
  409. cancelmonster();
  410. break;
  411. case SM_KOBOLD:
  412. /* steal a gold piece and run */
  413. mvprintw(Lines++, 0,
  414. "%s stole one gold piece and ran away.", Enemyname);
  415. Player.p_gold = MAX(0.0, Player.p_gold - 1.0);
  416. cancelmonster();
  417. break;
  418. case SM_SHELOB:
  419. /* bite and (medium) poison */
  420. mvprintw(Lines++, 0,
  421. "%s has bitten and poisoned you!", Enemyname);
  422. Player.p_poison -= 1.0;
  423. break;
  424. case SM_LAMPREY:
  425. /* bite and (small) poison */
  426. mvprintw(Lines++, 0, "%s bit and poisoned you!", Enemyname);
  427. Player.p_poison += 0.25;
  428. break;
  429. case SM_BONNACON:
  430. /* fart and run */
  431. mvprintw(Lines++, 0, "%s farted and scampered off.", Enemyname);
  432. Player.p_energy /= 2.0; /* damage from fumes */
  433. cancelmonster();
  434. break;
  435. case SM_SMEAGOL:
  436. if (Player.p_ring.ring_type != R_NONE)
  437. /* try to steal ring */
  438. {
  439. mvprintw(Lines++, 0,
  440. "%s tried to steal your ring, ", Enemyname);
  441. if (drandom() > 0.1)
  442. addstr("but was unsuccessful.");
  443. else {
  444. addstr("and ran away with it!");
  445. Player.p_ring.ring_type = R_NONE;
  446. cancelmonster();
  447. }
  448. }
  449. break;
  450. case SM_SUCCUBUS:
  451. /* inflict damage through shield */
  452. inflict = ROLL(15.0, Circle * 10.0);
  453. inflict = MIN(inflict, Player.p_energy);
  454. mvprintw(Lines++, 0, "%s sapped %.0f of your energy.",
  455. Enemyname, inflict);
  456. Player.p_energy -= inflict;
  457. break;
  458. case SM_CERBERUS:
  459. /* take all metal treasures */
  460. mvprintw(Lines++, 0,
  461. "%s took all your metal treasures!", Enemyname);
  462. Player.p_crowns = 0;
  463. Player.p_sword =
  464. Player.p_shield =
  465. Player.p_gold = 0.0;
  466. cancelmonster();
  467. break;
  468. case SM_UNGOLIANT:
  469. /* (large) poison and take a quickness */
  470. mvprintw(Lines++, 0,
  471. "%s poisoned you, and took one quik.", Enemyname);
  472. Player.p_poison += 5.0;
  473. Player.p_quickness -= 1.0;
  474. break;
  475. case SM_JABBERWOCK:
  476. /* fly away, and leave either a Jubjub bird or
  477. * Bonnacon */
  478. mvprintw(Lines++, 0,
  479. "%s flew away, and left you to contend with one of its friends.",
  480. Enemyname);
  481. Whichmonster = 55 + ((drandom() > 0.5) ? 22 : 0);
  482. longjmp(Fightenv, 0);
  483. /* NOTREACHED */
  484. case SM_TROLL:
  485. /* partially regenerate monster */
  486. mvprintw(Lines++, 0,
  487. "%s partially regenerated his energy.!", Enemyname);
  488. Curmonster.m_energy +=
  489. floor((Curmonster.m_o_energy - Curmonster.m_energy) / 2.0);
  490. Curmonster.m_strength = Curmonster.m_o_strength;
  491. Curmonster.m_melee = Curmonster.m_skirmish = 0.0;
  492. Curmonster.m_maxspeed = Curmonster.m_o_speed;
  493. break;
  494. case SM_WRAITH:
  495. if (!Player.p_blindness)
  496. /* make blind */
  497. {
  498. mvprintw(Lines++, 0, "%s blinded you!", Enemyname);
  499. Player.p_blindness = TRUE;
  500. Enemyname = "A monster";
  501. }
  502. break;
  503. }
  504. return;
  505. }
  506. /* fall through to here if monster inflicts a normal hit */
  507. inflict = drandom() * Curmonster.m_strength + 0.5;
  508. SPECIALHIT:
  509. mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, inflict);
  510. if ((Shield -= inflict) < 0) {
  511. Player.p_energy += Shield;
  512. Shield = 0.0;
  513. }
  514. }
  515. void
  516. cancelmonster()
  517. {
  518. Curmonster.m_energy = 0.0;
  519. Curmonster.m_experience = 0.0;
  520. Curmonster.m_treasuretype = 0;
  521. Curmonster.m_flock = 0.0;
  522. }
  523. void
  524. hitmonster(inflict)
  525. double inflict;
  526. {
  527. mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, inflict);
  528. Curmonster.m_energy -= inflict;
  529. if (Curmonster.m_energy > 0.0) {
  530. if (Curmonster.m_type == SM_DARKLORD || Curmonster.m_type == SM_SHRIEKER)
  531. /* special monster didn't die */
  532. monsthits();
  533. } else
  534. /* monster died. print message. */
  535. {
  536. if (Curmonster.m_type == SM_MORGOTH)
  537. mvaddstr(Lines++, 0, "You have defeated Morgoth, but he may return. . .");
  538. else
  539. /* all other types of monsters */
  540. {
  541. mvprintw(Lines++, 0, "You killed it. Good work, %s.", Player.p_name);
  542. if (Curmonster.m_type == SM_MIMIC
  543. && strcmp(Curmonster.m_name, "A Mimic") != 0
  544. && !Player.p_blindness)
  545. mvaddstr(Lines++, 0, "The body slowly changes into the form of a mimic.");
  546. }
  547. }
  548. }
  549. void
  550. throwspell()
  551. {
  552. double inflict; /* damage inflicted */
  553. double dtemp; /* for dtemporary calculations */
  554. int ch; /* input */
  555. inflict = 0;
  556. mvaddstr(7, 0, "\n\n"); /* clear menu area */
  557. if (Player.p_magiclvl >= ML_ALLORNOTHING)
  558. mvaddstr(7, 0, "1:All or Nothing ");
  559. if (Player.p_magiclvl >= ML_MAGICBOLT)
  560. addstr("2:Magic Bolt ");
  561. if (Player.p_magiclvl >= ML_FORCEFIELD)
  562. addstr("3:Force Field ");
  563. if (Player.p_magiclvl >= ML_XFORM)
  564. addstr("4:Transform ");
  565. if (Player.p_magiclvl >= ML_INCRMIGHT)
  566. addstr("5:Increase Might\n");
  567. if (Player.p_magiclvl >= ML_INVISIBLE)
  568. mvaddstr(8, 0, "6:Invisibility ");
  569. if (Player.p_magiclvl >= ML_XPORT)
  570. addstr("7:Transport ");
  571. if (Player.p_magiclvl >= ML_PARALYZE)
  572. addstr("8:Paralyze ");
  573. if (Player.p_specialtype >= SC_COUNCIL)
  574. addstr("9:Specify");
  575. mvaddstr(4, 0, "Spell ? ");
  576. ch = getanswer(" ", TRUE);
  577. mvaddstr(7, 0, "\n\n"); /* clear menu area */
  578. if (Curmonster.m_type == SM_MORGOTH && ch != '3')
  579. /* can only throw force field against Morgoth */
  580. ILLSPELL();
  581. else
  582. switch (ch) {
  583. case '1': /* all or nothing */
  584. if (drandom() < 0.25)
  585. /* success */
  586. {
  587. inflict = Curmonster.m_energy * 1.01 + 1.0;
  588. if (Curmonster.m_type == SM_DARKLORD)
  589. /* all or nothing doesn't quite work
  590. * against D. L. */
  591. inflict *= 0.9;
  592. } else
  593. /* failure -- monster gets stronger and
  594. * quicker */
  595. {
  596. Curmonster.m_o_strength = Curmonster.m_strength *= 2.0;
  597. Curmonster.m_maxspeed *= 2.0;
  598. Curmonster.m_o_speed *= 2.0;
  599. /* paralyzed monsters wake up a bit */
  600. Curmonster.m_speed = MAX(1.0, Curmonster.m_speed * 2.0);
  601. }
  602. if (Player.p_mana >= MM_ALLORNOTHING)
  603. /* take a mana if player has one */
  604. Player.p_mana -= MM_ALLORNOTHING;
  605. hitmonster(inflict);
  606. break;
  607. case '2': /* magic bolt */
  608. if (Player.p_magiclvl < ML_MAGICBOLT)
  609. ILLSPELL();
  610. else {
  611. do
  612. /* prompt for amount to expend */
  613. {
  614. mvaddstr(4, 0, "How much mana for bolt? ");
  615. dtemp = floor(infloat());
  616. }
  617. while (dtemp < 0.0 || dtemp > Player.p_mana);
  618. Player.p_mana -= dtemp;
  619. if (Curmonster.m_type == SM_DARKLORD)
  620. /* magic bolts don't work against D.
  621. * L. */
  622. inflict = 0.0;
  623. else
  624. inflict = dtemp * ROLL(15.0, sqrt(Player.p_magiclvl / 3.0 + 1.0));
  625. mvaddstr(5, 0, "Magic Bolt fired!\n");
  626. hitmonster(inflict);
  627. }
  628. break;
  629. case '3': /* force field */
  630. if (Player.p_magiclvl < ML_FORCEFIELD)
  631. ILLSPELL();
  632. else
  633. if (Player.p_mana < MM_FORCEFIELD)
  634. NOMANA();
  635. else {
  636. Player.p_mana -= MM_FORCEFIELD;
  637. Shield = (Player.p_maxenergy + Player.p_shield) * 4.2 + 45.0;
  638. mvaddstr(5, 0, "Force Field up.\n");
  639. }
  640. break;
  641. case '4': /* transform */
  642. if (Player.p_magiclvl < ML_XFORM)
  643. ILLSPELL();
  644. else
  645. if (Player.p_mana < MM_XFORM)
  646. NOMANA();
  647. else {
  648. Player.p_mana -= MM_XFORM;
  649. Whichmonster = (int) ROLL(0.0, 100.0);
  650. longjmp(Fightenv, 0);
  651. /* NOTREACHED */
  652. }
  653. break;
  654. case '5': /* increase might */
  655. if (Player.p_magiclvl < ML_INCRMIGHT)
  656. ILLSPELL();
  657. else
  658. if (Player.p_mana < MM_INCRMIGHT)
  659. NOMANA();
  660. else {
  661. Player.p_mana -= MM_INCRMIGHT;
  662. Player.p_might +=
  663. (1.2 * (Player.p_strength + Player.p_sword)
  664. + 5.0 - Player.p_might) / 2.0;
  665. mvprintw(5, 0, "New strength: %.0f\n", Player.p_might);
  666. }
  667. break;
  668. case '6': /* invisible */
  669. if (Player.p_magiclvl < ML_INVISIBLE)
  670. ILLSPELL();
  671. else
  672. if (Player.p_mana < MM_INVISIBLE)
  673. NOMANA();
  674. else {
  675. Player.p_mana -= MM_INVISIBLE;
  676. Player.p_speed +=
  677. (1.2 * (Player.p_quickness + Player.p_quksilver)
  678. + 5.0 - Player.p_speed) / 2.0;
  679. mvprintw(5, 0, "New quickness: %.0f\n", Player.p_speed);
  680. }
  681. break;
  682. case '7': /* transport */
  683. if (Player.p_magiclvl < ML_XPORT)
  684. ILLSPELL();
  685. else
  686. if (Player.p_mana < MM_XPORT)
  687. NOMANA();
  688. else {
  689. Player.p_mana -= MM_XPORT;
  690. if (Player.p_brains + Player.p_magiclvl
  691. < Curmonster.m_experience / 200.0 * drandom()) {
  692. mvaddstr(5, 0, "Transport backfired!\n");
  693. altercoordinates(0.0, 0.0, A_FAR);
  694. cancelmonster();
  695. } else {
  696. mvprintw(5, 0, "%s is transported.\n", Enemyname);
  697. if (drandom() < 0.3)
  698. /* monster didn't drop
  699. * its treasure */
  700. Curmonster.m_treasuretype = 0;
  701. Curmonster.m_energy = 0.0;
  702. }
  703. }
  704. break;
  705. case '8': /* paralyze */
  706. if (Player.p_magiclvl < ML_PARALYZE)
  707. ILLSPELL();
  708. else
  709. if (Player.p_mana < MM_PARALYZE)
  710. NOMANA();
  711. else {
  712. Player.p_mana -= MM_PARALYZE;
  713. if (Player.p_magiclvl >
  714. Curmonster.m_experience / 1000.0 * drandom()) {
  715. mvprintw(5, 0, "%s is held.\n", Enemyname);
  716. Curmonster.m_speed = -2.0;
  717. } else
  718. mvaddstr(5, 0, "Monster unaffected.\n");
  719. }
  720. break;
  721. case '9': /* specify */
  722. if (Player.p_specialtype < SC_COUNCIL)
  723. ILLSPELL();
  724. else
  725. if (Player.p_mana < MM_SPECIFY)
  726. NOMANA();
  727. else {
  728. Player.p_mana -= MM_SPECIFY;
  729. mvaddstr(5, 0, "Which monster do you want [0-99] ? ");
  730. Whichmonster = (int) infloat();
  731. Whichmonster = MAX(0, MIN(99, Whichmonster));
  732. longjmp(Fightenv, 0);
  733. /* NOTREACHED */
  734. }
  735. break;
  736. }
  737. }
  738. void
  739. callmonster(which)
  740. int which;
  741. {
  742. struct monster Othermonster; /* to find a name for mimics */
  743. which = MIN(which, 99); /* make sure within range */
  744. /* fill structure */
  745. fseek(Monstfp, (long) which * (long) SZ_MONSTERSTRUCT, SEEK_SET);
  746. fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
  747. /* handle some special monsters */
  748. if (Curmonster.m_type == SM_MODNAR) {
  749. if (Player.p_specialtype < SC_COUNCIL)
  750. /* randomize some stats */
  751. {
  752. Curmonster.m_strength *= drandom() + 0.5;
  753. Curmonster.m_brains *= drandom() + 0.5;
  754. Curmonster.m_speed *= drandom() + 0.5;
  755. Curmonster.m_energy *= drandom() + 0.5;
  756. Curmonster.m_experience *= drandom() + 0.5;
  757. Curmonster.m_treasuretype =
  758. (int) ROLL(0.0, (double) Curmonster.m_treasuretype);
  759. } else
  760. /* make Modnar into Morgoth */
  761. {
  762. strcpy(Curmonster.m_name, "Morgoth");
  763. Curmonster.m_strength = drandom() * (Player.p_maxenergy + Player.p_shield) / 1.4
  764. + drandom() * (Player.p_maxenergy + Player.p_shield) / 1.5;
  765. Curmonster.m_brains = Player.p_brains;
  766. Curmonster.m_energy = Player.p_might * 30.0;
  767. Curmonster.m_type = SM_MORGOTH;
  768. Curmonster.m_speed = Player.p_speed * 1.1
  769. + ((Player.p_specialtype == SC_EXVALAR) ? Player.p_speed : 0.0);
  770. Curmonster.m_flock = 0.0;
  771. Curmonster.m_treasuretype = 0;
  772. Curmonster.m_experience = 0.0;
  773. }
  774. } else
  775. if (Curmonster.m_type == SM_MIMIC)
  776. /* pick another name */
  777. {
  778. which = (int) ROLL(0.0, 100.0);
  779. fseek(Monstfp, (long) which * (long) SZ_MONSTERSTRUCT, SEEK_SET);
  780. fread(&Othermonster, SZ_MONSTERSTRUCT, 1, Monstfp);
  781. strcpy(Curmonster.m_name, Othermonster.m_name);
  782. }
  783. truncstring(Curmonster.m_name);
  784. if (Curmonster.m_type != SM_MORGOTH)
  785. /* adjust stats based on which circle player is in */
  786. {
  787. Curmonster.m_strength *= (1.0 + Circle / 2.0);
  788. Curmonster.m_brains *= Circle;
  789. Curmonster.m_speed += Circle * 1.e-9;
  790. Curmonster.m_energy *= Circle;
  791. Curmonster.m_experience *= Circle;
  792. }
  793. if (Player.p_blindness)
  794. /* cannot see monster if blind */
  795. Enemyname = "A monster";
  796. else
  797. Enemyname = Curmonster.m_name;
  798. if (Player.p_speed <= 0.0)
  799. /* make Player.p_speed positive */
  800. {
  801. Curmonster.m_speed += -Player.p_speed;
  802. Player.p_speed = 1.0;
  803. }
  804. /* fill up the rest of the structure */
  805. Curmonster.m_o_strength = Curmonster.m_strength;
  806. Curmonster.m_o_speed = Curmonster.m_maxspeed = Curmonster.m_speed;
  807. Curmonster.m_o_energy = Curmonster.m_energy;
  808. Curmonster.m_melee = Curmonster.m_skirmish = 0.0;
  809. }
  810. void
  811. awardtreasure()
  812. {
  813. int whichtreasure; /* calculated treasure to grant */
  814. int temp; /* temporary */
  815. int ch; /* input */
  816. double treasuretype; /* monster's treasure type */
  817. double gold = 0.0; /* gold awarded */
  818. double gems = 0.0; /* gems awarded */
  819. double dtemp; /* for temporary calculations */
  820. whichtreasure = (int) ROLL(1.0, 3.0); /* pick a treasure */
  821. treasuretype = (double) Curmonster.m_treasuretype;
  822. move(4, 0);
  823. clrtobot();
  824. move(6, 0);
  825. if (drandom() > 0.65)
  826. /* gold and gems */
  827. {
  828. if (Curmonster.m_treasuretype > 7)
  829. /* gems */
  830. {
  831. gems = ROLL(1.0, (treasuretype - 7.0)
  832. * (treasuretype - 7.0) * (Circle - 1.0) / 4.0);
  833. printw("You have discovered %.0f gems!", gems);
  834. } else
  835. /* gold */
  836. {
  837. gold = ROLL(treasuretype * 10.0, treasuretype
  838. * treasuretype * 10.0 * (Circle - 1.0));
  839. printw("You have found %.0f gold pieces.", gold);
  840. }
  841. addstr(" Do you want to pick them up ? ");
  842. ch = getanswer("NY", FALSE);
  843. addstr("\n\n");
  844. if (ch == 'Y') {
  845. if (drandom() < treasuretype / 35.0 + 0.04)
  846. /* cursed */
  847. {
  848. addstr("They were cursed!\n");
  849. cursedtreasure();
  850. } else
  851. collecttaxes(gold, gems);
  852. }
  853. return;
  854. } else
  855. /* other treasures */
  856. {
  857. addstr("You have found some treasure. Do you want to inspect it ? ");
  858. ch = getanswer("NY", FALSE);
  859. addstr("\n\n");
  860. if (ch != 'Y')
  861. return;
  862. else
  863. if (drandom() < 0.08 && Curmonster.m_treasuretype != 4) {
  864. addstr("It was cursed!\n");
  865. cursedtreasure();
  866. return;
  867. } else
  868. switch (Curmonster.m_treasuretype) {
  869. case 1: /* treasure type 1 */
  870. switch (whichtreasure) {
  871. case 1:
  872. addstr("You've discovered a power booster!\n");
  873. Player.p_mana += ROLL(Circle * 4.0, Circle * 30.0);
  874. break;
  875. case 2:
  876. addstr("You have encountered a druid.\n");
  877. Player.p_experience +=
  878. ROLL(0.0, 2000.0 + Circle * 400.0);
  879. break;
  880. case 3:
  881. addstr("You have found a holy orb.\n");
  882. Player.p_sin = MAX(0.0, Player.p_sin - 0.25);
  883. break;
  884. }
  885. break;
  886. /* end treasure type 1 */
  887. case 2: /* treasure type 2 */
  888. switch (whichtreasure) {
  889. case 1:
  890. addstr("You have found an amulet.\n");
  891. ++Player.p_amulets;
  892. break;
  893. case 2:
  894. addstr("You've found some holy water!\n");
  895. ++Player.p_holywater;
  896. break;
  897. case 3:
  898. addstr("You've met a hermit!\n");
  899. Player.p_sin *= 0.75;
  900. Player.p_mana += 12.0 * Circle;
  901. break;
  902. }
  903. break;
  904. /* end treasure type 2 */
  905. case 3: /* treasure type 3 */
  906. switch (whichtreasure) {
  907. case 1:
  908. dtemp = ROLL(7.0, 30.0 + Circle / 10.0);
  909. printw("You've found a +%.0f shield!\n", dtemp);
  910. if (dtemp >= Player.p_shield)
  911. Player.p_shield = dtemp;
  912. else
  913. SOMEBETTER();
  914. break;
  915. case 2:
  916. addstr("You have rescued a virgin. Will you be honorable ? ");
  917. ch = getanswer("NY", FALSE);
  918. addstr("\n\n");
  919. if (ch == 'Y')
  920. Player.p_virgin = TRUE;
  921. else {
  922. Player.p_experience += 2000.0 * Circle;
  923. ++Player.p_sin;
  924. }
  925. break;
  926. case 3:
  927. addstr("You've discovered some athelas!\n");
  928. --Player.p_poison;
  929. break;
  930. }
  931. break;
  932. /* end treasure type 3 */
  933. case 4: /* treasure type 4 */
  934. addstr("You've found a scroll. Will you read it ? ");
  935. ch = getanswer("NY", FALSE);
  936. addstr("\n\n");
  937. if (ch == 'Y')
  938. switch ((int) ROLL(1, 6)) {
  939. case 1:
  940. addstr("It throws up a shield for you next monster.\n");
  941. getyx(stdscr, whichtreasure, ch);
  942. more(whichtreasure);
  943. Shield =
  944. (Player.p_maxenergy + Player.p_energy) * 5.5 + Circle * 50.0;
  945. Whichmonster = pickmonster();
  946. longjmp(Fightenv, 0);
  947. /* NOTREACHED */
  948. case 2:
  949. addstr("It makes you invisible for you next monster.\n");
  950. getyx(stdscr, whichtreasure, ch);
  951. more(whichtreasure);
  952. Player.p_speed = 1e6;
  953. Whichmonster = pickmonster();
  954. longjmp(Fightenv, 0);
  955. /* NOTREACHED */
  956. case 3:
  957. addstr("It increases your strength ten fold to fight your next monster.\n");
  958. getyx(stdscr, whichtreasure, ch);
  959. more(whichtreasure);
  960. Player.p_might *= 10.0;
  961. Whichmonster = pickmonster();
  962. longjmp(Fightenv, 0);
  963. /* NOTREACHED */
  964. case 4:
  965. addstr("It is a general knowledge scroll.\n");
  966. Player.p_brains += ROLL(2.0, Circle);
  967. Player.p_magiclvl += ROLL(1.0, Circle / 2.0);
  968. break;
  969. case 5:
  970. addstr("It tells you how to pick your next monster.\n");
  971. addstr("Which monster do you want [0-99] ? ");
  972. Whichmonster = (int) infloat();
  973. Whichmonster = MIN(99, MAX(0, Whichmonster));
  974. longjmp(Fightenv, 0);
  975. case 6:
  976. addstr("It was cursed!\n");
  977. cursedtreasure();
  978. break;
  979. }
  980. break;
  981. /* end treasure type 4 */
  982. case 5: /* treasure type 5 */
  983. switch (whichtreasure) {
  984. case 1:
  985. dtemp = ROLL(Circle / 4.0 + 5.0, Circle / 2.0 + 9.0);
  986. printw("You've discovered a +%.0f dagger.\n", dtemp);
  987. if (dtemp >= Player.p_sword)
  988. Player.p_sword = dtemp;
  989. else
  990. SOMEBETTER();
  991. break;
  992. case 2:
  993. dtemp = ROLL(7.5 + Circle * 3.0, Circle * 2.0 + 160.0);
  994. printw("You have found some +%.0f armour!\n", dtemp);
  995. if (dtemp >= Player.p_shield)
  996. Player.p_shield = dtemp;
  997. else
  998. SOMEBETTER();
  999. break;
  1000. case 3:
  1001. addstr("You've found a tablet.\n");
  1002. Player.p_brains += 4.5 * Circle;
  1003. break;
  1004. }
  1005. break;
  1006. /* end treasure type 5 */
  1007. case 6: /* treasure type 6 */
  1008. switch (whichtreasure) {
  1009. case 1:
  1010. addstr("You've found a priest.\n");
  1011. Player.p_energy = Player.p_maxenergy + Player.p_shield;
  1012. Player.p_sin /= 2.0;
  1013. Player.p_mana += 24.0 * Circle;
  1014. Player.p_brains += Circle;
  1015. break;
  1016. case 2:
  1017. addstr("You have come upon Robin Hood!\n");
  1018. Player.p_shield += Circle * 2.0;
  1019. Player.p_strength += Circle / 2.5 + 1.0;
  1020. break;
  1021. case 3:
  1022. dtemp = ROLL(2.0 + Circle / 4.0, Circle / 1.2 + 10.0);
  1023. printw("You have found a +%.0f axe!\n", dtemp);
  1024. if (dtemp >= Player.p_sword)
  1025. Player.p_sword = dtemp;
  1026. else
  1027. SOMEBETTER();
  1028. break;
  1029. }
  1030. break;
  1031. /* end treasure type 6 */
  1032. case 7: /* treasure type 7 */
  1033. switch (whichtreasure) {
  1034. case 1:
  1035. addstr("You've discovered a charm!\n");
  1036. ++Player.p_charms;
  1037. break;
  1038. case 2:
  1039. addstr("You have encountered Merlyn!\n");
  1040. Player.p_brains += Circle + 5.0;
  1041. Player.p_magiclvl += Circle / 3.0 + 5.0;
  1042. Player.p_mana += Circle * 10.0;
  1043. break;
  1044. case 3:
  1045. dtemp = ROLL(5.0 + Circle / 3.0, Circle / 1.5 + 20.0);
  1046. printw("You have found a +%.0f war hammer!\n", dtemp);
  1047. if (dtemp >= Player.p_sword)
  1048. Player.p_sword = dtemp;
  1049. else
  1050. SOMEBETTER();
  1051. break;
  1052. }
  1053. break;
  1054. /* end treasure type 7 */
  1055. case 8: /* treasure type 8 */
  1056. switch (whichtreasure) {
  1057. case 1:
  1058. addstr("You have found a healing potion.\n");
  1059. Player.p_poison = MIN(-2.0, Player.p_poison - 2.0);
  1060. break;
  1061. case 2:
  1062. addstr("You have discovered a transporter. Do you wish to go anywhere ? ");
  1063. ch = getanswer("NY", FALSE);
  1064. addstr("\n\n");
  1065. if (ch == 'Y') {
  1066. double x, y;
  1067. addstr("X Y Coordinates ? ");
  1068. getstring(Databuf, SZ_DATABUF);
  1069. sscanf(Databuf, "%lf %lf", &x, &y);
  1070. altercoordinates(x, y, A_FORCED);
  1071. }
  1072. break;
  1073. case 3:
  1074. dtemp = ROLL(10.0 + Circle / 1.2, Circle * 3.0 + 30.0);
  1075. printw("You've found a +%.0f sword!\n", dtemp);
  1076. if (dtemp >= Player.p_sword)
  1077. Player.p_sword = dtemp;
  1078. else
  1079. SOMEBETTER();
  1080. break;
  1081. }
  1082. break;
  1083. /* end treasure type 8 */
  1084. case 10:
  1085. case 11:
  1086. case 12:
  1087. case 13: /* treasure types 10 - 13 */
  1088. if (drandom() < 0.33) {
  1089. if (Curmonster.m_treasuretype == 10) {
  1090. addstr("You've found a pair of elven boots!\n");
  1091. Player.p_quickness += 2.0;
  1092. break;
  1093. } else
  1094. if (Curmonster.m_treasuretype == 11
  1095. && !Player.p_palantir) {
  1096. addstr("You've acquired Saruman's palantir.\n");
  1097. Player.p_palantir = TRUE;
  1098. break;
  1099. } else
  1100. if (Player.p_ring.ring_type == R_NONE
  1101. && Player.p_specialtype < SC_COUNCIL
  1102. && (Curmonster.m_treasuretype == 12
  1103. || Curmonster.m_treasuretype == 13))
  1104. /* roll
  1105. * up
  1106. * a
  1107. * ring
  1108. * */
  1109. {
  1110. if (drandom() < 0.8)
  1111. /* r
  1112. * e
  1113. * g
  1114. * u
  1115. * l
  1116. * a
  1117. * r
  1118. *
  1119. * ri
  1120. * n
  1121. * g
  1122. * s
  1123. * */
  1124. {
  1125. if (Curmonster.m_treasuretype == 12) {
  1126. whichtreasure = R_NAZREG;
  1127. temp = 35;
  1128. } else {
  1129. whichtreasure = R_DLREG;
  1130. temp = 0;
  1131. }
  1132. } else
  1133. /* b
  1134. * a
  1135. * d
  1136. *
  1137. * ri
  1138. * n
  1139. * g
  1140. * s
  1141. * */
  1142. {
  1143. whichtreasure = R_BAD;
  1144. temp = 15 + Statptr->c_ringduration + (int) ROLL(0, 5);
  1145. }
  1146. addstr("You've discovered a ring. Will you pick it up ? ");
  1147. ch = getanswer("NY", FALSE);
  1148. addstr("\n\n");
  1149. if (ch == 'Y') {
  1150. Player.p_ring.ring_type = whichtreasure;
  1151. Player.p_ring.ring_duration = temp;
  1152. }
  1153. break;
  1154. }
  1155. }
  1156. /* end treasure types 10 - 13 */
  1157. /* fall through to treasure type 9 if
  1158. * no treasure from above */
  1159. case 9: /* treasure type 9 */
  1160. switch (whichtreasure) {
  1161. case 1:
  1162. if (Player.p_level <= 1000.0
  1163. && Player.p_crowns <= 3
  1164. && Player.p_level >= 10.0) {
  1165. addstr("You have found a golden crown!\n");
  1166. ++Player.p_crowns;
  1167. break;
  1168. }
  1169. /* fall through otherwise */
  1170. case 2:
  1171. addstr("You've been blessed!\n");
  1172. Player.p_blessing = TRUE;
  1173. Player.p_sin /= 3.0;
  1174. Player.p_energy = Player.p_maxenergy + Player.p_shield;
  1175. Player.p_mana += 100.0 * Circle;
  1176. break;
  1177. case 3:
  1178. dtemp = ROLL(1.0, Circle / 5.0 + 5.0);
  1179. dtemp = MIN(dtemp, 99.0);
  1180. printw("You have discovered some +%.0f quicksilver!\n", dtemp);
  1181. if (dtemp >= Player.p_quksilver)
  1182. Player.p_quksilver = dtemp;
  1183. else
  1184. SOMEBETTER();
  1185. break;
  1186. }
  1187. break;
  1188. /* end treasure type 9 */
  1189. }
  1190. }
  1191. }
  1192. void
  1193. cursedtreasure()
  1194. {
  1195. if (Player.p_charms > 0) {
  1196. addstr("But your charm saved you!\n");
  1197. --Player.p_charms;
  1198. } else
  1199. if (Player.p_amulets > 0) {
  1200. addstr("But your amulet saved you!\n");
  1201. --Player.p_amulets;
  1202. } else {
  1203. Player.p_energy =
  1204. (Player.p_maxenergy + Player.p_shield) / 10.0;
  1205. Player.p_poison += 0.25;
  1206. }
  1207. }
  1208. void
  1209. scramblestats()
  1210. {
  1211. double dbuf[6]; /* to put statistic in */
  1212. double dtemp1, dtemp2; /* for swapping values */
  1213. int first, second; /* indices for swapping */
  1214. double *dptr; /* pointer for filling and emptying buf[] */
  1215. /* fill buffer */
  1216. dptr = &dbuf[0];
  1217. *dptr++ = Player.p_strength;
  1218. *dptr++ = Player.p_mana;
  1219. *dptr++ = Player.p_brains;
  1220. *dptr++ = Player.p_magiclvl;
  1221. *dptr++ = Player.p_energy;
  1222. *dptr = Player.p_sin;
  1223. /* pick values to swap */
  1224. first = (int) ROLL(0, 5);
  1225. second = (int) ROLL(0, 5);
  1226. /* swap values */
  1227. dptr = &dbuf[0];
  1228. dtemp1 = dptr[first];
  1229. /* this expression is split to prevent a compiler loop on some
  1230. * compilers */
  1231. dtemp2 = dptr[second];
  1232. dptr[first] = dtemp2;
  1233. dptr[second] = dtemp1;
  1234. /* empty buffer */
  1235. Player.p_strength = *dptr++;
  1236. Player.p_mana = *dptr++;
  1237. Player.p_brains = *dptr++;
  1238. Player.p_magiclvl = *dptr++;
  1239. Player.p_energy = *dptr++;
  1240. Player.p_sin = *dptr;
  1241. }