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