Source:NetHack 3.0.0/attrib.c

Below is the full text to attrib.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/attrib.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

1.   /*  2.     *	attrib.c	- attribute modification routines. 3.    *  4.     *	Copyright 1988, M. Stephenson 5.    */  6.    /* NetHack may be freely redistributed. See license for details. */ 7.     8.    #include	"hack.h"  9. 10.  const char	*plusattr[] = {	/* part of the output on gain of attribute */ 11.   12.   	"strong", "smart", "wise", "agile", "tough", "charismatic" 13.  };  14.    15.   const char	*minusattr[] = { /* part of the output on loss of attribute */ 16.   17.   	"weak", "stupid", "foolish", "clumsy", "vulnerable", "ugly" 18.  };  19.    20.   struct attribs	attrmax = {	/* max values for the attributes */ 21.   22.   	118, 18, 18, 18, 18, 18  23.   },  24.   		attrmin = {	/* min values for the attributes */ 25.   26.   	3, 3, 3, 3, 3, 3  27.   };  28.    29.   const struct innate { 30.   31.   	schar	ulevel; 32.  	long	*ability; 33.  	char	*gainstr, *losestr; 34.  }	a_abil[] = { {	 0, &(Stealth), "", "" }, 35.  		     {   0, &(Fast), "", "" }, 36.  		     {  10, &(Searching), "perceptive", "" }, 37.  		     {	 0, 0, 0, 0 } },  38.    39.   	b_abil[] = { {	 0, &(HPoison_resistance), "", "" }, 40.  		     {   7, &(Fast), "quick", "slow" }, 41.  		     {  15, &(Stealth), "stealthy", "" }, 42.  		     {	 0, 0, 0, 0 } },  43.    44.   	c_abil[] = { {	 7, &(Fast), "quick", "slow" }, 45.  		     {	15, &(Warning), "sensitive", "" }, 46.  		     {	 0, 0, 0, 0 } },  47.    48.   	e_abil[] = { {   0, &(Fast), "", "" }, 49.  		     {	 0, &(HSee_invisible), "", "" }, 50.  		     {	 0, &(Searching), "", "" }, 51.  		     {	 0, &(HSleep_resistance), "", "" }, 52.  		     {	 0, 0, 0, 0 } },  53.    54.   	h_abil[] = { {	 0, &(HPoison_resistance), "", "" }, 55.  		     {	15, &(Warning), "sensitive", "" }, 56.  		     {	 0, 0, 0, 0 } },  57.    58.   	k_abil[] = { {	 7, &(Fast), "quick", "slow" }, 59.  		     {	 0, 0, 0, 0 } },  60.    61.   	p_abil[] = { {	15, &(Warning), "sensitive", "" }, 62.  		     {  20, &(HFire_resistance), "cool", "warmer" }, 63.  		     {	 0, 0, 0, 0 } },  64.    65.   	r_abil[] = { {	 0, &(Stealth), "", ""  }, 66.  		     {  10, &(Searching), "perceptive", "" }, 67.  		     {	 0, 0, 0, 0 } },  68.    69.   	s_abil[] = { {	 0, &(Fast), "", "" }, 70.  		     {  15, &(Stealth), "stealthy", "" }, 71.  		     {	 0, 0, 0, 0 } },  72.    73.   	t_abil[] = { {	10, &(Searching), "perceptive", "" }, 74.  		     {	20, &(HPoison_resistance), "hardy", "" }, 75.  		     {	 0, 0, 0, 0 } },  76.    77.   	v_abil[] = { {	 0, &(HCold_resistance), "", "" }, 78.  		     {	 0, &(Stealth), "", "" }, 79.  		     {   7, &(Fast), "quick", "slow" }, 80.  		     {	 0, 0, 0, 0 } },  81.    82.   	w_abil[] = { {	15, &(Warning), "sensitive", "" }, 83.  		     {  17, &(HTeleport_control), "controlled","uncontrolled" }, 84.  		     {	 0, 0, 0, 0 } };  85.    86.   const struct clattr { 87.   88.   	struct	attribs	base, dist; 89.   	schar	align, aligntyp; 90.  	schar	shp, hd, xlev, ndx; 91.  /* According to AD&D, HD for some classes (i.e. Wizard) should be smaller 92.   * (4-sided for wizards). But this is not AD&D, and using the AD&D 93.   * rule here produces an unplayable character. This I have used a minimum 94.   * of an 10-sided hit die for everything. Another AD&D change: wizards get 95.   * a minimum strength of 6 since without one you can't teleport or cast 96.   * spells. --KAA 97.   */  98.   	struct	innate *abil; 99.  }	a_attr = { {	 6,  9,  9,  6,  6,  6 },  /* Archeologist */ 100. 		   {	20, 20, 20, 10, 20, 10 },  101.  		    10,  1, 13, 10, 14,  2, a_abil }, 102.  103.  	b_attr = { {	15,  6,  6, 14, 15,  5 },  /* Barbarian */ 104. 		   {	30,  6,  7, 20, 30,  7 },  105.  		    10, -1, 16, 12, 10,  3, b_abil }, 106.  107.  	c_attr = { {	 9,  6,  6,  6,  7,  5 },  /* Caveman (fighter) */ 108. 		   {	30,  6,  7, 20, 30,  7 },  109.  		     0,  1, 16, 10, 10,  3, c_abil }, 110.  111.  /*  112.  	e_attr = { {	13, 13, 14,  6, 14,  6 }, 113.  */  114.  	e_attr = { {	12, 12, 12,  8, 12,  6 },  /* Elf (ranger) */ 115. 		   {	30, 10, 10, 20, 20, 10 },  116.  		    10,  1, 15, 10, 11,  2, e_abil }, 117.  118.  	h_attr = { {	 6,  6, 12,  6, 10, 15 },  /* Healer (druid) */ 119. 		   {	15, 20, 20, 15, 25, 10 },  120.  		    10,  1, 13, 10, 20,  2, h_abil }, 121.  122.  	k_attr = { {	12,  6, 13,  6,  9, 17 },  /* Knight (paladin) */ 123. 		   {	20, 15, 15, 10, 20, 10 },  124.  		    10,  1, 16, 10, 10,  3, k_abil }, 125.  126.  	p_attr = { {	 6,  6,  9,  6,  6,  6 },  /* Priest (cleric) */ 127. 		   {	15, 10, 30, 15, 20, 10 },  128.  		     0,  0, 14, 10, 10,  2, p_abil }, 129.  130.  	r_attr = { {	 6,  6,  6,  9,  6,  5 },  /* Rogue (thief) */ 131. 		   {	20, 10, 10, 30, 20, 10 },  132.  		    10, -1, 12, 10, 11,  2, r_abil }, 133.  134.  	s_attr = { {	 9,  6,  6,  9, 17,  5 },  /* Samurai (fighter/thief) */ 135. 		   {	30, 10, 10, 30, 14, 10 },  136.  		    10,  1, 15, 10, 11,  2, s_abil }, 137.  138.  	t_attr = { {	 6,  9,  5,  6,  6,  9 },  /* Tourist */ 139. 		   {	15, 10, 10, 15, 30, 20 },  140.  		     0,  0, 10, 10, 14,  1, t_abil }, 141.  142.  	v_attr = { {	 9,  6,  6,  6,  9,  6 },  /* Valkyrie (fighter) */ 143. 		   {	30,  6,  7, 20, 30,  7 },  144.  		     0, -1, 16, 10, 10,  3, v_abil }, 145.  146.  	w_attr = { {	 6,  9,  6,  6,  6,  6 },  /* Wizard (magic-user) */ 147. 		   {	10, 30, 10, 20, 20, 10 },  148.  		     0,  0, 12, 10, 12,  1, w_abil }, 149.  150.  	X_attr = { {	 3,  3,  3,  3,  3,  3 }, 151. 		   {	20, 15, 15, 15, 20, 15 },  152.  		     0,  0, 12, 10, 14,  1,  0 };  153.   154.  void 155. adjattrib(ndx, incr, silent) 156.  157.  	int	ndx, incr; 158. 	boolean	silent; 159. {  160.  	if(!incr) return; 161.  162.  	if(incr > 0) { 163. 	    if((AMAX(ndx) >= attrmax.a[ndx]) && (ACURR(ndx) == AMAX(ndx))) { 164.  165.  		if(!silent && flags.verbose) 166. 		    pline("You're already as %s as you can get.",  167.  			  plusattr[ndx]); 168. 		ABASE(ndx) = AMAX(ndx) = attrmax.a[ndx]; /* just in case */ 169. 		return; 170. 	    }  171.   172.  	    ABASE(ndx) += incr; 173. 	    if(ABASE(ndx) > AMAX(ndx)) { 174. 		incr = ABASE(ndx) - AMAX(ndx); 175. 		AMAX(ndx) += incr; 176. 		if(AMAX(ndx) > attrmax.a[ndx]) 177. 		    AMAX(ndx) = attrmax.a[ndx]; 178. 		ABASE(ndx) = AMAX(ndx); 179. 	    }  180.  	} else { 181. 	    if((AMAX(ndx) <= attrmin.a[ndx]) && (ABASE(ndx) == AMAX(ndx))) { 182. 		if(!silent && flags.verbose) 183. 		    pline("You're already as %s as you can get.",  184.  			  minusattr[ndx]); 185. 		ABASE(ndx) = AMAX(ndx) = attrmin.a[ndx]; /* just in case */ 186. 		return; 187. 	    }  188.   189.  	    ABASE(ndx) += incr; 190. 	    if(ABASE(ndx) < attrmin.a[ndx]) { 191. 		incr = ABASE(ndx) - attrmin.a[ndx]; 192. 		ABASE(ndx) = attrmin.a[ndx]; 193. 		AMAX(ndx) += incr; 194. 		if(AMAX(ndx) < attrmin.a[ndx]) 195. 		    AMAX(ndx) = attrmin.a[ndx]; 196. 	    }  197.  	}  198.  	if(!silent) 199. 	    You("feel %s%s!",  200.  		  (incr > 1) ? "very ": "",  201.  		  (incr > 0) ? plusattr[ndx] : minusattr[ndx]); 202. 	flags.botl = 1; 203. 	return; 204. }  205.   206.  void 207. gainstr(otmp, incr) 208. 	register struct obj *otmp; 209. 	register int incr; 210. {  211.  	int num = 1; 212.  213.  	if(incr) num = incr; 214. 	else { 215. 	    if(ABASE(A_STR) < 18) num = (rn2(4) ? 1 : rnd(6) ); 216. 	    else if (ABASE(A_STR) < 103) num = rnd(10); 217. 	}  218.  	adjattrib(A_STR, (otmp && otmp->cursed) ? -num : num, TRUE); 219. }  220.   221.  void 222. losestr(num)	/* may kill you; cause may be poison or monster like 'a' */ 223. 	register int num; 224. {  225.  	int ustr = ABASE(A_STR) - num; 226.  227.  	while(ustr < 3) { 228. 		ustr++; 229. 		num--; 230. 		u.uhp -= 6; 231. 		u.uhpmax -= 6; 232. 	}  233.  	adjattrib(A_STR, -num, TRUE); 234. }  235.   236.  void 237. change_luck(n) 238. 	register schar n;  239. { 240.  	u.uluck += n;  241. if (u.uluck < 0 && u.uluck < LUCKMIN)	u.uluck = LUCKMIN; 242. 	if (u.uluck > 0 && u.uluck > LUCKMAX)	u.uluck = LUCKMAX; 243. }  244.   245.  int 246. stone_luck(parameter) 247. boolean parameter; /* So I can't think up of a good name. So sue me. --KAA */ 248. {  249.  	register struct obj *otmp; 250. 	register int bonchance = 0; 251.  252.  	for(otmp = invent; otmp; otmp=otmp->nobj) 253. 	    if(otmp->otyp == LUCKSTONE) { 254. 		if (otmp->cursed) bonchance -= otmp->quan; 255. 		else if (otmp->blessed) bonchance += otmp->quan; 256. 		else if (parameter) bonchance += otmp->quan; 257. 	    }  258.   259.  	return sgn(bonchance); 260. }  261.   262.  void 263. restore_attrib { 264.  265.  	int	i; 266.  267.  	for(i = 0; i < A_MAX; i++) {	/* all temporary losses/gains */ 268.  269.  	   if(ATEMP(i) && ATIME(i)) { 270. 		if(!(--(ATIME(i)))) { /* countdown for change */ 271. 		    ATEMP(i) += ATEMP(i) > 0 ? -1 : 1; 272.   273.  		    if(ATEMP(i)) /* reset timer */ 274. 			ATIME(i) = 100 / ACURR(A_CON); 275. 		}  276.  	    }  277.  	}  278.  }  279.   280.  static struct	clattr * 281. clx  { 282.  283.  	register struct	clattr	*attr; 284.  285.  	switch	(pl_character[0]) { 286.  287.  	    case 'A':	attr = &a_attr; 288. 			break; 289. 	    case 'B':	attr = &b_attr; 290. 			break; 291. 	    case 'C':	attr = &c_attr; 292. 			break; 293. 	    case 'E':	attr = &e_attr; 294. 			break; 295. 	    case 'H':	attr = &h_attr; 296. 			break; 297. 	    case 'K':	attr = &k_attr; 298. 			break; 299. 	    case 'P':	attr = &p_attr; 300. 			break; 301. 	    case 'R':	attr = &r_attr; 302. 			break; 303. 	    case 'S':	attr = &s_attr; 304. 			break; 305. 	    case 'T':	attr = &t_attr; 306. 			break; 307. 	    case 'V':	attr = &v_attr; 308. 			break; 309. 	    case 'W':	attr = &w_attr; 310. 			break; 311. 	    default:	/* unknown type */ 312. 			attr = &X_attr; 313. 			break; 314. 	}  315.  	return(attr); 316. }  317.   318.  static void 319. init_align {	/* called from newhp if u.ulevel is 0 */ 320.  321.  	register struct	clattr	*attr = clx; 322.  323.  	u.ualign = (int)attr->align; 324. 	u.ualigntyp = attr->aligntyp; 325. }  326.   327.  void 328. init_attr(np) 329. 	register int	np; 330. {  331.  	register int	i, x, tryct; 332. 	register struct	clattr	*attr = clx; 333.  334.  	for(i = 0; i < A_MAX; i++) { 335.  336.  	    ABASE(i) = AMAX(i) = attr->base.a[i]; 337. 	    ATEMP(i) = ATIME(i) = 0; 338. 	    np -= attr->base.a[i]; 339. 	}  340.   341.  	tryct = 0; 342. 	while(np > 0 && tryct < 100) { 343.  344.  	    x = rn2(100); 345. 	    for(i = 0; (i < A_MAX) && ((x -= attr->dist.a[i]) > 0); i++); 346. 	    if(i >= A_MAX) continue; /* impossible */ 347.  348.  	    if(ABASE(i) >= attrmax.a[i]) { 349.  350.  		tryct++; 351. 		continue; 352. 	    }  353.  	    tryct = 0; 354. 	    ABASE(i)++; 355. 	    AMAX(i)++; 356. 	    np--; 357. 	}  358.   359.  	tryct = 0; 360. 	while(np < 0 && tryct < 100) {		/* for redistribution */ 361.  362.  	    x = rn2(100); 363. 	    for(i = 0; (i < A_MAX) && ((x -= attr->dist.a[i]) > 0); i++); 364. 	    if(i >= A_MAX) continue; /* impossible */ 365.  366.  	    if(ABASE(i) <= attrmin.a[i]) { 367.  368.  		tryct++; 369. 		continue; 370. 	    }  371.  	    tryct = 0; 372. 	    ABASE(i)--; 373. 	    AMAX(i)--; 374. 	    np++; 375. 	}  376.  }  377.   378.  #ifdef POLYSELF 379. void 380. redist_attr { 381.  382.  	register int i, tmp; 383.  384.  	for(i = 0; i < A_MAX; i++) { 385. 	    if (i==A_INT || i==A_WIS) continue; 386. 		/* Polymorphing doesn't change your mind */ 387. 	    tmp = AMAX(i); 388. 	    AMAX(i) += (rn2(5)-2); 389. 	    if (AMAX(i) > attrmax.a[i]) AMAX(i) = attrmax.a[i]; 390. 	    if (AMAX(i) < attrmin.a[i]) AMAX(i) = attrmin.a[i]; 391. 	    ABASE(i) = ABASE(i) * AMAX(i) / tmp; 392. 	    /* ABASE(i) > attrmax.a[i] is impossible */ 393. 	    if (ABASE(i) < attrmin.a[i]) ABASE(i) = attrmin.a[i]; 394. 	}  395.  }  396.  #endif 397.  398.  void 399. adjabil(flag) 400.  401.  	int	flag;		/* +ve/-ve  = gain/lose */ 402. {  403.  	register struct	clattr	*attr = clx; 404. 	register struct innate	*abil = attr->abil; 405.  406.  	if(abil) { 407.  408.  	    for(abil->ability; abil++) { 409. 		if ((flag>0 && u.ulevel >= abil->ulevel) ||  410.  					(flag<0 && u.ulevel < abil->ulevel)) { 411. 		    if(flag > 0) { 412. 			if(!(*(abil->ability) & INTRINSIC)) { 413. 			    *(abil->ability) |= INTRINSIC; 414. 			    if(strlen(abil->gainstr)) 415. 				You("feel %s!", abil->gainstr); 416. 			}  417.  		    } else { 418. 			if((*(abil->ability) & INTRINSIC)) { 419. 			    *(abil->ability) &= ~INTRINSIC; 420. 			    if(strlen(abil->losestr)) 421. 				You("feel %s!", abil->losestr); 422. 			    else if(strlen(abil->gainstr)) 423. 				You("feel less %s!", abil->gainstr); 424. 			}  425.  		    }  426.  		}  427.  	    }  428.  	}  429.  }  430.   431.  int 432. newhp { 433. 	register struct	clattr	*attr = clx; 434. 	int	hp, conplus; 435.  436.  	if(u.ulevel == 0) { 437.  438.  		hp = attr->shp; 439. 		init_align;	/* initialize alignment stuff */ 440. 		return hp; 441. 	} else { 442.  443.  	    if(u.ulevel < attr->xlev) 444. 		hp = rnd(attr->hd); 445. 	    else 446. 		hp = attr->ndx; 447. 	}  448.   449.  	switch(ACURR(A_CON)) { 450. 		case	3:	conplus = -2; break; 451. 		case	4: 452. 		case	5: 453. 		case	6:	conplus = -1; break; 454. 		case	15: 455. 		case	16:	conplus = 1; break; 456. 		case	17:	conplus = 2; break; 457. 		case	18:	conplus = 3; break; 458. 		default:	conplus = 0; 459. 	}  460.  	hp += conplus; 461. 	return((hp <= 0) ? 1 : hp); 462. }  463.   464.  schar 465. acurr(x) { 466. 	register int tmp = (u.abon.a[x] + u.atemp.a[x] + u.acurr.a[x]); 467.  468.  	if (x == A_STR) { 469. 		if (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER) return(125); 470. 		else return((tmp >= 125) ? 125 : (tmp <= 3) ? 3 : tmp); 471. 	}  472.  	else return((tmp >= 25) ? 25 : (tmp <= 3) ? 3 : tmp); 473. }  474.   475.  /* avoid possible problems with alignment overflow, and provide a centralized 476.  * location for any future alignment limits 477.  */  478.  void 479. adjalign(n) 480. register int n;  481. { 482.  	register int newalign = u.ualign + n;  483. 484. 	if(n < 0) { 485. 		if(newalign < u.ualign) 486. 			u.ualign = newalign; 487. 	} else 488. 		if(newalign > u.ualign) 489. 			u.ualign = newalign; 490. }