Below is the full text to exper.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/exper.c#line123]], for example.
The latest source code for vanilla NetHack is at Source code.
The NetHack General Public License applies to screenshots, source code and other content from NetHack. |
1. /* SCCS Id: @(#)exper.c 3.4 2002/11/20 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. 7. /*STATIC_DCL*/ long FDECL(newuexp, (int)); 8. STATIC_DCL int FDECL(enermod, (int)); 9. 10. /*STATIC_OVL*/ long 11. newuexp(lev) 12. int lev; 13. { 14. /* KMH, balance patch -- changed again! */ 15. if (lev < 9) return (20L * (1L << lev)); 16. if (lev < 13) return (10000L * (1L << (lev - 9))); 17. if (lev == 13) return (150000L); 18. return (50000L * ((long)(lev - 9))); 19. /* Old XP routine */ 20. /* if (lev < 10) return (10L * (1L << lev)); */ 21. /* if (lev < 20) return (10000L * (1L << (lev - 10))); */ 22. /* return (10000000L * ((long)(lev - 19))); */ 23. /* if (lev == 1) return (75L); 24. if (lev == 2) return (150L); 25. if (lev == 3) return (300L); 26. if (lev == 4) return (600L); 27. if (lev == 5) return (1200L); */ 28. #if 0 29. if (lev == 1) return (50L); /* need 50 */ 30. if (lev == 2) return (100L); /* need 50 */ 31. if (lev == 3) return (200L); /* need 100 */ 32. if (lev == 4) return (500L); /* need 300 */ 33. if (lev == 5) return (1000L); /* need 500 */ 34. if (lev == 6) return (1750L); /* need 750 */ 35. if (lev == 7) return (2750L); /* need 1000 */ 36. if (lev == 8) return (4250L); /* need 1500 */ 37. if (lev == 9) return (6250L); /* need 2000 */ 38. if (lev == 10) return (8750L); /* need 2500 */ 39. if (lev == 11) return (11750L); /* need 3000 */ 40. if (lev == 12) return (15500L); /* need 3750 */ 41. if (lev == 13) return (20000L); /* need 4500 */ 42. if (lev == 14) return (25000L); /* need 5000 */ 43. if (lev == 15) return (31000L); /* need 6000 */ 44. if (lev == 16) return (38500L); /* need 7500 */ 45. if (lev == 17) return (48000L); /* need 9500 */ 46. if (lev == 18) return (60000L); /* need 12000 */ 47. if (lev == 19) return (76000L); /* need 16000 */ 48. if (lev == 20) return (97000L); /* need 21000 */ 49. if (lev == 21) return (125000L); /* need 28000 +7 */ 50. if (lev == 22) return (163000L); /* need 38000 +10 */ 51. if (lev == 23) return (213000L); /* need 50000 +12 */ 52. if (lev == 24) return (279000L); /* need 66000 +16 */ 53. if (lev == 25) return (365000L); /* need 86000 + 20 */ 54. if (lev == 26) return (476000L); /* need 111000 + 25 */ 55. if (lev == 27) return (617000L); /* need 141000+ 30 */ 56. if (lev == 28) return (798000L); /* need 181000 + 40 */ 57. if (lev == 29) return (1034000L); /* need 236000 + 55 */ 58. return (1750000L); 59. #endif 60. } 61. 62. STATIC_OVL int 63. enermod(en) 64. int en; 65. { 66. switch (Role_switch) { 67. /* WAC 'F' and 'I' get bonus similar to 'W' */ 68. case PM_FLAME_MAGE: 69. case PM_ICE_MAGE: 70. case PM_PRIEST: 71. case PM_WIZARD: 72. return(2 * en); 73. case PM_HEALER: 74. case PM_KNIGHT: 75. return((3 * en) / 2); 76. case PM_BARBARIAN: 77. case PM_VALKYRIE: 78. return((3 * en) / 4); 79. default: 80. return (en); 81. } 82. } 83. 84. int 85. experience(mtmp, nk) /* return # of exp points for mtmp after nk killed */ 86. register struct monst *mtmp; 87. register int nk; 88. #if defined(MAC_MPW) 89. # pragma unused(nk) 90. #endif 91. { 92. register struct permonst *ptr = mtmp->data; 93. int i, tmp, tmp2; 94. 95. tmp = 1 + mtmp->m_lev * mtmp->m_lev; 96. 97. /* For higher ac values, give extra experience */ 98. if ((i = find_mac(mtmp)) < 3) tmp += (7 - i) * ((i < 0) ? 2 : 1); 99. 100. /* For very fast monsters, give extra experience */ 101. if (ptr->mmove > NORMAL_SPEED) 102. tmp += (ptr->mmove > (3*NORMAL_SPEED/2)) ? 5 : 3; 103. 104. /* For each "special" attack type give extra experience */ 105. for(i = 0; i < NATTK; i++) { 106. tmp2 = ptr->mattk[i].aatyp; 107. if(tmp2 > AT_BUTT) { 108. 109. if(tmp2 == AT_WEAP) tmp += 5; 110. else if(tmp2 == AT_MAGC) tmp += 10; 111. else tmp += 3; 112. } 113. } 114. 115. /* For each "special" damage type give extra experience */ 116. for(i = 0; i < NATTK; i++) { 117. tmp2 = ptr->mattk[i].adtyp; 118. if(tmp2 > AD_PHYS && tmp2 < AD_BLND) tmp += 2*mtmp->m_lev; 119. else if((tmp2 == AD_DRLI) || (tmp2 == AD_STON) || 120. (tmp2 == AD_SLIM)) tmp += 50; 121. else if(tmp != AD_PHYS) tmp += mtmp->m_lev; 122. /* extra heavy damage bonus */ 123. if((int)(ptr->mattk[i].damd * ptr->mattk[i].damn) > 23) 124. tmp += mtmp->m_lev; 125. if (tmp2 == AD_WRAP && ptr->mlet == S_EEL && !Amphibious) 126. tmp += 1000; 127. } 128. 129. /* For certain "extra nasty" monsters, give even more */ 130. if (extra_nasty(ptr)) tmp += (7 * mtmp->m_lev); 131. 132. /* For higher level monsters, an additional bonus is given */ 133. if(mtmp->m_lev > 8) tmp += 50; 134. 135. #ifdef MAIL 136. /* Mail daemons put up no fight. */ 137. if(mtmp->data == &mons[PM_MAIL_DAEMON]) tmp = 1; 138. #endif 139. 140. return(tmp); 141. } 142. 143. void 144. more_experienced(exp, rexp) 145. register int exp, rexp; 146. { 147. u.uexp += exp; 148. u.urexp += 4*exp + rexp; 149. if(exp 150. #ifdef SCORE_ON_BOTL 151. || flags.showscore 152. #endif 153. ) flags.botl = 1; 154. if (u.urexp >= (Role_if(PM_WIZARD) ? 1000 : 2000)) 155. flags.beginner = 0; 156. } 157. 158. void 159. losexp(drainer,force) /* e.g., hit by drain life attack */ 160. const char *drainer; /* cause of death, if drain should be fatal */ 161. boolean force; /* Force the loss of an experience level */ 162. { 163. register int num; 164. 165. #ifdef WIZARD 166. /* explicit wizard mode requests to reduce level are never fatal. */ 167. if (drainer && !strcmp(drainer, "#levelchange")) 168. drainer = 0; 169. #endif 170. 171. if (!force && Drain_resistance) return; 172. 173. if (u.ulevel > 1) { 174. pline("%s level %d.", Goodbye(), u.ulevel--); 175. /* remove intrinsic abilities */ 176. adjabil(u.ulevel + 1, u.ulevel); 177. reset_rndmonst(NON_PM); /* new monster selection */ 178. } else { 179. if (drainer) { 180. killer_format = KILLED_BY; 181. killer = drainer; 182. done(DIED); 183. } 184. /* no drainer or lifesaved */ 185. u.uexp = 0; 186. } 187. num = newhp(); 188. u.uhpmax -= num; 189. if (u.uhpmax < 1) u.uhpmax = 1; 190. u.uhp -= num; 191. if (u.uhp < 1) u.uhp = 1; 192. else if (u.uhp > u.uhpmax) u.uhp = u.uhpmax; 193. 194. if (u.ulevel < urole.xlev) 195. num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.lornd + urace.enadv.lornd, 196. urole.enadv.lofix + urace.enadv.lofix); 197. else 198. num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.hirnd + urace.enadv.hirnd, 199. urole.enadv.hifix + urace.enadv.hifix); 200. num = enermod(num); /* M. Stephenson */ 201. u.uenmax -= num; 202. if (u.uenmax < 0) u.uenmax = 0; 203. u.uen -= num; 204. if (u.uen < 0) u.uen = 0; 205. else if (u.uen > u.uenmax) u.uen = u.uenmax; 206. 207. if (u.uexp > 0) 208. u.uexp = newuexp(u.ulevel) - 1; 209. flags.botl = 1; 210. } 211. 212. /* 213. * Make experience gaining similar to AD&D(tm), whereby you can at most go 214. * up by one level at a time, extra expr possibly helping you along. 215. * After all, how much real experience does one get shooting a wand of death 216. * at a dragon created with a wand of polymorph?? 217. */ 218. void 219. newexplevel() 220. { 221. if (u.ulevel < MAXULEV && u.uexp >= newuexp(u.ulevel)) 222. pluslvl(TRUE); 223. } 224. 225. #if 0 /* The old newexplevel() */ 226. { 227. register int tmp; 228. 229. if(u.ulevel < MAXULEV && u.uexp >= newuexp(u.ulevel)) { 230. 231. u.ulevel++; 232. if (u.ulevelmax < u.ulevel) u.ulevelmax = u.ulevel; /* KMH */ 233. if (u.uexp >= newuexp(u.ulevel)) u.uexp = newuexp(u.ulevel) - 1; 234. pline("Welcome to experience level %d.", u.ulevel); 235. /* give new intrinsics */ 236. adjabil(u.ulevel - 1, u.ulevel); 237. reset_rndmonst(NON_PM); /* new monster selection */ 238. /* STEPHEN WHITE'S NEW CODE */ 239. tmp = newhp(); 240. u.uhpmax += tmp; 241. u.uhp += tmp; 242. switch (Role_switch) { 243. case PM_ARCHEOLOGIST: u.uenbase += rnd(4) + 1; break; 244. case PM_BARBARIAN: u.uenbase += rnd(2); break; 245. case PM_CAVEMAN: u.uenbase += rnd(2); break; 246. case PM_DOPPELGANGER: u.uenbase += rnd(5) + 1; break; 247. case PM_ELF: case PM_DROW: u.uenbase += rnd(5) + 1; break; 248. case PM_FLAME_MAGE: u.uenbase += rnd(6) + 2; break; 249. case PM_GNOME: u.uenbase += rnd(3); break; 250. case PM_HEALER: u.uenbase += rnd(6) + 2; break; 251. case PM_ICE_MAGE: u.uenbase += rnd(6) + 2; break; 252. #ifdef YEOMAN 253. case PM_YEOMAN: 254. #endif 255. case PM_KNIGHT: u.uenbase += rnd(3); break; 256. case PM_HUMAN_WEREWOLF: u.uenbase += rnd(5) + 1; break; 257. case PM_MONK: u.uenbase += rnd(5) + 1; break; 258. case PM_NECROMANCER: u.uenbase += rnd(6) + 2; break; 259. case PM_PRIEST: u.uenbase += rnd(6) + 2; break; 260. case PM_ROGUE: u.uenbase += rnd(4) + 1; break; 261. case PM_SAMURAI: u.uenbase += rnd(2); break; 262. #ifdef TOURIST 263. case PM_TOURIST: u.uenbase += rnd(4) + 1; break; 264. #endif 265. case PM_UNDEAD_SLAYER: u.uenbase += rnd(3); break; 266. case PM_VALKYRIE: u.uenbase += rnd(2); break; 267. case PM_WIZARD: u.uenbase += rnd(6) + 2; break; 268. default: u.uenbase += rnd(2) + 1; break; 269. } 270. flags.botl = 1; 271. } 272. } 273. #endif /* old newexplevel() */ 274. 275. void 276. pluslvl(incr) 277. boolean incr; /* true iff via incremental experience growth */ 278. { /* (false for potion of gain level) */ 279. register int num; 280. 281. if (!incr) You_feel("more experienced."); 282. num = newhp(); 283. u.uhpmax += num; 284. u.uhp += num; 285. if (Upolyd) { 286. num = rnd(8); 287. u.mhmax += num; 288. u.mh += num; 289. } 290. if (u.ulevel < urole.xlev) 291. num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.lornd + urace.enadv.lornd, 292. urole.enadv.lofix + urace.enadv.lofix); 293. else 294. num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.hirnd + urace.enadv.hirnd, 295. urole.enadv.hifix + urace.enadv.hifix); 296. num = enermod(num); /* M. Stephenson */ 297. u.uenmax += num; 298. u.uen += num; 299. 300. if(u.ulevel < MAXULEV) { 301. if (incr) { 302. long tmp = newuexp(u.ulevel + 1); 303. if (u.uexp >= tmp) u.uexp = tmp - 1; 304. } else { 305. u.uexp = newuexp(u.ulevel); 306. } 307. ++u.ulevel; 308. if (u.ulevelmax < u.ulevel) u.ulevelmax = u.ulevel; 309. pline("Welcome to experience level %d.", u.ulevel); 310. adjabil(u.ulevel - 1, u.ulevel); /* give new intrinsics */ 311. reset_rndmonst(NON_PM); /* new monster selection */ 312. } 313. flags.botl = 1; 314. } 315. 316. /* compute a random amount of experience points suitable for the hero's 317. experience level: base number of points needed to reach the current 318. level plus a random portion of what it takes to get to the next level */ 319. long 320. rndexp(gaining) 321. boolean gaining; /* gaining XP via potion vs setting XP for polyself */ 322. { 323. long minexp, maxexp, diff, factor, result; 324. 325. minexp = (u.ulevel == 1) ? 0L : newuexp(u.ulevel - 1); 326. maxexp = newuexp(u.ulevel); 327. diff = maxexp - minexp, factor = 1L; 328. /* make sure that `diff' is an argument which rn2() can handle */ 329. while (diff >= (long)LARGEST_INT) 330. diff /= 2L, factor *= 2L; 331. result = minexp + factor * (long)rn2((int)diff); 332. /* 3.4.1: if already at level 30, add to current experience 333. points rather than to threshold needed to reach the current 334. level; otherwise blessed potions of gain level can result 335. in lowering the experience points instead of raising them */ 336. if (u.ulevel == MAXULEV && gaining) { 337. result += (u.uexp - minexp); 338. /* avoid wrapping (over 400 blessed potions needed for that...) */ 339. if (result < u.uexp) result = u.uexp; 340. } 341. return result; 342. } 343. 344. /*exper.c*/