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*/