1 /* NetHack 3.6 exper.c $NHDT-Date: 1562114352 2019/07/03 00:39:12 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.33 $ */
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-2020 */
9 /* JNetHack may be freely redistributed. See license for details. */
16 STATIC_DCL int FDECL(enermod, (int));
22 if (lev < 1) /* for newuexp(u.ulevel - 1) when u.ulevel is 1 */
25 return (10L * (1L << lev));
27 return (10000L * (1L << (lev - 10)));
28 return (10000000L * ((long) (lev - 19)));
35 switch (Role_switch) {
41 return ((3 * en) / 2);
44 return ((3 * en) / 4);
50 /* calculate spell power/energy points for new level */
54 int en = 0, enrnd, enfix;
57 en = urole.enadv.infix + urace.enadv.infix;
58 if (urole.enadv.inrnd > 0)
59 en += rnd(urole.enadv.inrnd);
60 if (urace.enadv.inrnd > 0)
61 en += rnd(urace.enadv.inrnd);
63 enrnd = (int) ACURR(A_WIS) / 2;
64 if (u.ulevel < urole.xlev) {
65 enrnd += urole.enadv.lornd + urace.enadv.lornd;
66 enfix = urole.enadv.lofix + urace.enadv.lofix;
68 enrnd += urole.enadv.hirnd + urace.enadv.hirnd;
69 enfix = urole.enadv.hifix + urace.enadv.hifix;
71 en = enermod(rn1(enrnd, enfix));
75 if (u.ulevel < MAXULEV)
76 u.ueninc[u.ulevel] = (xchar) en;
80 /* return # of exp points for mtmp after nk killed */
83 register struct monst *mtmp;
86 register struct permonst *ptr = mtmp->data;
89 tmp = 1 + mtmp->m_lev * mtmp->m_lev;
91 /* For higher ac values, give extra experience */
92 if ((i = find_mac(mtmp)) < 3)
93 tmp += (7 - i) * ((i < 0) ? 2 : 1);
95 /* For very fast monsters, give extra experience */
96 if (ptr->mmove > NORMAL_SPEED)
97 tmp += (ptr->mmove > (3 * NORMAL_SPEED / 2)) ? 5 : 3;
99 /* For each "special" attack type give extra experience */
100 for (i = 0; i < NATTK; i++) {
101 tmp2 = ptr->mattk[i].aatyp;
102 if (tmp2 > AT_BUTT) {
105 else if (tmp2 == AT_MAGC)
112 /* For each "special" damage type give extra experience */
113 for (i = 0; i < NATTK; i++) {
114 tmp2 = ptr->mattk[i].adtyp;
115 if (tmp2 > AD_PHYS && tmp2 < AD_BLND)
116 tmp += 2 * mtmp->m_lev;
117 else if ((tmp2 == AD_DRLI) || (tmp2 == AD_STON) || (tmp2 == AD_SLIM))
119 else if (tmp2 != AD_PHYS)
121 /* extra heavy damage bonus */
122 if ((int) (ptr->mattk[i].damd * ptr->mattk[i].damn) > 23)
124 if (tmp2 == AD_WRAP && ptr->mlet == S_EEL && !Amphibious)
128 /* For certain "extra nasty" monsters, give even more */
129 if (extra_nasty(ptr))
130 tmp += (7 * mtmp->m_lev);
132 /* For higher level monsters, an additional bonus is given */
137 /* Mail daemons put up no fight. */
138 if (mtmp->data == &mons[PM_MAIL_DAEMON])
142 if (mtmp->mrevived || mtmp->mcloned) {
144 * Reduce experience awarded for repeated killings of
145 * "the same monster". Kill count includes all of this
146 * monster's type which have been killed--including the
147 * current monster--regardless of how they were created.
148 * 1.. 20 full experience
156 for (i = 0, tmp2 = 20; nk > tmp2 && tmp > 1; ++i) {
168 more_experienced(exper, rexp)
169 register int exper, rexp;
171 long oldexp = u.uexp,
173 newexp = oldexp + exper,
174 rexpincr = 4 * exper + rexp,
175 newrexp = oldrexp + rexpincr;
177 /* cap experience and score on wraparound */
178 if (newexp < 0 && exper > 0)
180 if (newrexp < 0 && rexpincr > 0)
183 if (newexp != oldexp) {
187 /* even when experience points aren't being shown, experience level
188 might be highlighted with a percentage highlight rule and that
189 percentage depends upon experience points */
190 if (!context.botl && exp_percent_changing())
193 /* newrexp will always differ from oldrexp unless they're LONG_MAX */
194 if (newrexp != oldrexp) {
201 if (u.urexp >= (Role_if(PM_WIZARD) ? 1000 : 2000))
205 /* e.g., hit by drain life attack */
208 const char *drainer; /* cause of death, if drain should be fatal */
212 /* override life-drain resistance when handling an explicit
213 wizard mode request to reduce level; never fatal though */
214 if (drainer && !strcmp(drainer, "#levelchange"))
216 else if (resists_drli(&youmonst))
221 pline("%s level %d.", Goodbye(), u.ulevel--);
223 pline("
\82³
\82æ
\82¤
\82È
\82ç
\83\8c\83x
\83\8b%d
\81D", u.ulevel--);
224 /* remove intrinsic abilities */
225 adjabil(u.ulevel + 1, u.ulevel);
226 reset_rndmonst(NON_PM); /* new monster selection */
229 killer.format = KILLED_BY;
230 if (killer.name != drainer)
231 Strcpy(killer.name, drainer);
234 /* no drainer or lifesaved */
237 num = (int) u.uhpinc[u.ulevel];
244 else if (u.uhp > u.uhpmax)
247 num = (int) u.ueninc[u.ulevel];
254 else if (u.uen > u.uenmax)
258 u.uexp = newuexp(u.ulevel) - 1;
261 num = monhp_per_lvl(&youmonst);
272 * Make experience gaining similar to AD&D(tm), whereby you can at most go
273 * up by one level at a time, extra expr possibly helping you along.
274 * After all, how much real experience does one get shooting a wand of death
275 * at a dragon created with a wand of polymorph??
280 if (u.ulevel < MAXULEV && u.uexp >= newuexp(u.ulevel))
286 boolean incr; /* true iff via incremental experience growth */
287 { /* (false for potion of gain level) */
292 You_feel("more experienced.");
294 You("
\82æ
\82è
\8co
\8c±
\82ð
\82Â
\82ñ
\82¾
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D");
296 /* increase hit points (when polymorphed, do monster form first
297 in order to retain normal human/whatever increase for later) */
299 hpinc = monhp_per_lvl(&youmonst);
307 /* increase spell power/energy points */
312 /* increase level (unless already maxxed) */
313 if (u.ulevel < MAXULEV) {
314 /* increase experience points to reflect new level */
316 long tmp = newuexp(u.ulevel + 1);
320 u.uexp = newuexp(u.ulevel);
324 pline("Welcome %sto experience level %d.",
325 (u.ulevelmax < u.ulevel) ? "" : "back ",
328 pline("%s
\83\8c\83x
\83\8b%d
\82É
\82æ
\82¤
\82±
\82»
\81D",
329 (u.ulevelmax < u.ulevel) ? "" : "
\8dÄ
\82Ñ",
332 if (u.ulevelmax < u.ulevel)
333 u.ulevelmax = u.ulevel;
334 adjabil(u.ulevel - 1, u.ulevel); /* give new intrinsics */
335 reset_rndmonst(NON_PM); /* new monster selection */
340 /* compute a random amount of experience points suitable for the hero's
341 experience level: base number of points needed to reach the current
342 level plus a random portion of what it takes to get to the next level */
345 boolean gaining; /* gaining XP via potion vs setting XP for polyself */
347 long minexp, maxexp, diff, factor, result;
349 minexp = (u.ulevel == 1) ? 0L : newuexp(u.ulevel - 1);
350 maxexp = newuexp(u.ulevel);
351 diff = maxexp - minexp, factor = 1L;
352 /* make sure that `diff' is an argument which rn2() can handle */
353 while (diff >= (long) LARGEST_INT)
354 diff /= 2L, factor *= 2L;
355 result = minexp + factor * (long) rn2((int) diff);
356 /* 3.4.1: if already at level 30, add to current experience
357 points rather than to threshold needed to reach the current
358 level; otherwise blessed potions of gain level can result
359 in lowering the experience points instead of raising them */
360 if (u.ulevel == MAXULEV && gaining) {
361 result += (u.uexp - minexp);
362 /* avoid wrapping (over 400 blessed potions needed for that...) */