player.c 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010
  1. /* =============================================================================
  2. * PROGRAM: ularn
  3. * FILENAME: player.c
  4. *
  5. * DESCRIPTION:
  6. * This module contains functions to maintain information about the player
  7. * and to process the effects of various actions.
  8. *
  9. * =============================================================================
  10. * EXPORTED VARIABLES
  11. *
  12. * char_class : The name of the player's selected class
  13. * class_num : The number to identify the character class
  14. * ramboflag : Is the character rambo?
  15. * sex : Character's gender
  16. * wizard : The wizard flag
  17. * cheat : Has the player cheated
  18. * char_picked : The character class letter picked
  19. * playerx : The player's current x coordiante
  20. * playery : The player's current y coordinate
  21. * lastpx : The player's previous x coordinate
  22. * lastpy : The player's previous y coordiante
  23. * initialtime : The time play started
  24. * gtime : The clock for the game
  25. * outstanding_taxes : The taxes owed from the score file
  26. * c : The character attributes array
  27. * cbak : The last displayed attributes array
  28. * iven : The inventory items
  29. * ivenarg : The inventory item args
  30. * class : The character class (level) strings
  31. * skill : Experience required for each level
  32. * potionknown : Array indicating potions discovered
  33. * spelknow : Array indicating spells learnt by the player
  34. *
  35. * =============================================================================
  36. * EXPORTED FUNCTIONS
  37. *
  38. * identify_class : Identify the class from the class name
  39. * makeplayer : Make a new player
  40. * moveplayer : Move the player
  41. * player_has_item : Check if the player has a particular item
  42. * raiselevel : Raise experience level
  43. * loselevel : Lose an experience level
  44. * raiseexperience : Increase experience
  45. * loseexperience : Decrease experience
  46. * losehp : Lose hitpoints
  47. * losemhp : Lower max hitpoints
  48. * raisehp : Raise hitpoints
  49. * raisemhp : Increase max hitpoints
  50. * raisespells : Raise spell points
  51. * raisemspells : Raise max spell points
  52. * losespells : Lose spell points
  53. * losemspells : Decrease max spell points
  54. * positionplayer : Position the player on a level
  55. * recalc : Recalculate AC and WC
  56. * take : Take an item
  57. * drop_object : Drop an object
  58. * adjustivenarg : Adjust the ivenarg for an item the player is carrying
  59. * enchantarmour : Enchant armour being worn
  60. * enchweapon : Enchant item being wielded
  61. * pocketfull : Check if pockets are full
  62. * nearbymonst : Check if the player is near a monster
  63. * stealsomething : Steal an item from the player
  64. * emptyhanded : Check if the player is empty handed
  65. * creategem : Creat a gem by the player
  66. * adjustcvalues : Adjust attributes when dropping/losing an item
  67. * packweight : Get the weight of the player's inventory
  68. * adjust_ability : Adjust an ability score
  69. * regen : Regen player for passing of a turn
  70. * removecurse : Remove curses inflicted upon player
  71. * adjusttime : Adjust time base effects for the passage of time
  72. * write_player : Write the player data to the save file
  73. * read_player : Read the player data from the save file
  74. *
  75. * =============================================================================
  76. */
  77. #include "ularn_game.h"
  78. #include "ularn_win.h"
  79. #include "ularn_ask.h"
  80. #include "header.h"
  81. #include "saveutils.h"
  82. #include "scores.h"
  83. #include "player.h"
  84. #include "monster.h"
  85. #include "dungeon.h"
  86. #include "dungeon_obj.h"
  87. #include "scroll.h"
  88. #include "potion.h"
  89. #include "spell.h"
  90. #include "show.h"
  91. #include "itm.h"
  92. /* =============================================================================
  93. * Exported variables
  94. */
  95. /*
  96. * class[c[LEVEL]-1] gives the correct name of the player's experience level
  97. */
  98. static char aa1[] = " mighty evil master";
  99. static char aa2[] = "apprentice demi-god";
  100. static char aa3[] = " minor demi-god ";
  101. static char aa4[] = " major demi-god ";
  102. static char aa5[] = " minor deity ";
  103. static char aa6[] = " major deity ";
  104. static char aa7[] = " novice guardian ";
  105. static char aa8[] = "apprentice guardian";
  106. static char aa9[] = " The Creator ";
  107. char *class[] =
  108. {
  109. " novice explorer ", "apprentice explorer", " practiced explorer", /* -3*/
  110. " expert explorer ", " novice adventurer ", " adventurer ", /* -6*/
  111. "apprentice conjurer", " conjurer ", " master conjurer ", /* -9*/
  112. " apprentice mage ", " mage ", " experienced mage ", /* -12*/
  113. " master mage ", " apprentice warlord", " novice warlord ", /* -15*/
  114. " expert warlord ", " master warlord ", " apprentice gorgon ", /* -18*/
  115. " gorgon ", " practiced gorgon ", " master gorgon ", /* -21*/
  116. " demi-gorgon ", " evil master ", " great evil master ", /* -24*/
  117. aa1, aa1, aa1, /* -27*/
  118. aa1, aa1, aa1, /* -30*/
  119. aa1, aa1, aa1, /* -33*/
  120. aa1, aa1, aa1, /* -36*/
  121. aa1, aa1, aa1, /* -39*/
  122. aa2, aa2, aa2, /* -42*/
  123. aa2, aa2, aa2, /* -45*/
  124. aa2, aa2, aa2, /* -48*/
  125. aa3, aa3, aa3, /* -51*/
  126. aa3, aa3, aa3, /* -54*/
  127. aa3, aa3, aa3, /* -57*/
  128. aa4, aa4, aa4, /* -60*/
  129. aa4, aa4, aa4, /* -63*/
  130. aa4, aa4, aa4, /* -66*/
  131. aa5, aa5, aa5, /* -69*/
  132. aa5, aa5, aa5, /* -72*/
  133. aa5, aa5, aa5, /* -75*/
  134. aa6, aa6, aa6, /* -78*/
  135. aa6, aa6, aa6, /* -81*/
  136. aa6, aa6, aa6, /* -84*/
  137. aa7, aa7, aa7, /* -87*/
  138. aa8, aa8, aa8, /* -90*/
  139. aa8, aa8, aa8, /* -93*/
  140. " earth guardian ", " air guardian ", " fire guardian ", /* -96*/
  141. " water guardian ", " time guardian ", " ethereal guardian ", /* -99*/
  142. aa9, aa9, aa9, /* -102*/
  143. };
  144. /*
  145. * table of experience needed to be a certain level of player
  146. * skill[c[LEVEL]] is the experience required to attain the next level
  147. */
  148. #define MEG 1000000
  149. long skill[] = {
  150. 0, 10, 20, 40, 80, 160, 320, 640, 1280, 2560, 5120, /* 1-11 */
  151. 10240, 20480, 40960, 100000, 200000, 400000, 700000, 1 * MEG, /* 12-19 */
  152. 2 * MEG, 3 * MEG, 4 * MEG, 5 * MEG, 6 * MEG, 8 * MEG, 10 * MEG, /* 20-26 */
  153. 12 * MEG, 14 * MEG, 16 * MEG, 18 * MEG, 20 * MEG, 22 * MEG, 24 * MEG, 26 * MEG, 28 * MEG, /* 27-35 */
  154. 30 * MEG, 32 * MEG, 34 * MEG, 36 * MEG, 38 * MEG, 40 * MEG, 42 * MEG, 44 * MEG, 46 * MEG, /* 36-44 */
  155. 48 * MEG, 50 * MEG, 52 * MEG, 54 * MEG, 56 * MEG, 58 * MEG, 60 * MEG, 62 * MEG, 64 * MEG, /* 45-53 */
  156. 66 * MEG, 68 * MEG, 70 * MEG, 72 * MEG, 74 * MEG, 76 * MEG, 78 * MEG, 80 * MEG, 82 * MEG, /* 54-62 */
  157. 84 * MEG, 86 * MEG, 88 * MEG, 90 * MEG, 92 * MEG, 94 * MEG, 96 * MEG, 98 * MEG, 100 * MEG, /* 63-71 */
  158. 105 * MEG, 110 * MEG, 115 * MEG, 120 * MEG, 125 * MEG, 130 * MEG, 135 * MEG, 140 * MEG, /* 72-79 */
  159. 145 * MEG, 150 * MEG, 155 * MEG, 160 * MEG, 165 * MEG, 170 * MEG, 175 * MEG, 180 * MEG, /* 80-87 */
  160. 185 * MEG, 190 * MEG, 195 * MEG, 200 * MEG, 210 * MEG, 220 * MEG, 230 * MEG, 240 * MEG, /* 88-95 */
  161. 260 * MEG, 280 * MEG, 300 * MEG, 320 * MEG, 340 * MEG, 370 * MEG /* 96-101*/
  162. };
  163. #undef MEG
  164. /*
  165. * Exported variables
  166. */
  167. char hitflag = 0; /* flag for if player has been hit when running */
  168. char hit2flag = 0; /* flag for if player has been hit when running */
  169. char hit3flag = 0; /* flag for if player has been hit flush input*/
  170. char char_class[20]; /* character class */
  171. int class_num; /* character class number */
  172. char ramboflag = 0;
  173. char sex = 1; /* default is man, 0=woman */
  174. char wizard = 0; /* the wizard mode flag */
  175. char cheat = 0; /* 1 if the player has fudged save file */
  176. char char_picked; /* the character chosen */
  177. int playerx, playery; /* the room on the present level of the player*/
  178. int lastpx, lastpy; /* 0 --- MAXX-1 or 0 --- MAXY-1 */
  179. time_t initialtime = 0; /* time playing began */
  180. long gtime = 0; /* the clock for the game */
  181. long outstanding_taxes = 0; /* present tax bill from score file */
  182. long c[ATTRIBUTE_COUNT]; /* Character description array */
  183. long cbak[ATTRIBUTE_COUNT]; /* Backup array for detecting changes */
  184. char iven[IVENSIZE]; /* inventory for player */
  185. short ivenarg[IVENSIZE]; /* inventory args for player */
  186. int potionknown[MAXPOTION];
  187. int scrollknown[MAXSCROLL];
  188. int spelknow[SPELL_COUNT];
  189. /* =============================================================================
  190. * Local variables
  191. */
  192. #define MAXPLEVEL 100 /* maximum player level allowed */
  193. /*
  194. * Haste step to keep track of frations of moves when hasted
  195. */
  196. static int HasteStep = 0;
  197. /*
  198. * Character fields affected by the passage of time
  199. */
  200. #define TIME_CHANGED_COUNT 28
  201. static AttributeType time_change[TIME_CHANGED_COUNT] =
  202. {
  203. HERO,
  204. ALTPRO,
  205. PROTECTIONTIME,
  206. DEXCOUNT,
  207. STRCOUNT,
  208. GIANTSTR,
  209. CHARMCOUNT,
  210. INVISIBILITY,
  211. CANCELLATION,
  212. HASTESELF,
  213. AGGRAVATE,
  214. SCAREMONST,
  215. STEALTH,
  216. AWARENESS,
  217. HOLDMONST,
  218. HASTEMONST,
  219. FIRERESISTANCE,
  220. GLOBE,
  221. SPIRITPRO,
  222. UNDEADPRO,
  223. HALFDAM,
  224. SEEINVISIBLE,
  225. ITCHING,
  226. CLUMSINESS,
  227. WTW,
  228. COKED,
  229. BLINDCOUNT,
  230. CONFUSE
  231. };
  232. /*
  233. * Character fields for curses
  234. */
  235. #define CURSE_COUNT 10
  236. static AttributeType curse[CURSE_COUNT] =
  237. {
  238. BLINDCOUNT,
  239. CONFUSE,
  240. AGGRAVATE,
  241. HASTEMONST,
  242. ITCHING,
  243. LAUGHING,
  244. DRAINSTRENGTH,
  245. CLUMSINESS,
  246. INFEEBLEMENT,
  247. HALFDAM
  248. };
  249. #define MAX_CLASSES 8
  250. #define MAX_INITIAL_SPELLS 2
  251. #define MAX_INITIAL_ITEMS 3
  252. struct InitialClassDataType {
  253. char *ClassName;
  254. long Attr[6];
  255. int InitialSP;
  256. int InitialHP;
  257. SpellType KnownSpells[MAX_INITIAL_SPELLS];
  258. int Item[MAX_INITIAL_ITEMS];
  259. int ItemArg[MAX_INITIAL_ITEMS];
  260. int WearItem;
  261. int WieldItem;
  262. };
  263. static struct InitialClassDataType InitialClassData[MAX_CLASSES] =
  264. {
  265. {
  266. "Ogre", /* Class name */
  267. { 18, 4, 6, 16, 6, 4 }, /* STR, INT, WIS, CON, DEX, CHA */
  268. 1, 16, /* SP, HP */
  269. { SPELL_MLE, SPELL_COUNT }, /* Spells */
  270. { OPOTION, OPOTION, ONOTHING }, /* Items */
  271. { -6, -6, 0 }, /* Item args */
  272. -1, -1 /* Wear, Wield*/
  273. },
  274. {
  275. "Wizard", /* Class name */
  276. { 8, 16, 16, 6, 6, 8 }, /* STR, INT, WIS, CON, DEX, CHA */
  277. 2, 8, /* SP, HP */
  278. { SPELL_MLE, SPELL_CHM }, /* Spells */
  279. { OPOTION, OSCROLL, OSCROLL }, /* Items */
  280. { PTREASURE, -6, -6 }, /* Item args */
  281. -1, -1 /* Wear, Wield */
  282. },
  283. {
  284. "Klingon", /* Class name */
  285. { 14, 12, 4, 12, 8, 3 }, /* STR, INT, WIS, CON, DEX, CHA */
  286. 1, 14, /* SP, HP */
  287. { SPELL_SSP, SPELL_COUNT }, /* Spells */
  288. { OSTUDLEATHER, OPOTION, ONOTHING }, /* Items */
  289. { 0, -6, 0 }, /* Item args */
  290. 0, -1 /* Wear, Wield */
  291. },
  292. {
  293. "Elf", /* Class name */
  294. { 8, 14, 12, 8, 8, 14 }, /* STR, INT, WIS, CON, DEX, CHA */
  295. 2, 8, /* SP, HP */
  296. { SPELL_MLE, SPELL_COUNT }, /* Spells */
  297. { OLEATHER, OSCROLL, ONOTHING }, /* Items */
  298. { 0, -6, 0 }, /* Item args */
  299. 0, -1 /* Wear, Wield */
  300. },
  301. {
  302. "Rogue", /* Class name */
  303. { 8, 12, 8, 10, 14, 6 }, /* STR, INT, WIS, CON, DEX, CHA */
  304. 1, 12, /* SP, HP */
  305. { SPELL_MLE, SPELL_COUNT }, /* Spells */
  306. { OLEATHER, ODAGGER, OSCROLL }, /* Items */
  307. { 0, 0, SSTEALTH }, /* Item args */
  308. 0, 1 /* Wield, wear */
  309. },
  310. {
  311. "Adventurer", /* Class name */
  312. { 12, 12, 12, 12, 12, 12 }, /* STR, INT, WIS, CON, DEX, CHA */
  313. 1, 10, /* SP, HP */
  314. { SPELL_PRO, SPELL_MLE }, /* Spells */
  315. { OLEATHER, ODAGGER, ONOTHING }, /* Items */
  316. { 0, 0, 0 }, /* Item args */
  317. 0, 1 /* Wear, Wield */
  318. },
  319. {
  320. "Dwarf", /* Class name */
  321. { 16, 6, 8, 16, 4, 4 }, /* STR, INT, WIS, CON, DEX, CHA */
  322. 1, 12, /* SP, HP */
  323. { SPELL_PRO, SPELL_COUNT }, /* Spells */
  324. { OSPEAR, ONOTHING, ONOTHING }, /* Items */
  325. { 0, 0, 0 }, /* Item args */
  326. -1, 0 /* Wear, Wield */
  327. },
  328. {
  329. "Rambo", /* Class name */
  330. { 3, 3, 3, 3, 3, 3 }, /* STR, INT, WIS, CON, DEX, CHA */
  331. 0, 1, /* SP, HP */
  332. { SPELL_MLE, SPELL_COUNT }, /* Spells */
  333. { OLANCE, ONOTHING, ONOTHING }, /* Items */
  334. { 0, 0, 0 }, /* Item args */
  335. -1, 0 /* Wear, Wield */
  336. }
  337. };
  338. /* =============================================================================
  339. * Local functions
  340. */
  341. /* =============================================================================
  342. * FUNCTION: pick_char
  343. *
  344. * DESCRIPTION:
  345. * Pick the player's character class and set initial attributes and inventory.
  346. *
  347. * PARAMETERS:
  348. *
  349. * foo : This is the character selection specified in the ularn opts file.
  350. * If no character is specified then this should be set to 0.
  351. * If a character is selected then this should be set to the key
  352. * selection for the character ('a' .. 'h').
  353. *
  354. * RETURN VALUE:
  355. *
  356. * None.
  357. */
  358. static void pick_char(int foo)
  359. {
  360. int i;
  361. int j;
  362. set_display(DISPLAY_TEXT);
  363. nosignal = 1; /* disable signals */
  364. if (foo == 0) {
  365. ClearText();
  366. MoveCursor(29, 1);
  367. Standout("The Addiction of VLarn\n\n");
  368. Print("Pick a character class...\n\n");
  369. Print("\ta) Ogre - Exceptional strength, but thick as a brick\n");
  370. Print("\n");
  371. Print("\tb) Wizard - Smart, good at magic, but very weak\n");
  372. Print("\n");
  373. Print("\tc) Klingon - Strong and average IQ, but unwise & very ugly\n");
  374. Print("\n");
  375. Print("\td) Elf - OK at magic, but a mediocre fighter\n");
  376. Print("\n");
  377. Print("\te) Rogue - Nimble and smart, but only average strength\n");
  378. Print("\n");
  379. Print("\tf) Adventurer - Jack of all trades, master of none\n");
  380. Print("\n");
  381. Print("\tg) Dwarf - Strong and healthy, but not good at magic\n");
  382. Print("\n");
  383. Print("\th) Rambo - A special challenge.\n");
  384. Print("\t Bad at everything, but has a lance of death");
  385. MoveCursor(1, 24);
  386. i = get_prompt_input("So, what are ya? ", "abcdefgh", 1);
  387. }else {
  388. //
  389. // Character selected in ops
  390. //
  391. i = foo;
  392. c[SHIELD] = c[WEAR] = c[WIELD] = -1;
  393. }
  394. i = i - 'a';
  395. class_num = i;
  396. strcpy(char_class, InitialClassData[i].ClassName);
  397. c[SPELLMAX] = InitialClassData[i].InitialSP;
  398. c[SPELLS] = InitialClassData[i].InitialSP;
  399. c[HPMAX] = InitialClassData[i].InitialHP;
  400. c[HP] = InitialClassData[i].InitialHP;;
  401. for (j = ABILITY_FIRST; j <= ABILITY_LAST; j++)
  402. c[j] = InitialClassData[i].Attr[j - ABILITY_FIRST];
  403. for (j = 0; j < MAX_INITIAL_SPELLS; j++)
  404. if (InitialClassData[i].KnownSpells[j] < SPELL_COUNT)
  405. spelknow[InitialClassData[i].KnownSpells[j]] = 1;
  406. for (j = 0; j < MAX_INITIAL_ITEMS; j++) {
  407. iven[j] = (char)InitialClassData[i].Item[j];
  408. if (iven[j] == OLANCE) {
  409. c[LANCEDEATH] = 1;
  410. ramboflag = 1;
  411. }
  412. if (InitialClassData[i].ItemArg[j] >= 0)
  413. ivenarg[j] = (short)InitialClassData[i].ItemArg[j];
  414. else
  415. ivenarg[j] = (short)rund(-InitialClassData[i].ItemArg[j]);
  416. }
  417. c[WEAR] = InitialClassData[i].WearItem;
  418. c[WIELD] = InitialClassData[i].WieldItem;
  419. nosignal = 0;
  420. } /* end pick_char */
  421. /* =============================================================================
  422. * Exported functions
  423. */
  424. /* =============================================================================
  425. * FUNCTION: identify_class
  426. */
  427. char identify_class(char *class_str)
  428. {
  429. int cls;
  430. int found;
  431. int i;
  432. int len;
  433. char class_cmp_str[20];
  434. if (class_str == NULL)
  435. /* no class string specified */
  436. return 0;
  437. len = strlen(class_str);
  438. for (i = 0; i < len; i++)
  439. class_str[i] = (char)tolower(class_str[i]);
  440. cls = 0;
  441. found = 0;
  442. while ((cls < MAX_CLASSES) && (!found)) {
  443. strcpy(class_cmp_str, InitialClassData[cls].ClassName);
  444. len = strlen(class_cmp_str);
  445. for (i = 0; i < len; i++)
  446. class_cmp_str[i] = (char)tolower(class_cmp_str[i]);
  447. if (strcmp(class_str, class_cmp_str) == 0)
  448. found = 1;
  449. else
  450. cls++;
  451. }
  452. if (cls < MAX_CLASSES)
  453. return (char)('a' + cls);
  454. else
  455. return 0;
  456. }
  457. /* =============================================================================
  458. * FUNCTION: makeplayer
  459. */
  460. void makeplayer(void)
  461. {
  462. int i;
  463. /*
  464. * Clear the player's attributes
  465. */
  466. for (i = 0; i < ATTRIBUTE_COUNT; i++) {
  467. c[i] = 0;
  468. cbak[i] = 0;
  469. }
  470. /*
  471. * Clear the player's inventory
  472. */
  473. for (i = 0; i < IVENSIZE; i++) {
  474. iven[i] = ONOTHING;
  475. ivenarg[i] = 0;
  476. }
  477. /* Clear spells, potions and scrolls known */
  478. for (i = 0; i < MAXPOTION; i++)
  479. potionknown[i] = 0;
  480. for (i = 0; i < MAXSCROLL; i++)
  481. scrollknown[i] = 0;
  482. for (i = 0; i < SPELL_COUNT; i++)
  483. spelknow[i] = 0;
  484. c[LEVEL] = 1; /* player starts at level one */
  485. c[REGENCOUNTER] = 16;
  486. c[ECOUNTER] = 96; /* start regeneration correctly */
  487. c[SHIELD] = -1;
  488. c[WEAR] = -1;
  489. c[WIELD] = -1;
  490. if (char_picked >= 'a' && char_picked <= 'h')
  491. /* Class specified on command line */
  492. pick_char(char_picked);
  493. else
  494. /* Ask for the class */
  495. pick_char(0);
  496. /*
  497. * Position the player in the home level
  498. */
  499. playerx = (char)rnd(MAXX - 2);
  500. playery = (char)rnd(MAXY - 2);
  501. lastpx = 0;
  502. lastpy = 0;
  503. /* time clock starts at zero */
  504. gtime = 0;
  505. cbak[SPELLS] = -50;
  506. recalc();
  507. }
  508. /* =============================================================================
  509. * FUNCTION: moveplayer
  510. */
  511. int moveplayer(int dir)
  512. {
  513. int k, m, i, j;
  514. if (c[CONFUSE]) {
  515. if (c[LEVEL] < rnd(30)) {
  516. dir = rund(9); /*if confused any dir*/
  517. }
  518. }
  519. k = playerx + diroffx[dir];
  520. m = playery + diroffy[dir];
  521. if ((k < 0) || (k >= MAXX) || (m < 0) || (m >= MAXY)) {
  522. nomove = 1;
  523. yrepcount = 0;
  524. return 0;
  525. }
  526. i = item[k][m];
  527. j = mitem[k][m].mon;
  528. /* hit a wall */
  529. if ((i == OWALL) && (c[WTW] == 0)) {
  530. nomove = 1;
  531. yrepcount = 0;
  532. return 0;
  533. }
  534. /* Can't move onto closed doors if using the enhanced interface */
  535. if ((enhance_interface) && (i == OCLOSEDDOOR)) {
  536. nomove = 1;
  537. yrepcount = 0;
  538. return 0;
  539. }
  540. if ((k == 33) && (m == MAXY - 1) && (level == 1)) {
  541. newcavelevel(0);
  542. /*
  543. * Returning to the home level from the dungeon, so find the
  544. * dungeon entrance and locate the player at the dungeon entrance.
  545. */
  546. for (k = 0; k < MAXX; k++) {
  547. for (m = 0; m < MAXY; m++) {
  548. if (item[k][m] == OENTRANCE) {
  549. playerx = (char)k;
  550. playery = (char)m;
  551. positionplayer();
  552. drawscreen();
  553. return 0;
  554. }
  555. }
  556. }
  557. }
  558. if (j > 0) {
  559. hitmonster(k, m);
  560. yrepcount = 0;
  561. return 0;
  562. } /* hit a monster*/
  563. lastpx = playerx;
  564. lastpy = playery;
  565. playerx = (char)k;
  566. playery = (char)m;
  567. if ((i != ONOTHING) &&
  568. (i != OTRAPARROWIV) &&
  569. (i != OIVTELETRAP) &&
  570. (i != OIVDARTRAP) &&
  571. (i != OIVTRAPDOOR)) {
  572. yrepcount = 0;
  573. return 0;
  574. }else
  575. return 1;
  576. }
  577. /* =============================================================================
  578. * FUNCTION: player_has_item
  579. */
  580. int player_has_item(int Item)
  581. {
  582. int i;
  583. int have_item;
  584. have_item = 0;
  585. for (i = 0; i < IVENSIZE; i++)
  586. if (iven[i] == Item)
  587. have_item = 1;
  588. return have_item;
  589. }
  590. /* =============================================================================
  591. * FUNCTION: raiselevel
  592. */
  593. void raiselevel(void)
  594. {
  595. if (c[LEVEL] < MAXPLEVEL)
  596. raiseexperience((long)(skill[c[LEVEL]] - c[EXPERIENCE]));
  597. }
  598. /* =============================================================================
  599. * FUNCTION: loselevel
  600. */
  601. void loselevel(void)
  602. {
  603. if (c[LEVEL] > 1)
  604. loseexperience((long)(c[EXPERIENCE] - skill[c[LEVEL] - 1] + 1));
  605. }
  606. /* =============================================================================
  607. * FUNCTION: raiseexperience
  608. */
  609. void raiseexperience(long x)
  610. {
  611. int i, tmp;
  612. i = c[LEVEL];
  613. c[EXPERIENCE] += x;
  614. while (c[EXPERIENCE] >= skill[c[LEVEL]] && (c[LEVEL] < MAXPLEVEL)) {
  615. tmp = (c[CONSTITUTION] - c[HARDGAME]) >> 1;
  616. c[LEVEL]++;
  617. raisemhp((int)(rnd(3) + rnd((tmp > 0)?tmp:1)));
  618. raisemspells((int)rund(3));
  619. if (c[LEVEL] < 7 - c[HARDGAME])
  620. raisemhp((int)(c[CONSTITUTION] >> 2));
  621. }
  622. if (c[LEVEL] != i) {
  623. /* Alert the player to level up */
  624. UlarnBeep();
  625. Printf("\nWelcome to level %d!", (long)c[LEVEL]);
  626. /* if we changed levels */
  627. switch ((int)c[LEVEL]) {
  628. case 94: /* earth guardian */
  629. c[WTW] = 99999L;
  630. break;
  631. case 95: /* air guardian */
  632. c[INVISIBILITY] = 99999L;
  633. break;
  634. case 96: /* fire guardian */
  635. c[FIRERESISTANCE] = 99999L;
  636. break;
  637. case 97: /* water guardian */
  638. c[CANCELLATION] = 99999L;
  639. break;
  640. case 98: /* time guardian */
  641. c[HASTESELF] = 99999L;
  642. break;
  643. case 99: /* ethereal guardian */
  644. c[STEALTH] = 99999L;
  645. c[SPIRITPRO] = 99999L;
  646. break;
  647. case 100:
  648. Print("\nYou are now The Creator!");
  649. {
  650. int i, j;
  651. for (i = 0; i < MAXY; i++) for (j = 0; j < MAXX; j++) know[j][i] = item[j][i];
  652. for (i = 0; i < SPELL_COUNT; i++) spelknow[i] = 1;
  653. for (i = 0; i < MAXSCROLL; i++) scrollknown[i] = 1;
  654. for (i = 0; i < MAXPOTION; i++) potionknown[i] = 1;
  655. }
  656. break;
  657. default:
  658. break;
  659. }
  660. }
  661. UpdateStatusAndEffects();
  662. }
  663. /* =============================================================================
  664. * FUNCTION: loseexperience
  665. */
  666. void loseexperience(long x)
  667. {
  668. int i, tmp;
  669. i = c[LEVEL];
  670. c[EXPERIENCE] -= x;
  671. if (c[EXPERIENCE] < 0) c[EXPERIENCE] = 0;
  672. while (c[EXPERIENCE] < skill[c[LEVEL] - 1]) {
  673. if (--c[LEVEL] <= 1) c[LEVEL] = 1; /* down one level */
  674. tmp = (c[CONSTITUTION] - c[HARDGAME]) >> 1; /* lose hpoints */
  675. losemhp((int)rnd((tmp > 0)?tmp:1)); /* lose hpoints */
  676. if (c[LEVEL] < 7 - c[HARDGAME]) losemhp((int)(c[CONSTITUTION] >> 2));
  677. losemspells((int)rund(3)); /* lose spells */
  678. }
  679. if (i != c[LEVEL])
  680. Printf("\nYou went down to level %d!", (long)c[LEVEL]);
  681. recalc();
  682. UpdateStatus();
  683. }
  684. /* =============================================================================
  685. * FUNCTION: losehp
  686. */
  687. void losehp(DiedReasonType Reason, int x)
  688. {
  689. if ((c[HP] -= x) <= 0) {
  690. UlarnBeep();
  691. Print("\nAlas, you have died.\n");
  692. Print("\n");
  693. nap(3000);
  694. if ((Reason == DIED_MONSTER) && (last_monst_id == MONST_NONE))
  695. Reason = DIED_UNSEEN_ATTACKER;
  696. died(Reason, last_monst_id);
  697. }
  698. }
  699. /* =============================================================================
  700. * FUNCTION: losemhp
  701. */
  702. void losemhp(int x)
  703. {
  704. c[HP] -= x;
  705. if (c[HP] < 1) c[HP] = 1;
  706. c[HPMAX] -= x;
  707. if (c[HPMAX] < 1) c[HPMAX] = 1;
  708. }
  709. /* =============================================================================
  710. * FUNCTION: raisehp
  711. */
  712. void raisehp(int x)
  713. {
  714. if ((c[HP] += x) > c[HPMAX])
  715. c[HP] = c[HPMAX];
  716. }
  717. /* =============================================================================
  718. * FUNCTION: raisemhp
  719. */
  720. void raisemhp(int x)
  721. {
  722. c[HPMAX] += x;
  723. c[HP] += x;
  724. }
  725. /* =============================================================================
  726. * FUNCTION: raisespells
  727. */
  728. void raisespells(int x)
  729. {
  730. if ((c[SPELLS] += x) > c[SPELLMAX])
  731. c[SPELLS] = c[SPELLMAX];
  732. }
  733. /* =============================================================================
  734. * FUNCTION: raisemspells
  735. */
  736. void raisemspells(int x)
  737. {
  738. c[SPELLMAX] += x;
  739. c[SPELLS] += x;
  740. }
  741. /* =============================================================================
  742. * FUNCTION: losespells
  743. */
  744. void losespells(int x)
  745. {
  746. if ((c[SPELLS] -= x) < 0)
  747. c[SPELLS] = 0;
  748. }
  749. /* =============================================================================
  750. * FUNCTION: losemspells
  751. */
  752. void losemspells(int x)
  753. {
  754. if ((c[SPELLMAX] -= x) < 0)
  755. c[SPELLMAX] = 0;
  756. if ((c[SPELLS] -= x) < 0)
  757. c[SPELLS] = 0;
  758. }
  759. /* =============================================================================
  760. * FUNCTION: positionplayer
  761. */
  762. void positionplayer(void)
  763. {
  764. int x, y;
  765. int cx = 0, cy = 0;
  766. int dist, closest;
  767. if ((item[playerx][playery] == ONOTHING) &&
  768. (mitem[playerx][playery].mon == MONST_NONE))
  769. /* location is clear, so nothing to do */
  770. return;
  771. closest = 10000;
  772. for (x = 0; x < MAXX; x++) {
  773. for (y = 0; y < MAXY; y++) {
  774. if ((item[x][y] == ONOTHING) &&
  775. (mitem[x][y].mon == MONST_NONE)) {
  776. /*
  777. * This location is empty, so see how far it is from the desired
  778. * location.
  779. */
  780. dist = (playerx - x) * (playerx - x) + (playery - y) * (playery - y);
  781. if (dist < closest) {
  782. /* This is the closest location found so far */
  783. cx = x;
  784. cy = y;
  785. closest = dist;
  786. }
  787. }
  788. }
  789. }
  790. if (closest == 10000)
  791. Print("Failure in positionplayer\n");
  792. else{
  793. playerx = cx;
  794. playery = cy;
  795. }
  796. }
  797. /* =============================================================================
  798. * FUNCTION: recalc
  799. */
  800. void recalc(void)
  801. {
  802. int i;
  803. c[AC] = c[MOREDEFENSES];
  804. if (c[WEAR] >= 0) {
  805. switch (iven[c[WEAR]]) {
  806. case OSHIELD:
  807. c[AC] += 2 + ivenarg[c[WEAR]];
  808. break;
  809. case OLEATHER:
  810. c[AC] += 2 + ivenarg[c[WEAR]];
  811. break;
  812. case OSTUDLEATHER:
  813. c[AC] += 3 + ivenarg[c[WEAR]];
  814. break;
  815. case ORING:
  816. c[AC] += 5 + ivenarg[c[WEAR]];
  817. break;
  818. case OCHAIN:
  819. c[AC] += 6 + ivenarg[c[WEAR]];
  820. break;
  821. case OSPLINT:
  822. c[AC] += 7 + ivenarg[c[WEAR]];
  823. break;
  824. case OPLATE:
  825. c[AC] += 9 + ivenarg[c[WEAR]];
  826. break;
  827. case OPLATEARMOR:
  828. c[AC] += 10 + ivenarg[c[WEAR]];
  829. break;
  830. case OSSPLATE:
  831. c[AC] += 12 + ivenarg[c[WEAR]];
  832. break;
  833. case OELVENCHAIN:
  834. c[AC] += 15 + ivenarg[c[WEAR]];
  835. break;
  836. default:
  837. break;
  838. }
  839. }
  840. if (c[SHIELD] >= 0 && iven[c[SHIELD]] == OSHIELD)
  841. c[AC] += 2 + ivenarg[c[SHIELD]];
  842. c[LANCEDEATH] = 0;
  843. if (c[WIELD] < 0)
  844. c[WCLASS] = 0;
  845. else{
  846. i = ivenarg[c[WIELD]];
  847. switch (iven[c[WIELD]]) {
  848. case ODAGGER:
  849. c[WCLASS] = 3 + i;
  850. break;
  851. case OBELT:
  852. c[WCLASS] = 7 + i;
  853. break;
  854. case OSHIELD:
  855. c[WCLASS] = 8 + i;
  856. break;
  857. case OPSTAFF:
  858. case OSPEAR:
  859. c[WCLASS] = 10 + i;
  860. break;
  861. case OFLAIL:
  862. c[WCLASS] = 14 + i;
  863. break;
  864. case OBATTLEAXE:
  865. c[WCLASS] = 17 + i;
  866. break;
  867. case OLANCE:
  868. c[LANCEDEATH] = 1;
  869. c[WCLASS] = 20 + i;
  870. break;
  871. case OLONGSWORD:
  872. case OVORPAL:
  873. c[WCLASS] = 22 + i;
  874. break;
  875. case O2SWORD:
  876. c[WCLASS] = 26 + i;
  877. break;
  878. case OSWORDofSLASHING:
  879. c[WCLASS] = 30 + i;
  880. break;
  881. case OSLAYER:
  882. c[WCLASS] = 30 + i;
  883. break;
  884. case OSWORD:
  885. c[WCLASS] = 32 + i;
  886. break;
  887. case OHAMMER:
  888. c[WCLASS] = 35 + i;
  889. break;
  890. default:
  891. c[WCLASS] = 0;
  892. }
  893. }
  894. c[WCLASS] += c[MOREDAM];
  895. /* now for regeneration abilities based on rings */
  896. c[REGEN] = 1;
  897. c[ENERGY] = 0;
  898. for (i = 0; i <= IVENSIZE; i++) {
  899. switch (iven[i]) {
  900. case OPROTRING:
  901. c[AC] += ivenarg[i] + 1;
  902. break;
  903. case ODAMRING:
  904. c[WCLASS] += ivenarg[i] + 1;
  905. break;
  906. case OBELT:
  907. c[WCLASS] += ((ivenarg[i] << 1)) + 2;
  908. break;
  909. case OREGENRING:
  910. c[REGEN] += ivenarg[i] + 1;
  911. break;
  912. case ORINGOFEXTRA:
  913. c[REGEN] += 5 * (ivenarg[i] + 1);
  914. break;
  915. case OENERGYRING:
  916. c[ENERGY] += ivenarg[i] + 1;
  917. break;
  918. default:
  919. break;
  920. }
  921. }
  922. }
  923. /* =============================================================================
  924. * FUNCTION: take
  925. */
  926. int take(int itm, int arg)
  927. {
  928. int i;
  929. int limit;
  930. int slot;
  931. int need_recalc;
  932. char eyeflag = 0;
  933. /*
  934. * Decide how many items the player can carry
  935. */
  936. limit = 16 + (c[LEVEL] >> 1);
  937. if (limit > IVENSIZE)
  938. limit = IVENSIZE;
  939. /*
  940. * find a free inventory slot
  941. */
  942. i = 0;
  943. slot = -1;
  944. while ((i < limit) && (slot == -1)) {
  945. if (iven[i] == ONOTHING)
  946. slot = i;
  947. i++;
  948. }
  949. if (slot != -1) {
  950. /* found a free inventory slot, so store the item */
  951. need_recalc = 0;
  952. iven[slot] = (char)itm;
  953. ivenarg[slot] = (short)arg;
  954. switch (itm) {
  955. case OPROTRING:
  956. case ODAMRING:
  957. case OBELT:
  958. need_recalc = 1;
  959. break;
  960. case ODEXRING:
  961. c[DEXTERITY] += ivenarg[slot] + 1;
  962. need_recalc = 1;
  963. break;
  964. case OSTRRING:
  965. c[STREXTRA] += ivenarg[slot] + 1;
  966. need_recalc = 1;
  967. break;
  968. case OCLEVERRING:
  969. c[INTELLIGENCE] += ivenarg[slot] + 1;
  970. need_recalc = 1;
  971. break;
  972. case OHAMMER:
  973. c[DEXTERITY] += 10;
  974. c[STREXTRA] += 10;
  975. c[TMP2] = c[INTELLIGENCE];
  976. c[INTELLIGENCE] = (c[TMP2] - 10 <= 2)?3:c[TMP2] - 10;
  977. need_recalc = 1;
  978. break;
  979. case OORB:
  980. c[ORB]++;
  981. c[AWARENESS]++;
  982. break;
  983. case OORBOFDRAGON:
  984. c[SLAYING]++;
  985. break;
  986. case OSPIRITSCARAB:
  987. c[NEGATESPIRIT]++;
  988. break;
  989. case OCUBEofUNDEAD:
  990. c[CUBEofUNDEAD]++;
  991. break;
  992. case ONOTHEFT:
  993. c[NOTHEFT]++;
  994. break;
  995. case OSWORDofSLASHING:
  996. c[DEXTERITY] += 5;
  997. need_recalc = 1;
  998. break;
  999. case OSLAYER:
  1000. c[INTELLIGENCE] += 10;
  1001. need_recalc = 1;
  1002. break;
  1003. case OPSTAFF:
  1004. c[WISDOM] += 10;
  1005. need_recalc = 1;
  1006. break;
  1007. case OLARNEYE:
  1008. c[EYEOFLARN] = 1;
  1009. eyeflag = 1;
  1010. break;
  1011. }
  1012. Print("\nYou pick up:");
  1013. show3(slot);
  1014. if (need_recalc) {
  1015. recalc();
  1016. UpdateStatus();
  1017. }
  1018. if ((c[BLINDCOUNT] == 0) && eyeflag) {
  1019. Print("\nYour sight fades for a moment...");
  1020. nap(2000);
  1021. drawscreen();
  1022. Print("\nYour sight returns, and everything looks crystal-clear!");
  1023. }
  1024. return 0;
  1025. }
  1026. Print("\nYou can't carry anything else.");
  1027. return 1;
  1028. }
  1029. /* =============================================================================
  1030. * FUNCTION: drop_object
  1031. */
  1032. int drop_object(int k)
  1033. {
  1034. int itm, pitflag = 0;
  1035. if ((k < 0) || (k > 25))
  1036. return 0;
  1037. itm = iven[k];
  1038. if (itm == ONOTHING) {
  1039. Printf("\nYou don't have item %c! ", k + 'a');
  1040. return 1;
  1041. }
  1042. if (item[playerx][playery] == OPIT)
  1043. pitflag = 1;
  1044. else if (item[playerx][playery] > ONOTHING) {
  1045. UlarnBeep();
  1046. Print("\nThere's something here already.");
  1047. return 1;
  1048. }
  1049. if (playery == MAXY - 1 && playerx == 33) {
  1050. return 1; /* not in entrance */
  1051. }
  1052. if (!pitflag) {
  1053. item[playerx][playery] = (char)itm;
  1054. iarg[playerx][playery] = (short)ivenarg[k];
  1055. }
  1056. /* show what item you dropped*/
  1057. Print("\n You drop:");
  1058. show3(k);
  1059. /* Update the player's inventory and status */
  1060. iven[k] = ONOTHING;
  1061. if (c[WIELD] == k) c[WIELD] = -1;
  1062. if (c[WEAR] == k) c[WEAR] = -1;
  1063. if (c[SHIELD] == k) c[SHIELD] = -1;
  1064. adjustcvalues(itm, ivenarg[k]);
  1065. recalc();
  1066. UpdateStatus();
  1067. if (pitflag)
  1068. Printf("\nIt disappears down the pit.");
  1069. /* say dropped an item so wont ask to pick it up right away */
  1070. dropflag = 1;
  1071. return 0;
  1072. }
  1073. /* =============================================================================
  1074. * FUNCTION: adjustivenarg
  1075. */
  1076. void adjustivenarg(int Idx, int Amount)
  1077. {
  1078. ivenarg[Idx] += (short)Amount;
  1079. switch (iven[Idx]) {
  1080. /* Armour */
  1081. case OPLATE:
  1082. case OCHAIN:
  1083. case OLEATHER:
  1084. case ORING:
  1085. case OSTUDLEATHER:
  1086. case OSPLINT:
  1087. case OPLATEARMOR:
  1088. case OSSPLATE:
  1089. case OSHIELD:
  1090. case OELVENCHAIN:
  1091. recalc();
  1092. UpdateStatus();
  1093. break;
  1094. /* Weapons */
  1095. case OSWORDofSLASHING:
  1096. case OHAMMER:
  1097. case OSWORD:
  1098. case O2SWORD:
  1099. case OSPEAR:
  1100. case ODAGGER:
  1101. case OBATTLEAXE:
  1102. case OLONGSWORD:
  1103. case OFLAIL:
  1104. case OLANCE:
  1105. case OVORPAL:
  1106. case OSLAYER:
  1107. case OBELT:
  1108. recalc();
  1109. UpdateStatus();
  1110. break;
  1111. /* Rings */
  1112. case ORINGOFEXTRA:
  1113. recalc();
  1114. break;
  1115. case OREGENRING:
  1116. recalc();
  1117. break;
  1118. case OPROTRING:
  1119. recalc();
  1120. UpdateStatus();
  1121. break;
  1122. case OENERGYRING:
  1123. recalc();
  1124. break;
  1125. case ODEXRING:
  1126. c[DEXTERITY] += Amount;
  1127. recalc();
  1128. UpdateStatus();
  1129. break;
  1130. case OSTRRING:
  1131. c[STREXTRA] += Amount;
  1132. recalc();
  1133. UpdateStatus();
  1134. break;
  1135. case OCLEVERRING:
  1136. c[INTELLIGENCE] += Amount;
  1137. recalc();
  1138. UpdateStatus();
  1139. break;
  1140. case ODAMRING:
  1141. recalc();
  1142. UpdateStatus();
  1143. break;
  1144. default:
  1145. break;
  1146. }
  1147. }
  1148. /* =============================================================================
  1149. * FUNCTION: enchantarmor
  1150. */
  1151. void enchantarmor(int how)
  1152. {
  1153. int which;
  1154. /*
  1155. * Bomb out if we're not wearing anything.
  1156. */
  1157. if (c[WEAR] < 0 && c[SHIELD] < 0) {
  1158. UlarnBeep();
  1159. Print("\nYou feel a sense of loss.");
  1160. return;
  1161. }
  1162. /*
  1163. * Choose what to enchant.
  1164. */
  1165. which = (rund(100) < 50) ? SHIELD : WEAR;
  1166. if (c[which] < 0)
  1167. which = (which == SHIELD) ? WEAR : SHIELD;
  1168. /*
  1169. * Enchant it and check for destruction at >= +10.
  1170. */
  1171. if (ivenarg[c[which]] >= 9) {
  1172. if (how == ENCH_ALTAR)
  1173. Printf("\nYour %s glows briefly.", objectname[(int)iven[c[which]]]);
  1174. else if (rnd(10) <= 9) {
  1175. Printf("\nYour %s vibrates violently and crumbles into dust!",
  1176. objectname[(int)iven[c[which]]]);
  1177. /* Recalculated any attributes affected by destroying the armour */
  1178. adjustcvalues(iven[c[which]], ivenarg[c[which]]);
  1179. /* Destroy the armour */
  1180. iven[c[which]] = ONOTHING;
  1181. ivenarg[c[which]] = 0;
  1182. c[which] = -1;
  1183. /* Recalculate player's AC */
  1184. recalc();
  1185. }
  1186. }else {
  1187. Printf("\nYour %s glows for a moment.", objectname[(int)iven[c[which]]]);
  1188. /* Increase enchantment level by 1 */
  1189. adjustivenarg(c[which], 1);
  1190. }
  1191. UpdateStatus();
  1192. }
  1193. /* =============================================================================
  1194. * FUNCTION: enchweapon
  1195. */
  1196. void enchweapon(int how)
  1197. {
  1198. ObjectIdType Obj;
  1199. int Idx;
  1200. if (c[WIELD] < 0) {
  1201. UlarnBeep();
  1202. Print("\nYou feel depressed.");
  1203. return;
  1204. }
  1205. Idx = c[WIELD];
  1206. Obj = iven[c[WIELD]];
  1207. if ((Obj != OSCROLL) && (Obj != OPOTION)) {
  1208. if ((ivenarg[Idx] >= 9) && (rnd(10) <= 9)) {
  1209. if (how == ENCH_ALTAR)
  1210. Print("\nYour weapon glows a little.");
  1211. else{
  1212. Print("\nYour weapon vibrates violently and crumbles into dust!");
  1213. /* Recalculate any attributes affected by destroying the weapon */
  1214. adjustcvalues(iven[Idx], ivenarg[Idx]);
  1215. /* destroy the weapon */
  1216. iven[Idx] = ONOTHING;
  1217. ivenarg[Idx] = 0;
  1218. c[WIELD] = -1;
  1219. /* Recalculate the player's WC */
  1220. recalc();
  1221. }
  1222. }else {
  1223. Print("\nYour weapon glows for a moment.");
  1224. adjustivenarg(Idx, 1);
  1225. }
  1226. }
  1227. UpdateStatus();
  1228. }
  1229. /* =============================================================================
  1230. * FUNCTION: pocketfull
  1231. */
  1232. int pocketfull(void)
  1233. {
  1234. int i, limit;
  1235. if ((limit = 15 + (c[LEVEL] >> 1)) > IVENSIZE)
  1236. limit = IVENSIZE;
  1237. for (i = 0; i < limit; i++)
  1238. if (iven[i] == ONOTHING) return 0;
  1239. return 1;
  1240. }
  1241. /* =============================================================================
  1242. * FUNCTION: nearbymonst
  1243. */
  1244. int nearbymonst(void)
  1245. {
  1246. int tx, ty;
  1247. int x1, y1;
  1248. int x2, y2;
  1249. x1 = playerx - 1;
  1250. x2 = playerx + 1;
  1251. y1 = playery - 1;
  1252. y2 = playery + 1;
  1253. if (x1 < 0) x1 = 0;
  1254. if (x2 >= MAXX) x2 = (MAXX - 1);
  1255. if (y1 < 0) y1 = 0;
  1256. if (y2 >= MAXY) y2 = (MAXY - 1);
  1257. for (tx = x1; tx <= x2; tx++)
  1258. for (ty = y1; ty <= y2; ty++)
  1259. if (mitem[tx][ty].mon != MONST_NONE) return 1; /* monster nearby */
  1260. return 0;
  1261. }
  1262. /* =============================================================================
  1263. * FUNCTION: stealsomething
  1264. */
  1265. int stealsomething(int x, int y)
  1266. {
  1267. int i, n = 100;
  1268. /* max of 6 stolen items per monster */
  1269. if (mitem[x][y].n >= 6)
  1270. return 0;
  1271. while (n--) {
  1272. i = rund(IVENSIZE);
  1273. if (iven[i] != ONOTHING) {
  1274. if (c[WEAR] != i && c[WIELD] != i && c[SHIELD] != i) {
  1275. show3(i);
  1276. adjustcvalues(iven[i], ivenarg[i]);
  1277. n = mitem[x][y].n++;
  1278. mitem[x][y].it[n].item = iven[i];
  1279. mitem[x][y].it[n].itemarg = ivenarg[i];
  1280. iven[i] = ONOTHING;
  1281. ivenarg[i] = 0;
  1282. beenhere[level]++;
  1283. return 1;
  1284. }
  1285. }
  1286. }
  1287. return 0;
  1288. }
  1289. /* =============================================================================
  1290. * FUNCTION: emptyhanded
  1291. */
  1292. int emptyhanded(void)
  1293. {
  1294. int i;
  1295. for (i = 0; i < IVENSIZE; i++) {
  1296. if (iven[i] != ONOTHING)
  1297. if ((i != c[WIELD]) && (i != c[WEAR]) && (i != c[SHIELD]))
  1298. return 0;
  1299. }
  1300. return 1;
  1301. }
  1302. /* =============================================================================
  1303. * FUNCTION: creategem
  1304. */
  1305. void creategem(void)
  1306. {
  1307. int i, j;
  1308. switch (rnd(4)) {
  1309. case 1:
  1310. i = ODIAMOND;
  1311. j = 50;
  1312. break;
  1313. case 2:
  1314. i = ORUBY;
  1315. j = 40;
  1316. break;
  1317. case 3:
  1318. i = OEMERALD;
  1319. j = 30;
  1320. break;
  1321. default:
  1322. i = OSAPPHIRE;
  1323. j = 20;
  1324. break;
  1325. }
  1326. ;
  1327. createitem(playerx, playery, i, (long)(rndl(j) + (j / 10)));
  1328. }
  1329. /* =============================================================================
  1330. * FUNCTION: adjustcvalues
  1331. */
  1332. void adjustcvalues(int itm, int arg)
  1333. {
  1334. int flag, i;
  1335. flag = 0;
  1336. switch (itm) {
  1337. case ODEXRING:
  1338. c[DEXTERITY] -= arg + 1;
  1339. flag = 1;
  1340. break;
  1341. case OSTRRING:
  1342. c[STREXTRA] -= arg + 1;
  1343. flag = 1;
  1344. break;
  1345. case OCLEVERRING:
  1346. c[INTELLIGENCE] -= arg + 1;
  1347. flag = 1;
  1348. break;
  1349. case OHAMMER:
  1350. c[DEXTERITY] -= 10;
  1351. c[STREXTRA] -= 10;
  1352. c[INTELLIGENCE] = c[TMP2];
  1353. flag = 1;
  1354. break;
  1355. case OORB:
  1356. c[ORB]--;
  1357. c[AWARENESS]--;
  1358. break;
  1359. case OSWORDofSLASHING:
  1360. c[DEXTERITY] -= 5;
  1361. flag = 1;
  1362. break;
  1363. case OSLAYER:
  1364. c[INTELLIGENCE] -= 10;
  1365. flag = 1;
  1366. break;
  1367. case OPSTAFF:
  1368. c[WISDOM] -= 10;
  1369. flag = 1;
  1370. break;
  1371. case OORBOFDRAGON:
  1372. --c[SLAYING];
  1373. break;
  1374. case OSPIRITSCARAB:
  1375. --c[NEGATESPIRIT];
  1376. break;
  1377. case OCUBEofUNDEAD:
  1378. --c[CUBEofUNDEAD];
  1379. break;
  1380. case ONOTHEFT:
  1381. --c[NOTHEFT];
  1382. break;
  1383. case OLANCE:
  1384. c[LANCEDEATH] = 0;
  1385. break;
  1386. case OLARNEYE:
  1387. c[EYEOFLARN] = 0;
  1388. if (c[BLINDCOUNT] == 0) {
  1389. Print("\nYour sight fades for a moment...");
  1390. nap(2000);
  1391. drawscreen();
  1392. Print("\nYour sight returns but everything looks dull and faded.");
  1393. }
  1394. break;
  1395. case OPOTION:
  1396. case OSCROLL:
  1397. break;
  1398. default:
  1399. flag = 1;
  1400. break;
  1401. }
  1402. for (i = ABILITY_FIRST; i <= ABILITY_LAST; i++)
  1403. if (c[i] < 3)
  1404. c[i] = 3;
  1405. if (flag) {
  1406. recalc();
  1407. UpdateStatusAndEffects();
  1408. }
  1409. }
  1410. /* =============================================================================
  1411. * FUNCTION: packweight
  1412. */
  1413. int packweight(void)
  1414. {
  1415. int i, j, k;
  1416. k = c[GOLD] / 1000;
  1417. j = 25;
  1418. while ((iven[j] == ONOTHING) && (j > 0)) --j;
  1419. for (i = 0; i <= j; i++) {
  1420. switch (iven[i]) {
  1421. case ONOTHING: break;
  1422. case OSSPLATE:
  1423. case OPLATEARMOR:
  1424. k += 40;
  1425. break;
  1426. case OPLATE:
  1427. k += 35;
  1428. break;
  1429. case OHAMMER:
  1430. k += 30;
  1431. break;
  1432. case OSPLINT:
  1433. k += 26;
  1434. break;
  1435. case OCHAIN:
  1436. case OBATTLEAXE:
  1437. case O2SWORD:
  1438. k += 23;
  1439. break;
  1440. case OLONGSWORD:
  1441. case OPSTAFF:
  1442. case OSWORD:
  1443. case ORING:
  1444. case OFLAIL:
  1445. k += 20;
  1446. break;
  1447. case OELVENCHAIN:
  1448. case OSWORDofSLASHING:
  1449. case OLANCE:
  1450. case OSLAYER:
  1451. case OSTUDLEATHER:
  1452. k += 15;
  1453. break;
  1454. case OLEATHER:
  1455. case OSPEAR:
  1456. k += 8;
  1457. break;
  1458. case OORBOFDRAGON:
  1459. case OORB:
  1460. case OBELT:
  1461. k += 4;
  1462. break;
  1463. case OSHIELD:
  1464. k += 7;
  1465. break;
  1466. case OCHEST:
  1467. k += 30 + ivenarg[i];
  1468. break;
  1469. default:
  1470. k++;
  1471. }
  1472. }
  1473. return k;
  1474. }
  1475. /* =============================================================================
  1476. * FUNCTION: adjust_ability
  1477. */
  1478. void adjust_ability(AttributeType ability, int amount)
  1479. {
  1480. /* check that it is an ability being adjusted */
  1481. if ((ability < ABILITY_FIRST) || (ability > ABILITY_LAST))
  1482. return;
  1483. c[ability] += amount;
  1484. if (c[ability] < 3)
  1485. c[ability] = 3;
  1486. }
  1487. /* =============================================================================
  1488. * FUNCTION: regen
  1489. */
  1490. void regen(void)
  1491. {
  1492. int i, j;
  1493. AttributeType Attr;
  1494. int flag; // indicates whether effect and/or status need update.
  1495. // 1 = Status, 2 = effects, 3 = both
  1496. /* Handle stop time spell */
  1497. if (c[TIMESTOP]) {
  1498. if (--c[TIMESTOP] <= 0) {
  1499. recalc();
  1500. UpdateStatusAndEffects();
  1501. }
  1502. return;
  1503. }
  1504. flag = 0;
  1505. if (c[HASTESELF] == 0)
  1506. gtime++;
  1507. else{
  1508. /*
  1509. * Player is moving at double speed, so time only passes every
  1510. * second move
  1511. */
  1512. HasteStep++;
  1513. if (HasteStep == 2) {
  1514. gtime++;
  1515. HasteStep = 0;
  1516. }
  1517. }
  1518. /* regenerate hit points */
  1519. if (c[HP] != c[HPMAX]) {
  1520. c[REGENCOUNTER]--;
  1521. if (c[REGENCOUNTER] < 0) {
  1522. c[REGENCOUNTER] = 22 + (c[HARDGAME] << 1) - c[LEVEL];
  1523. if ((c[HP] += c[REGEN]) > c[HPMAX])
  1524. c[HP] = c[HPMAX];
  1525. flag |= 1;
  1526. }
  1527. }
  1528. /* regenerate spells */
  1529. if (c[SPELLS] < c[SPELLMAX]) {
  1530. c[ECOUNTER]--;
  1531. if (c[ECOUNTER] < 0) {
  1532. c[ECOUNTER] = 100 + 4 * (c[HARDGAME] - c[LEVEL] - c[ENERGY]);
  1533. c[SPELLS]++;
  1534. flag |= 1;
  1535. }
  1536. }
  1537. for (j = 0; j < TIME_CHANGED_COUNT; j++) {
  1538. Attr = time_change[j];
  1539. if (c[Attr] != 0) {
  1540. /* Reduce time remaining for this effect */
  1541. c[Attr]--;
  1542. /* AWARENESS doesn't wear off if the player has the orb */
  1543. if (Attr == AWARENESS)
  1544. if (c[ORB] != 0) c[AWARENESS]++;
  1545. if (c[Attr] == 0) {
  1546. /* Effect has worn off, so perform appropriate action */
  1547. switch (Attr) {
  1548. case HERO:
  1549. for (i = ABILITY_FIRST; i <= ABILITY_LAST; i++)
  1550. adjust_ability(i, -(PHEROISM_BOOST - 1));
  1551. flag |= 1;
  1552. break;
  1553. case COKED:
  1554. for (i = ABILITY_FIRST; i <= ABILITY_LAST; i++)
  1555. adjust_ability(i, -34);
  1556. flag |= 1;
  1557. break;
  1558. case ALTPRO:
  1559. c[MOREDEFENSES] -= ALTAR_PRO_BOOST;
  1560. flag |= 3;
  1561. break;
  1562. case PROTECTIONTIME:
  1563. c[MOREDEFENSES] -= SPELL_PRO_BOOST;
  1564. flag |= 3;
  1565. break;
  1566. case DEXCOUNT:
  1567. adjust_ability(DEXTERITY, SDEXTERITY_BOOST);
  1568. flag |= 3;
  1569. break;
  1570. case STRCOUNT:
  1571. c[STREXTRA] -= SSTRENGTH_BOOST;
  1572. flag |= 3;
  1573. break;
  1574. case BLINDCOUNT:
  1575. Print("\nThe blindness lifts.");
  1576. UlarnBeep();
  1577. break;
  1578. case CONFUSE:
  1579. Print("\nYou regain your senses.");
  1580. UlarnBeep();
  1581. break;
  1582. case GIANTSTR:
  1583. /*
  1584. * Giant strength wears off, but the playre gets a permanent +1
  1585. * boost to extra strength.
  1586. * (unaffected by effects that lower strength).
  1587. */
  1588. c[STREXTRA] -= (PGIANTSTR_BOOST - 1);
  1589. flag |= 3;
  1590. break;
  1591. case GLOBE:
  1592. c[MOREDEFENSES] -= SPELL_GLOBE_BOOST;
  1593. flag |= 1;
  1594. break;
  1595. case HALFDAM:
  1596. Print("\nYou now feel better.");
  1597. UlarnBeep();
  1598. break;
  1599. case SEEINVISIBLE:
  1600. if (player_has_item(OAMULET))
  1601. /*
  1602. * See inv doesn't wear off if player has amulet of invisibility
  1603. */
  1604. c[SEEINVISIBLE]++;
  1605. break;
  1606. case ITCHING:
  1607. Print("\nThe irritation subsides.");
  1608. UlarnBeep();
  1609. break;
  1610. case CLUMSINESS:
  1611. Print("\nYou now feel less awkward.");
  1612. UlarnBeep();
  1613. break;
  1614. case CHARMCOUNT:
  1615. flag |= 3;
  1616. break;
  1617. case INVISIBILITY:
  1618. case CANCELLATION:
  1619. case WTW:
  1620. case HASTESELF:
  1621. case SCAREMONST:
  1622. case STEALTH:
  1623. case HOLDMONST:
  1624. case FIRERESISTANCE:
  1625. case SPIRITPRO:
  1626. case UNDEADPRO:
  1627. flag |= 2;
  1628. break;
  1629. case AGGRAVATE:
  1630. case HASTEMONST:
  1631. case AWARENESS:
  1632. break;
  1633. default:
  1634. break;
  1635. } /* switch */
  1636. } /* if now expired */
  1637. } /* if active */
  1638. } /* for each time based effect */
  1639. /*
  1640. * If the player is still itching then check to see if armour is to be
  1641. * removed
  1642. */
  1643. if (c[ITCHING]) {
  1644. if ((c[WEAR] != -1) || (c[SHIELD] != -1)) {
  1645. if (rnd(100) < 50) {
  1646. c[WEAR] = -1;
  1647. c[SHIELD] = -1;
  1648. Print("\nThe hysteria of itching forces you to remove your armor!");
  1649. UlarnBeep();
  1650. recalc();
  1651. flag |= 1;
  1652. }
  1653. }
  1654. }
  1655. /*
  1656. * If the player is still clumsy, check to see if the weapon is dropped
  1657. */
  1658. if (c[CLUMSINESS]) {
  1659. if (c[WIELD] != -1) {
  1660. /* if nothing there */
  1661. if (item[playerx][playery] == ONOTHING) {
  1662. /* drop your weapon 1/3 of the time */
  1663. if (rnd(100) < 33)
  1664. drop_object((int)c[WIELD]);
  1665. }
  1666. }
  1667. }
  1668. if (flag == 1)
  1669. UpdateStatus();
  1670. else if (flag == 2)
  1671. UpdateEffects();
  1672. else if (flag == 3)
  1673. UpdateStatusAndEffects();
  1674. }
  1675. /* =============================================================================
  1676. * FUNCTION: removecurse
  1677. */
  1678. void removecurse(void)
  1679. {
  1680. int i;
  1681. for (i = 0; i < CURSE_COUNT; i++) {
  1682. if (c[curse[i]])
  1683. /*
  1684. * Set the time remaining on each curse to 1 so that the next regen
  1685. * will clear the curse
  1686. */
  1687. c[curse[i]] = 1;
  1688. }
  1689. }
  1690. /* =============================================================================
  1691. * FUNCTION: adjusttime
  1692. */
  1693. void adjusttime(long tim)
  1694. {
  1695. int j;
  1696. /* adjust time related parameters */
  1697. for (j = 0; j < TIME_CHANGED_COUNT; j++) {
  1698. if (c[time_change[j]]) {
  1699. c[time_change[j]] -= tim;
  1700. if (c[time_change[j]] <= 0)
  1701. /*
  1702. * if effect would wear off then set the time remaining to 1 so that
  1703. * the next regen will cancel the effect
  1704. */
  1705. c[time_change[j]] = 1;
  1706. }
  1707. }
  1708. regen();
  1709. }
  1710. /* =============================================================================
  1711. * FUNCTION: write_player
  1712. */
  1713. void write_player(FILE *fp)
  1714. {
  1715. bwrite(fp, char_class, 20);
  1716. bwrite(fp, &ramboflag, 1);
  1717. bwrite(fp, &wizard, 1);
  1718. bwrite(fp, &cheat, 1);
  1719. bwrite(fp, (char *)&playerx, sizeof(int));
  1720. bwrite(fp, (char *)&playery, sizeof(int));
  1721. bwrite(fp, (char *)&initialtime, sizeof(long));
  1722. bwrite(fp, (char *)&gtime, sizeof(long));
  1723. bwrite(fp, (char *)&outstanding_taxes, sizeof(long));
  1724. bwrite(fp, (char *)c, ATTRIBUTE_COUNT * sizeof(long));
  1725. bwrite(fp, iven, IVENSIZE);
  1726. bwrite(fp, (char *)ivenarg, IVENSIZE * sizeof(short));
  1727. bwrite(fp, (char *)potionknown, MAXPOTION * sizeof(int));
  1728. bwrite(fp, (char *)scrollknown, MAXSCROLL * sizeof(int));
  1729. bwrite(fp, (char *)spelknow, SPELL_COUNT * sizeof(int));
  1730. }
  1731. /* =============================================================================
  1732. * FUNCTION: read_player
  1733. */
  1734. void read_player(FILE *fp)
  1735. {
  1736. bread(fp, char_class, 20);
  1737. bread(fp, &ramboflag, 1);
  1738. bread(fp, &wizard, 1);
  1739. bread(fp, &cheat, 1);
  1740. bread(fp, (char *)&playerx, sizeof(int));
  1741. bread(fp, (char *)&playery, sizeof(int));
  1742. bread(fp, (char *)&initialtime, sizeof(long));
  1743. bread(fp, (char *)&gtime, sizeof(long));
  1744. bread(fp, (char *)&outstanding_taxes, sizeof(long));
  1745. bread(fp, (char *)c, ATTRIBUTE_COUNT * sizeof(long));
  1746. bread(fp, iven, IVENSIZE);
  1747. bread(fp, (char *)ivenarg, IVENSIZE * sizeof(short));
  1748. bread(fp, (char *)potionknown, MAXPOTION * sizeof(int));
  1749. bread(fp, (char *)scrollknown, MAXSCROLL * sizeof(int));
  1750. bread(fp, (char *)spelknow, SPELL_COUNT * sizeof(int));
  1751. /*
  1752. * Identify the class number from the class string.
  1753. * identify_class returns the character selection for the class, or 0
  1754. * if the string matches no valid class.
  1755. */
  1756. class_num = identify_class(char_class);
  1757. if (class_num != 0)
  1758. class_num -= 'a';
  1759. else
  1760. /* class got corrupt somehow, so reset to the first class */
  1761. strcpy(char_class, InitialClassData[0].ClassName);
  1762. }