Wikihack
Advertisement

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