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 /*-Copyright (c) Robert Patrick Rankin, 2007. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
9 /* JNetHack may be freely redistributed. See license for details. */
14 STATIC_DCL long FDECL(newuexp, (int));
15 STATIC_DCL int FDECL(enermod, (int));
22 return (10L * (1L << lev));
24 return (10000L * (1L << (lev - 10)));
25 return (10000000L * ((long) (lev - 19)));
32 switch (Role_switch) {
38 return ((3 * en) / 2);
41 return ((3 * en) / 4);
47 /* calculate spell power/energy points for new level */
51 int en = 0, enrnd, enfix;
54 en = urole.enadv.infix + urace.enadv.infix;
55 if (urole.enadv.inrnd > 0)
56 en += rnd(urole.enadv.inrnd);
57 if (urace.enadv.inrnd > 0)
58 en += rnd(urace.enadv.inrnd);
60 enrnd = (int) ACURR(A_WIS) / 2;
61 if (u.ulevel < urole.xlev) {
62 enrnd += urole.enadv.lornd + urace.enadv.lornd;
63 enfix = urole.enadv.lofix + urace.enadv.lofix;
65 enrnd += urole.enadv.hirnd + urace.enadv.hirnd;
66 enfix = urole.enadv.hifix + urace.enadv.hifix;
68 en = enermod(rn1(enrnd, enfix));
72 if (u.ulevel < MAXULEV)
73 u.ueninc[u.ulevel] = (xchar) en;
77 /* return # of exp points for mtmp after nk killed */
80 register struct monst *mtmp;
83 register struct permonst *ptr = mtmp->data;
86 tmp = 1 + mtmp->m_lev * mtmp->m_lev;
88 /* For higher ac values, give extra experience */
89 if ((i = find_mac(mtmp)) < 3)
90 tmp += (7 - i) * ((i < 0) ? 2 : 1);
92 /* For very fast monsters, give extra experience */
93 if (ptr->mmove > NORMAL_SPEED)
94 tmp += (ptr->mmove > (3 * NORMAL_SPEED / 2)) ? 5 : 3;
96 /* For each "special" attack type give extra experience */
97 for (i = 0; i < NATTK; i++) {
98 tmp2 = ptr->mattk[i].aatyp;
102 else if (tmp2 == AT_MAGC)
109 /* For each "special" damage type give extra experience */
110 for (i = 0; i < NATTK; i++) {
111 tmp2 = ptr->mattk[i].adtyp;
112 if (tmp2 > AD_PHYS && tmp2 < AD_BLND)
113 tmp += 2 * mtmp->m_lev;
114 else if ((tmp2 == AD_DRLI) || (tmp2 == AD_STON) || (tmp2 == AD_SLIM))
116 else if (tmp2 != AD_PHYS)
118 /* extra heavy damage bonus */
119 if ((int) (ptr->mattk[i].damd * ptr->mattk[i].damn) > 23)
121 if (tmp2 == AD_WRAP && ptr->mlet == S_EEL && !Amphibious)
125 /* For certain "extra nasty" monsters, give even more */
126 if (extra_nasty(ptr))
127 tmp += (7 * mtmp->m_lev);
129 /* For higher level monsters, an additional bonus is given */
134 /* Mail daemons put up no fight. */
135 if (mtmp->data == &mons[PM_MAIL_DAEMON])
139 if (mtmp->mrevived || mtmp->mcloned) {
141 * Reduce experience awarded for repeated killings of
142 * "the same monster". Kill count includes all of this
143 * monster's type which have been killed--including the
144 * current monster--regardless of how they were created.
145 * 1.. 20 full experience
153 for (i = 0, tmp2 = 20; nk > tmp2 && tmp > 1; ++i) {
165 more_experienced(exper, rexp)
166 register int exper, rexp;
168 long newexp = u.uexp + exper;
169 long rexpincr = 4 * exper + rexp;
170 long newrexp = u.urexp + rexpincr;
172 /* cap experience and score on wraparound */
173 if (newexp < 0 && exper > 0)
175 if (newrexp < 0 && rexpincr > 0)
186 if (u.urexp >= (Role_if(PM_WIZARD) ? 1000 : 2000))
190 /* e.g., hit by drain life attack */
193 const char *drainer; /* cause of death, if drain should be fatal */
197 /* override life-drain resistance when handling an explicit
198 wizard mode request to reduce level; never fatal though */
199 if (drainer && !strcmp(drainer, "#levelchange"))
201 else if (resists_drli(&youmonst))
206 pline("%s level %d.", Goodbye(), u.ulevel--);
208 pline("
\82³
\82æ
\82¤
\82È
\82ç
\83\8c\83x
\83\8b%d
\81D", u.ulevel--);
209 /* remove intrinsic abilities */
210 adjabil(u.ulevel + 1, u.ulevel);
211 reset_rndmonst(NON_PM); /* new monster selection */
214 killer.format = KILLED_BY;
215 if (killer.name != drainer)
216 Strcpy(killer.name, drainer);
219 /* no drainer or lifesaved */
222 num = (int) u.uhpinc[u.ulevel];
229 else if (u.uhp > u.uhpmax)
232 num = (int) u.ueninc[u.ulevel];
239 else if (u.uen > u.uenmax)
243 u.uexp = newuexp(u.ulevel) - 1;
246 num = monhp_per_lvl(&youmonst);
257 * Make experience gaining similar to AD&D(tm), whereby you can at most go
258 * up by one level at a time, extra expr possibly helping you along.
259 * After all, how much real experience does one get shooting a wand of death
260 * at a dragon created with a wand of polymorph??
265 if (u.ulevel < MAXULEV && u.uexp >= newuexp(u.ulevel))
271 boolean incr; /* true iff via incremental experience growth */
272 { /* (false for potion of gain level) */
277 You_feel("more experienced.");
279 You("
\82æ
\82è
\8co
\8c±
\82ð
\82Â
\82ñ
\82¾
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D");
281 /* increase hit points (when polymorphed, do monster form first
282 in order to retain normal human/whatever increase for later) */
284 hpinc = monhp_per_lvl(&youmonst);
292 /* increase spell power/energy points */
297 /* increase level (unless already maxxed) */
298 if (u.ulevel < MAXULEV) {
299 /* increase experience points to reflect new level */
301 long tmp = newuexp(u.ulevel + 1);
305 u.uexp = newuexp(u.ulevel);
309 pline("Welcome %sto experience level %d.",
310 u.ulevelmax < u.ulevel ? "" : "back ",
313 pline("%s
\83\8c\83x
\83\8b%d
\82É
\82æ
\82¤
\82±
\82»
\81D",
314 u.ulevelmax < u.ulevel ? "" : "
\8dÄ
\82Ñ",
317 if (u.ulevelmax < u.ulevel)
318 u.ulevelmax = u.ulevel;
319 adjabil(u.ulevel - 1, u.ulevel); /* give new intrinsics */
320 reset_rndmonst(NON_PM); /* new monster selection */
325 /* compute a random amount of experience points suitable for the hero's
326 experience level: base number of points needed to reach the current
327 level plus a random portion of what it takes to get to the next level */
330 boolean gaining; /* gaining XP via potion vs setting XP for polyself */
332 long minexp, maxexp, diff, factor, result;
334 minexp = (u.ulevel == 1) ? 0L : newuexp(u.ulevel - 1);
335 maxexp = newuexp(u.ulevel);
336 diff = maxexp - minexp, factor = 1L;
337 /* make sure that `diff' is an argument which rn2() can handle */
338 while (diff >= (long) LARGEST_INT)
339 diff /= 2L, factor *= 2L;
340 result = minexp + factor * (long) rn2((int) diff);
341 /* 3.4.1: if already at level 30, add to current experience
342 points rather than to threshold needed to reach the current
343 level; otherwise blessed potions of gain level can result
344 in lowering the experience points instead of raising them */
345 if (u.ulevel == MAXULEV && gaining) {
346 result += (u.uexp - minexp);
347 /* avoid wrapping (over 400 blessed potions needed for that...) */