Source:SLASH'EM 0.0.7E7F2/exper.c

From NetHackWiki
Jump to navigation Jump to search

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.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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