scroll.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /* =============================================================================
  2. * PROGRAM: ularn
  3. * FILENAME: scroll.c
  4. *
  5. * DESCRIPTION:
  6. * This module handles the processing for scrolls and books.
  7. *
  8. * =============================================================================
  9. * EXPORTED VARIABLES
  10. *
  11. * scrollname : The name of each scroll.
  12. *
  13. * =============================================================================
  14. * EXPORTED FUNCTIONS
  15. *
  16. * newscroll : Function to create a new scroll # with the correct probability
  17. * read_scroll : Function to process reading a scroll.
  18. * readbook : Function to process reading a book.
  19. *
  20. * =============================================================================
  21. */
  22. #include "scroll.h"
  23. #include "dungeon.h"
  24. #include "dungeon_obj.h"
  25. #include "header.h"
  26. #include "itm.h"
  27. #include "monster.h"
  28. #include "player.h"
  29. #include "potion.h"
  30. #include "spell.h"
  31. #include "ularn_win.h"
  32. /* =============================================================================
  33. * Exported variables
  34. */
  35. /* name array for scrolls */
  36. char *scrollname[MAXSCROLL] = {" enchant armor",
  37. " enchant weapon",
  38. " enlightenment",
  39. " blank paper",
  40. " create monster",
  41. " create artifact",
  42. " aggravate monsters",
  43. " time warp",
  44. " teleportation",
  45. " expanded awareness",
  46. " haste monsters",
  47. " monster healing",
  48. " spirit protection",
  49. " undead protection",
  50. " stealth",
  51. " magic mapping",
  52. " hold monsters",
  53. " gem perfection",
  54. " spell extension",
  55. " identify",
  56. " remove curse",
  57. " annihilation",
  58. " pulverization",
  59. " life protection",
  60. " ",
  61. " ",
  62. " ",
  63. " "};
  64. /* =============================================================================
  65. * Local variables
  66. */
  67. /*
  68. * data for the function to read a scroll
  69. */
  70. static int xh, yh, yl, xl;
  71. /*
  72. * List of attributes affected by spell extension
  73. */
  74. #define EXTENSION_COUNT 11
  75. static int exten[EXTENSION_COUNT] = {PROTECTIONTIME, DEXCOUNT, STRCOUNT,
  76. CHARMCOUNT, INVISIBILITY, CANCELLATION,
  77. HASTESELF, GLOBE, SCAREMONST,
  78. HOLDMONST, TIMESTOP};
  79. /*
  80. * Array to create scroll numbers with appropriate probability of
  81. * occurrence.
  82. */
  83. #define SCROLL_PROB_SIZE 81
  84. static char scprob[SCROLL_PROB_SIZE] = {
  85. SENCHANTARM, SENCHANTARM, SENCHANTARM, SENCHANTARM, SENCHANTWEAP,
  86. SENCHANTWEAP, SENCHANTWEAP, SENCHANTWEAP, SENCHANTWEAP, SENLIGHTEN,
  87. SENLIGHTEN, SENLIGHTEN, SENLIGHTEN, SENLIGHTEN, SENLIGHTEN,
  88. SBLANK, SBLANK, SBLANK, SBLANK, SBLANK,
  89. SCREATEMONST, SCREATEMONST, SCREATEMONST, SCREATEITEM, SCREATEITEM,
  90. SCREATEITEM, SCREATEITEM, SCREATEITEM, SAGGMONST, SAGGMONST,
  91. SAGGMONST, SAGGMONST, SAGGMONST, STIMEWARP, STIMEWARP,
  92. STIMEWARP, STIMEWARP, STELEPORT, STELEPORT, STELEPORT,
  93. SAWARENESS, SAWARENESS, SAWARENESS, SAWARENESS, SHASTEMONST,
  94. SHASTEMONST, SHASTEMONST, SHASTEMONST, SMONSTHEAL, SMONSTHEAL,
  95. SMONSTHEAL, SSPIRITPROT, SSPIRITPROT, SSPIRITPROT, SUNDEADPROT,
  96. SUNDEADPROT, SUNDEADPROT, SUNDEADPROT, SSTEALTH, SSTEALTH,
  97. SMAGICMAP, SMAGICMAP, SHOLDMONST, SHOLDMONST, SHOLDMONST,
  98. SGEMPERFECT, SGEMPERFECT, SSPELLEXT, SSPELLEXT, SIDENTIFY,
  99. SIDENTIFY, SIDENTIFY, SREMCURSE, SREMCURSE, SREMCURSE,
  100. SREMCURSE, SANNIHILATE, SPULVERIZE, SPULVERIZE, SPULVERIZE,
  101. SLIFEPROT};
  102. /* =============================================================================
  103. * Exported functions
  104. */
  105. /* =============================================================================
  106. * FUNCTION: newscroll
  107. */
  108. int newscroll(void) { return scprob[rund(SCROLL_PROB_SIZE)]; }
  109. /* =============================================================================
  110. * FUNCTION: read_scroll
  111. */
  112. void read_scroll(int typ) {
  113. int i, j;
  114. if (typ < 0 || typ >= MAXSCROLL)
  115. return; /* be sure we are within bounds */
  116. if (scrollknown[typ] == 0)
  117. scrollknown[typ] = 1;
  118. Printf("\nYou read a scroll of %s.", &(scrollname[typ][1]));
  119. switch (typ) {
  120. case SENCHANTARM:
  121. enchantarmor(ENCH_SCROLL);
  122. return;
  123. case SENCHANTWEAP:
  124. enchweapon(ENCH_SCROLL);
  125. return;
  126. case SENLIGHTEN:
  127. yh = min(playery + 7, MAXY);
  128. xh = min(playerx + 25, MAXX);
  129. yl = max(playery - 7, 0);
  130. xl = max(playerx - 25, 0);
  131. for (i = yl; i < yh; i++) {
  132. for (j = xl; j < xh; j++) {
  133. know[j][i] = item[j][i];
  134. if (mitem[j][i].mon != MONST_NONE)
  135. stealth[j][i] |= STEALTH_SEEN;
  136. }
  137. }
  138. nap(2000);
  139. draws(xl, xh, yl, yh);
  140. return;
  141. case SBLANK:
  142. return;
  143. case SCREATEMONST:
  144. createmonster(makemonst(level + 1));
  145. return;
  146. case SCREATEITEM:
  147. something(playerx, playery, level);
  148. return;
  149. case SAGGMONST:
  150. c[AGGRAVATE] += 800;
  151. return;
  152. case STIMEWARP:
  153. /*
  154. * This code is slightly wrong in that, if gtime is small and
  155. * we can't go back by the required number of mobuls, it's
  156. * still reported that we did. I don't think this is
  157. * critical -- dmr
  158. */
  159. i = (rnd(1000) - 850) / 100;
  160. if (i == 0)
  161. i = 1;
  162. gtime += 100 * i;
  163. if (gtime < 0)
  164. gtime = 0;
  165. Printf("\nYou go %sward in time by %d mobul%s", (i < 0) ? "back" : "for",
  166. abs(i), plural(i));
  167. adjusttime((long)(i * 100)); /* adjust time for time warping */
  168. return;
  169. case STELEPORT:
  170. oteleport(0);
  171. return;
  172. case SAWARENESS:
  173. c[AWARENESS] += 1800;
  174. return;
  175. case SHASTEMONST:
  176. c[HASTEMONST] += rnd(55) + 12;
  177. Printf(" You feel nervous.");
  178. return;
  179. case SMONSTHEAL:
  180. for (i = 0; i < MAXY; i++) {
  181. for (j = 0; j < MAXX; j++)
  182. if (mitem[j][i].mon)
  183. hitp[j][i] = monster[(int)mitem[j][i].mon].hitpoints;
  184. }
  185. Printf(" You feel uneasy.");
  186. return;
  187. case SSPIRITPROT:
  188. c[SPIRITPRO] += 300 + rnd(200);
  189. UpdateEffects();
  190. return;
  191. case SUNDEADPROT:
  192. c[UNDEADPRO] += 300 + rnd(200);
  193. UpdateEffects();
  194. return;
  195. case SSTEALTH:
  196. c[STEALTH] += 250 + rnd(250);
  197. UpdateEffects();
  198. return;
  199. case SMAGICMAP:
  200. for (i = 0; i < MAXY; i++) {
  201. for (j = 0; j < MAXX; j++) {
  202. know[j][i] = item[j][i];
  203. if (mitem[j][i].mon != MONST_NONE)
  204. stealth[j][i] |= STEALTH_SEEN;
  205. }
  206. }
  207. nap(2000);
  208. draws(0, MAXX, 0, MAXY);
  209. return;
  210. case SHOLDMONST:
  211. c[HOLDMONST] += 30;
  212. UpdateEffects();
  213. return;
  214. case SGEMPERFECT:
  215. for (i = 0; i < IVENSIZE; i++) {
  216. switch (iven[i]) {
  217. case ODIAMOND:
  218. case ORUBY:
  219. case OEMERALD:
  220. case OSAPPHIRE:
  221. j = ivenarg[i];
  222. j *= 2;
  223. if ((j <= 0) && ivenarg[i])
  224. j = 2550;
  225. ivenarg[i] = (short)j;
  226. break;
  227. default:
  228. break;
  229. }
  230. }
  231. break;
  232. case SSPELLEXT:
  233. for (i = 0; i < EXTENSION_COUNT; i++)
  234. c[exten[i]] <<= 1;
  235. break;
  236. case SIDENTIFY:
  237. for (i = 0; i < IVENSIZE; i++) {
  238. if (iven[i] == OPOTION)
  239. potionknown[ivenarg[i]] = 1;
  240. if (iven[i] == OSCROLL)
  241. scrollknown[ivenarg[i]] = 1;
  242. }
  243. break;
  244. case SREMCURSE:
  245. removecurse();
  246. break;
  247. case SANNIHILATE:
  248. annihilate();
  249. break;
  250. case SPULVERIZE:
  251. godirect(SPELL_LIT, 150, "The ray hits the %s.", 10, EFFECT_LIT);
  252. break;
  253. case SLIFEPROT:
  254. c[LIFEPROT]++;
  255. break;
  256. }
  257. }
  258. /* =============================================================================
  259. * FUNCTION: readbook
  260. */
  261. void readbook(int arg) {
  262. int i, tmp;
  263. if (arg <= 3) {
  264. tmp = max(splev[arg], 1);
  265. i = rund(tmp + 1);
  266. } else {
  267. if (arg >= NLEVELS)
  268. arg = NLEVELS - 1;
  269. /* Stop finding lower level spells deeper in the dungeon */
  270. tmp = max(splev[arg] - 9, 1);
  271. i = rnd(tmp) + 9;
  272. }
  273. /* Learn this spell more */
  274. spelknow[i]++;
  275. Printf("\nSpell \"%s\": %s\n%s.", spelcode[i], spelname[i], speldescript[i]);
  276. /*
  277. * Boost int 40% of the time
  278. */
  279. if (rnd(10) == 4) {
  280. Print("\nYou feel clever!");
  281. c[INTELLIGENCE]++;
  282. UpdateStatus();
  283. }
  284. }