Source:Attrib.c

Below is the full text to src/attrib.c from NetHack 3.4.3. To link to a particular line, write [[attrib.c#line123 ]], for example. 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*/