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
adjattrib(ndx,incr,msgflg)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
gainstr(otmp,incr)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
losestr(num)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
change_luck(n)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
stone_luck(parameter)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
set_moreluck()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
restore_attrib()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
exercise(i,inc_or_dec)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
exerper()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
exerchk()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
reset_attribute_clock()441 reset_attribute_clock()
442 {
443 	if (moves > 600L) next_check = moves + rn1(50,800);
444 }
445 
446 
447 void
init_attr(np)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
redist_attr()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
adjabil(oldlevel,newlevel)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
newhp()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
acurr(x)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
acurrstr()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
adjalign(n)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*/
710