Source:Exper.c

Below is the full text to src/exper.c from NetHack 3.4.3. To link to a particular line, write [[exper.c#line123 ]], for example. 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.   	if (lev < 10) return (10L * (1L << lev)); 15.  	if (lev < 20) return (10000L * (1L << (lev - 10))); 16.  	return (10000000L * ((long)(lev - 19))); 17.  }  18.    19.   STATIC_OVL int 20.  enermod(en) 21.  int en; 22.  {  23.   	switch (Role_switch) { 24.  	case PM_PRIEST: 25.  	case PM_WIZARD: 26.  	    return(2 * en); 27.  	case PM_HEALER: 28.  	case PM_KNIGHT: 29.  	    return((3 * en) / 2); 30.  	case PM_BARBARIAN: 31.  	case PM_VALKYRIE: 32.  	    return((3 * en) / 4); 33.  	default: 34.  	    return (en); 35.  	}  36.   }  37.    38.   int 39.  experience(mtmp, nk)	/* return # of exp points for mtmp after nk killed */ 40.  	register struct	monst *mtmp; 41.  	register int	nk; 42.  #if defined(macintosh) && (defined(__SC__) || defined(__MRC__)) 43.  # pragma unused(nk) 44.  #endif 45.  {  46.   	register struct permonst *ptr = mtmp->data; 47.  	int	i, tmp, tmp2; 48.   49.   	tmp = 1 + mtmp->m_lev * mtmp->m_lev; 50.   51.   /*	For higher ac values, give extra experience */ 52.  	if ((i = find_mac(mtmp)) < 3) tmp += (7 - i) * ((i < 0) ? 2 : 1); 53.   54.   /*	For very fast monsters, give extra experience */ 55.  	if (ptr->mmove > NORMAL_SPEED) 56.  	    tmp += (ptr->mmove > (3*NORMAL_SPEED/2)) ? 5 : 3; 57.    58.   /*	For each "special" attack type give extra experience */ 59.  	for(i = 0; i < NATTK; i++) { 60.   61.   	    tmp2 = ptr->mattk[i].aatyp; 62.  	    if(tmp2 > AT_BUTT) { 63.   64.   		if(tmp2 == AT_WEAP) tmp += 5; 65.  		else if(tmp2 == AT_MAGC) tmp += 10; 66.  		else tmp += 3; 67.  	    }  68.   	}  69.    70.   /*	For each "special" damage type give extra experience */ 71.  	for(i = 0; i < NATTK; i++) { 72.  	    tmp2 = ptr->mattk[i].adtyp; 73.  	    if(tmp2 > AD_PHYS && tmp2 < AD_BLND) tmp += 2*mtmp->m_lev; 74.  	    else if((tmp2 == AD_DRLI) || (tmp2 == AD_STON) ||  75.   	    		(tmp2 == AD_SLIM)) tmp += 50; 76.  	    else if(tmp != AD_PHYS) tmp += mtmp->m_lev; 77.  		/* extra heavy damage bonus */ 78.  	    if((int)(ptr->mattk[i].damd * ptr->mattk[i].damn) > 23) 79.  		tmp += mtmp->m_lev; 80.  	    if (tmp2 == AD_WRAP && ptr->mlet == S_EEL && !Amphibious) 81.  		tmp += 1000; 82.  	}  83.    84.   /*	For certain "extra nasty" monsters, give even more */ 85.  	if (extra_nasty(ptr)) tmp += (7 * mtmp->m_lev); 86.   87.   /*	For higher level monsters, an additional bonus is given */ 88.  	if(mtmp->m_lev > 8) tmp += 50; 89.   90.   #ifdef MAIL 91.  	/* Mail daemons put up no fight. */ 92.   	if(mtmp->data == &mons[PM_MAIL_DAEMON]) tmp = 1; 93.  #endif 94.   95.   	return(tmp); 96.  }  97.    98.   void 99.  more_experienced(exp, rexp) 100. 	register int exp, rexp; 101. {  102.  	u.uexp += exp; 103. 	u.urexp += 4*exp + rexp; 104. 	if(exp  105.  #ifdef SCORE_ON_BOTL  106.  	   || flags.showscore  107.  #endif  108.  	   ) flags.botl = 1; 109. 	if (u.urexp >= (Role_if(PM_WIZARD) ? 1000 : 2000)) 110.  		flags.beginner = 0; 111. }  112.   113.  void 114. losexp(drainer)		/* e.g., hit by drain life attack */ 115. const char *drainer;	/* cause of death, if drain should be fatal */ 116. {  117.  	register int num; 118.  119.  #ifdef WIZARD 120. 	/* override life-drain resistance when handling an explicit 121. 	   wizard mode request to reduce level; never fatal though */ 122. 	if (drainer && !strcmp(drainer, "#levelchange")) 123. 	    drainer = 0; 124. 	else 125. #endif 126. 	    if (resists_drli(&youmonst)) return; 127.  128.  	if (u.ulevel > 1) { 129. 		pline("%s level %d.", Goodbye, u.ulevel--); 130. 		/* remove intrinsic abilities */ 131. 		adjabil(u.ulevel + 1, u.ulevel); 132. 		reset_rndmonst(NON_PM);	/* new monster selection */ 133. 	} else { 134. 		if (drainer) { 135. 			killer_format = KILLED_BY; 136. 			killer = drainer; 137. 			done(DIED); 138. 		}  139.  		/* no drainer or lifesaved */ 140. 		u.uexp = 0; 141. 	}  142.  	num = newhp; 143. 	u.uhpmax -= num; 144. 	if (u.uhpmax < 1) u.uhpmax = 1; 145. 	u.uhp -= num; 146. 	if (u.uhp < 1) u.uhp = 1; 147. 	else if (u.uhp > u.uhpmax) u.uhp = u.uhpmax; 148.  149.  	if (u.ulevel < urole.xlev) 150. 	    num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.lornd + urace.enadv.lornd,  151.  			urole.enadv.lofix + urace.enadv.lofix); 152. 	else 153. 	    num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.hirnd + urace.enadv.hirnd,  154.  			urole.enadv.hifix + urace.enadv.hifix); 155. 	num = enermod(num);		/* M. Stephenson */ 156. 	u.uenmax -= num; 157. 	if (u.uenmax < 0) u.uenmax = 0; 158. 	u.uen -= num; 159. 	if (u.uen < 0) u.uen = 0; 160. 	else if (u.uen > u.uenmax) u.uen = u.uenmax; 161.  162.  	if (u.uexp > 0) 163. 		u.uexp = newuexp(u.ulevel) - 1; 164. 	flags.botl = 1; 165. }  166.   167.  /*  168.   * Make experience gaining similar to AD&D(tm), whereby you can at most go  169. * up by one level at a time, extra expr possibly helping you along. 170.  * After all, how much real experience does one get shooting a wand of death 171.  * at a dragon created with a wand of polymorph?? 172.  */  173.  void 174. newexplevel 175. {  176.  	if (u.ulevel < MAXULEV && u.uexp >= newuexp(u.ulevel)) 177. 	    pluslvl(TRUE); 178. }  179.   180.  void 181. pluslvl(incr) 182. boolean incr;	/* true iff via incremental experience growth */ 183. {		/*	(false for potion of gain level)      */ 184. 	register int num; 185.  186.  	if (!incr) You_feel("more experienced."); 187. 	num = newhp; 188. 	u.uhpmax += num; 189. 	u.uhp += num; 190. 	if (Upolyd) { 191. 	    num = rnd(8); 192. 	    u.mhmax += num; 193. 	    u.mh += num; 194. 	}  195.  	if (u.ulevel < urole.xlev) 196. 	    num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.lornd + urace.enadv.lornd,  197.  			urole.enadv.lofix + urace.enadv.lofix); 198. 	else 199. 	    num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.hirnd + urace.enadv.hirnd,  200.  			urole.enadv.hifix + urace.enadv.hifix); 201. 	num = enermod(num);	/* M. Stephenson */ 202. 	u.uenmax += num; 203. 	u.uen += num; 204. 	if (u.ulevel < MAXULEV) { 205. 	    if (incr) { 206. 		long tmp = newuexp(u.ulevel + 1); 207. 		if (u.uexp >= tmp) u.uexp = tmp - 1; 208. 	    } else { 209. 		u.uexp = newuexp(u.ulevel); 210. 	    }  211.  	    ++u.ulevel; 212. 	    if (u.ulevelmax < u.ulevel) u.ulevelmax = u.ulevel; 213. 	    pline("Welcome to experience level %d.", u.ulevel); 214. 	    adjabil(u.ulevel - 1, u.ulevel);	/* give new intrinsics */ 215. 	    reset_rndmonst(NON_PM);		/* new monster selection */ 216. 	}  217.  	flags.botl = 1; 218. }  219.   220.  /* compute a random amount of experience points suitable for the hero's  221. experience level: base number of points needed to reach the current 222.    level plus a random portion of what it takes to get to the next level */ 223. long 224. rndexp(gaining) 225. boolean gaining;	/* gaining XP via potion vs setting XP for polyself */ 226. {  227.  	long minexp, maxexp, diff, factor, result; 228.  229.  	minexp = (u.ulevel == 1) ? 0L : newuexp(u.ulevel - 1); 230. 	maxexp = newuexp(u.ulevel); 231. 	diff = maxexp - minexp,  factor = 1L; 232. 	/* make sure that `diff' is an argument which rn2 can handle */ 233. 	while (diff >= (long)LARGEST_INT) 234. 	    diff /= 2L,  factor *= 2L; 235. 	result = minexp + factor * (long)rn2((int)diff); 236. 	/* 3.4.1:  if already at level 30, add to current experience 237. 	   points rather than to threshold needed to reach the current 238. 	   level; otherwise blessed potions of gain level can result 239. 	   in lowering the experience points instead of raising them */ 240. 	if (u.ulevel == MAXULEV && gaining) { 241. 	    result += (u.uexp - minexp); 242. 	    /* avoid wrapping (over 400 blessed potions needed for that...) */ 243. 	    if (result < u.uexp) result = u.uexp; 244. 	}  245.  	return result; 246. }  247.   248.  /*exper.c*/