spell.c 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843
  1. /* =============================================================================
  2. * PROGRAM: ularn
  3. * FILENAME: spell.c
  4. *
  5. * DESCRIPTION:
  6. * This module contains the functions used to process spells and spell like
  7. * effects.
  8. *
  9. * =============================================================================
  10. * EXPORTED VARIABLES
  11. *
  12. * splev : The maximum spell num to be learnt from a book found on each
  13. * dungeon level
  14. * spelcode : The three letter codes for the spells
  15. * spelname : The text name of each spell
  16. * speldescript : The text description of each spell.
  17. *
  18. * =============================================================================
  19. * EXPORTED FUNCTIONS
  20. *
  21. * godirect : Function to process ranged spell effects (including scrolls)
  22. * annihilate : Function to process the annihilate scroll
  23. * get_spell_code : Function to get the three letter spell code from the player
  24. * cast : Function to cast a spell
  25. *
  26. * =============================================================================
  27. */
  28. #include "spell.h"
  29. #include "dungeon.h"
  30. #include "header.h"
  31. #include "itm.h"
  32. #include "monster.h"
  33. #include "player.h"
  34. #include "show.h"
  35. #include "sphere.h"
  36. #include "ularn_ask.h"
  37. #include "ularn_game.h"
  38. #include "ularn_win.h"
  39. /* =============================================================================
  40. * Exported variables
  41. */
  42. char splev[NLEVELS] = {1, 4, 7, 11, 15, 20, 24, 28, 30, 32, 33,
  43. 34, 35, 36, 37, 38, 38, 38, 38, 38, 38};
  44. char *spelcode[SPELL_COUNT] = {
  45. "pro", "mle", "dex", "sle", "chm", "ssp", /* 0 - 5 */
  46. "web", "str", "enl", "hel", "cbl", "cre", "pha", "inv", /*6-13 */
  47. "bal", "cld", "ply", "can", "has", "ckl", "vpr", /* 14-20 */
  48. "dry", "lit", "drl", "glo", "flo", "fgr", /* 21 - 26 */
  49. "sca", "hld", "stp", "tel", "mfi", "mkw", /* 27 - 34 */
  50. "sph", "gen", "sum", "wtw", "alt", "per" /* 35 - 38 */
  51. };
  52. char *spelname[SPELL_COUNT] = {
  53. "protection", /* 0 */
  54. "magic missile",
  55. "dexterity",
  56. "sleep",
  57. "charm monster",
  58. "sonic spear", /* 5 */
  59. "web",
  60. "strength",
  61. "enlightenment",
  62. "healing",
  63. "cure blindness", /* 10 */
  64. "create monster",
  65. "phantasmal forces",
  66. "invisibility",
  67. "fireball",
  68. "cold", /* 15 */
  69. "polymorph",
  70. "cancellation",
  71. "haste self",
  72. "cloud kill",
  73. "vaporize rock", /* 20 */
  74. "dehydration",
  75. "lightning",
  76. "drain life",
  77. "invulnerability",
  78. "flood", /* 25 */
  79. "finger of death",
  80. "scare monster",
  81. "hold monster",
  82. "time stop",
  83. "teleport away", /* 30 */
  84. "magic fire",
  85. "make a wall",
  86. "sphere of annihilation",
  87. "genocide", /* 34 */
  88. "summon demon",
  89. "walk through walls",
  90. "alter reality",
  91. "permanence" /* 38 */
  92. };
  93. char *speldescript[SPELL_COUNT] = {
  94. /* 1 */
  95. "Generates a +2 protection field",
  96. "Creates and hurls a magic missile equivalent to a +1 magic arrow",
  97. "Adds +2 to the caster's dexterity", "Causes some monsters to go to sleep",
  98. "Some monsters may be awed at your magnificence",
  99. "Causes the caster's hands to emit a screeching sound",
  100. /* 7 */
  101. "Causes strands of sticky thread to entangle an enemy",
  102. "Adds +2 to the caster's strength for a time",
  103. "The caster becomes more aware of things around them",
  104. "Restores some of the caster's health",
  105. "Restores sight to one so unfortunate as to be blinded",
  106. "Creates a monster near to the caster",
  107. "Creates illusions which, if believed, cause monsters to die",
  108. "The caster becomes invisible",
  109. /* 15 */
  110. "Creates a ball of fire that burns whatever it hits",
  111. "Sends forth a cone of cold which freezes whatever it touches",
  112. "You can find out what this does for yourself",
  113. "Stops a monster from using its special abilities",
  114. "Speeds up the caster's movements",
  115. "Creates a fog of poisonous gas which kills all that is within it",
  116. "Changes rock to air",
  117. /* 22 */
  118. "Dries up water in the immediate vicinity",
  119. "Causes the caster's finger to emit lightning bolts",
  120. "Subtracts hit points from both you and a monster",
  121. "This globe helps to protect the player from physical attack",
  122. "Creates a deluge of water, flooding the immediate chamber",
  123. "A holy spell calling on your god to back you up",
  124. /* 28 */
  125. "Terrifies the monster so that it may not hit the caster",
  126. "Freezes monsters in their tracks",
  127. "All movement in the caverns ceases for a limited duration",
  128. "Teleports a monster", "Creates a curtain of fire around the caster",
  129. /* 33 */
  130. "Makes a wall in the specified place",
  131. "Anything caught in this sphere is instantly killed.",
  132. "Eliminates a species of monster from the game",
  133. "Summons a demon who may help you out",
  134. "Allows the player to walk through walls for a short period of time",
  135. "God only knows what this will do",
  136. "Makes a character spell permanent, e.g. protection, strength, etc."};
  137. /* =============================================================================
  138. * Local variables
  139. */
  140. /*
  141. * spelweird[ monster ] [ spell ] = [ reaction ]
  142. *
  143. * spell = index into spelldescript[] and spellname[]
  144. * reaction = index into spelmes[]
  145. */
  146. static char spelweird[MONST_COUNT][SPELL_COUNT] = {
  147. /*p m d s c s w s e h c c p i b c p c h c v d l d g f f s h s t
  148. m s g s w a p */
  149. /* None (placeholder) */
  150. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  151. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  152. /* lemming */
  153. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  154. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  155. /* gnome */
  156. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0,
  157. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  158. /* hobgoblin */
  159. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  160. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  161. /* jackal */
  162. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  163. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  164. /* kobold */
  165. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0,
  166. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  167. /*p m d s c s w s e h c c p i b c p c h c v d l d g f f s h s t
  168. m s g s w a p */
  169. /* orc */
  170. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  171. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  172. /* snake */
  173. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  174. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  175. /* giant centipede */
  176. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  177. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  178. /* jaculi */
  179. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  180. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  181. /* troglodyte */
  182. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  183. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  184. /*p m d s c s w s e h c c p i b c p c h c v d l d g f f s h s t
  185. m s g s w a p */
  186. /* giant ant */
  187. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  188. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  189. /* floating eye */
  190. {0, 0, 0, 8, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  191. 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  192. /* leprechaun */
  193. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  194. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  195. /* nymph */
  196. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  197. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  198. /* quasit */
  199. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  200. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  201. /* rust monster */
  202. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  203. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  204. /* zombie */
  205. {0, 0, 0, 8, 0, 4, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0,
  206. 4, 0, 4, 0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  207. /* assassin bug */
  208. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  209. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  210. /* bugbear */
  211. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0,
  212. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  213. /* hell hound */
  214. {0, 6, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  215. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  216. /*p m d s c s w s e h c c p i b c p c h c v d l d g f f s h s t
  217. m s g s w a p */
  218. /* ice lizard */
  219. {0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0,
  220. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  221. /* centaur */
  222. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  223. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  224. /* troll */
  225. {0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  226. 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  227. /* yeti */
  228. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0,
  229. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  230. /* white dragon */
  231. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 15, 0, 0, 0,
  232. 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  233. /* elf */
  234. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 5, 0, 0, 0, 0, 0,
  235. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  236. /* gelatinous cube */
  237. {0, 13, 0, 8, 0, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  238. 4, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  239. /* metamorph */
  240. {0, 13, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  241. 4, 0, 4, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  242. /* vortex */
  243. {0, 13, 0, 0, 0, 10, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  244. 4, 0, 4, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  245. /* ziller */
  246. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  247. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  248. /*p m d s c s w s e h c c p i f c p c h c v d l d g f f s h s t
  249. m s g s w a p */
  250. /* violet fungi */
  251. {0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  252. 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  253. /* wraith */
  254. {0, 13, 0, 8, 0, 4, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0,
  255. 4, 0, 4, 0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  256. /* forvalaka */
  257. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0,
  258. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  259. /* lama nobe */
  260. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  261. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  262. /* osequip */
  263. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  264. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  265. /* rothe */
  266. {0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0,
  267. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  268. /* xorn */
  269. {0, 7, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0,
  270. 0, 0, 4, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  271. /* vampire */
  272. {0, 0, 0, 0, 0, 4, 2, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0,
  273. 4, 0, 0, 0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  274. /* invisible staker*/
  275. {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  276. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  277. /* poltergeist */
  278. {0, 13, 0, 8, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
  279. 4, 0, 4, 0, 4, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  280. /*p m d s c s w s e h c c p i b c p c h c v d l d g f f s h s t
  281. m s g s w a p */
  282. /* disenchantress */
  283. {0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  284. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  285. /* shambling mound */
  286. {0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  287. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  288. /* yellow mold */
  289. {0, 0, 0, 8, 0, 10, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  290. 4, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  291. /* umber hulk */
  292. {0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0,
  293. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  294. /* gnome king */
  295. {0, 7, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 9, 0, 0,
  296. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  297. /* mimic */
  298. {0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  299. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  300. /* water lord */
  301. {0, 13, 0, 8, 3, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0,
  302. 4, 0, 0, 0, 0, 0, 16, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  303. /* bronze dragon */
  304. {0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  305. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  306. /* green dragon */
  307. {0, 7, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  308. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  309. /* purple worm */
  310. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  311. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  312. /*p m d s c s w s e h c c p i b c p c h c v d l d g f f s h s t
  313. m s g s w a p */
  314. /* xvart */
  315. {0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  316. 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  317. /* spirit naga */
  318. {0, 13, 0, 8, 3, 4, 1, 0, 0, 0, 0, 0, 14, 5, 0, 4, 9, 0, 0,
  319. 4, 0, 4, 0, 4, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  320. /* silver dragon */
  321. {0, 6, 0, 9, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0,
  322. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  323. /* platinum dragon */
  324. {0, 7, 0, 9, 0, 0, 11, 0, 0, 0, 0, 0, 14, 0, 0, 0, 9, 0, 0,
  325. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  326. /* green urchin */
  327. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  328. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  329. /* red dragon */
  330. {0, 6, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  331. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  332. /*p m d s c s w s e h c c p i b c p c h c v d l d g f f s h s t
  333. m s g s w a p */
  334. /* demon lord */
  335. {0, 13, 0, 8, 3, 10, 1, 0, 0, 0, 0, 0, 14, 5, 0, 0, 9, 0, 0,
  336. 4, 0, 4, 0, 9, 0, 4, 4, 3, 0, 0, 9, 4, 9, 0, 0, 0, 0, 0},
  337. /* demon lord */
  338. {0, 13, 0, 8, 3, 10, 1, 0, 0, 0, 0, 0, 14, 5, 0, 0, 9, 0, 0,
  339. 4, 0, 4, 0, 9, 0, 4, 4, 3, 0, 0, 9, 4, 9, 0, 0, 0, 0, 0},
  340. /* demon lord */
  341. {0, 13, 0, 8, 3, 10, 1, 0, 0, 0, 0, 0, 14, 5, 0, 0, 9, 0, 0,
  342. 4, 0, 4, 0, 9, 0, 4, 4, 3, 0, 0, 9, 4, 9, 0, 0, 0, 0, 0},
  343. /* demon lord */
  344. {0, 13, 0, 8, 3, 10, 1, 0, 0, 0, 0, 0, 14, 5, 0, 0, 9, 0, 0,
  345. 4, 0, 4, 0, 9, 0, 4, 4, 3, 0, 0, 9, 4, 9, 0, 0, 0, 0, 0},
  346. /* demon lord */
  347. {0, 13, 0, 8, 3, 10, 1, 0, 0, 0, 0, 0, 14, 5, 0, 0, 9, 0, 0,
  348. 4, 0, 4, 0, 9, 0, 4, 4, 3, 0, 0, 9, 4, 9, 0, 0, 0, 0, 0},
  349. /* demon lord */
  350. {0, 13, 0, 8, 3, 10, 1, 0, 0, 0, 0, 0, 14, 5, 0, 0, 4, 0, 0,
  351. 4, 0, 4, 0, 0, 0, 4, 4, 3, 0, 0, 9, 4, 9, 0, 0, 0, 0, 0},
  352. /* demon lord */
  353. {0, 13, 0, 8, 3, 10, 1, 0, 0, 0, 0, 0, 14, 5, 0, 0, 4, 0, 0,
  354. 4, 0, 4, 0, 0, 0, 4, 4, 3, 0, 0, 9, 4, 9, 0, 0, 0, 0, 0},
  355. /*p m d s c s w s e h c c p i b c p c h c v d l d g f f s h s t
  356. m s g s w a p */
  357. /* demon prince */
  358. {0, 13, 0, 8, 3, 10, 1, 0, 0, 0, 0, 0, 14, 5, 0, 0, 4, 0, 0,
  359. 4, 0, 4, 0, 4, 0, 4, 4, 3, 0, 0, 9, 4, 9, 0, 0, 0, 0, 0},
  360. /*p m d s c s w s e h c c p i b c p c h c v d l d g f f s h s t
  361. m s g s w a p */
  362. /* God of Hellfire */
  363. {0, 13, 0, 8, 3, 10, 1, 0, 0, 0, 0, 0, 14, 5, 18, 0, 9, 0, 0,
  364. 4, 0, 4, 18, 4, 0, 0, 4, 4, 4, 0, 9, 4, 9, 0, 17, 0, 0, 0}};
  365. static char *spelmes[] = {
  366. /* 0 */ "", /* spell has no effect on the monster */
  367. /* 1 */ "the web had no effect on the %s",
  368. /* 2 */ "the %s changed shape to avoid the web",
  369. /* 3 */ "the %s isn't afraid of you",
  370. /* 4 */ "the %s isn't affected",
  371. /* 5 */ "the %s can see you with his infravision",
  372. /* 6 */ "the %s vaporizes your missile",
  373. /* 7 */ "your missile bounces off the %s",
  374. /* 8 */ "the %s doesn't sleep",
  375. /* 9 */ "the %s resists",
  376. /* 10 */ "the %s can't hear the noise",
  377. /* 11 */ "the %s's tail cuts it free of the web",
  378. /* 12 */ "the %s burns through the web",
  379. /* 13 */ "your missiles pass right through the %s",
  380. /* 14 */ "the %s sees through your illusions",
  381. /* 15 */ "the %s loves the cold!",
  382. /* 16 */ "the %s loves the water!",
  383. /* 17 */ "the demon is terrified of the %s!",
  384. /* 18 */ "the %s loves fire and lightning!"};
  385. static char eys[] = "\nEnter your spell [D for list, ESC to abort]: ";
  386. /* used for alter reality spell */
  387. struct isave {
  388. char type; /* 0=item, 1=monster */
  389. short id; /* item number or monster number */
  390. short arg; /* the type of item or hitpoints of monster */
  391. };
  392. /* =============================================================================
  393. * Local functions
  394. */
  395. /* =============================================================================
  396. * FUNCTION: isconfuse
  397. *
  398. * DESCRIPTION:
  399. * Function to check to see if player is confused.
  400. * Prints a message if the player is confused indicating that magic can't be
  401. * used.
  402. *
  403. * PARAMETERS:
  404. *
  405. * None.
  406. *
  407. * RETURN VALUE:
  408. *
  409. * 0 => not confused
  410. * != 0 => confused (returns confused time remaining)
  411. */
  412. static int isconfuse(void) {
  413. if (c[CONFUSE]) {
  414. Print(" You can't aim your magic!");
  415. UlarnBeep();
  416. }
  417. return c[CONFUSE];
  418. }
  419. /* =============================================================================
  420. * FUNCTION: nospell
  421. *
  422. * DESCRIPTION:
  423. * Function to check if a spell affects a monster.
  424. * Prints an appropriate message if the monster is unaffected by the spell.
  425. *
  426. * PARAMETERS:
  427. *
  428. * x : The spell being cast
  429. *
  430. * monst : The mosnter being hit by the spell
  431. *
  432. * RETURN VALUE:
  433. *
  434. * 0 => monster affected by the spell
  435. * 1 => monster is immune to the spell
  436. */
  437. static int nospell(SpellType x, MonsterIdType monst) {
  438. int tmp;
  439. /* bad spell or monst */
  440. if ((x >= SPELL_COUNT) || (monst >= MONST_COUNT) || ((signed)monst < 0) ||
  441. ((signed)x < 0))
  442. return 0;
  443. if ((tmp = spelweird[monst][x]) == 0)
  444. return 0;
  445. Print("\n");
  446. Printf(spelmes[tmp], monster[monst].name);
  447. return 1;
  448. }
  449. /* =============================================================================
  450. * FUNCTION: do_magic_fx
  451. *
  452. * DESCRIPTION:
  453. * Function to display the magic effect on the map.
  454. *
  455. * PARAMETERS:
  456. *
  457. * x : The x location for the effect
  458. *
  459. * y : The y location for the effect
  460. *
  461. * fx : The effect type to show.
  462. *
  463. * RETURN VALUE:
  464. *
  465. * None.
  466. */
  467. static void do_magic_fx(int x, int y, MagicEffectsType fx) {
  468. int frame;
  469. int frame_count;
  470. frame_count = magic_effect_frames(fx);
  471. for (frame = 0; frame < frame_count; frame++) {
  472. magic_effect(x, y, fx, frame);
  473. nap(75);
  474. }
  475. }
  476. /* =============================================================================
  477. * FUNCTION: vaporize_rock
  478. *
  479. * DESCRIPTION:
  480. * Function to handle the processing for the vaporise rock spell.
  481. *
  482. * PARAMETERS:
  483. *
  484. * None.
  485. *
  486. * RETURN VALUE:
  487. *
  488. * None.
  489. */
  490. static void vaporize_rock(void) {
  491. int xl, xh;
  492. int yl, yh;
  493. char it;
  494. MonsterIdType pm;
  495. int i, j;
  496. int frame;
  497. int frame_count;
  498. int show_effect;
  499. /* calculate the area for vaporize rock */
  500. xl = max(playerx - 1, 1);
  501. yl = max(playery - 1, 1);
  502. xh = min(playerx + 1, MAXX - 2);
  503. yh = min(playery + 1, MAXY - 2);
  504. frame_count = magic_effect_frames(MAGIC_VAPORIZE);
  505. /* Show fx */
  506. for (frame = 0; frame < frame_count; frame++) {
  507. for (i = xl; i <= xh; i++) {
  508. for (j = yl; j <= yh; j++) {
  509. /* only show effect on objects/monsters that are rock */
  510. it = item[i][j];
  511. pm = mitem[i][j].mon;
  512. show_effect = 0;
  513. switch (it) {
  514. case OWALL:
  515. /* can't vpr below V2 */
  516. if (level < VBOTTOM - 2)
  517. show_effect = 1;
  518. break;
  519. case OSTATUE:
  520. case OTHRONE:
  521. case OALTAR:
  522. show_effect = 1;
  523. break;
  524. default:
  525. break;
  526. }
  527. switch (pm) {
  528. /* Rock based monsters take damage from vpr */
  529. case XORN:
  530. case TROLL:
  531. show_effect = 1;
  532. break;
  533. default:
  534. break;
  535. }
  536. if (show_effect)
  537. magic_effect(i, j, MAGIC_VAPORIZE, frame);
  538. }
  539. }
  540. nap(75);
  541. }
  542. /* process spell effect */
  543. for (i = xl; i <= xh; i++) {
  544. for (j = yl; j <= yh; j++) {
  545. pm = mitem[i][j].mon;
  546. it = item[i][j];
  547. switch (it) {
  548. case OWALL:
  549. /* can't vpr below V2 */
  550. if (level < VBOTTOM - 2)
  551. it = ONOTHING;
  552. break;
  553. case OSTATUE:
  554. if ((c[HARDGAME] > 3) && (rnd(60) < 30)) {
  555. /* Redisplay statue */
  556. show1cell(i, j);
  557. break;
  558. }
  559. it = OBOOK;
  560. iarg[i][j] = (char)level;
  561. break;
  562. case OTHRONE:
  563. pm = GNOMEKING;
  564. it = OTHRONE2;
  565. hitp[i][j] = monster[GNOMEKING].hitpoints;
  566. break;
  567. case OALTAR:
  568. pm = DEMONPRINCE;
  569. hitp[i][j] = monster[DEMONPRINCE].hitpoints;
  570. createmonster(DEMONPRINCE);
  571. createmonster(DEMONPRINCE);
  572. createmonster(DEMONPRINCE);
  573. createmonster(DEMONPRINCE);
  574. break;
  575. default:
  576. break;
  577. }
  578. switch (pm) {
  579. /* Rock based monsters take damage from vpr */
  580. case XORN:
  581. ifblind(i, j);
  582. hitm(i, j, 200, 1);
  583. break;
  584. case TROLL:
  585. ifblind(i, j);
  586. hitm(i, j, 200, 1);
  587. break;
  588. default:
  589. break;
  590. }
  591. item[i][j] = it;
  592. }
  593. }
  594. /* Work out the new wall tiles for adjacent walls to those vaporised */
  595. AnalyseWalls(playerx - 2, playery - 2, playerx + 2, playery + 2);
  596. for (i = playerx - 2; i <= playerx + 2; i++) {
  597. for (j = playery - 2; j <= playery + 2; j++) {
  598. if (checkxy(i, j))
  599. if ((know[i][j] != OUNKNOWN) && (item[i][j] == OWALL))
  600. show1cell(i, j);
  601. }
  602. }
  603. }
  604. /* =============================================================================
  605. * FUNCTION: direct
  606. *
  607. * DESCRIPTION:
  608. * Routine to ask for a direction to a spell and then hit the monster.
  609. *
  610. * PARAMETERS:
  611. *
  612. * spnum : The spell number
  613. *
  614. * dam : The amount of damage to be done by the spell
  615. *
  616. * str : The string to print if the spell does damage.
  617. * The first format specifier should be '%s' for the monster name
  618. * The second format specifier should be '%d' for the arg.
  619. * Not all specifiers are required.
  620. *
  621. * arg : Any special arguments
  622. *
  623. * fx : The magic effect to display
  624. *
  625. * RETURN VALUE:
  626. *
  627. * None.
  628. */
  629. static void direct(SpellType spnum, int dam, char *str, int arg,
  630. MagicEffectsType fx) {
  631. int x, y;
  632. MonsterIdType m;
  633. /* check for bad arguments */
  634. if (((signed)spnum < 0) || (spnum >= SPELL_COUNT) || (str == 0))
  635. return;
  636. /* check player confusion */
  637. if (isconfuse())
  638. return;
  639. /* Ask for direction */
  640. dirsub(&x, &y);
  641. if (!checkxy(x, y))
  642. /* The direction selected is off the map */
  643. return;
  644. m = mitem[x][y].mon;
  645. if (item[x][y] == OMIRROR) {
  646. if (spnum == SPELL_SLE) {
  647. /* sleep */
  648. Print("You fall asleep! ");
  649. UlarnBeep();
  650. arg += 2;
  651. while (arg-- > 0) {
  652. parse2();
  653. nap(1000);
  654. }
  655. return;
  656. } else if (spnum == SPELL_WEB) {
  657. /* web */
  658. Print("You get stuck in your own web! ");
  659. UlarnBeep();
  660. arg += 2;
  661. while (arg-- > 0) {
  662. parse2();
  663. nap(1000);
  664. }
  665. return;
  666. } else {
  667. Printf(str, "spell caster (that's you)", (long)arg);
  668. UlarnBeep();
  669. losehp(DIED_OWN_MAGIC, dam);
  670. return;
  671. }
  672. }
  673. if (m == MONST_NONE) {
  674. Print(" There wasn't anything there!");
  675. return;
  676. }
  677. ifblind(x, y);
  678. /* Do magic fx */
  679. do_magic_fx(x, y, fx);
  680. show1cell(x, y);
  681. if (nospell(spnum, m)) {
  682. last_monst_hx = (char)x;
  683. last_monst_hy = (char)y;
  684. return;
  685. }
  686. Printf(str, lastmonst, (long)arg);
  687. hitm(x, y, dam, 1);
  688. }
  689. /* =============================================================================
  690. * FUNCTION: tdirect
  691. *
  692. * DESCRIPTION:
  693. * Routine to ask for a direction to a spell and then teleport away monster.
  694. *
  695. * PARAMETERS:
  696. *
  697. * spnum : The spell that wants to teleport the monster
  698. *
  699. * RETURN VALUE:
  700. *
  701. * None.
  702. */
  703. static void tdirect(SpellType spnum) {
  704. int x, y;
  705. MonsterIdType m;
  706. /* check for bad args */
  707. if (((signed)spnum < 0) || (spnum >= SPELL_COUNT))
  708. return;
  709. /* check for player confusion */
  710. if (isconfuse())
  711. return;
  712. /* Ask for direction */
  713. dirsub(&x, &y);
  714. if (!checkxy(x, y))
  715. /* The direction selected is off the map */
  716. return;
  717. m = mitem[x][y].mon;
  718. if (m == MONST_NONE) {
  719. Print(" There wasn't anything there!");
  720. return;
  721. }
  722. ifblind(x, y);
  723. if (nospell(spnum, m)) {
  724. last_monst_hx = (char)x;
  725. last_monst_hy = (char)y;
  726. return;
  727. }
  728. do_magic_fx(x, y, MAGIC_TELEPORT);
  729. teleportmonst(x, y, m);
  730. }
  731. /* =============================================================================
  732. * FUNCTION: makewall
  733. *
  734. * DESCRIPTION:
  735. * Function to process the makewall spell.
  736. *
  737. * PARAMETERS:
  738. *
  739. * spnum ; The spell creating the wall.
  740. *
  741. * RETURN VALUE:
  742. *
  743. * None.
  744. */
  745. static void makewall(SpellType spnum) {
  746. int x, y;
  747. int tx, ty;
  748. /* check for bad args */
  749. if (((signed)spnum < 0) || (spnum >= SPELL_COUNT))
  750. return;
  751. /* check for player confusion */
  752. if (isconfuse())
  753. return;
  754. /* Ask for direction */
  755. dirsub(&x, &y);
  756. if (checkxy(x, y)) {
  757. /* within bounds */
  758. if (item[x][y] != OWALL) {
  759. /* can't make anything on walls */
  760. if (item[x][y] == ONOTHING) {
  761. /* is it free of items? */
  762. if (mitem[x][y].mon == MONST_NONE) {
  763. /* is it free of monsters? */
  764. if ((level != 1) || (x != 33) || (y != MAXY - 1)) {
  765. do_magic_fx(x, y, MAGIC_WALL);
  766. item[x][y] = OWALL;
  767. show1cell(x, y);
  768. /* Work out the new wall tiles for adjacent walls */
  769. AnalyseWalls(x - 1, y - 1, x + 1, y + 1);
  770. for (tx = x - 1; tx <= x + 1; tx++) {
  771. for (ty = y - 1; ty <= y + 1; ty++) {
  772. if (checkxy(tx, ty))
  773. if ((know[tx][ty] != OUNKNOWN) && (item[tx][ty] == OWALL))
  774. show1cell(tx, ty);
  775. }
  776. }
  777. } else
  778. Print("\nyou can't make a wall there!");
  779. } else
  780. Print("\nthere's a monster there!");
  781. } else
  782. Print("\nthere's something there already!");
  783. } else
  784. Print("\nthere's a wall there already!");
  785. }
  786. }
  787. /* =============================================================================
  788. * FUNCTION: omnidirect
  789. *
  790. * DESCRIPTION:
  791. * Routine to cast a spell and then hit the monster in all directions.
  792. *
  793. * PARAMETERS:
  794. *
  795. * spnum : The spell being cast
  796. *
  797. * dam : The amount of damage
  798. *
  799. * str : The format string to dislay for monsters hit by the spell.
  800. * The string should contains a '%s' for the monster name.
  801. *
  802. * fx : The magic efect to display.
  803. *
  804. * RETURN VALUE:
  805. *
  806. * None.
  807. */
  808. static void omnidirect(SpellType spnum, int dam, char *str,
  809. MagicEffectsType fx) {
  810. int xl, yl;
  811. int xh, yh;
  812. int x, y;
  813. MonsterIdType m;
  814. int frame;
  815. int frame_count;
  816. /* check for bad args */
  817. if ((signed)spnum < 0 || spnum >= SPELL_COUNT || str == 0)
  818. return;
  819. /* get the area affected */
  820. xl = max(playerx - 1, 0);
  821. yl = max(playery - 1, 0);
  822. xh = min(playerx + 1, MAXX - 1);
  823. yh = min(playery + 1, MAXY - 1);
  824. /* Show magic effect */
  825. frame_count = magic_effect_frames(fx);
  826. for (frame = 0; frame < frame_count; frame++) {
  827. for (x = xl; x <= xh; x++) {
  828. for (y = yl; y <= yh; y++)
  829. if ((x != playerx) || (y != playery))
  830. magic_effect(x, y, fx, frame);
  831. }
  832. nap(75);
  833. }
  834. /* Redisplay cell */
  835. for (x = xl; x <= xh; x++) {
  836. for (y = yl; y <= yh; y++)
  837. if ((x != playerx) || (y != playery))
  838. show1cell(x, y);
  839. }
  840. for (x = xl; x <= xh; x++) {
  841. for (y = yl; y <= yh; y++) {
  842. m = mitem[x][y].mon;
  843. if (m != MONST_NONE) {
  844. if (nospell(spnum, m) == 0) {
  845. ifblind(x, y);
  846. Printc('\n');
  847. Printf(str, lastmonst);
  848. hitm(x, y, dam, 1);
  849. nap(800);
  850. } else {
  851. last_monst_hx = (char)x;
  852. last_monst_hy = (char)y;
  853. }
  854. }
  855. }
  856. }
  857. }
  858. /* =============================================================================
  859. * FUNCTION: dirpoly
  860. *
  861. * DESCRIPTION:
  862. * Routine to ask for a direction and polymorph a monst
  863. *
  864. * PARAMETERS:
  865. *
  866. * spnum : The spell causing the polymorph.
  867. *
  868. * RETURN VALUE:
  869. *
  870. * None.
  871. */
  872. static void dirpoly(SpellType spnum) {
  873. int x, y;
  874. MonsterIdType m;
  875. /* check for bad args */
  876. if ((signed)spnum < 0 || spnum >= SPELL_COUNT)
  877. return;
  878. /* check for player confusion */
  879. if (isconfuse())
  880. return;
  881. /* Ask for direction */
  882. dirsub(&x, &y);
  883. if (!checkxy(x, y))
  884. /* The direction selected is off the map */
  885. return;
  886. if (mitem[x][y].mon == MONST_NONE) {
  887. Print(" There wasn't anything there!");
  888. return;
  889. }
  890. ifblind(x, y);
  891. if (nospell(spnum, mitem[x][y].mon)) {
  892. last_monst_hx = (char)x;
  893. last_monst_hy = (char)y;
  894. return;
  895. }
  896. /* show some magic animation */
  897. do_magic_fx(x, y, MAGIC_SPARKLE);
  898. /* Transform into a non-genocided monster */
  899. do {
  900. m = rnd(MAXMONST + 7);
  901. mitem[x][y].mon = (char)m;
  902. } while ((monster[m].flags & FL_GENOCIDED) != 0);
  903. hitp[x][y] = monster[m].hitpoints;
  904. show1cell(x, y); /* show the new monster */
  905. }
  906. /* =============================================================================
  907. * FUNCTION: genmonst
  908. *
  909. * DESCRIPTION:
  910. * Function to ask for monster and genocide from game
  911. * This is done by setting a flag in the monster[] structure
  912. *
  913. * PARAMETERS:
  914. *
  915. * None.
  916. *
  917. * RETURN VALUE:
  918. *
  919. * None.
  920. */
  921. static void genmonst(void) {
  922. int i, j;
  923. int done;
  924. int textmode;
  925. int column;
  926. int row;
  927. textmode = 0;
  928. done = 0;
  929. while (!done) {
  930. Print("\nEnter the number of the monster to genocide [* for list]: ");
  931. i = get_num_input(-1);
  932. if (i == -1) {
  933. set_display(DISPLAY_TEXT);
  934. ClearText();
  935. textmode = 1;
  936. Print("Monster numbers");
  937. column = 0;
  938. row = 3;
  939. for (j = 1; j < DEMONLORD; j++) {
  940. MoveCursor(column * 28 + 1, row);
  941. if ((monster[i].flags & FL_GENOCIDED) == 0)
  942. Printf("%-2d) %s", j, monster[j].name);
  943. else
  944. Printf("%-2d) Genocided", j);
  945. column++;
  946. if (column > 2) {
  947. column = 0;
  948. row++;
  949. }
  950. }
  951. Print("\n");
  952. } else if ((i > 0) && (i < DEMONLORD)) {
  953. if (((monster[i].flags & FL_GENOCIDED) == 0) || wizard) {
  954. if (textmode) {
  955. set_display(DISPLAY_MAP);
  956. textmode = 0;
  957. }
  958. /* genocided from game */
  959. monster[i].flags |= FL_GENOCIDED;
  960. Printf("\n There will be no more %ss.", monster[i].name);
  961. /* now wipe out monsters on this level */
  962. newcavelevel(level);
  963. draws(0, MAXX, 0, MAXY);
  964. UpdateStatusAndEffects();
  965. done = 1;
  966. }
  967. } else {
  968. if (textmode) {
  969. set_display(DISPLAY_MAP);
  970. textmode = 0;
  971. }
  972. Print("\n You sense failure!");
  973. done = 1;
  974. }
  975. }
  976. /*
  977. * Make sure the map is displayed on exit
  978. */
  979. if (textmode)
  980. set_display(DISPLAY_MAP);
  981. }
  982. /* =============================================================================
  983. * FUNCTION: speldamage
  984. *
  985. * DESCRIPTION:
  986. * Function to perform spell actions cast by the player.
  987. * Please insure that there are 2 spaces before all messages here.
  988. *
  989. * PARAMETERS:
  990. *
  991. * Spell : The spell being cast.
  992. *
  993. * RETURN VALUE:
  994. *
  995. * None.
  996. */
  997. static void speldamage(SpellType Spell) {
  998. int i, j, clev;
  999. int xl, yl;
  1000. int xh, yh;
  1001. char *s;
  1002. /* no such spell */
  1003. if (Spell >= SPELL_COUNT)
  1004. return;
  1005. if (c[TIMESTOP]) {
  1006. /* not if time stopped */
  1007. Print("\n It didn't seem to work.");
  1008. return;
  1009. }
  1010. if ((rnd(23) == 7) || (rnd(18) > c[INTELLIGENCE])) {
  1011. Print("\n It didn't work!");
  1012. return;
  1013. }
  1014. clev = c[LEVEL];
  1015. if ((clev * 3 + 2) < (int)Spell) {
  1016. Print("\n Nothing happens. You seem inexperienced.");
  1017. return;
  1018. }
  1019. switch (Spell) {
  1020. /* ----- LEVEL 1 SPELLS ----- */
  1021. case SPELL_PRO:
  1022. if (c[PROTECTIONTIME] == 0) {
  1023. c[MOREDEFENSES] += SPELL_PRO_BOOST; /* protection field +2 */
  1024. }
  1025. c[PROTECTIONTIME] += 250;
  1026. do_magic_fx(playerx, playery, MAGIC_SPARKLE);
  1027. return;
  1028. case SPELL_MLE:
  1029. /* magic missile */
  1030. i = rnd(((clev + 1) << 1)) + clev + 3;
  1031. godirect(Spell, i,
  1032. (clev >= 2) ? " Your missiles hit the %s."
  1033. : " Your missile hit the %s.",
  1034. 100, EFFECT_MLE);
  1035. return;
  1036. case SPELL_DEX:
  1037. /* dexterity */
  1038. if (c[DEXCOUNT] == 0)
  1039. adjust_ability(DEXTERITY, SDEXTERITY_BOOST);
  1040. c[DEXCOUNT] += 400;
  1041. do_magic_fx(playerx, playery, MAGIC_SPARKLE);
  1042. return;
  1043. case SPELL_SLE:
  1044. /* sleep */
  1045. i = rnd(3) + 1;
  1046. s = " While the %s slept, you smashed it %d times.";
  1047. direct(Spell, fullhit(i), s, i, MAGIC_SLEEP);
  1048. return;
  1049. case SPELL_CHM:
  1050. /* charm monster */
  1051. c[CHARMCOUNT] += c[CHARISMA] << 1;
  1052. do_magic_fx(playerx, playery, MAGIC_SPARKLE);
  1053. return;
  1054. case SPELL_SSP:
  1055. /* sonic spear */
  1056. godirect(Spell, rnd(10) + 15 + clev, " The sound damages the %s.", 70,
  1057. EFFECT_SSP);
  1058. return;
  1059. /* ----- LEVEL 2 SPELLS ----- */
  1060. case SPELL_WEB:
  1061. /* web */
  1062. i = rnd(3) + 2;
  1063. s = " While the %s is entangled, you hit it %d times.";
  1064. direct(Spell, fullhit(i), s, i, MAGIC_WEB);
  1065. return;
  1066. case SPELL_STR:
  1067. /* strength */
  1068. if (c[STRCOUNT] == 0)
  1069. c[STREXTRA] += SSTRENGTH_BOOST;
  1070. c[STRCOUNT] += 150 + rnd(100);
  1071. do_magic_fx(playerx, playery, MAGIC_SPARKLE);
  1072. return;
  1073. case SPELL_ENL:
  1074. /* enlightenment */
  1075. yl = playery - 5;
  1076. yh = playery + 6;
  1077. xl = playerx - 15;
  1078. xh = playerx + 16;
  1079. vxy(xl, yl);
  1080. vxy(xh, yh); /* check bounds */
  1081. for (i = yl; i <= yh; i++) /* enlightenment */
  1082. for (j = xl; j <= xh; j++)
  1083. know[j][i] = item[j][i];
  1084. draws(xl, xh + 1, yl, yh + 1);
  1085. return;
  1086. case SPELL_HEL:
  1087. /* healing */
  1088. raisehp(20 + (clev << 1));
  1089. do_magic_fx(playerx, playery, MAGIC_SPARKLE);
  1090. return;
  1091. case SPELL_CBL:
  1092. /* cure blindness */
  1093. c[BLINDCOUNT] = 0;
  1094. do_magic_fx(playerx, playery, MAGIC_SPARKLE);
  1095. return;
  1096. case SPELL_CRE:
  1097. if (wizard) {
  1098. Printf("Number: ");
  1099. if ((i = get_num_input((long)-1)) != -1) {
  1100. createmonster(i);
  1101. return;
  1102. }
  1103. }
  1104. createmonster(makemonst(level + 1) + 8);
  1105. return;
  1106. case SPELL_PHA:
  1107. /* illusion */
  1108. if (rnd(11) + 7 <= c[WISDOM])
  1109. direct(Spell, rnd(20) + 20 + clev, " The %s believed!", 0,
  1110. MAGIC_PHANTASMAL);
  1111. else
  1112. Print(" It didn't believe the illusions!");
  1113. return;
  1114. case SPELL_INV:
  1115. /* if he has the amulet of invisibility then add more time */
  1116. j = 0;
  1117. for (i = 0; i < IVENSIZE; i++)
  1118. if (iven[i] == OAMULET)
  1119. j += 1 + ivenarg[i];
  1120. c[INVISIBILITY] += (j << 7) + 12;
  1121. do_magic_fx(playerx, playery, MAGIC_SPARKLE);
  1122. return;
  1123. /* ----- LEVEL 3 SPELLS ----- */
  1124. case SPELL_BAL:
  1125. /* fireball */
  1126. godirect(Spell, rnd(25 + clev) + 25 + clev, " The fireball hits the %s.",
  1127. 40, EFFECT_BAL);
  1128. return;
  1129. case SPELL_CLD:
  1130. /* cold */
  1131. godirect(Spell, rnd(25) + 20 + clev, " The cone of cold strikes the %s.",
  1132. 60, EFFECT_CLD);
  1133. return;
  1134. case SPELL_PLY:
  1135. /* polymorph */
  1136. dirpoly(Spell);
  1137. return;
  1138. case SPELL_CAN:
  1139. /* cancellation */
  1140. c[CANCELLATION] += 5 + clev;
  1141. return;
  1142. case SPELL_HAS:
  1143. /* haste self */
  1144. c[HASTESELF] += 7 + clev;
  1145. do_magic_fx(playerx, playery, MAGIC_SPARKLE);
  1146. return;
  1147. case SPELL_CKL:
  1148. /* cloud kill */
  1149. omnidirect(Spell, 30 + rnd(10), " The %s gasps for air!", MAGIC_CLOUD);
  1150. return;
  1151. case SPELL_VPR:
  1152. vaporize_rock();
  1153. return;
  1154. /* ----- LEVEL 4 SPELLS ----- */
  1155. case SPELL_DRY:
  1156. /* dehydration */
  1157. direct(Spell, 100 + clev, " The %s shrivels up.", 0, MAGIC_DEHYDRATE);
  1158. return;
  1159. case SPELL_LIT:
  1160. /* lightning */
  1161. godirect(Spell, rnd(25) + 20 + (clev << 1),
  1162. " A lightning bolt hits the %s.", 10, EFFECT_LIT);
  1163. return;
  1164. case SPELL_DRL:
  1165. /* drain life */
  1166. i = min(c[HP] - 1, c[HPMAX] / 2);
  1167. direct(Spell, i + i, "", 0, MAGIC_DRAIN);
  1168. c[HP] -= i;
  1169. return;
  1170. case SPELL_GLO:
  1171. /* globe of invulnerability */
  1172. if (c[GLOBE] == 0)
  1173. c[MOREDEFENSES] += SPELL_GLOBE_BOOST;
  1174. c[GLOBE] += 200;
  1175. adjust_ability(INTELLIGENCE, -1);
  1176. do_magic_fx(playerx, playery, MAGIC_SPARKLE);
  1177. return;
  1178. case SPELL_FLO:
  1179. /* flood */
  1180. omnidirect(Spell, 32 + clev, " The %s struggles for air in your flood!",
  1181. MAGIC_FLOOD);
  1182. return;
  1183. case SPELL_FGR:
  1184. /* finger of death */
  1185. if (rnd(151) == 63) {
  1186. UlarnBeep();
  1187. Print("\nYour heart stopped!\n");
  1188. nap(4000);
  1189. died(DIED_ERASED_BY_WAYWARD_FINGER, 0);
  1190. return;
  1191. }
  1192. if (c[WISDOM] > rnd(10) + 10)
  1193. direct(Spell, 2000, " The %s's heart stopped.", 0, MAGIC_FINGER);
  1194. else
  1195. Print(" It didn't work.");
  1196. return;
  1197. /* ----- LEVEL 5 SPELLS ----- */
  1198. case SPELL_SCA:
  1199. /* scare monster */
  1200. c[SCAREMONST] += rnd(10) + clev;
  1201. /* if have HANDofFEAR make last longer */
  1202. for (i = 0; i < IVENSIZE; i++) {
  1203. if (iven[i] == OHANDofFEAR) {
  1204. c[SCAREMONST] *= 3;
  1205. break;
  1206. }
  1207. }
  1208. do_magic_fx(playerx, playery, MAGIC_SPARKLE);
  1209. return;
  1210. case SPELL_HLD:
  1211. /* hold monster */
  1212. c[HOLDMONST] += rnd(10) + clev;
  1213. return;
  1214. case SPELL_STP:
  1215. /* time stop */
  1216. c[TIMESTOP] += rnd(20) + (clev << 1);
  1217. return;
  1218. case SPELL_TEL:
  1219. /* teleport */
  1220. tdirect(Spell);
  1221. return;
  1222. case SPELL_MFI:
  1223. /* magic fire */
  1224. omnidirect(Spell, 35 + rnd(10) + clev, " The %s cringes from the flame.",
  1225. MAGIC_FIRE);
  1226. return;
  1227. /* ----- LEVEL 6 SPELLS ----- */
  1228. case SPELL_MKW:
  1229. /* make wall */
  1230. makewall(Spell);
  1231. return;
  1232. case SPELL_SPH:
  1233. /* sphere of annihilation */
  1234. if ((rnd(23) == 5) && (wizard == 0)) {
  1235. if (!player_has_item(OSPHTALISMAN)) {
  1236. UlarnBeep();
  1237. Print("\nYou have been enveloped by the zone of nothingness!\n");
  1238. nap(4000);
  1239. died(DIED_SELF_ANNIHLATED, 0);
  1240. return;
  1241. }
  1242. }
  1243. xl = playerx;
  1244. yl = playery;
  1245. adjust_ability(INTELLIGENCE, -1);
  1246. i = dirsub(&xl, &yl); /* get direction of sphere */
  1247. newsphere(xl, yl, i, rnd(20) + 11); /* make a sphere */
  1248. return;
  1249. case SPELL_GEN:
  1250. /* genocide */
  1251. genmonst();
  1252. spelknow[SPELL_GEN]--;
  1253. adjust_ability(INTELLIGENCE, -1);
  1254. return;
  1255. case SPELL_SUM:
  1256. /* summon demon */
  1257. if (rnd(100) > 30) {
  1258. direct(Spell, 150, " The demon strikes at the %s.", 0, MAGIC_DEMON);
  1259. return;
  1260. }
  1261. if (rnd(100) > 15) {
  1262. Print(" Nothing seems to have happened.");
  1263. return;
  1264. }
  1265. Print(" The demon turned on you and then vanished!");
  1266. UlarnBeep();
  1267. i = rnd(40) + 30;
  1268. losehp(DIED_ATTACKED_BY_DEMON, i); /* must say killed by a demon */
  1269. return;
  1270. case SPELL_WTW:
  1271. /* walk through walls */
  1272. c[WTW] += rnd(10) + 5;
  1273. do_magic_fx(playerx, playery, MAGIC_SPARKLE);
  1274. return;
  1275. case SPELL_ALT: {
  1276. /* alter reality */
  1277. struct isave *save;
  1278. /* pointer to item save structure */
  1279. int sc;
  1280. sc = 0; /* # items saved */
  1281. save = (struct isave *)malloc(sizeof(struct isave) * MAXX * MAXY * 2);
  1282. if (save == (struct isave *)NULL)
  1283. died(DIED_MALLOC_FAILURE, 0);
  1284. /* save all items and monsters */
  1285. for (j = 0; j < MAXY; j++) {
  1286. for (i = 0; i < MAXX; i++) {
  1287. xl = item[i][j];
  1288. if ((xl != ONOTHING) && (xl != OWALL) && (xl != OANNIHILATION)) {
  1289. save[sc].type = 0;
  1290. save[sc].id = item[i][j];
  1291. save[sc++].arg = iarg[i][j];
  1292. }
  1293. if (mitem[i][j].mon) {
  1294. save[sc].type = 1;
  1295. save[sc].id = mitem[i][j].mon;
  1296. save[sc++].arg = hitp[i][j];
  1297. }
  1298. item[i][j] = OWALL;
  1299. mitem[i][j].mon = MONST_NONE;
  1300. }
  1301. }
  1302. eat(1, 1);
  1303. if (level == 1)
  1304. item[33][MAXY - 1] = ONOTHING;
  1305. for (j = rnd(MAXY - 2), i = 1; i < MAXX - 1; i++)
  1306. item[i][j] = ONOTHING;
  1307. /* put objects back in level */
  1308. while (sc > 0) {
  1309. --sc;
  1310. if (save[sc].type == 0) {
  1311. int trys;
  1312. trys = 100;
  1313. do {
  1314. trys--;
  1315. i = rnd(MAXX - 1);
  1316. j = rnd(MAXY - 1);
  1317. } while ((trys > 0) && (item[i][j] != ONOTHING));
  1318. if (trys) {
  1319. item[i][j] = save[sc].id;
  1320. iarg[i][j] = save[sc].arg;
  1321. }
  1322. } else {
  1323. /* put monsters back in */
  1324. int trys;
  1325. trys = 100;
  1326. do {
  1327. trys--;
  1328. i = rnd(MAXX - 1);
  1329. j = rnd(MAXY - 1);
  1330. } while ((trys > 0) && ((item[i][j] == OWALL) || mitem[i][j].mon));
  1331. if (trys) {
  1332. mitem[i][j].mon = save[sc].id;
  1333. hitp[i][j] = save[sc].arg;
  1334. }
  1335. }
  1336. }
  1337. adjust_ability(INTELLIGENCE, -1);
  1338. AnalyseWalls(0, 0, MAXX, MAXY);
  1339. for (i = 0; i < MAXX; i++) {
  1340. for (j = 0; j < MAXY; j++) {
  1341. if (wizard)
  1342. know[i][j] = item[i][j];
  1343. else
  1344. know[i][j] = OUNKNOWN;
  1345. }
  1346. }
  1347. draws(0, MAXX, 0, MAXY);
  1348. if (wizard == 0)
  1349. spelknow[SPELL_ALT]--;
  1350. if (save)
  1351. free((char *)save);
  1352. positionplayer();
  1353. return;
  1354. }
  1355. case SPELL_PER:
  1356. /* permanence */
  1357. adjusttime(-99999L);
  1358. spelknow[SPELL_PER]--; /* forget */
  1359. adjust_ability(INTELLIGENCE, -1);
  1360. do_magic_fx(playerx, playery, MAGIC_SPARKLE);
  1361. return;
  1362. default:
  1363. Printf(" spell %d not available!", (long)Spell);
  1364. UlarnBeep();
  1365. return;
  1366. }
  1367. }
  1368. /* =============================================================================
  1369. * Exported functions
  1370. */
  1371. /* =============================================================================
  1372. * FUNCTION: godirect
  1373. */
  1374. void godirect(SpellType spnum, int dam, char *str, int delay,
  1375. DirEffectsType cshow) {
  1376. char *it;
  1377. int x, y;
  1378. MonsterIdType m;
  1379. int dir;
  1380. int dx, dy;
  1381. int tx, ty;
  1382. /* check for bad args */
  1383. if (((signed)spnum < 0) || (spnum >= SPELL_COUNT) || (str == 0) ||
  1384. (delay < 0))
  1385. return;
  1386. /* Check player confusion */
  1387. if (isconfuse())
  1388. return;
  1389. /* Ask for direction */
  1390. dir = dirsub(&x, &y);
  1391. dx = x - playerx;
  1392. dy = y - playery;
  1393. x = playerx;
  1394. y = playery;
  1395. while (dam > 0) {
  1396. x += dx;
  1397. y += dy;
  1398. if (!checkxy(x, y))
  1399. /* out of bounds */
  1400. break;
  1401. /* if energy hits player */
  1402. if ((x == playerx) && (y == playery)) {
  1403. Print("\nYou are hit by your own magic!");
  1404. UlarnBeep();
  1405. losehp(DIED_OWN_MAGIC, dam);
  1406. return;
  1407. }
  1408. /* if not blind show effect */
  1409. if (c[BLINDCOUNT] == 0) {
  1410. mapeffect(x, y, cshow, dir);
  1411. nap(delay);
  1412. show1cell(x, y);
  1413. }
  1414. /* is there a monster there? */
  1415. if ((m = mitem[x][y].mon) != MONST_NONE) {
  1416. ifblind(x, y);
  1417. /* cannot cast a missile spell at lucifer!! */
  1418. if ((m == LUCIFER) || (m >= DEMONLORD && rnd(100) < 10)) {
  1419. dx *= -1;
  1420. dy *= -1;
  1421. Print("\n");
  1422. Printf("\nthe %s returns your puny missile!", monster[m].name);
  1423. } else {
  1424. if (nospell(spnum, m)) {
  1425. last_monst_hx = (char)x;
  1426. last_monst_hy = (char)y;
  1427. return;
  1428. }
  1429. Printc('\n');
  1430. Printf(str, lastmonst);
  1431. dam -= hitm(x, y, dam, 1);
  1432. show1cell(x, y);
  1433. nap(1000);
  1434. x -= dx;
  1435. y -= dy;
  1436. }
  1437. } else {
  1438. it = &item[x][y];
  1439. switch (*it) {
  1440. case OWALL:
  1441. Printc('\n');
  1442. Printf(str, "wall");
  1443. if (dam >= 50 + c[HARDGAME]) {
  1444. /*enough damage?*/
  1445. if (level < VBOTTOM - 2) {
  1446. /* can't break wall below V2 */
  1447. if ((x < MAXX - 1) && (y < MAXY - 1) && (x) && (y)) {
  1448. Print(" The wall crumbles.");
  1449. *it = ONOTHING;
  1450. show1cell(x, y);
  1451. /* Work out the new wall tiles for adjacent walls */
  1452. AnalyseWalls(x - 1, y - 1, x + 1, y + 1);
  1453. for (tx = x - 1; tx <= x + 1; tx++) {
  1454. for (ty = y - 1; ty <= y + 1; ty++) {
  1455. if (checkxy(tx, ty))
  1456. if ((know[tx][ty] != OUNKNOWN) && (item[tx][ty] == OWALL))
  1457. show1cell(tx, ty);
  1458. }
  1459. }
  1460. }
  1461. }
  1462. }
  1463. dam = 0;
  1464. break;
  1465. case OCLOSEDDOOR:
  1466. Printc('\n');
  1467. Printf(str, "door");
  1468. if (dam >= 40) {
  1469. Print(" The door is blasted apart.");
  1470. *it = ONOTHING;
  1471. show1cell(x, y);
  1472. }
  1473. dam = 0;
  1474. break;
  1475. case OSTATUE:
  1476. Printc('\n');
  1477. Printf(str, "statue");
  1478. if (dam > 44) {
  1479. if ((c[HARDGAME] <= 3) && (rnd(60) < 30)) {
  1480. /*
  1481. * 50% chance of revealing a book if difficulty <= 3
  1482. */
  1483. Print(" The statue crumbles.");
  1484. *it = OBOOK;
  1485. iarg[x][y] = (char)level;
  1486. show1cell(x, y);
  1487. }
  1488. }
  1489. dam = 0;
  1490. break;
  1491. case OTHRONE:
  1492. Printc('\n');
  1493. Printf(str, "throne");
  1494. if (dam > 33) {
  1495. /*
  1496. * If destroying a throne, a gnome king appears
  1497. */
  1498. mitem[x][y].mon = GNOMEKING;
  1499. hitp[x][y] = monster[GNOMEKING].hitpoints;
  1500. *it = OTHRONE2;
  1501. show1cell(x, y);
  1502. }
  1503. dam = 0;
  1504. break;
  1505. case OMIRROR:
  1506. dx *= -1;
  1507. dy *= -1;
  1508. dir = ReverseDir[dir];
  1509. break;
  1510. default:
  1511. break;
  1512. }
  1513. }
  1514. dam -= 3 + (int)(c[HARDGAME] >> 1);
  1515. }
  1516. }
  1517. /* =============================================================================
  1518. * FUNCTION: annihilate
  1519. */
  1520. void annihilate(void) {
  1521. int frame_count;
  1522. int frame;
  1523. int xl, yl;
  1524. int xh, yh;
  1525. int x, y;
  1526. long xp;
  1527. MonsterIdType monst;
  1528. /* get the area affected */
  1529. xl = max(playerx - 1, 0);
  1530. yl = max(playery - 1, 0);
  1531. xh = min(playerx + 1, MAXX - 1);
  1532. yh = min(playery + 1, MAXY - 1);
  1533. frame_count = magic_effect_frames(MAGIC_ANNIHILATE);
  1534. for (frame = 0; frame < frame_count; frame++) {
  1535. for (x = xl; x <= xh; x++) {
  1536. for (y = yl; y <= yh; y++)
  1537. if ((x != playerx) || (y != playery))
  1538. magic_effect(x, y, MAGIC_ANNIHILATE, frame);
  1539. }
  1540. nap(75);
  1541. }
  1542. xp = 0;
  1543. for (x = xl; x <= xh; x++) {
  1544. for (y = yl; y <= yh; y++) {
  1545. monst = mitem[x][y].mon;
  1546. if (monst != MONST_NONE) {
  1547. /* if a monster there */
  1548. if (monst < DEMONLORD) {
  1549. xp += monster[monst].experience;
  1550. mitem[x][y].mon = MONST_NONE;
  1551. } else {
  1552. Printf("\nThe %s barely escapes being annihilated!",
  1553. monster[monst].name);
  1554. /* lose half hit points */
  1555. hitp[x][y] = (short)((hitp[x][y] >> 1) + 1);
  1556. }
  1557. }
  1558. }
  1559. }
  1560. if (xp > 0) {
  1561. Print("\nYou hear loud screams of agony!");
  1562. raiseexperience(xp);
  1563. }
  1564. /* redisplay cells */
  1565. for (x = xl; x <= xh; x++) {
  1566. for (y = yl; y <= yh; y++)
  1567. if ((x != playerx) || (y != playery))
  1568. show1cell(x, y);
  1569. }
  1570. }
  1571. /* =============================================================================
  1572. * FUNCTION: get_spell_code
  1573. */
  1574. void get_spell_code(char *prompt, char *code) {
  1575. int Pos;
  1576. char a;
  1577. Print(prompt);
  1578. Pos = 0;
  1579. do {
  1580. a = get_prompt_input("", "abcdefghijklmnopqrstuvwxyzD\033", 1);
  1581. if ((Pos == 0) && (a == 'D')) {
  1582. seemagic(-1);
  1583. Print(prompt);
  1584. } else if (a != ESC) {
  1585. Printc((char)a);
  1586. code[Pos] = (char)a;
  1587. Pos++;
  1588. }
  1589. } while ((a != ESC) && (Pos < 3));
  1590. if (a == ESC) {
  1591. /* to escape casting a spell */
  1592. Print("aborted.");
  1593. code[0] = 0;
  1594. return;
  1595. }
  1596. }
  1597. /* =============================================================================
  1598. * FUNCTION: cast
  1599. */
  1600. void cast(void) {
  1601. int i;
  1602. int Found;
  1603. char code[3];
  1604. if (c[SPELLS] <= 0) {
  1605. Print("\nYou don't have any spells!");
  1606. return;
  1607. }
  1608. do {
  1609. get_spell_code(eys, code);
  1610. if (code[0] == 0)
  1611. return;
  1612. /* seq search for his spell */
  1613. Found = 0;
  1614. i = 0;
  1615. while ((i < SPELL_COUNT) && !Found) {
  1616. if ((spelcode[i][0] == code[0]) && (spelcode[i][1] == code[1]) &&
  1617. (spelcode[i][2] == code[2])) {
  1618. if (spelknow[i]) {
  1619. c[SPELLS]--;
  1620. Printf(" (%s)", spelname[i]);
  1621. speldamage(i);
  1622. Found = 1;
  1623. }
  1624. }
  1625. i++;
  1626. }
  1627. if (!Found)
  1628. Print(" Unknown spell! Try again.");
  1629. recalc();
  1630. UpdateStatusAndEffects();
  1631. } while (!Found);
  1632. }