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. */
7 STATIC_DCL long FDECL(newuexp, (int));
8 STATIC_DCL int FDECL(enermod, (int));
14 if (lev < 10) return (10L * (1L << lev));
15 if (lev < 20) return (10000L * (1L << (lev - 10)));
16 return (10000000L * ((long)(lev - 19)));
23 switch (Role_switch) {
39 experience(mtmp, nk) /* return # of exp points for mtmp after nk killed */
40 register struct monst *mtmp;
42 #if defined(macintosh) && (defined(__SC__) || defined(__MRC__))
46 register struct permonst *ptr = mtmp->data;
49 tmp = 1 + mtmp->m_lev * mtmp->m_lev;
51 /* For higher ac values, give extra experience */
52 if ((i = find_mac(mtmp)) < 3) tmp += (7 - i) * ((i < 0) ? 2 : 1);
54 /* For very fast monsters, give extra experience */
55 if (ptr->mmove > NORMAL_SPEED)
56 tmp += (ptr->mmove > (3*NORMAL_SPEED/2)) ? 5 : 3;
58 /* For each "special" attack type give extra experience */
59 for(i = 0; i < NATTK; i++) {
61 tmp2 = ptr->mattk[i].aatyp;
64 if(tmp2 == AT_WEAP) tmp += 5;
65 else if(tmp2 == AT_MAGC) tmp += 10;
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)
80 if (tmp2 == AD_WRAP && ptr->mlet == S_EEL && !Amphibious)
84 /* For certain "extra nasty" monsters, give even more */
85 if (extra_nasty(ptr)) tmp += (7 * mtmp->m_lev);
87 /* For higher level monsters, an additional bonus is given */
88 if(mtmp->m_lev > 8) tmp += 50;
91 /* Mail daemons put up no fight. */
92 if(mtmp->data == &mons[PM_MAIL_DAEMON]) tmp = 1;
99 more_experienced(exp, rexp)
100 register int exp, rexp;
103 u.urexp += 4*exp + rexp;
109 if (u.urexp >= (Role_if(PM_WIZARD) ? 1000 : 2000))
114 losexp(drainer) /* e.g., hit by drain life attack */
115 const char *drainer; /* cause of death, if drain should be fatal */
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"))
126 if (resists_drli(&youmonst)) return;
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 */
135 killer_format = KILLED_BY;
139 /* no drainer or lifesaved */
144 if (u.uhpmax < 1) u.uhpmax = 1;
146 if (u.uhp < 1) u.uhp = 1;
147 else if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
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);
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 */
157 if (u.uenmax < 0) u.uenmax = 0;
159 if (u.uen < 0) u.uen = 0;
160 else if (u.uen > u.uenmax) u.uen = u.uenmax;
163 u.uexp = newuexp(u.ulevel) - 1;
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??
176 if (u.ulevel < MAXULEV && u.uexp >= newuexp(u.ulevel))
182 boolean incr; /* true iff via incremental experience growth */
183 { /* (false for potion of gain level) */
186 if (!incr) You_feel("more experienced.");
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);
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 */
204 if (u.ulevel < MAXULEV) {
206 long tmp = newuexp(u.ulevel + 1);
207 if (u.uexp >= tmp) u.uexp = tmp - 1;
209 u.uexp = newuexp(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 */
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 */
225 boolean gaining; /* gaining XP via potion vs setting XP for polyself */
227 long minexp, maxexp, diff, factor, result;
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;