1 /* NetHack 3.6 exper.c $NHDT-Date: 1446975467 2015/11/08 09:37:47 $ $NHDT-Branch: master $:$NHDT-Revision: 1.26 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* JNetHack Copyright */
6 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
8 /* JNetHack may be freely redistributed. See license for details. */
13 STATIC_DCL long FDECL(newuexp, (int));
14 STATIC_DCL int FDECL(enermod, (int));
21 return (10L * (1L << lev));
23 return (10000L * (1L << (lev - 10)));
24 return (10000000L * ((long) (lev - 19)));
31 switch (Role_switch) {
37 return ((3 * en) / 2);
40 return ((3 * en) / 4);
46 /* calculate spell power/energy points for new level */
50 int en = 0, enrnd, enfix;
53 en = urole.enadv.infix + urace.enadv.infix;
54 if (urole.enadv.inrnd > 0)
55 en += rnd(urole.enadv.inrnd);
56 if (urace.enadv.inrnd > 0)
57 en += rnd(urace.enadv.inrnd);
59 enrnd = (int) ACURR(A_WIS) / 2;
60 if (u.ulevel < urole.xlev) {
61 enrnd += urole.enadv.lornd + urace.enadv.lornd;
62 enfix = urole.enadv.lofix + urace.enadv.lofix;
64 enrnd += urole.enadv.hirnd + urace.enadv.hirnd;
65 enfix = urole.enadv.hifix + urace.enadv.hifix;
67 en = enermod(rn1(enrnd, enfix));
71 if (u.ulevel < MAXULEV)
72 u.ueninc[u.ulevel] = (xchar) en;
76 /* return # of exp points for mtmp after nk killed */
79 register struct monst *mtmp;
82 register struct permonst *ptr = mtmp->data;
85 tmp = 1 + mtmp->m_lev * mtmp->m_lev;
87 /* For higher ac values, give extra experience */
88 if ((i = find_mac(mtmp)) < 3)
89 tmp += (7 - i) * ((i < 0) ? 2 : 1);
91 /* For very fast monsters, give extra experience */
92 if (ptr->mmove > NORMAL_SPEED)
93 tmp += (ptr->mmove > (3 * NORMAL_SPEED / 2)) ? 5 : 3;
95 /* For each "special" attack type give extra experience */
96 for (i = 0; i < NATTK; i++) {
97 tmp2 = ptr->mattk[i].aatyp;
101 else if (tmp2 == AT_MAGC)
108 /* For each "special" damage type give extra experience */
109 for (i = 0; i < NATTK; i++) {
110 tmp2 = ptr->mattk[i].adtyp;
111 if (tmp2 > AD_PHYS && tmp2 < AD_BLND)
112 tmp += 2 * mtmp->m_lev;
113 else if ((tmp2 == AD_DRLI) || (tmp2 == AD_STON) || (tmp2 == AD_SLIM))
115 else if (tmp2 != AD_PHYS)
117 /* extra heavy damage bonus */
118 if ((int) (ptr->mattk[i].damd * ptr->mattk[i].damn) > 23)
120 if (tmp2 == AD_WRAP && ptr->mlet == S_EEL && !Amphibious)
124 /* For certain "extra nasty" monsters, give even more */
125 if (extra_nasty(ptr))
126 tmp += (7 * mtmp->m_lev);
128 /* For higher level monsters, an additional bonus is given */
133 /* Mail daemons put up no fight. */
134 if (mtmp->data == &mons[PM_MAIL_DAEMON])
138 if (mtmp->mrevived || mtmp->mcloned) {
140 * Reduce experience awarded for repeated killings of
141 * "the same monster". Kill count includes all of this
142 * monster's type which have been killed--including the
143 * current monster--regardless of how they were created.
144 * 1.. 20 full experience
152 for (i = 0, tmp2 = 20; nk > tmp2 && tmp > 1; ++i) {
164 more_experienced(exper, rexp)
165 register int exper, rexp;
167 long newexp = u.uexp + exper;
168 long rexpincr = 4 * exper + rexp;
169 long newrexp = u.urexp + rexpincr;
171 /* cap experience and score on wraparound */
172 if (newexp < 0 && exper > 0)
174 if (newrexp < 0 && rexpincr > 0)
185 if (u.urexp >= (Role_if(PM_WIZARD) ? 1000 : 2000))
189 /* e.g., hit by drain life attack */
192 const char *drainer; /* cause of death, if drain should be fatal */
196 /* override life-drain resistance when handling an explicit
197 wizard mode request to reduce level; never fatal though */
198 if (drainer && !strcmp(drainer, "#levelchange"))
200 else if (resists_drli(&youmonst))
205 pline("%s level %d.", Goodbye(), u.ulevel--);
207 pline("
\82³
\82æ
\82¤
\82È
\82ç
\83\8c\83x
\83\8b%d
\81D", u.ulevel--);
208 /* remove intrinsic abilities */
209 adjabil(u.ulevel + 1, u.ulevel);
210 reset_rndmonst(NON_PM); /* new monster selection */
213 killer.format = KILLED_BY;
214 if (killer.name != drainer)
215 Strcpy(killer.name, drainer);
218 /* no drainer or lifesaved */
221 num = (int) u.uhpinc[u.ulevel];
228 else if (u.uhp > u.uhpmax)
231 num = (int) u.ueninc[u.ulevel];
238 else if (u.uen > u.uenmax)
242 u.uexp = newuexp(u.ulevel) - 1;
245 num = monhp_per_lvl(&youmonst);
256 * Make experience gaining similar to AD&D(tm), whereby you can at most go
257 * up by one level at a time, extra expr possibly helping you along.
258 * After all, how much real experience does one get shooting a wand of death
259 * at a dragon created with a wand of polymorph??
264 if (u.ulevel < MAXULEV && u.uexp >= newuexp(u.ulevel))
270 boolean incr; /* true iff via incremental experience growth */
271 { /* (false for potion of gain level) */
276 You_feel("more experienced.");
278 You("
\82æ
\82è
\8co
\8c±
\82ð
\82Â
\82ñ
\82¾
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D");
280 /* increase hit points (when polymorphed, do monster form first
281 in order to retain normal human/whatever increase for later) */
283 hpinc = monhp_per_lvl(&youmonst);
291 /* increase spell power/energy points */
296 /* increase level (unless already maxxed) */
297 if (u.ulevel < MAXULEV) {
298 /* increase experience points to reflect new level */
300 long tmp = newuexp(u.ulevel + 1);
304 u.uexp = newuexp(u.ulevel);
307 if (u.ulevelmax < u.ulevel)
308 u.ulevelmax = u.ulevel;
310 pline("Welcome to experience level %d.", u.ulevel);
312 pline("
\83\8c\83x
\83\8b%d
\82É
\82æ
\82¤
\82±
\82»
\81D", u.ulevel);
313 adjabil(u.ulevel - 1, u.ulevel); /* give new intrinsics */
314 reset_rndmonst(NON_PM); /* new monster selection */
319 /* compute a random amount of experience points suitable for the hero's
320 experience level: base number of points needed to reach the current
321 level plus a random portion of what it takes to get to the next level */
324 boolean gaining; /* gaining XP via potion vs setting XP for polyself */
326 long minexp, maxexp, diff, factor, result;
328 minexp = (u.ulevel == 1) ? 0L : newuexp(u.ulevel - 1);
329 maxexp = newuexp(u.ulevel);
330 diff = maxexp - minexp, factor = 1L;
331 /* make sure that `diff' is an argument which rn2() can handle */
332 while (diff >= (long) LARGEST_INT)
333 diff /= 2L, factor *= 2L;
334 result = minexp + factor * (long) rn2((int) diff);
335 /* 3.4.1: if already at level 30, add to current experience
336 points rather than to threshold needed to reach the current
337 level; otherwise blessed potions of gain level can result
338 in lowering the experience points instead of raising them */
339 if (u.ulevel == MAXULEV && gaining) {
340 result += (u.uexp - minexp);
341 /* avoid wrapping (over 400 blessed potions needed for that...) */