1 /* SCCS Id: @(#)attrib.c 3.4 2002/10/07 */
2 /* Copyright 1988, 1989, 1990, 1992, M. Stephenson */
3 /* NetHack may be freely redistributed. See license for details. */
4
5 /* attribute modification routines. */
6
7 #include "hack.h"
8
9 /* #define DEBUG */ /* uncomment for debugging info */
10
11 #ifdef OVLB
12
13 /* part of the output on gain or loss of attribute */
14 static
15 const char * const plusattr[] = {
16 "strong", "smart", "wise", "agile", "tough", "charismatic"
17 },
18 * const minusattr[] = {
19 "weak", "stupid", "foolish", "clumsy", "fragile", "repulsive"
20 };
21
22
23 /* KMH, intrinsics patch -- many of these are updated */
24 static
25 const struct innate {
26 schar ulevel;
27 long *ability;
28 const char *gainstr, *losestr;
29 } arc_abil[] = { { 1, &(HStealth), "", "" },
30 { 1, &(HFast), "", "" },
31 { 10, &(HSearching), "perceptive", "" },
32 { 0, 0, 0, 0 } },
33
34 bar_abil[] = { { 1, &(HPoison_resistance), "", "" },
35 { 7, &(HFast), "quick", "slow" },
36 { 15, &(HStealth), "stealthy", "" },
37 { 0, 0, 0, 0 } },
38
39 cav_abil[] = { { 7, &(HFast), "quick", "slow" },
40 { 15, &(HWarning), "sensitive", "" },
41 { 0, 0, 0, 0 } },
42
43 fla_abil[] = { { 1, &(HFire_resistance), "", "" },
44 { 13, &(HCold_resistance), "warm", "cooler" },
45 { 0, 0, 0, 0 } },
46
47 hea_abil[] = { { 1, &(HPoison_resistance), "", "" },
48 { 15, &(HWarning), "sensitive", "" },
49 { 0, 0, 0, 0 } },
50
51 ice_abil[] = { { 1, &(HCold_resistance), "", "" },
52 { 13, &(HFire_resistance), "cool", "warmer" },
53 { 0, 0, 0, 0 } },
54
55 kni_abil[] = { { 7, &(HFast), "quick", "slow" },
56 { 0, 0, 0, 0 } },
57
58 mon_abil[] = { { 1, &(HFast), "", "" },
59 { 1, &(HSleep_resistance), "", "" },
60 { 1, &(HSee_invisible), "", "" },
61 { 3, &(HPoison_resistance), "healthy", "" },
62 { 5, &(HStealth), "stealthy", "" },
63 { 7, &(HWarning), "sensitive", "" },
64 { 9, &(HSearching), "perceptive", "unaware" },
65 #if 0
66 { 11, &(HFire_resistance), "cool", "warmer" },
67 { 13, &(HCold_resistance), "warm", "cooler" },
68 { 15, &(HShock_resistance), "insulated", "conductive" },
69 /* WAC -- made the above three attribs techs */
70 #endif
71 { 17, &(HTeleport_control), "controlled","uncontrolled" },
72 { 0, 0, 0, 0 } },
73
74 nec_abil[] = { { 1, &(HDrain_resistance), "", "" },
75 { 1, &(HSick_resistance), "", "" },
76 { 3, &(HUndead_warning), "sensitive", "" },
77 { 0, 0, 0, 0 } },
78
79 pri_abil[] = { { 15, &(HWarning), "sensitive", "" },
80 { 20, &(HFire_resistance), "cool", "warmer" },
81 { 0, 0, 0, 0 } },
82
83 ran_abil[] = { { 1, &(HSearching), "", "" },
84 { 7, &(HStealth), "stealthy", "" },
85 { 15, &(HSee_invisible), "", "" },
86 { 0, 0, 0, 0 } },
87
88 rog_abil[] = { { 1, &(HStealth), "", "" },
89 { 10, &(HSearching), "perceptive", "" },
90 { 0, 0, 0, 0 } },
91
92 sam_abil[] = { { 1, &(HFast), "", "" },
93 { 15, &(HStealth), "stealthy", "" },
94 { 0, 0, 0, 0 } },
95
96 tou_abil[] = { { 10, &(HSearching), "perceptive", "" },
97 { 20, &(HPoison_resistance), "hardy", "" },
98 { 0, 0, 0, 0 } },
99
100 und_abil[] = { { 1, &(HStealth), "", "" },
101 { 1, &(HDrain_resistance), "", "" },
102 { 1, &(HSick_resistance), "", "" },
103 { 1, &(HUndead_warning), "", "" },
104 { 7, &(HFast), "quick", "slow" },
105 { 9, &(HPoison_resistance), "hardy", "less healthy" },
106 { 0, 0, 0, 0 } },
107
108 val_abil[] = { { 1, &(HCold_resistance), "", "" },
109 { 1, &(HStealth), "", "" },
110 { 7, &(HFast), "quick", "slow" },
111 { 0, 0, 0, 0 } },
112
113 #ifdef YEOMAN
114 yeo_abil[] = {
115 { 7, &(HFast), "quick", "slow" },
116 { 15, &(HSwimming), "ready to swim","afraid of the water" },
117 { 0, 0, 0, 0 } },
118 #endif
119
120 wiz_abil[] = { { 15, &(HWarning), "sensitive", "" },
121 { 17, &(HTeleport_control), "controlled","uncontrolled" },
122 { 0, 0, 0, 0 } },
123
124 /* Intrinsics conferred by race */
125 dop_abil[] = {/* { 1, &(HPolymorph), "", "" },*/
126 { 9, &(HPolymorph_control), "your choices improve", "choiceless" },
127 { 0, 0, 0, 0 } },
128
129 #ifdef DWARF
130 dwa_abil[] = { { 1, &(HSearching), "", "" },
131 /* { 10, &(HFire_resistance), "cool", "warmer" },*/
132 { 0, 0, 0, 0 } },
133 #endif
134
135 elf_abil[] = { { 4, &(HSleep_resistance), "awake", "tired" },
136 { 0, 0, 0, 0 } },
137
138 gno_abil[] = { { 5, &(HStealth), "stealthy", "" },
139 /* { 9, &(HFast), "quick", "slow" },
140 { 11, &(HSearching), "perceptive", "unaware" },*/
141 { 0, 0, 0, 0 } },
142
143 hob_abil[] = { { 1, &(HStealth), "", "" },
144 { 7, &(HFast), "quick", "slow" },
145 { 0, 0, 0, 0 } },
146
147
148 lyc_abil[] = { /*{ 1, &(HPoison_resistance), "", "" },*/
149 { 1, &(HRegeneration), "", "" },
150 /* { 7, &(HStealth), "stealthy", "" },*/
151 { 0, 0, 0, 0 } },
152
153 orc_abil[] = { { 1, &(HPoison_resistance), "", "" },
154 { 0, 0, 0, 0 } };
155
156 static long next_check = 600L; /* arbitrary first setting */
157 STATIC_DCL void NDECL(exerper);
158 STATIC_DCL void FDECL(postadjabil, (long *));
159
160 /* adjust an attribute; return TRUE if change is made, FALSE otherwise */
161 boolean
adjattrib(ndx,incr,msgflg)162 adjattrib(ndx, incr, msgflg)
163 int ndx, incr;
164 int msgflg; /* 2 => no message at all, 1 => no message */
165 /* except encumber, zero => message, and */
166 { /* negative => conditional (msg if change made) */
167 if (Fixed_abil || !incr) return FALSE;
168
169 if ((ndx == A_INT || ndx == A_WIS)
170 && uarmh && uarmh->otyp == DUNCE_CAP) {
171 if (msgflg == 0)
172 Your("cap constricts briefly, then relaxes again.");
173 return FALSE;
174 }
175
176 if (incr > 0) {
177 if ((AMAX(ndx) >= ATTRMAX(ndx)) && (ACURR(ndx) >= AMAX(ndx))) {
178 if (msgflg == 0 && flags.verbose)
179 pline("You're already as %s as you can get.",
180 plusattr[ndx]);
181 ABASE(ndx) = AMAX(ndx) = ATTRMAX(ndx); /* just in case */
182 return FALSE;
183 }
184
185 ABASE(ndx) += incr;
186 if(ABASE(ndx) > AMAX(ndx)) {
187 incr = ABASE(ndx) - AMAX(ndx);
188 AMAX(ndx) += incr;
189 if(AMAX(ndx) > ATTRMAX(ndx))
190 AMAX(ndx) = ATTRMAX(ndx);
191 ABASE(ndx) = AMAX(ndx);
192 }
193 } else {
194 if (ABASE(ndx) <= ATTRMIN(ndx)) {
195 if (msgflg == 0 && flags.verbose)
196 pline("You're already as %s as you can get.",
197 minusattr[ndx]);
198 ABASE(ndx) = ATTRMIN(ndx); /* just in case */
199 return FALSE;
200 }
201
202 ABASE(ndx) += incr;
203 if(ABASE(ndx) < ATTRMIN(ndx)) {
204 incr = ABASE(ndx) - ATTRMIN(ndx);
205 ABASE(ndx) = ATTRMIN(ndx);
206 AMAX(ndx) += incr;
207 if(AMAX(ndx) < ATTRMIN(ndx))
208 AMAX(ndx) = ATTRMIN(ndx);
209 }
210 }
211 if (msgflg <= 0)
212 You_feel("%s%s!",
213 (incr > 1 || incr < -1) ? "very ": "",
214 (incr > 0) ? plusattr[ndx] : minusattr[ndx]);
215 flags.botl = 1;
216 if (msgflg <= 1 && moves > 1 && (ndx == A_STR || ndx == A_CON))
217 (void)encumber_msg();
218 return TRUE;
219 }
220
221 void
gainstr(otmp,incr)222 gainstr(otmp, incr)
223 register struct obj *otmp;
224 register int incr;
225 {
226 int num = 1;
227
228 if(incr) num = incr;
229 else {
230 if(ABASE(A_STR) < 18) num = (rn2(4) ? 1 : rnd(6) );
231 else if (ABASE(A_STR) < STR18(85)) num = rnd(10);
232 }
233 (void) adjattrib(A_STR, (otmp && otmp->cursed) ? -num : num, TRUE);
234 }
235
236 void
losestr(num)237 losestr(num) /* may kill you; cause may be poison or monster like 'a' */
238 register int num;
239 {
240 int ustr = ABASE(A_STR) - num;
241
242 while(ustr < 3) {
243 ++ustr;
244 --num;
245 if (Upolyd) {
246 u.mh -= 6;
247 u.mhmax -= 6;
248 } else {
249 u.uhp -= 6;
250 u.uhpmax -= 6;
251 }
252 }
253 (void) adjattrib(A_STR, -num, TRUE);
254 }
255
256 void
change_luck(n)257 change_luck(n)
258 register schar n;
259 {
260 u.uluck += n;
261 if (u.uluck < 0 && u.uluck < LUCKMIN) u.uluck = LUCKMIN;
262 if (u.uluck > 0 && u.uluck > LUCKMAX) u.uluck = LUCKMAX;
263 }
264
265 int
stone_luck(parameter)266 stone_luck(parameter)
267 boolean parameter; /* So I can't think up of a good name. So sue me. --KAA */
268 {
269 register struct obj *otmp;
270 register long bonchance = 0;
271
272 for (otmp = invent; otmp; otmp = otmp->nobj)
273 if (confers_luck(otmp)) {
274 if (otmp->cursed) bonchance -= otmp->quan;
275 else if (otmp->blessed) bonchance += otmp->quan;
276 else if (parameter) bonchance += otmp->quan;
277 }
278
279 /* STEPHEN WHITE'S NEW CODE */
280 if (uarmh && uarmh->otyp == FEDORA && !uarmh->cursed) bonchance += 2;
281
282 return sgn((int)bonchance);
283 }
284
285 /* there has just been an inventory change affecting a luck-granting item */
286 void
set_moreluck()287 set_moreluck()
288 {
289 int luckbon = stone_luck(TRUE);
290
291 if (!luckbon && !carrying(LUCKSTONE)) u.moreluck = 0;
292 else if (luckbon >= 0) u.moreluck = LUCKADD;
293 else u.moreluck = -LUCKADD;
294 }
295
296
297 /* KMH, balance patch -- new function for healthstones */
298 void
recalc_health()299 recalc_health()
300 {
301 register struct obj *otmp;
302
303
304 u.uhealbonus = 0;
305 for(otmp = invent; otmp; otmp=otmp->nobj)
306 if (otmp->otyp == HEALTHSTONE)
307 u.uhealbonus += otmp->quan *
308 (otmp->blessed ? 2 : otmp->cursed ? -2 : 1);
309 return;
310 }
311
312
313 #endif /* OVLB */
314 #ifdef OVL1
315
316 void
restore_attrib()317 restore_attrib()
318 {
319 int i;
320
321 for(i = 0; i < A_MAX; i++) { /* all temporary losses/gains */
322
323 if(ATEMP(i) && ATIME(i)) {
324 if(!(--(ATIME(i)))) { /* countdown for change */
325 ATEMP(i) += ATEMP(i) > 0 ? -1 : 1;
326
327 if(ATEMP(i)) /* reset timer */
328 ATIME(i) = 100 / ACURR(A_CON);
329 }
330 }
331 }
332 (void)encumber_msg();
333 }
334
335 #endif /* OVL1 */
336 #ifdef OVLB
337
338 #define AVAL 50 /* tune value for exercise gains */
339
340 void
exercise(i,inc_or_dec)341 exercise(i, inc_or_dec)
342 int i;
343 boolean inc_or_dec;
344 {
345 #ifdef DEBUG
346 pline("Exercise:");
347 #endif
348 if (i == A_INT || i == A_CHA) return; /* can't exercise these */
349
350 /* no physical exercise while polymorphed; the body's temporary */
351 if (Upolyd && i != A_WIS) return;
352
353 if(abs(AEXE(i)) < AVAL) {
354 /*
355 * Law of diminishing returns (Part I):
356 *
357 * Gain is harder at higher attribute values.
358 * 79% at "3" --> 0% at "18"
359 * Loss is even at all levels (50%).
360 *
361 * Note: *YES* ACURR is the right one to use.
362 */
363 AEXE(i) += (inc_or_dec) ? (rn2(19) > ACURR(i)) : -rn2(2);
364 #ifdef DEBUG
365 pline("%s, %s AEXE = %d",
366 (i == A_STR) ? "Str" : (i == A_WIS) ? "Wis" :
367 (i == A_DEX) ? "Dex" : "Con",
368 (inc_or_dec) ? "inc" : "dec", AEXE(i));
369 #endif
370 }
371 if (moves > 0 && (i == A_STR || i == A_CON)) (void)encumber_msg();
372 }
373
374 /* hunger values - from eat.c */
375 #define SATIATED 0
376 #define NOT_HUNGRY 1
377 #define HUNGRY 2
378 #define WEAK 3
379 #define FAINTING 4
380 #define FAINTED 5
381 #define STARVED 6
382
383 STATIC_OVL void
exerper()384 exerper()
385 {
386 if(!(moves % 10)) {
387 /* Hunger Checks */
388
389 int hs = (u.uhunger > 1000) ? SATIATED :
390 (u.uhunger > 150) ? NOT_HUNGRY :
391 (u.uhunger > 50) ? HUNGRY :
392 (u.uhunger > 0) ? WEAK : FAINTING;
393
394 #ifdef DEBUG
395 pline("exerper: Hunger checks");
396 #endif
397 switch (hs) {
398 case SATIATED: exercise(A_DEX, FALSE);
399 if (Role_if(PM_MONK))
400 exercise(A_WIS, FALSE);
401 break;
402 case NOT_HUNGRY: exercise(A_CON, TRUE); break;
403 case WEAK: exercise(A_STR, FALSE);
404 if (Role_if(PM_MONK)) /* fasting */
405 exercise(A_WIS, TRUE);
406 break;
407 case FAINTING:
408 case FAINTED: exercise(A_CON, FALSE); break;
409 }
410
411 /* Encumberance Checks */
412 #ifdef DEBUG
413 pline("exerper: Encumber checks");
414 #endif
415 switch (near_capacity()) {
416 case MOD_ENCUMBER: exercise(A_STR, TRUE); break;
417 case HVY_ENCUMBER: exercise(A_STR, TRUE);
418 exercise(A_DEX, FALSE); break;
419 case EXT_ENCUMBER: exercise(A_DEX, FALSE);
420 exercise(A_CON, FALSE); break;
421 }
422
423 }
424
425 /* status checks */
426 if(!(moves % 5)) {
427 #ifdef DEBUG
428 pline("exerper: Status checks");
429 #endif
430 /* KMH, intrinsic patch */
431 if ((HClairvoyant & (INTRINSIC|TIMEOUT)) &&
432 !BClairvoyant) exercise(A_WIS, TRUE);
433 if (HRegeneration) exercise(A_STR, TRUE);
434
435 if(Sick || Vomiting) exercise(A_CON, FALSE);
436 if(Confusion || Hallucination) exercise(A_WIS, FALSE);
437 if((Wounded_legs
438 #ifdef STEED
439 && !u.usteed
440 #endif
441 ) || Fumbling || HStun) exercise(A_DEX, FALSE);
442 }
443 }
444
445 void
exerchk()446 exerchk()
447 {
448 int i, mod_val;
449
450 /* Check out the periodic accumulations */
451 exerper();
452
453 #ifdef DEBUG
454 if(moves >= next_check)
455 pline("exerchk: ready to test. multi = %d.", multi);
456 #endif
457 /* Are we ready for a test? */
458 if(moves >= next_check && !multi) {
459 #ifdef DEBUG
460 pline("exerchk: testing.");
461 #endif
462 /*
463 * Law of diminishing returns (Part II):
464 *
465 * The effects of "exercise" and "abuse" wear
466 * off over time. Even if you *don't* get an
467 * increase/decrease, you lose some of the
468 * accumulated effects.
469 *
470 * Note that if you are polymorphed then the
471 * effects of any physical exercise done in your
472 * own body will just wear off with no checking
473 * until you return to your natural form.
474 */
475 for(i = 0; i < A_MAX; AEXE(i++) /= 2) {
476
477 if(Upolyd && i != A_WIS) continue;
478 if(ABASE(i) >= 18 || !AEXE(i)) continue;
479 if(i == A_INT || i == A_CHA) continue;/* can't exercise these */
480
481 #ifdef DEBUG
482 pline("exerchk: testing %s (%d).",
483 (i == A_STR) ? "Str" : (i == A_WIS) ? "Wis" :
484 (i == A_DEX) ? "Dex" : "Con", AEXE(i));
485 #endif
486 /*
487 * Law of diminishing returns (Part III):
488 *
489 * You don't *always* gain by exercising.
490 * [MRS 92/10/28 - Treat Wisdom specially for balance.]
491 */
492 if(rn2(AVAL) > ((i != A_WIS) ? abs(AEXE(i)*2/3) : abs(AEXE(i))))
493 continue;
494 mod_val = sgn(AEXE(i));
495
496 #ifdef DEBUG
497 pline("exerchk: changing %d.", i);
498 #endif
499 if(adjattrib(i, mod_val, -1)) {
500 #ifdef DEBUG
501 pline("exerchk: changed %d.", i);
502 #endif
503 /* if you actually changed an attrib - zero accumulation */
504 AEXE(i) = 0;
505 /* then print an explanation */
506 switch(i) {
507 case A_STR: You((mod_val >0) ?
508 "must have been exercising." :
509 "must have been abusing your body.");
510 break;
511 case A_WIS: You((mod_val >0) ?
512 "must have been very observant." :
513 "haven't been paying attention.");
514 break;
515 case A_DEX: You((mod_val >0) ?
516 "must have been working on your reflexes." :
517 "haven't been working on reflexes lately.");
518 break;
519 case A_CON: You((mod_val >0) ?
520 "must be leading a healthy life-style." :
521 "haven't been watching your health.");
522 break;
523 }
524 }
525 }
526 next_check += rn1(2000,2000);
527 #ifdef DEBUG
528 pline("exerchk: next check at %ld.", next_check);
529 #endif
530 }
531 }
532
533 /* next_check will otherwise have its initial 600L after a game restore */
534 void
reset_attribute_clock()535 reset_attribute_clock()
536 {
537 if (moves > 600L) next_check = moves + rn1(50,800);
538 }
539
540
541 void
init_attr(np)542 init_attr(np)
543 register int np;
544 {
545 register int i, x, tryct;
546
547
548 for(i = 0; i < A_MAX; i++) {
549 ABASE(i) = AMAX(i) = urole.attrbase[i];
550 ATEMP(i) = ATIME(i) = 0;
551 np -= urole.attrbase[i];
552 }
553
554 tryct = 0;
555 while(np > 0 && tryct < 100) {
556
557 x = rn2(100);
558 for (i = 0; (i < A_MAX) && ((x -= urole.attrdist[i]) > 0); i++) ;
559 if(i >= A_MAX) continue; /* impossible */
560
561 if(ABASE(i) >= ATTRMAX(i)) {
562
563 tryct++;
564 continue;
565 }
566 tryct = 0;
567 ABASE(i)++;
568 AMAX(i)++;
569 np--;
570 }
571
572 tryct = 0;
573 while(np < 0 && tryct < 100) { /* for redistribution */
574
575 x = rn2(100);
576 for (i = 0; (i < A_MAX) && ((x -= urole.attrdist[i]) > 0); i++) ;
577 if(i >= A_MAX) continue; /* impossible */
578
579 if(ABASE(i) <= ATTRMIN(i)) {
580
581 tryct++;
582 continue;
583 }
584 tryct = 0;
585 ABASE(i)--;
586 AMAX(i)--;
587 np++;
588 }
589 }
590
591 void
redist_attr()592 redist_attr()
593 {
594 register int i, tmp;
595
596 for(i = 0; i < A_MAX; i++) {
597 if (i==A_INT || i==A_WIS) continue;
598 /* Polymorphing doesn't change your mind */
599 tmp = AMAX(i);
600 AMAX(i) += (rn2(5)-2);
601 if (AMAX(i) > ATTRMAX(i)) AMAX(i) = ATTRMAX(i);
602 if (AMAX(i) < ATTRMIN(i)) AMAX(i) = ATTRMIN(i);
603 ABASE(i) = ABASE(i) * AMAX(i) / tmp;
604 /* ABASE(i) > ATTRMAX(i) is impossible */
605 if (ABASE(i) < ATTRMIN(i)) ABASE(i) = ATTRMIN(i);
606 }
607 (void)encumber_msg();
608 }
609
610 STATIC_OVL
611 void
postadjabil(ability)612 postadjabil(ability)
613 long *ability;
614 {
615 if (!ability) return;
616 if (ability == &(HWarning) || ability == &(HSee_invisible))
617 see_monsters();
618 }
619
620 void
adjabil(oldlevel,newlevel)621 adjabil(oldlevel,newlevel)
622 int oldlevel, newlevel;
623 {
624 register const struct innate *abil, *rabil;
625 long mask = FROMEXPER;
626
627 switch (Role_switch) {
628 case PM_ARCHEOLOGIST: abil = arc_abil; break;
629 case PM_BARBARIAN: abil = bar_abil; break;
630 case PM_CAVEMAN: abil = cav_abil; break;
631 case PM_FLAME_MAGE: abil = fla_abil; break;
632 case PM_HEALER: abil = hea_abil; break;
633 case PM_ICE_MAGE: abil = ice_abil; break;
634 case PM_KNIGHT: abil = kni_abil; break;
635 case PM_MONK: abil = mon_abil; break;
636 case PM_NECROMANCER: abil = nec_abil; break;
637 case PM_PRIEST: abil = pri_abil; break;
638 case PM_RANGER: abil = ran_abil; break;
639 case PM_ROGUE: abil = rog_abil; break;
640 case PM_SAMURAI: abil = sam_abil; break;
641 #ifdef TOURIST
642 case PM_TOURIST: abil = tou_abil; break;
643 #endif
644 case PM_UNDEAD_SLAYER: abil = und_abil; break;
645 case PM_VALKYRIE: abil = val_abil; break;
646 case PM_WIZARD: abil = wiz_abil; break;
647 #ifdef YEOMAN
648 case PM_YEOMAN: abil = yeo_abil; break;
649 #endif
650 default: abil = 0; break;
651 }
652
653 switch (Race_switch) {
654 case PM_DOPPELGANGER: rabil = dop_abil; break;
655 #ifdef DWARF
656 case PM_DWARF: rabil = dwa_abil; break;
657 #endif
658 case PM_DROW:
659 case PM_ELF: rabil = elf_abil; break;
660 case PM_GNOME: rabil = gno_abil; break;
661 case PM_HOBBIT: rabil = hob_abil; break;
662 case PM_ORC: rabil = orc_abil; break;
663 case PM_HUMAN_WEREWOLF: rabil = lyc_abil; break;
664 case PM_HUMAN:
665 case PM_VAMPIRE:
666 default: rabil = 0; break;
667 }
668
669 while (abil || rabil) {
670 long prevabil;
671 /* Have we finished with the intrinsics list? */
672 if (!abil || !abil->ability) {
673 /* Try the race intrinsics */
674 if (!rabil || !rabil->ability) break;
675 abil = rabil;
676 rabil = 0;
677 mask = FROMRACE;
678 }
679 prevabil = *(abil->ability);
680 if(oldlevel < abil->ulevel && newlevel >= abil->ulevel) {
681 /* Abilities gained at level 1 can never be lost
682 * via level loss, only via means that remove _any_
683 * sort of ability. A "gain" of such an ability from
684 * an outside source is devoid of meaning, so we set
685 * FROMOUTSIDE to avoid such gains.
686 */
687 if (abil->ulevel == 1)
688 *(abil->ability) |= (mask|FROMOUTSIDE);
689 else
690 *(abil->ability) |= mask;
691 if(!(*(abil->ability) & INTRINSIC & ~mask)) {
692 if(*(abil->gainstr))
693 You_feel("%s!", abil->gainstr);
694 }
695 } else if (oldlevel >= abil->ulevel && newlevel < abil->ulevel) {
696 *(abil->ability) &= ~mask;
697 if(!(*(abil->ability) & INTRINSIC)) {
698 if(*(abil->losestr))
699 You_feel("%s!", abil->losestr);
700 else if(*(abil->gainstr))
701 You_feel("less %s!", abil->gainstr);
702 }
703 }
704 if (prevabil != *(abil->ability)) /* it changed */
705 postadjabil(abil->ability);
706 abil++;
707 }
708
709 if (oldlevel > 0) {
710 if (newlevel > oldlevel)
711 add_weapon_skill(newlevel - oldlevel);
712 else
713 lose_weapon_skill(oldlevel - newlevel);
714 }
715
716 /* ALI -- update Warn_of_mon */
717 HWarn_of_mon = HUndead_warning;
718 if (HUndead_warning)
719 flags.warntype |= M2_UNDEAD;
720 else
721 flags.warntype &= ~M2_UNDEAD;
722
723 /* WAC -- adjust techniques */
724 adjtech(oldlevel, newlevel);
725 }
726
727
728 /* STEPHEN WHITE'S NEW CODE */
729 int
newhp()730 newhp()
731 {
732 int hp, conplus;
733
734 if(u.ulevel == 0) {
735 /* Initialize hit points */
736 hp = urole.hpadv.infix + urace.hpadv.infix;
737 if (urole.hpadv.inrnd > 0) hp += rnd(urole.hpadv.inrnd);
738 if (urace.hpadv.inrnd > 0) hp += rnd(urace.hpadv.inrnd);
739
740 /* Initialize alignment stuff */
741 u.ualign.type = aligns[flags.initalign].value;
742 u.ualign.record = urole.initrecord;
743 return hp;
744 } else {
745 if (u.ulevel < urole.xlev) {
746 hp = urole.hpadv.lofix + urace.hpadv.lofix;
747 if (urole.hpadv.lornd > 0) hp += rnd(urole.hpadv.lornd);
748 if (urace.hpadv.lornd > 0) hp += rnd(urace.hpadv.lornd);
749 } else {
750 hp = urole.hpadv.hifix + urace.hpadv.hifix;
751 if (urole.hpadv.hirnd > 0) hp += rnd(urole.hpadv.hirnd);
752 if (urace.hpadv.hirnd > 0) hp += rnd(urace.hpadv.hirnd);
753 }
754 }
755
756 if (ACURR(A_CON) <= 3) conplus = -2;
757 else if (ACURR(A_CON) <= 6) conplus = -1;
758 else if (ACURR(A_CON) <= 14) conplus = 0;
759 else if (ACURR(A_CON) <= 16) conplus = 1;
760 else if (ACURR(A_CON) == 17) conplus = 2;
761 else if (ACURR(A_CON) == 18) conplus = 3;
762 else conplus = 4;
763
764 hp += conplus;
765 return((hp <= 0) ? 1 : hp);
766 }
767
768 #endif /* OVLB */
769 #ifdef OVL0
770
771 /* STEPHEN WHITE'S NEW CODE */
772 schar
acurr(x)773 acurr(x)
774 int x;
775 {
776 register int tmp = (u.abon.a[x] + u.atemp.a[x] + u.acurr.a[x]);
777
778 if (x == A_STR) {
779 /* WAC twiddle so that wearing rings and gauntlets have
780 a bonus */
781 /* robe of weakness and gauntlets of power will cancel */
782 int base = u.acurr.a[x];
783 int bonus = tmp - base;
784 boolean nobonus = (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER
785 && uarm && uarm->otyp == ROBE_OF_WEAKNESS);
786
787 if (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER && !nobonus) {
788 if ((uarmg->spe > 7)
789 || ((118 + bonus + uarmg->spe) > 125)
790 || ((tmp + uarmg->spe) > 125))
791 return(125);
792 else if (base > 118) return (base + uarmg->spe + bonus);
793 else return(118 + uarmg->spe + bonus);
794 } else if (uarm && uarm->otyp == ROBE_OF_WEAKNESS && !nobonus)
795 return(3 + bonus);
796 else return((tmp >= 125) ? 125 : (tmp <= 3) ? 3 : tmp);
797 } else if (x == A_CHA) {
798 if (tmp < 18 && (youmonst.data->mlet == S_NYMPH ||
799 u.umonnum == PM_SUCCUBUS || u.umonnum == PM_INCUBUS))
800 tmp = 18;
801 if (uarmh && uarmh->otyp == FEDORA) tmp += 1;
802 return((tmp >= 25) ? 25 : (tmp <= 3) ? 3 : tmp);
803 } else if (x == A_INT || x == A_WIS) {
804 /* yes, this may raise int/wis if player is sufficiently
805 * stupid. there are lower levels of cognition than "dunce".
806 */
807 if (uarmh && uarmh->otyp == DUNCE_CAP) return(6);
808 }
809 #ifdef WIN32_BUG
810 return(x=((tmp >= 25) ? 25 : (tmp <= 3) ? 3 : tmp));
811 #else
812 return((schar)((tmp >= 25) ? 25 : (tmp <= 3) ? 3 : tmp));
813 #endif
814 }
815
816 /* condense clumsy ACURR(A_STR) value into value that fits into game formulas
817 */
818 schar
acurrstr()819 acurrstr()
820 {
821 register int str = ACURR(A_STR);
822
823 if (str <= 18) return str;
824 if (str <= 121) return (19 + str / 50); /* map to 19-21 */
825 else return str - 100;
826 }
827
828 #endif /* OVL0 */
829 #ifdef OVL2
830
831 /* avoid possible problems with alignment overflow, and provide a centralized
832 * location for any future alignment limits
833 */
834 void
adjalign(n)835 adjalign(n)
836 register int n;
837 {
838 register int newalign = u.ualign.record + n;
839
840 if (n < 0) {
841 if (newalign < u.ualign.record)
842 u.ualign.record = newalign;
843 } else
844 if (newalign > u.ualign.record) {
845 u.ualign.record = newalign;
846 if(u.ualign.record > ALIGNLIM)
847 u.ualign.record = ALIGNLIM;
848 }
849 }
850
851 #endif /* OVL2 */
852
853 /*attrib.c*/
854