1 | /* SCCS Id: @(#)exper.c 3.3 2000/07/23 */ 2 | /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3 | /* NetHack may be freely redistributed. See license for details. */ 4 | 5 | #include "hack.h" 6 | 7 | STATIC_DCL long FDECL(newuexp, (int)); 8 | STATIC_DCL int FDECL(enermod, (int)); 9 | 10 | STATIC_OVL long 11 | newuexp(lev) 12 | int lev; 13 | { 14 | if (lev < 10) return (10L * (1L << lev)); 15 | if (lev < 20) return (10000L * (1L << (lev - 10))); 16 | return (10000000L * ((long)(lev - 19))); 17 | } 18 | 19 | STATIC_OVL int 20 | enermod(en) 21 | int en; 22 | { 23 | switch (Role_switch) { 24 | case PM_PRIEST: 25 | case PM_WIZARD: 26 | return(2 * en); 27 | case PM_HEALER: 28 | case PM_KNIGHT: 29 | return((3 * en) / 2); 30 | case PM_BARBARIAN: 31 | case PM_VALKYRIE: 32 | return((3 * en) / 4); 33 | default: 34 | return (en); 35 | } 36 | } 37 | 38 | int 39 | experience(mtmp, nk) /* return # of exp points for mtmp after nk killed */ 40 | register struct monst *mtmp; 41 | register int nk; 42 | #if defined(applec) 43 | # pragma unused(nk) 44 | #endif 45 | { 46 | register struct permonst *ptr = mtmp->data; 47 | int i, tmp, tmp2; 48 | 49 | tmp = 1 + mtmp->m_lev * mtmp->m_lev; 50 | 51 | /* For higher ac values, give extra experience */ 52 | if((i = find_mac(mtmp)) < 3) tmp += (7 - i) * (i < 0) ? 2 : 1; 53 | 54 | /* For very fast monsters, give extra experience */ 55 | if(ptr->mmove >= 12) tmp += (ptr->mmove >= 18) ? 5 : 3; 56 | 57 | /* For each "special" attack type give extra experience */ 58 | for(i = 0; i < NATTK; i++) { 59 | 60 | tmp2 = ptr->mattk[i].aatyp; 61 | if(tmp2 > AT_BUTT) { 62 | 63 | if(tmp2 == AT_WEAP) tmp += 5; 64 | else if(tmp2 == AT_MAGC) tmp += 10; 65 | else tmp += 3; 66 | } 67 | } 68 | 69 | /* For each "special" damage type give extra experience */ 70 | for(i = 0; i < NATTK; i++) { 71 | tmp2 = ptr->mattk[i].adtyp; 72 | if(tmp2 > AD_PHYS && tmp2 < AD_BLND) tmp += 2*mtmp->m_lev; 73 | else if((tmp2 == AD_DRLI) || (tmp2 == AD_STON) || 74 | (tmp2 == AD_SLIM)) tmp += 50; 75 | else if(tmp != AD_PHYS) tmp += mtmp->m_lev; 76 | /* extra heavy damage bonus */ 77 | if((int)(ptr->mattk[i].damd * ptr->mattk[i].damn) > 23) 78 | tmp += mtmp->m_lev; 79 | if (tmp2 == AD_WRAP && ptr->mlet == S_EEL && !Amphibious) 80 | tmp += 1000; 81 | } 82 | 83 | /* For certain "extra nasty" monsters, give even more */ 84 | if (extra_nasty(ptr)) tmp += (7 * mtmp->m_lev); 85 | 86 | /* For higher level monsters, an additional bonus is given */ 87 | if(mtmp->m_lev > 8) tmp += 50; 88 | 89 | #ifdef MAIL 90 | /* Mail daemons put up no fight. */ 91 | if(mtmp->data == &mons[PM_MAIL_DAEMON]) tmp = 1; 92 | #endif 93 | 94 | return(tmp); 95 | } 96 | 97 | void 98 | more_experienced(exp, rexp) 99 | register int exp, rexp; 100 | { 101 | u.uexp += exp; 102 | u.urexp += 4*exp + rexp; 103 | if(exp 104 | #ifdef SCORE_ON_BOTL 105 | || flags.showscore 106 | #endif 107 | ) flags.botl = 1; 108 | if (u.urexp >= (Role_if(PM_WIZARD) ? 1000 : 2000)) 109 | flags.beginner = 0; 110 | } 111 | 112 | void 113 | losexp(drainer) /* e.g., hit by drain life attack */ 114 | const char *drainer; /* cause of death, if drain should be fatal */ 115 | { 116 | register int num; 117 | 118 | if (resists_drli(&youmonst)) return; 119 | 120 | if (u.ulevel > 1) { 121 | pline("%s level %d.", Goodbye(), u.ulevel--); 122 | /* remove intrinsic abilities */ 123 | adjabil(u.ulevel + 1, u.ulevel); 124 | reset_rndmonst(NON_PM); /* new monster selection */ 125 | } else { 126 | if (drainer) { 127 | killer_format = KILLED_BY; 128 | killer = drainer; 129 | done(DIED); 130 | } 131 | /* no drainer or lifesaved */ 132 | u.uexp = 0; 133 | } 134 | num = newhp(); 135 | u.uhpmax -= num; 136 | if (u.uhpmax < 1) u.uhpmax = 1; 137 | u.uhp -= num; 138 | if (u.uhp < 1) u.uhp = 1; 139 | else if (u.uhp > u.uhpmax) u.uhp = u.uhpmax; 140 | 141 | if (u.ulevel < urole.xlev) 142 | num = rn1(u.ulevel/2 + urole.enadv.lornd + urace.enadv.lornd, 143 | urole.enadv.lofix + urace.enadv.lofix); 144 | else 145 | num = rn1(u.ulevel/2 + urole.enadv.hirnd + urace.enadv.hirnd, 146 | urole.enadv.hifix + urace.enadv.hifix); 147 | num = enermod(num); /* M. Stephenson */ 148 | u.uenmax -= num; 149 | if (u.uenmax < 0) u.uenmax = 0; 150 | u.uen -= num; 151 | if (u.uen < 0) u.uen = 0; 152 | else if (u.uen > u.uenmax) u.uen = u.uenmax; 153 | 154 | if (u.uexp > 0) 155 | u.uexp = newuexp(u.ulevel) - 1; 156 | flags.botl = 1; 157 | } 158 | 159 | /* 160 | * Make experience gaining similar to AD&D(tm), whereby you can at most go 161 | * up by one level at a time, extra expr possibly helping you along. 162 | * After all, how much real experience does one get shooting a wand of death 163 | * at a dragon created with a wand of polymorph?? 164 | */ 165 | void 166 | newexplevel() 167 | { 168 | if (u.ulevel < MAXULEV && u.uexp >= newuexp(u.ulevel)) 169 | pluslvl(TRUE); 170 | } 171 | 172 | void 173 | pluslvl(incr) 174 | boolean incr; /* true iff via incremental experience growth */ 175 | { /* (false for potion of gain level) */ 176 | register int num; 177 | 178 | if (!incr) You_feel("more experienced."); 179 | num = newhp(); 180 | u.uhpmax += num; 181 | u.uhp += num; 182 | if (u.ulevel < urole.xlev) 183 | num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.lornd + urace.enadv.lornd, 184 | urole.enadv.lofix + urace.enadv.lofix); 185 | else 186 | num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.hirnd + urace.enadv.hirnd, 187 | urole.enadv.hifix + urace.enadv.hifix); 188 | num = enermod(num); /* M. Stephenson */ 189 | u.uenmax += num; 190 | u.uen += num; 191 | if (u.ulevel < MAXULEV) { 192 | if (incr) { 193 | long tmp = newuexp(u.ulevel + 1); 194 | if (u.uexp >= tmp) u.uexp = tmp - 1; 195 | } else { 196 | u.uexp = newuexp(u.ulevel); 197 | } 198 | ++u.ulevel; 199 | if (u.ulevelmax < u.ulevel) u.ulevelmax = u.ulevel; 200 | pline("Welcome to experience level %d.", u.ulevel); 201 | adjabil(u.ulevel - 1, u.ulevel); /* give new intrinsics */ 202 | reset_rndmonst(NON_PM); /* new monster selection */ 203 | } 204 | flags.botl = 1; 205 | } 206 | 207 | long 208 | rndexp() 209 | { 210 | long minexp, maxexp, diff, factor; 211 | 212 | minexp = (u.ulevel == 1) ? 0L : newuexp(u.ulevel - 1); 213 | maxexp = newuexp(u.ulevel); 214 | diff = maxexp - minexp, factor = 1L; 215 | while (diff >= (long)LARGEST_INT) 216 | diff /= 2L, factor *= 2L; 217 | return minexp + factor * (long)rn2((int)diff); 218 | } 219 | 220 | /*exper.c*/