Source:SLASH'EM 0.0.7E7F2/exper.c

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.

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*/