1236099Sdes/* SCCS Id: @(#)attrib.c 3.4 2002/10/07 */ 2236099Sdes/* Copyright 1988, 1989, 1990, 1992, M. Stephenson */ 3236099Sdes/* NetHack may be freely redistributed. See license for details. */ 4236099Sdes 5236099Sdes/* attribute modification routines. */ 6236099Sdes 7236099Sdes#include "hack.h" 8236099Sdes 9255376Sdes/* #define DEBUG */ /* uncomment for debugging info */ 10236099Sdes 11236099Sdes#ifdef OVLB 12236099Sdes 13236099Sdes /* part of the output on gain or loss of attribute */ 14236099Sdesstatic 15236099Sdesconst char * const plusattr[] = { 16236099Sdes "strong", "smart", "wise", "agile", "tough", "charismatic" 17236099Sdes}, 18236099Sdes * const minusattr[] = { 19236099Sdes "weak", "stupid", "foolish", "clumsy", "fragile", "repulsive" 20236099Sdes}; 21236099Sdes 22236099Sdes 23236099Sdesstatic 24236099Sdesconst struct innate { 25236099Sdes schar ulevel; 26236099Sdes long *ability; 27236099Sdes const char *gainstr, *losestr; 28236099Sdes} arc_abil[] = { { 1, &(HStealth), "", "" }, 29255376Sdes { 1, &(HFast), "", "" }, 30236099Sdes { 10, &(HSearching), "perceptive", "" }, 31236099Sdes { 0, 0, 0, 0 } }, 32236099Sdes 33236099Sdes bar_abil[] = { { 1, &(HPoison_resistance), "", "" }, 34236099Sdes { 7, &(HFast), "quick", "slow" }, 35236099Sdes { 15, &(HStealth), "stealthy", "" }, 36236099Sdes { 0, 0, 0, 0 } }, 37236099Sdes 38236099Sdes cav_abil[] = { { 7, &(HFast), "quick", "slow" }, 39236099Sdes { 15, &(HWarning), "sensitive", "" }, 40236099Sdes { 0, 0, 0, 0 } }, 41236099Sdes 42236099Sdes hea_abil[] = { { 1, &(HPoison_resistance), "", "" }, 43236099Sdes { 15, &(HWarning), "sensitive", "" }, 44236099Sdes { 0, 0, 0, 0 } }, 45236099Sdes 46236099Sdes kni_abil[] = { { 7, &(HFast), "quick", "slow" }, 47236099Sdes { 0, 0, 0, 0 } }, 48236099Sdes 49236099Sdes mon_abil[] = { { 1, &(HFast), "", "" }, 50236099Sdes { 1, &(HSleep_resistance), "", "" }, 51236099Sdes { 1, &(HSee_invisible), "", "" }, 52236099Sdes { 3, &(HPoison_resistance), "healthy", "" }, 53236099Sdes { 5, &(HStealth), "stealthy", "" }, 54236099Sdes { 7, &(HWarning), "sensitive", "" }, 55236099Sdes { 9, &(HSearching), "perceptive", "unaware" }, 56236099Sdes { 11, &(HFire_resistance), "cool", "warmer" }, 57236099Sdes { 13, &(HCold_resistance), "warm", "cooler" }, 58273326Sdes { 15, &(HShock_resistance), "insulated", "conductive" }, 59236099Sdes { 17, &(HTeleport_control), "controlled","uncontrolled" }, 60236099Sdes { 0, 0, 0, 0 } }, 61236099Sdes 62236099Sdes pri_abil[] = { { 15, &(HWarning), "sensitive", "" }, 63236099Sdes { 20, &(HFire_resistance), "cool", "warmer" }, 64273326Sdes { 0, 0, 0, 0 } }, 65273326Sdes 66273326Sdes ran_abil[] = { { 1, &(HSearching), "", "" }, 67273326Sdes { 7, &(HStealth), "stealthy", "" }, 68273326Sdes { 15, &(HSee_invisible), "", "" }, 69273326Sdes { 0, 0, 0, 0 } }, 70273326Sdes 71273326Sdes rog_abil[] = { { 1, &(HStealth), "", "" }, 72273326Sdes { 10, &(HSearching), "perceptive", "" }, 73273326Sdes { 0, 0, 0, 0 } }, 74273326Sdes 75236099Sdes sam_abil[] = { { 1, &(HFast), "", "" }, 76273326Sdes { 15, &(HStealth), "stealthy", "" }, 77273326Sdes { 0, 0, 0, 0 } }, 78273326Sdes 79273326Sdes tou_abil[] = { { 10, &(HSearching), "perceptive", "" }, 80273326Sdes { 20, &(HPoison_resistance), "hardy", "" }, 81273326Sdes { 0, 0, 0, 0 } }, 82273326Sdes 83273326Sdes val_abil[] = { { 1, &(HCold_resistance), "", "" }, 84273326Sdes { 1, &(HStealth), "", "" }, 85273326Sdes { 7, &(HFast), "quick", "slow" }, 86273326Sdes { 0, 0, 0, 0 } }, 87236099Sdes 88236099Sdes wiz_abil[] = { { 15, &(HWarning), "sensitive", "" }, 89236099Sdes { 17, &(HTeleport_control), "controlled","uncontrolled" }, 90236099Sdes { 0, 0, 0, 0 } }, 91236099Sdes 92236099Sdes /* Intrinsics conferred by race */ 93236099Sdes elf_abil[] = { { 4, &(HSleep_resistance), "awake", "tired" }, 94236099Sdes { 0, 0, 0, 0 } }, 95236099Sdes 96236099Sdes orc_abil[] = { { 1, &(HPoison_resistance), "", "" }, 97236099Sdes { 0, 0, 0, 0 } }; 98236099Sdes 99236099Sdesstatic long next_check = 600L; /* arbitrary first setting */ 100236099SdesSTATIC_DCL void NDECL(exerper); 101236099SdesSTATIC_DCL void FDECL(postadjabil, (long *)); 102236099Sdes 103236099Sdes/* adjust an attribute; return TRUE if change is made, FALSE otherwise */ 104247809Sdesboolean 105236099Sdesadjattrib(ndx, incr, msgflg) 106236099Sdes int ndx, incr; 107236099Sdes int msgflg; /* positive => no message, zero => message, and */ 108236099Sdes{ /* negative => conditional (msg if change made) */ 109273326Sdes if (Fixed_abil || !incr) return FALSE; 110236099Sdes 111236099Sdes if ((ndx == A_INT || ndx == A_WIS) 112236099Sdes && uarmh && uarmh->otyp == DUNCE_CAP) { 113236099Sdes if (msgflg == 0) 114236099Sdes Your("cap constricts briefly, then relaxes again."); 115236099Sdes return FALSE; 116236099Sdes } 117236099Sdes 118236099Sdes if (incr > 0) { 119236099Sdes if ((AMAX(ndx) >= ATTRMAX(ndx)) && (ACURR(ndx) >= AMAX(ndx))) { 120236099Sdes if (msgflg == 0 && flags.verbose) 121236099Sdes pline("You're already as %s as you can get.", 122236099Sdes plusattr[ndx]); 123236099Sdes ABASE(ndx) = AMAX(ndx) = ATTRMAX(ndx); /* just in case */ 124236099Sdes return FALSE; 125236099Sdes } 126236099Sdes 127236099Sdes ABASE(ndx) += incr; 128236099Sdes if(ABASE(ndx) > AMAX(ndx)) { 129236099Sdes incr = ABASE(ndx) - AMAX(ndx); 130236099Sdes AMAX(ndx) += incr; 131236099Sdes if(AMAX(ndx) > ATTRMAX(ndx)) 132236099Sdes AMAX(ndx) = ATTRMAX(ndx); 133236099Sdes ABASE(ndx) = AMAX(ndx); 134236099Sdes } 135236099Sdes } else { 136236099Sdes if (ABASE(ndx) <= ATTRMIN(ndx)) { 137236099Sdes if (msgflg == 0 && flags.verbose) 138236099Sdes pline("You're already as %s as you can get.", 139236099Sdes minusattr[ndx]); 140236099Sdes ABASE(ndx) = ATTRMIN(ndx); /* just in case */ 141236099Sdes return FALSE; 142236099Sdes } 143236099Sdes 144236099Sdes ABASE(ndx) += incr; 145236099Sdes if(ABASE(ndx) < ATTRMIN(ndx)) { 146236099Sdes incr = ABASE(ndx) - ATTRMIN(ndx); 147236099Sdes ABASE(ndx) = ATTRMIN(ndx); 148236099Sdes AMAX(ndx) += incr; 149236099Sdes if(AMAX(ndx) < ATTRMIN(ndx)) 150236099Sdes AMAX(ndx) = ATTRMIN(ndx); 151236099Sdes } 152236099Sdes } 153236099Sdes if (msgflg <= 0) 154236099Sdes You_feel("%s%s!", 155236099Sdes (incr > 1 || incr < -1) ? "very ": "", 156236099Sdes (incr > 0) ? plusattr[ndx] : minusattr[ndx]); 157236099Sdes flags.botl = 1; 158236099Sdes if (moves > 1 && (ndx == A_STR || ndx == A_CON)) 159236099Sdes (void)encumber_msg(); 160236099Sdes return TRUE; 161236099Sdes} 162236099Sdes 163236099Sdesvoid 164236099Sdesgainstr(otmp, incr) 165236099Sdes register struct obj *otmp; 166236099Sdes register int incr; 167236099Sdes{ 168236099Sdes int num = 1; 169236099Sdes 170236099Sdes if(incr) num = incr; 171236099Sdes else { 172236099Sdes if(ABASE(A_STR) < 18) num = (rn2(4) ? 1 : rnd(6) ); 173236099Sdes else if (ABASE(A_STR) < STR18(85)) num = rnd(10); 174236099Sdes } 175236099Sdes (void) adjattrib(A_STR, (otmp && otmp->cursed) ? -num : num, TRUE); 176236099Sdes} 177236099Sdes 178236099Sdesvoid 179236099Sdeslosestr(num) /* may kill you; cause may be poison or monster like 'a' */ 180236099Sdes register int num; 181236099Sdes{ 182236099Sdes int ustr = ABASE(A_STR) - num; 183236099Sdes 184236099Sdes while(ustr < 3) { 185236099Sdes ++ustr; 186236099Sdes --num; 187236099Sdes if (Upolyd) { 188236099Sdes u.mh -= 6; 189236099Sdes u.mhmax -= 6; 190236099Sdes } else { 191236099Sdes u.uhp -= 6; 192236099Sdes u.uhpmax -= 6; 193236099Sdes } 194236099Sdes } 195236099Sdes (void) adjattrib(A_STR, -num, TRUE); 196236099Sdes} 197236099Sdes 198236099Sdesvoid 199236099Sdeschange_luck(n) 200236099Sdes register schar n; 201236099Sdes{ 202236099Sdes u.uluck += n; 203236099Sdes if (u.uluck < 0 && u.uluck < LUCKMIN) u.uluck = LUCKMIN; 204236099Sdes if (u.uluck > 0 && u.uluck > LUCKMAX) u.uluck = LUCKMAX; 205236099Sdes} 206236099Sdes 207236099Sdesint 208236099Sdesstone_luck(parameter) 209236099Sdesboolean parameter; /* So I can't think up of a good name. So sue me. --KAA */ 210236099Sdes{ 211236099Sdes register struct obj *otmp; 212236099Sdes register long bonchance = 0; 213236099Sdes 214236099Sdes for (otmp = invent; otmp; otmp = otmp->nobj) 215236099Sdes if (confers_luck(otmp)) { 216236099Sdes if (otmp->cursed) bonchance -= otmp->quan; 217236099Sdes 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 */ 225void 226set_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 238void 239restore_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 262void 263exercise(i, inc_or_dec) 264int i; 265boolean inc_or_dec; 266{ 267#ifdef NETHACK_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 NETHACK_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 305STATIC_OVL void 306exerper() 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 NETHACK_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 NETHACK_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 NETHACK_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 366void 367exerchk() 368{ 369 int i, mod_val; 370 371 /* Check out the periodic accumulations */ 372 exerper(); 373 374#ifdef NETHACK_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 NETHACK_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 NETHACK_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 NETHACK_DEBUG 412 pline("exerchk: changing %d.", i); 413#endif 414 if(adjattrib(i, mod_val, -1)) { 415#ifdef NETHACK_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 NETHACK_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 */ 449void 450reset_attribute_clock() 451{ 452 if (moves > 600L) next_check = moves + rn1(50,800); 453} 454 455 456void 457init_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 506void 507redist_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 525STATIC_OVL 526void 527postadjabil(ability) 528long *ability; 529{ 530 if (!ability) return; 531 if (ability == &(HWarning) || ability == &(HSee_invisible)) 532 see_monsters(); 533} 534 535void 536adjabil(oldlevel,newlevel) 537int 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 620int 621newhp() 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 664schar 665acurr(x) 666int 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 */ 696schar 697acurrstr() 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 */ 712void 713adjalign(n) 714register 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*/ 732