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. */
8 STATIC_DCL
long FDECL(newuexp
, (int));
9 STATIC_DCL
int FDECL(enermod
, (int));
16 return (10L * (1L << lev
));
18 return (10000L * (1L << (lev
- 10)));
19 return (10000000L * ((long) (lev
- 19)));
26 switch (Role_switch
) {
32 return ((3 * en
) / 2);
35 return ((3 * en
) / 4);
41 /* calculate spell power/energy points for new level */
45 int en
= 0, enrnd
, enfix
;
48 en
= urole
.enadv
.infix
+ urace
.enadv
.infix
;
49 if (urole
.enadv
.inrnd
> 0)
50 en
+= rnd(urole
.enadv
.inrnd
);
51 if (urace
.enadv
.inrnd
> 0)
52 en
+= rnd(urace
.enadv
.inrnd
);
54 enrnd
= (int) ACURR(A_WIS
) / 2;
55 if (u
.ulevel
< urole
.xlev
) {
56 enrnd
+= urole
.enadv
.lornd
+ urace
.enadv
.lornd
;
57 enfix
= urole
.enadv
.lofix
+ urace
.enadv
.lofix
;
59 enrnd
+= urole
.enadv
.hirnd
+ urace
.enadv
.hirnd
;
60 enfix
= urole
.enadv
.hifix
+ urace
.enadv
.hifix
;
62 en
= enermod(rn1(enrnd
, enfix
));
66 if (u
.ulevel
< MAXULEV
)
67 u
.ueninc
[u
.ulevel
] = (xchar
) en
;
71 /* return # of exp points for mtmp after nk killed */
74 register struct monst
*mtmp
;
77 register struct permonst
*ptr
= mtmp
->data
;
80 tmp
= 1 + mtmp
->m_lev
* mtmp
->m_lev
;
82 /* For higher ac values, give extra experience */
83 if ((i
= find_mac(mtmp
)) < 3)
84 tmp
+= (7 - i
) * ((i
< 0) ? 2 : 1);
86 /* For very fast monsters, give extra experience */
87 if (ptr
->mmove
> NORMAL_SPEED
)
88 tmp
+= (ptr
->mmove
> (3 * NORMAL_SPEED
/ 2)) ? 5 : 3;
90 /* For each "special" attack type give extra experience */
91 for (i
= 0; i
< NATTK
; i
++) {
92 tmp2
= ptr
->mattk
[i
].aatyp
;
96 else if (tmp2
== AT_MAGC
)
103 /* For each "special" damage type give extra experience */
104 for (i
= 0; i
< NATTK
; i
++) {
105 tmp2
= ptr
->mattk
[i
].adtyp
;
106 if (tmp2
> AD_PHYS
&& tmp2
< AD_BLND
)
107 tmp
+= 2 * mtmp
->m_lev
;
108 else if ((tmp2
== AD_DRLI
) || (tmp2
== AD_STON
) || (tmp2
== AD_SLIM
))
110 else if (tmp2
!= AD_PHYS
)
112 /* extra heavy damage bonus */
113 if ((int) (ptr
->mattk
[i
].damd
* ptr
->mattk
[i
].damn
) > 23)
115 if (tmp2
== AD_WRAP
&& ptr
->mlet
== S_EEL
&& !Amphibious
)
119 /* For certain "extra nasty" monsters, give even more */
120 if (extra_nasty(ptr
))
121 tmp
+= (7 * mtmp
->m_lev
);
123 /* For higher level monsters, an additional bonus is given */
128 /* Mail daemons put up no fight. */
129 if (mtmp
->data
== &mons
[PM_MAIL_DAEMON
])
133 if (mtmp
->mrevived
|| mtmp
->mcloned
) {
135 * Reduce experience awarded for repeated killings of
136 * "the same monster". Kill count includes all of this
137 * monster's type which have been killed--including the
138 * current monster--regardless of how they were created.
139 * 1.. 20 full experience
147 for (i
= 0, tmp2
= 20; nk
> tmp2
&& tmp
> 1; ++i
) {
159 more_experienced(exper
, rexp
)
160 register int exper
, rexp
;
162 long newexp
= u
.uexp
+ exper
;
163 long rexpincr
= 4 * exper
+ rexp
;
164 long newrexp
= u
.urexp
+ rexpincr
;
166 /* cap experience and score on wraparound */
167 if (newexp
< 0 && exper
> 0)
169 if (newrexp
< 0 && rexpincr
> 0)
180 if (u
.urexp
>= (Role_if(PM_WIZARD
) ? 1000 : 2000))
184 /* e.g., hit by drain life attack */
187 const char *drainer
; /* cause of death, if drain should be fatal */
191 /* override life-drain resistance when handling an explicit
192 wizard mode request to reduce level; never fatal though */
193 if (drainer
&& !strcmp(drainer
, "#levelchange"))
195 else if (resists_drli(&youmonst
))
199 pline("%s level %d.", Goodbye(), u
.ulevel
--);
200 /* remove intrinsic abilities */
201 adjabil(u
.ulevel
+ 1, u
.ulevel
);
202 reset_rndmonst(NON_PM
); /* new monster selection */
205 killer
.format
= KILLED_BY
;
206 if (killer
.name
!= drainer
)
207 Strcpy(killer
.name
, drainer
);
210 /* no drainer or lifesaved */
213 num
= (int) u
.uhpinc
[u
.ulevel
];
220 else if (u
.uhp
> u
.uhpmax
)
223 num
= (int) u
.ueninc
[u
.ulevel
];
230 else if (u
.uen
> u
.uenmax
)
234 u
.uexp
= newuexp(u
.ulevel
) - 1;
237 num
= monhp_per_lvl(&youmonst
);
248 * Make experience gaining similar to AD&D(tm), whereby you can at most go
249 * up by one level at a time, extra expr possibly helping you along.
250 * After all, how much real experience does one get shooting a wand of death
251 * at a dragon created with a wand of polymorph??
256 if (u
.ulevel
< MAXULEV
&& u
.uexp
>= newuexp(u
.ulevel
))
262 boolean incr
; /* true iff via incremental experience growth */
263 { /* (false for potion of gain level) */
267 You_feel("more experienced.");
269 /* increase hit points (when polymorphed, do monster form first
270 in order to retain normal human/whatever increase for later) */
272 hpinc
= monhp_per_lvl(&youmonst
);
280 /* increase spell power/energy points */
285 /* increase level (unless already maxxed) */
286 if (u
.ulevel
< MAXULEV
) {
287 /* increase experience points to reflect new level */
289 long tmp
= newuexp(u
.ulevel
+ 1);
293 u
.uexp
= newuexp(u
.ulevel
);
296 if (u
.ulevelmax
< u
.ulevel
)
297 u
.ulevelmax
= u
.ulevel
;
298 pline("Welcome to experience level %d.", u
.ulevel
);
299 adjabil(u
.ulevel
- 1, u
.ulevel
); /* give new intrinsics */
300 reset_rndmonst(NON_PM
); /* new monster selection */
305 /* compute a random amount of experience points suitable for the hero's
306 experience level: base number of points needed to reach the current
307 level plus a random portion of what it takes to get to the next level */
310 boolean gaining
; /* gaining XP via potion vs setting XP for polyself */
312 long minexp
, maxexp
, diff
, factor
, result
;
314 minexp
= (u
.ulevel
== 1) ? 0L : newuexp(u
.ulevel
- 1);
315 maxexp
= newuexp(u
.ulevel
);
316 diff
= maxexp
- minexp
, factor
= 1L;
317 /* make sure that `diff' is an argument which rn2() can handle */
318 while (diff
>= (long) LARGEST_INT
)
319 diff
/= 2L, factor
*= 2L;
320 result
= minexp
+ factor
* (long) rn2((int) diff
);
321 /* 3.4.1: if already at level 30, add to current experience
322 points rather than to threshold needed to reach the current
323 level; otherwise blessed potions of gain level can result
324 in lowering the experience points instead of raising them */
325 if (u
.ulevel
== MAXULEV
&& gaining
) {
326 result
+= (u
.uexp
- minexp
);
327 /* avoid wrapping (over 400 blessed potions needed for that...) */