diff --git a/src/exper.c b/src/exper.c new file mode 100644 index 000000000..de6e81c01 --- /dev/null +++ b/src/exper.c @@ -0,0 +1,220 @@ +/* SCCS Id: @(#)exper.c 3.3 2000/07/23 */ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "hack.h" + +STATIC_DCL long FDECL(newuexp, (int)); +STATIC_DCL int FDECL(enermod, (int)); + +STATIC_OVL long +newuexp(lev) +int lev; +{ + if (lev < 10) return (10L * (1L << lev)); + if (lev < 20) return (10000L * (1L << (lev - 10))); + return (10000000L * ((long)(lev - 19))); +} + +STATIC_OVL int +enermod(en) +int en; +{ + switch (Role_switch) { + case PM_PRIEST: + case PM_WIZARD: + return(2 * en); + case PM_HEALER: + case PM_KNIGHT: + return((3 * en) / 2); + case PM_BARBARIAN: + case PM_VALKYRIE: + return((3 * en) / 4); + default: + return (en); + } +} + +int +experience(mtmp, nk) /* return # of exp points for mtmp after nk killed */ + register struct monst *mtmp; + register int nk; +#if defined(applec) +# pragma unused(nk) +#endif +{ + register struct permonst *ptr = mtmp->data; + int i, tmp, tmp2; + + tmp = 1 + mtmp->m_lev * mtmp->m_lev; + +/* For higher ac values, give extra experience */ + if((i = find_mac(mtmp)) < 3) tmp += (7 - i) * (i < 0) ? 2 : 1; + +/* For very fast monsters, give extra experience */ + if(ptr->mmove >= 12) tmp += (ptr->mmove >= 18) ? 5 : 3; + +/* For each "special" attack type give extra experience */ + for(i = 0; i < NATTK; i++) { + + tmp2 = ptr->mattk[i].aatyp; + if(tmp2 > AT_BUTT) { + + if(tmp2 == AT_WEAP) tmp += 5; + else if(tmp2 == AT_MAGC) tmp += 10; + else tmp += 3; + } + } + +/* For each "special" damage type give extra experience */ + for(i = 0; i < NATTK; i++) { + tmp2 = ptr->mattk[i].adtyp; + if(tmp2 > AD_PHYS && tmp2 < AD_BLND) tmp += 2*mtmp->m_lev; + else if((tmp2 == AD_DRLI) || (tmp2 == AD_STON) || + (tmp2 == AD_SLIM)) tmp += 50; + else if(tmp != AD_PHYS) tmp += mtmp->m_lev; + /* extra heavy damage bonus */ + if((int)(ptr->mattk[i].damd * ptr->mattk[i].damn) > 23) + tmp += mtmp->m_lev; + if (tmp2 == AD_WRAP && ptr->mlet == S_EEL && !Amphibious) + tmp += 1000; + } + +/* For certain "extra nasty" monsters, give even more */ + if (extra_nasty(ptr)) tmp += (7 * mtmp->m_lev); + +/* For higher level monsters, an additional bonus is given */ + if(mtmp->m_lev > 8) tmp += 50; + +#ifdef MAIL + /* Mail daemons put up no fight. */ + if(mtmp->data == &mons[PM_MAIL_DAEMON]) tmp = 1; +#endif + + return(tmp); +} + +void +more_experienced(exp, rexp) + register int exp, rexp; +{ + u.uexp += exp; + u.urexp += 4*exp + rexp; + if(exp +#ifdef SCORE_ON_BOTL + || flags.showscore +#endif + ) flags.botl = 1; + if (u.urexp >= (Role_if(PM_WIZARD) ? 1000 : 2000)) + flags.beginner = 0; +} + +void +losexp(drainer) /* e.g., hit by drain life attack */ +const char *drainer; /* cause of death, if drain should be fatal */ +{ + register int num; + + if (resists_drli(&youmonst)) return; + + if (u.ulevel > 1) { + pline("%s level %d.", Goodbye(), u.ulevel--); + /* remove intrinsic abilities */ + adjabil(u.ulevel + 1, u.ulevel); + reset_rndmonst(NON_PM); /* new monster selection */ + } else { + if (drainer) { + killer_format = KILLED_BY; + killer = drainer; + done(DIED); + } + /* no drainer or lifesaved */ + u.uexp = 0; + } + num = newhp(); + u.uhpmax -= num; + if (u.uhpmax < 1) u.uhpmax = 1; + u.uhp -= num; + if (u.uhp < 1) u.uhp = 1; + else if (u.uhp > u.uhpmax) u.uhp = u.uhpmax; + + if (u.ulevel < urole.xlev) + num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.lornd + urace.enadv.lornd, + urole.enadv.lofix + urace.enadv.lofix); + else + num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.hirnd + urace.enadv.hirnd, + urole.enadv.hifix + urace.enadv.hifix); + num = enermod(num); /* M. Stephenson */ + u.uenmax -= num; + if (u.uenmax < 0) u.uenmax = 0; + u.uen -= num; + if (u.uen < 0) u.uen = 0; + else if (u.uen > u.uenmax) u.uen = u.uenmax; + + if (u.uexp > 0) + u.uexp = newuexp(u.ulevel) - 1; + flags.botl = 1; +} + +/* + * Make experience gaining similar to AD&D(tm), whereby you can at most go + * up by one level at a time, extra expr possibly helping you along. + * After all, how much real experience does one get shooting a wand of death + * at a dragon created with a wand of polymorph?? + */ +void +newexplevel() +{ + if (u.ulevel < MAXULEV && u.uexp >= newuexp(u.ulevel)) + pluslvl(TRUE); +} + +void +pluslvl(incr) +boolean incr; /* true iff via incremental experience growth */ +{ /* (false for potion of gain level) */ + register int num; + + if (!incr) You_feel("more experienced."); + num = newhp(); + u.uhpmax += num; + u.uhp += num; + if (u.ulevel < urole.xlev) + num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.lornd + urace.enadv.lornd, + urole.enadv.lofix + urace.enadv.lofix); + else + num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.hirnd + urace.enadv.hirnd, + urole.enadv.hifix + urace.enadv.hifix); + num = enermod(num); /* M. Stephenson */ + u.uenmax += num; + u.uen += num; + if (u.ulevel < MAXULEV) { + if (incr) { + long tmp = newuexp(u.ulevel + 1); + if (u.uexp >= tmp) u.uexp = tmp - 1; + } else { + u.uexp = newuexp(u.ulevel); + } + ++u.ulevel; + if (u.ulevelmax < u.ulevel) u.ulevelmax = u.ulevel; + pline("Welcome to experience level %d.", u.ulevel); + adjabil(u.ulevel - 1, u.ulevel); /* give new intrinsics */ + reset_rndmonst(NON_PM); /* new monster selection */ + } + flags.botl = 1; +} + +long +rndexp() +{ + long minexp, maxexp, diff, factor; + + minexp = (u.ulevel == 1) ? 0L : newuexp(u.ulevel - 1); + maxexp = newuexp(u.ulevel); + diff = maxexp - minexp, factor = 1L; + while (diff >= (long)LARGEST_INT) + diff /= 2L, factor *= 2L; + return minexp + factor * (long)rn2((int)diff); +} + +/*exper.c*/