OSDN Git Service

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