OSDN Git Service

update year to 2020
[jnethack/source.git] / src / attrib.c
1 /* NetHack 3.6  attrib.c        $NHDT-Date: 1575245050 2019/12/02 00:04:10 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.66 $ */
2 /*      Copyright 1988, 1989, 1990, 1992, M. Stephenson           */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 /* JNetHack Copyright */
6 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020            */
8 /* JNetHack may be freely redistributed.  See license for details. */
9
10
11 /*  attribute modification routines. */
12
13 #include "hack.h"
14 #include <ctype.h>
15
16 /* part of the output on gain or loss of attribute */
17 static const char
18 #if 0 /*JP:T*/
19     *const plusattr[] = { "strong", "smart", "wise",
20                           "agile",  "tough", "charismatic" },
21 #else
22     *const plusattr[] = { "\8b­\82¢", "\8c«\96¾\82¾", "\8c«\82¢",
23                           "\8b@\95q\82¾", "\8aæ\8fä\82¾", "\96£\97Í\93I\82¾" },
24 #endif
25 #if 0 /*JP:T*/
26     *const minusattr[] = { "weak",    "stupid",
27                            "foolish", "clumsy",
28                            "fragile", "repulsive" };
29 #else
30     *const minusattr[] = { "\8eã\82¢", "\8bð\82©\82¾",
31                            "\8aÔ\94²\82¯\82¾", "\95s\8aí\97p\82¾",
32                            "\82Ð\8eã\82¾", "\8fX\82¢" };
33 #endif
34 /* also used by enlightenment for non-abbreviated status info */
35 const char
36 #if 0 /*JP:T*/
37     *const attrname[] = { "strength", "intelligence", "wisdom",
38                           "dexterity", "constitution", "charisma" };
39 #else
40     *const attrname[] = { "\8b­\82³", "\92m\97Í", "\8c«\82³",
41                           "\91f\91\81\82³", "\91Ï\8bv\97Í", "\96£\97Í" };
42 #endif
43
44 static const struct innate {
45     schar ulevel;
46     long *ability;
47     const char *gainstr, *losestr;
48 } arc_abil[] = { { 1, &(HStealth), "", "" },
49                  { 1, &(HFast), "", "" },
50 /*JP
51                  { 10, &(HSearching), "perceptive", "" },
52 */
53                  { 10, &(HSearching), "\92m\8ao\97Í\82ð\93¾\82½", "\92m\8ao\97Í\82ð\8e¸\82Á\82½" },
54                  { 0, 0, 0, 0 } },
55
56   bar_abil[] = { { 1, &(HPoison_resistance), "", "" },
57 /*JP
58                  { 7, &(HFast), "quick", "slow" },
59 */
60                  { 7, &(HFast), "\91f\91\81\82³\82ð\93¾\82½", "\92x\82­\82È\82Á\82½" },
61 /*JP
62                  { 15, &(HStealth), "stealthy", "" },
63 */
64                  { 15, &(HStealth), "\90l\96Ú\82ð\93\90\82Þ\97Í\82ð\93¾\82½", "\90l\96Ú\82ð\93\90\82Þ\97Í\82ð\8e¸\82Á\82½" },
65                  { 0, 0, 0, 0 } },
66
67 /*JP
68   cav_abil[] = { { 7, &(HFast), "quick", "slow" },
69 */
70   cav_abil[] = { { 7, &(HFast), "\91f\91\81\82³\82ð\93¾\82½", "\92x\82­\82È\82Á\82½" },
71 /*JP
72                  { 15, &(HWarning), "sensitive", "" },
73 */
74                  { 15, &(HWarning), "\95q\8a´\82É\82È\82Á\82½", "\93Ý\8a´\82É\82È\82Á\82½" },
75                  { 0, 0, 0, 0 } },
76
77   hea_abil[] = { { 1, &(HPoison_resistance), "", "" },
78 /*JP
79                  { 15, &(HWarning), "sensitive", "" },
80 */
81                  { 15, &(HWarning), "\95q\8a´\82É\82È\82Á\82½", "\93Ý\8a´\82É\82È\82Á\82½" },
82                  { 0, 0, 0, 0 } },
83
84 /*JP
85   kni_abil[] = { { 7, &(HFast), "quick", "slow" }, { 0, 0, 0, 0 } },
86 */
87   kni_abil[] = { { 7, &(HFast), "\91f\91\81\82³\82ð\93¾\82½", "\92x\82­\82È\82Á\82½" }, { 0, 0, 0, 0 } },
88
89   mon_abil[] = { { 1, &(HFast), "", "" },
90                  { 1, &(HSleep_resistance), "", "" },
91                  { 1, &(HSee_invisible), "", "" },
92 /*JP
93                  { 3, &(HPoison_resistance), "healthy", "" },
94 */
95                  { 3, &(HPoison_resistance), "\8c\92\8dN\82É\82È\82Á\82½", "\95s\8c\92\8dN\82É\82È\82Á\82½" },
96 /*JP
97                  { 5, &(HStealth), "stealthy", "" },
98 */
99                  { 5, &(HStealth), "\90l\96Ú\82ð\93\90\82Þ\97Í\82ð\93¾\82½", "\90l\96Ú\82ð\93\90\82Þ\97Í\82ð\8e¸\82Á\82½" },
100 /*JP
101                  { 7, &(HWarning), "sensitive", "" },
102 */
103                  { 7, &(HWarning), "\95q\8a´\82É\82È\82Á\82½", "\93Ý\8a´\82É\82È\82Á\82½" },
104 /*JP
105                  { 9, &(HSearching), "perceptive", "unaware" },
106 */
107                  { 9, &(HSearching), "\92m\8ao\97Í\82ð\93¾\82½", "\92m\8ao\97Í\82ð\8e¸\82Á\82½" },
108 /*JP
109                  { 11, &(HFire_resistance), "cool", "warmer" },
110 */
111                  { 11, &(HFire_resistance), "\97â\82½\82­\82È\82Á\82½", "\92g\82©\82­\82È\82Á\82½" },
112 /*JP
113                  { 13, &(HCold_resistance), "warm", "cooler" },
114 */
115                  { 13, &(HCold_resistance), "\92g\82©\82­\82È\82Á\82½", "\97â\82½\82­\82È\82Á\82½"},
116 /*JP
117                  { 15, &(HShock_resistance), "insulated", "conductive" },
118 */
119                  { 15, &(HShock_resistance), "\90â\89\8f\82³\82ê\82½", "\93±\93d\82³\82ê\82½" },
120 /*JP
121                  { 17, &(HTeleport_control), "controlled", "uncontrolled" },
122 */
123                  { 17, &(HTeleport_control), "\90§\8cä\97Í\82ð\93¾\82½", "\90§\8cä\97Í\82ð\8e¸\82Á\82½" },
124                  { 0, 0, 0, 0 } },
125
126 /*JP
127   pri_abil[] = { { 15, &(HWarning), "sensitive", "" },
128 */
129   pri_abil[] = { { 15, &(HWarning), "\95q\8a´\82É\82È\82Á\82½", "\93Ý\8a´\82É\82È\82Á\82½" },
130 /*JP
131                  { 20, &(HFire_resistance), "cool", "warmer" },
132 */
133                  { 20, &(HFire_resistance), "\97â\82½\82­\82È\82Á\82½", "\92g\82©\82­\82È\82Á\82½" },
134                  { 0, 0, 0, 0 } },
135
136   ran_abil[] = { { 1, &(HSearching), "", "" },
137 /*JP
138                  { 7, &(HStealth), "stealthy", "" },
139 */
140                  { 7, &(HStealth), "\90l\96Ú\82ð\93\90\82Þ\97Í\82ð\93¾\82½", "\90l\96Ú\82ð\93\90\82Þ\97Í\82ð\8e¸\82Á\82½" },
141                  { 15, &(HSee_invisible), "", "" },
142                  { 0, 0, 0, 0 } },
143
144   rog_abil[] = { { 1, &(HStealth), "", "" },
145 /*JP
146                  { 10, &(HSearching), "perceptive", "" },
147 */
148                  { 10, &(HSearching), "\92m\8ao\97Í\82ð\93¾\82½", "\92m\8ao\97Í\82ð\8e¸\82Á\82½" },
149                  { 0, 0, 0, 0 } },
150
151   sam_abil[] = { { 1, &(HFast), "", "" },
152 /*JP
153                  { 15, &(HStealth), "stealthy", "" },
154 */
155                  { 15, &(HStealth), "\90l\96Ú\82ð\93\90\82Þ\97Í\82ð\93¾\82½", "\90l\96Ú\82ð\93\90\82Þ\97Í\82ð\8e¸\82Á\82½" },
156                  { 0, 0, 0, 0 } },
157
158 /*JP
159   tou_abil[] = { { 10, &(HSearching), "perceptive", "" },
160 */
161   tou_abil[] = { { 10, &(HSearching), "\92m\8ao\97Í\82ð\93¾\82½", "\92m\8ao\97Í\82ð\8e¸\82Á\82½" },
162 /*JP
163                  { 20, &(HPoison_resistance), "hardy", "" },
164 */
165                  { 20, &(HPoison_resistance), "\96Æ\89u\97Í\82ð\93¾\82½", "\96Æ\89u\97Í\82ð\8e¸\82Á\82½" },
166                  { 0, 0, 0, 0 } },
167
168   val_abil[] = { { 1, &(HCold_resistance), "", "" },
169                  { 1, &(HStealth), "", "" },
170 /*JP
171                  { 7, &(HFast), "quick", "slow" },
172 */
173                  { 7, &(HFast), "\91f\91\81\82³\82ð\93¾\82½", "\92x\82­\82È\82Á\82½" },
174                  { 0, 0, 0, 0 } },
175
176 /*JP
177   wiz_abil[] = { { 15, &(HWarning), "sensitive", "" },
178 */
179   wiz_abil[] = { { 15, &(HWarning), "\95q\8a´\82É\82È\82Á\82½", "\93Ý\8a´\82É\82È\82Á\82½" },
180 /*JP
181                  { 17, &(HTeleport_control), "controlled", "uncontrolled" },
182 */
183                  { 17, &(HTeleport_control), "\90§\8cä\97Í\82ð\93¾\82½", "\90§\8cä\97Í\82ð\8e¸\82Á\82½" },
184                  { 0, 0, 0, 0 } },
185
186   /* Intrinsics conferred by race */
187   dwa_abil[] = { { 1, &HInfravision, "", "" },
188                  { 0, 0, 0, 0 } },
189
190   elf_abil[] = { { 1, &HInfravision, "", "" },
191 /*JP
192                  { 4, &HSleep_resistance, "awake", "tired" },
193 */
194                  { 4, &(HSleep_resistance), "\96Ú\82ª\8ao\82ß\82½", "\96°\82­\82È\82Á\82½" },
195                  { 0, 0, 0, 0 } },
196
197   gno_abil[] = { { 1, &HInfravision, "", "" },
198                  { 0, 0, 0, 0 } },
199
200   orc_abil[] = { { 1, &HInfravision, "", "" },
201                  { 1, &HPoison_resistance, "", "" },
202                  { 0, 0, 0, 0 } },
203
204   hum_abil[] = { { 0, 0, 0, 0 } };
205
206 STATIC_DCL void NDECL(exerper);
207 STATIC_DCL void FDECL(postadjabil, (long *));
208 STATIC_DCL const struct innate *FDECL(role_abil, (int));
209 STATIC_DCL const struct innate *FDECL(check_innate_abil, (long *, long));
210 STATIC_DCL int FDECL(innately, (long *));
211
212 /* adjust an attribute; return TRUE if change is made, FALSE otherwise */
213 boolean
214 adjattrib(ndx, incr, msgflg)
215 int ndx, incr;
216 int msgflg; /* positive => no message, zero => message, and */
217 {           /* negative => conditional (msg if change made) */
218     int old_acurr, old_abase, old_amax, decr;
219     boolean abonflg;
220     const char *attrstr;
221
222     if (Fixed_abil || !incr)
223         return FALSE;
224
225     if ((ndx == A_INT || ndx == A_WIS) && uarmh && uarmh->otyp == DUNCE_CAP) {
226         if (msgflg == 0)
227 /*JP
228             Your("cap constricts briefly, then relaxes again.");
229 */
230             Your("\96X\8eq\82ª\82µ\82Î\82ç\82­\82Ì\8aÔ\83L\83\85\82Á\82Æ\92÷\82ß\82Â\82¯\81C\82»\82µ\82Ä\82ä\82é\82ñ\82¾\81D");
231         return FALSE;
232     }
233
234     old_acurr = ACURR(ndx);
235     old_abase = ABASE(ndx);
236     old_amax = AMAX(ndx);
237     ABASE(ndx) += incr; /* when incr is negative, this reduces ABASE() */
238     if (incr > 0) {
239         if (ABASE(ndx) > AMAX(ndx)) {
240             AMAX(ndx) = ABASE(ndx);
241             if (AMAX(ndx) > ATTRMAX(ndx))
242                 ABASE(ndx) = AMAX(ndx) = ATTRMAX(ndx);
243         }
244         attrstr = plusattr[ndx];
245         abonflg = (ABON(ndx) < 0);
246     } else { /* incr is negative */
247         if (ABASE(ndx) < ATTRMIN(ndx)) {
248             /*
249              * If base value has dropped so low that it is trying to be
250              * taken below the minimum, reduce max value (peak reached)
251              * instead.  That means that restore ability and repeated
252              * applications of unicorn horn will not be able to recover
253              * all the lost value.  As of 3.6.2, we only take away
254              * some (average half, possibly zero) of the excess from max
255              * instead of all of it, but without intervening recovery, it
256              * can still eventually drop to the minimum allowed.  After
257              * that, it can't be recovered, only improved with new gains.
258              *
259              * This used to assign a new negative value to incr and then
260              * add it, but that could affect messages below, possibly
261              * making a large decrease be described as a small one.
262              *
263              * decr = rn2(-(ABASE - ATTRMIN) + 1);
264              */
265             decr = rn2(ATTRMIN(ndx) - ABASE(ndx) + 1);
266             ABASE(ndx) = ATTRMIN(ndx);
267             AMAX(ndx) -= decr;
268             if (AMAX(ndx) < ATTRMIN(ndx))
269                 AMAX(ndx) = ATTRMIN(ndx);
270         }
271         attrstr = minusattr[ndx];
272         abonflg = (ABON(ndx) > 0);
273     }
274     if (ACURR(ndx) == old_acurr) {
275         if (msgflg == 0 && flags.verbose) {
276             if (ABASE(ndx) == old_abase && AMAX(ndx) == old_amax) {
277 #if 0 /*JP:T*/
278                 pline("You're %s as %s as you can get.",
279                       abonflg ? "currently" : "already", attrstr);
280 #else
281                 You("%s\8f\\95ª\82É%s\81D",
282                       abonflg ? "\8d¡\82Ì\82Æ\82±\82ë" : "\8aù\82É", attrstr);
283 #endif
284             } else {
285                 /* current stayed the same but base value changed, or
286                    base is at minimum and reduction caused max to drop */
287 #if 0 /*JP:T*/
288                 Your("innate %s has %s.", attrname[ndx],
289                      (incr > 0) ? "improved" : "declined");
290 #else
291                 Your("\96{\8e¿\93I\82È%s\82ª%s\82µ\82½\81D", attrname[ndx],
292                      (incr > 0) ? "\8cü\8fã" : "\92á\89º");
293 #endif
294             }
295         }
296         return FALSE;
297     }
298
299     if (msgflg <= 0)
300 /*JP
301         You_feel("%s%s!", (incr > 1 || incr < -1) ? "very " : "", attrstr);
302 */
303         You("%s%s\82È\82Á\82½\82æ\82¤\82È\8bC\82ª\82µ\82½\81I", (incr > 1 || incr < -1) ? "\82Æ\82Ä\82à" : "", jconj_adj(attrstr));
304     context.botl = TRUE;
305     if (program_state.in_moveloop && (ndx == A_STR || ndx == A_CON))
306         (void) encumber_msg();
307     return TRUE;
308 }
309
310 void
311 gainstr(otmp, incr, givemsg)
312 struct obj *otmp;
313 int incr;
314 boolean givemsg;
315 {
316     int num = incr;
317
318     if (!num) {
319         if (ABASE(A_STR) < 18)
320             num = (rn2(4) ? 1 : rnd(6));
321         else if (ABASE(A_STR) < STR18(85))
322             num = rnd(10);
323         else
324             num = 1;
325     }
326     (void) adjattrib(A_STR, (otmp && otmp->cursed) ? -num : num,
327                      givemsg ? -1 : 1);
328 }
329
330 /* may kill you; cause may be poison or monster like 'a' */
331 void
332 losestr(num)
333 register int num;
334 {
335     int ustr = ABASE(A_STR) - num;
336
337     while (ustr < 3) {
338         ++ustr;
339         --num;
340         if (Upolyd) {
341             u.mh -= 6;
342             u.mhmax -= 6;
343         } else {
344             u.uhp -= 6;
345             u.uhpmax -= 6;
346         }
347     }
348     (void) adjattrib(A_STR, -num, 1);
349 }
350
351 static const struct poison_effect_message {
352     void VDECL((*delivery_func), (const char *, ...));
353     const char *effect_msg;
354 } poiseff[] = {
355 #if 0 /*JP:T*/
356     { You_feel, "weaker" },             /* A_STR */
357 #else
358     { You_feel, "\8eã\82­\82È\82Á\82½" },         /* A_STR */
359 #endif
360 #if 0 /*JP:T*/
361     { Your, "brain is on fire" },       /* A_INT */
362 #else
363     { You, "\93ª\82É\8c\8c\82ª\82Ì\82Ú\82Á\82½" },        /* A_INT */
364 #endif
365 #if 0 /*JP:T*/
366     { Your, "judgement is impaired" },  /* A_WIS */
367 #else
368     { You, "\94»\92f\97Í\82ð\8e¸\82Á\82½" },          /* A_WIS */
369 #endif
370 #if 0 /*JP:T*/
371     { Your, "muscles won't obey you" }, /* A_DEX */
372 #else
373     { You, "\8ev\82¤\82æ\82¤\82É\93®\82¯\82È\82¢" },      /* A_DEX */
374 #endif
375 #if 0 /*JP:T*/
376     { You_feel, "very sick" },          /* A_CON */
377 #else
378     { You_feel, "\82Æ\82Ä\82à\8bC\95ª\82ª\88«\82­\82È\82Á\82½" }, /* A_CON */
379 #endif
380 #if 0 /*JP:T*/
381     { You, "break out in hives" }       /* A_CHA */
382 #else
383     { You, "\82\82ñ\82Ü\82µ\82ñ\82ª\82 \82ç\82í\82ê\82½" }   /* A_CHA */
384 #endif
385 };
386
387 /* feedback for attribute loss due to poisoning */
388 void
389 poisontell(typ, exclaim)
390 int typ;         /* which attribute */
391 boolean exclaim; /* emphasis */
392 {
393     void VDECL((*func), (const char *, ...)) = poiseff[typ].delivery_func;
394     const char *msg_txt = poiseff[typ].effect_msg;
395
396     /*
397      * "You feel weaker" or "you feel very sick" aren't appropriate when
398      * wearing or wielding something (gauntlets of power, Ogresmasher)
399      * which forces the attribute to maintain its maximum value.
400      * Phrasing for other attributes which might have fixed values
401      * (dunce cap) is such that we don't need message fixups for them.
402      */
403     if (typ == A_STR && ACURR(A_STR) == STR19(25))
404 /*JP
405         msg_txt = "innately weaker";
406 */
407         msg_txt = "\96{\8e¿\93I\82É\8eã\82­\82È\82Á\82½";
408     else if (typ == A_CON && ACURR(A_CON) == 25)
409 /*JP
410         msg_txt = "sick inside";
411 */
412         msg_txt = "\93à\95\94\82É\95a\82ð\82©\82©\82¦\82½";
413
414 /*JP
415     (*func)("%s%c", msg_txt, exclaim ? '!' : '.');
416 */
417     (*func)("%s%s", msg_txt, exclaim ? "\81I" : "\81D");
418 }
419
420 /* called when an attack or trap has poisoned hero (used to be in mon.c) */
421 void
422 poisoned(reason, typ, pkiller, fatal, thrown_weapon)
423 const char *reason,    /* controls what messages we display */
424            *pkiller;   /* for score+log file if fatal */
425 int typ, fatal;        /* if fatal is 0, limit damage to adjattrib */
426 boolean thrown_weapon; /* thrown weapons are less deadly */
427 {
428     int i, loss, kprefix = KILLED_BY_AN;
429
430     /* inform player about being poisoned unless that's already been done;
431        "blast" has given a "blast of poison gas" message; "poison arrow",
432        "poison dart", etc have implicitly given poison messages too... */
433 #if 0 /*JP:T*/
434     if (strcmp(reason, "blast") && !strstri(reason, "poison")) {
435 #else
436     if (strcmp(reason, "\95\97") && strcmp(reason, "\91§") && !strstri(reason, "\93Å")) {
437 #endif
438 #if 0 /*JP*/
439         boolean plural = (reason[strlen(reason) - 1] == 's') ? 1 : 0;
440 #endif
441
442         /* avoid "The" Orcus's sting was poisoned... */
443 #if 0 /*JP:T*/
444         pline("%s%s %s poisoned!",
445               isupper((uchar) *reason) ? "" : "The ", reason,
446               plural ? "were" : "was");
447 #else
448         pline("%s\82Í\93Å\82É\82¨\82©\82³\82ê\82Ä\82¢\82é\81I", reason);
449 #endif
450     }
451     if (Poison_resistance) {
452 #if 0 /*JP*/
453         if (!strcmp(reason, "blast"))
454 #else
455         if (!strcmp(reason, "\95\97") || !strcmp(reason, "\91§"))
456 #endif
457             shieldeff(u.ux, u.uy);
458 /*JP
459         pline_The("poison doesn't seem to affect you.");
460 */
461         pline("\93Å\82Í\8cø\82©\82È\82©\82Á\82½\82æ\82¤\82¾\81D");
462         return;
463     }
464
465 #if 0 /*JP*//*\93ú\96{\8cê\82Å\82Í\95s\97v*/
466     /* suppress killer prefix if it already has one */
467     i = name_to_mon(pkiller);
468     if (i >= LOW_PM && (mons[i].geno & G_UNIQ)) {
469         kprefix = KILLED_BY;
470         if (!type_is_pname(&mons[i]))
471             pkiller = the(pkiller);
472     } else if (!strncmpi(pkiller, "the ", 4) || !strncmpi(pkiller, "an ", 3)
473                || !strncmpi(pkiller, "a ", 2)) {
474         /*[ does this need a plural check too? ]*/
475         kprefix = KILLED_BY;
476     }
477 #endif
478
479     i = !fatal ? 1 : rn2(fatal + (thrown_weapon ? 20 : 0));
480     if (i == 0 && typ != A_CHA) {
481         /* instant kill */
482         u.uhp = -1;
483         context.botl = TRUE;
484 /*JP
485         pline_The("poison was deadly...");
486 */
487         pline("\93Å\82Í\92v\8e\80\97Ê\82¾\82Á\82½\81D\81D\81D");
488     } else if (i > 5) {
489         /* HP damage; more likely--but less severe--with missiles */
490         loss = thrown_weapon ? rnd(6) : rn1(10, 6);
491         losehp(loss, pkiller, kprefix); /* poison damage */
492     } else {
493         /* attribute loss; if typ is A_STR, reduction in current and
494            maximum HP will occur once strength has dropped down to 3 */
495         loss = (thrown_weapon || !fatal) ? 1 : d(2, 2); /* was rn1(3,3) */
496         /* check that a stat change was made */
497         if (adjattrib(typ, -loss, 1))
498             poisontell(typ, TRUE);
499     }
500
501     if (u.uhp < 1) {
502         killer.format = kprefix;
503         Strcpy(killer.name, pkiller);
504 #if 0 /*JP*/
505         /* "Poisoned by a poisoned ___" is redundant */
506         done(strstri(pkiller, "poison") ? DIED : POISONING);
507 #else /*JP:\93ú\96{\8cê\82Å\82Í\8bæ\95Ê\82µ\82Ä\82¢\82È\82¢*/
508         done(POISONING);
509 #endif
510     }
511     (void) encumber_msg();
512 }
513
514 void
515 change_luck(n)
516 register schar n;
517 {
518     u.uluck += n;
519     if (u.uluck < 0 && u.uluck < LUCKMIN)
520         u.uluck = LUCKMIN;
521     if (u.uluck > 0 && u.uluck > LUCKMAX)
522         u.uluck = LUCKMAX;
523 }
524
525 int
526 stone_luck(parameter)
527 boolean parameter; /* So I can't think up of a good name.  So sue me. --KAA */
528 {
529     register struct obj *otmp;
530     register long bonchance = 0;
531
532     for (otmp = invent; otmp; otmp = otmp->nobj)
533         if (confers_luck(otmp)) {
534             if (otmp->cursed)
535                 bonchance -= otmp->quan;
536             else if (otmp->blessed)
537                 bonchance += otmp->quan;
538             else if (parameter)
539                 bonchance += otmp->quan;
540         }
541
542     return sgn((int) bonchance);
543 }
544
545 /* there has just been an inventory change affecting a luck-granting item */
546 void
547 set_moreluck()
548 {
549     int luckbon = stone_luck(TRUE);
550
551     if (!luckbon && !carrying(LUCKSTONE))
552         u.moreluck = 0;
553     else if (luckbon >= 0)
554         u.moreluck = LUCKADD;
555     else
556         u.moreluck = -LUCKADD;
557 }
558
559 void
560 restore_attrib()
561 {
562     int i, equilibrium;;
563
564     /*
565      * Note:  this gets called on every turn but ATIME() is never set
566      * to non-zero anywhere, and ATEMP() is only used for strength loss
567      * from hunger, so it doesn't actually do anything.
568      */
569
570     for (i = 0; i < A_MAX; i++) { /* all temporary losses/gains */
571         equilibrium = (i == A_STR && u.uhs >= WEAK) ? -1 : 0;
572         if (ATEMP(i) != equilibrium && ATIME(i) != 0) {
573             if (!(--(ATIME(i)))) { /* countdown for change */
574                 ATEMP(i) += (ATEMP(i) > 0) ? -1 : 1;
575                 context.botl = TRUE;
576                 if (ATEMP(i)) /* reset timer */
577                     ATIME(i) = 100 / ACURR(A_CON);
578             }
579         }
580     }
581     if (context.botl)
582         (void) encumber_msg();
583 }
584
585 #define AVAL 50 /* tune value for exercise gains */
586
587 void
588 exercise(i, inc_or_dec)
589 int i;
590 boolean inc_or_dec;
591 {
592     debugpline0("Exercise:");
593     if (i == A_INT || i == A_CHA)
594         return; /* can't exercise these */
595
596     /* no physical exercise while polymorphed; the body's temporary */
597     if (Upolyd && i != A_WIS)
598         return;
599
600     if (abs(AEXE(i)) < AVAL) {
601         /*
602          *      Law of diminishing returns (Part I):
603          *
604          *      Gain is harder at higher attribute values.
605          *      79% at "3" --> 0% at "18"
606          *      Loss is even at all levels (50%).
607          *
608          *      Note: *YES* ACURR is the right one to use.
609          */
610         AEXE(i) += (inc_or_dec) ? (rn2(19) > ACURR(i)) : -rn2(2);
611         debugpline3("%s, %s AEXE = %d",
612                     (i == A_STR) ? "Str" : (i == A_WIS) ? "Wis" : (i == A_DEX)
613                                                                       ? "Dex"
614                                                                       : "Con",
615                     (inc_or_dec) ? "inc" : "dec", AEXE(i));
616     }
617     if (moves > 0 && (i == A_STR || i == A_CON))
618         (void) encumber_msg();
619 }
620
621 STATIC_OVL void
622 exerper()
623 {
624     if (!(moves % 10)) {
625         /* Hunger Checks */
626
627         int hs = (u.uhunger > 1000) ? SATIATED : (u.uhunger > 150)
628                                                      ? NOT_HUNGRY
629                                                      : (u.uhunger > 50)
630                                                            ? HUNGRY
631                                                            : (u.uhunger > 0)
632                                                                  ? WEAK
633                                                                  : FAINTING;
634
635         debugpline0("exerper: Hunger checks");
636         switch (hs) {
637         case SATIATED:
638             exercise(A_DEX, FALSE);
639             if (Role_if(PM_MONK))
640                 exercise(A_WIS, FALSE);
641             break;
642         case NOT_HUNGRY:
643             exercise(A_CON, TRUE);
644             break;
645         case WEAK:
646             exercise(A_STR, FALSE);
647             if (Role_if(PM_MONK)) /* fasting */
648                 exercise(A_WIS, TRUE);
649             break;
650         case FAINTING:
651         case FAINTED:
652             exercise(A_CON, FALSE);
653             break;
654         }
655
656         /* Encumbrance Checks */
657         debugpline0("exerper: Encumber checks");
658         switch (near_capacity()) {
659         case MOD_ENCUMBER:
660             exercise(A_STR, TRUE);
661             break;
662         case HVY_ENCUMBER:
663             exercise(A_STR, TRUE);
664             exercise(A_DEX, FALSE);
665             break;
666         case EXT_ENCUMBER:
667             exercise(A_DEX, FALSE);
668             exercise(A_CON, FALSE);
669             break;
670         }
671     }
672
673     /* status checks */
674     if (!(moves % 5)) {
675         debugpline0("exerper: Status checks");
676         if ((HClairvoyant & (INTRINSIC | TIMEOUT)) && !BClairvoyant)
677             exercise(A_WIS, TRUE);
678         if (HRegeneration)
679             exercise(A_STR, TRUE);
680
681         if (Sick || Vomiting)
682             exercise(A_CON, FALSE);
683         if (Confusion || Hallucination)
684             exercise(A_WIS, FALSE);
685         if ((Wounded_legs && !u.usteed) || Fumbling || HStun)
686             exercise(A_DEX, FALSE);
687     }
688 }
689
690 /* exercise/abuse text (must be in attribute order, not botl order);
691    phrased as "You must have been [][0]." or "You haven't been [][1]." */
692 static NEARDATA const char *const exertext[A_MAX][2] = {
693 #if 0 /*JP:T*/
694     { "exercising diligently", "exercising properly" },           /* Str */
695     { 0, 0 },                                                     /* Int */
696     { "very observant", "paying attention" },                     /* Wis */
697     { "working on your reflexes", "working on reflexes lately" }, /* Dex */
698     { "leading a healthy life-style", "watching your health" },   /* Con */
699     { 0, 0 },                                                     /* Cha */
700 #else
701     { "\94O\93ü\82è\82É\89^\93®\82µ\82Ä\82¢\82½", "\93K\90Ø\82É\89^\93®\82µ\82Ä\82¢\82È\82©\82Á\82½" },       /* Str */
702     { 0, 0 },                                                     /* Int */
703     { "\90T\8fd\82É\8ds\93®\82µ\82Ä\82¢\82½", "\92\8d\88Ó\95s\91«\82¾\82Á\82½" },                   /* Wis */
704     { "\94½\8eË\90_\8co\82ð\8eg\82Á\82Ä\82¢\82½", "\8dÅ\8bß\94½\8eË\90_\8co\82ð\8eg\82Á\82Ä\82¢\82È\82©\82Á\82½" }, /* Dex */
705     { "\8c\92\8dN\93I\82È\90\8a\88\82ð\82µ\82Ä\82¢\82½", "\8c\92\8dN\8aÇ\97\9d\82ð\91Ó\82Á\82Ä\82¢\82½" },         /* Con */
706     { 0, 0 },                                                     /* Cha */
707 #endif
708 };
709
710 void
711 exerchk()
712 {
713     int i, ax, mod_val, lolim, hilim;
714
715     /*  Check out the periodic accumulations */
716     exerper();
717
718     if (moves >= context.next_attrib_check) {
719         debugpline1("exerchk: ready to test. multi = %d.", multi);
720     }
721     /*  Are we ready for a test? */
722     if (moves >= context.next_attrib_check && !multi) {
723         debugpline0("exerchk: testing.");
724         /*
725          *      Law of diminishing returns (Part II):
726          *
727          *      The effects of "exercise" and "abuse" wear
728          *      off over time.  Even if you *don't* get an
729          *      increase/decrease, you lose some of the
730          *      accumulated effects.
731          */
732         for (i = 0; i < A_MAX; ++i) {
733             ax = AEXE(i);
734             /* nothing to do here if no exercise or abuse has occurred
735                (Int and Cha always fall into this category) */
736             if (!ax)
737                 continue; /* ok to skip nextattrib */
738
739             mod_val = sgn(ax); /* +1 or -1; used below */
740             /* no further effect for exercise if at max or abuse if at min;
741                can't exceed 18 via exercise even if actual max is higher */
742             lolim = ATTRMIN(i); /* usually 3; might be higher */
743             hilim = ATTRMAX(i); /* usually 18; maybe lower or higher */
744             if (hilim > 18)
745                 hilim = 18;
746             if ((ax < 0) ? (ABASE(i) <= lolim) : (ABASE(i) >= hilim))
747                 goto nextattrib;
748             /* can't exercise non-Wisdom while polymorphed; previous
749                exercise/abuse gradually wears off without impact then */
750             if (Upolyd && i != A_WIS)
751                 goto nextattrib;
752
753             debugpline2("exerchk: testing %s (%d).",
754                         (i == A_STR)
755                             ? "Str"
756                             : (i == A_INT)
757                                   ? "Int?"
758                                   : (i == A_WIS)
759                                         ? "Wis"
760                                         : (i == A_DEX)
761                                               ? "Dex"
762                                               : (i == A_CON)
763                                                     ? "Con"
764                                                     : (i == A_CHA)
765                                                           ? "Cha?"
766                                                           : "???",
767                         ax);
768             /*
769              *  Law of diminishing returns (Part III):
770              *
771              *  You don't *always* gain by exercising.
772              *  [MRS 92/10/28 - Treat Wisdom specially for balance.]
773              */
774             if (rn2(AVAL) > ((i != A_WIS) ? (abs(ax) * 2 / 3) : abs(ax)))
775                 goto nextattrib;
776
777             debugpline1("exerchk: changing %d.", i);
778             if (adjattrib(i, mod_val, -1)) {
779                 debugpline1("exerchk: changed %d.", i);
780                 /* if you actually changed an attrib - zero accumulation */
781                 AEXE(i) = ax = 0;
782                 /* then print an explanation */
783 #if 0 /*JP:T*/
784                 You("%s %s.",
785                     (mod_val > 0) ? "must have been" : "haven't been",
786                     exertext[i][(mod_val > 0) ? 0 : 1]);
787 #else
788                 You("%s\82É\88á\82¢\82È\82¢\81D",
789                     exertext[i][(mod_val > 0) ? 0 : 1]);
790 #endif
791             }
792  nextattrib:
793             /* this used to be ``AEXE(i) /= 2'' but that would produce
794                platform-dependent rounding/truncation for negative vals */
795             AEXE(i) = (abs(ax) / 2) * mod_val;
796         }
797         context.next_attrib_check += rn1(200, 800);
798         debugpline1("exerchk: next check at %ld.", context.next_attrib_check);
799     }
800 }
801
802 void
803 init_attr(np)
804 register int np;
805 {
806     register int i, x, tryct;
807
808     for (i = 0; i < A_MAX; i++) {
809         ABASE(i) = AMAX(i) = urole.attrbase[i];
810         ATEMP(i) = ATIME(i) = 0;
811         np -= urole.attrbase[i];
812     }
813
814     tryct = 0;
815     while (np > 0 && tryct < 100) {
816         x = rn2(100);
817         for (i = 0; (i < A_MAX) && ((x -= urole.attrdist[i]) > 0); i++)
818             ;
819         if (i >= A_MAX)
820             continue; /* impossible */
821
822         if (ABASE(i) >= ATTRMAX(i)) {
823             tryct++;
824             continue;
825         }
826         tryct = 0;
827         ABASE(i)++;
828         AMAX(i)++;
829         np--;
830     }
831
832     tryct = 0;
833     while (np < 0 && tryct < 100) { /* for redistribution */
834
835         x = rn2(100);
836         for (i = 0; (i < A_MAX) && ((x -= urole.attrdist[i]) > 0); i++)
837             ;
838         if (i >= A_MAX)
839             continue; /* impossible */
840
841         if (ABASE(i) <= ATTRMIN(i)) {
842             tryct++;
843             continue;
844         }
845         tryct = 0;
846         ABASE(i)--;
847         AMAX(i)--;
848         np++;
849     }
850 }
851
852 void
853 redist_attr()
854 {
855     register int i, tmp;
856
857     for (i = 0; i < A_MAX; i++) {
858         if (i == A_INT || i == A_WIS)
859             continue;
860         /* Polymorphing doesn't change your mind */
861         tmp = AMAX(i);
862         AMAX(i) += (rn2(5) - 2);
863         if (AMAX(i) > ATTRMAX(i))
864             AMAX(i) = ATTRMAX(i);
865         if (AMAX(i) < ATTRMIN(i))
866             AMAX(i) = ATTRMIN(i);
867         ABASE(i) = ABASE(i) * AMAX(i) / tmp;
868         /* ABASE(i) > ATTRMAX(i) is impossible */
869         if (ABASE(i) < ATTRMIN(i))
870             ABASE(i) = ATTRMIN(i);
871     }
872     (void) encumber_msg();
873 }
874
875 STATIC_OVL
876 void
877 postadjabil(ability)
878 long *ability;
879 {
880     if (!ability)
881         return;
882     if (ability == &(HWarning) || ability == &(HSee_invisible))
883         see_monsters();
884 }
885
886 STATIC_OVL const struct innate *
887 role_abil(r)
888 int r;
889 {
890     const struct {
891         short role;
892         const struct innate *abil;
893     } roleabils[] = {
894         { PM_ARCHEOLOGIST, arc_abil },
895         { PM_BARBARIAN, bar_abil },
896         { PM_CAVEMAN, cav_abil },
897         { PM_HEALER, hea_abil },
898         { PM_KNIGHT, kni_abil },
899         { PM_MONK, mon_abil },
900         { PM_PRIEST, pri_abil },
901         { PM_RANGER, ran_abil },
902         { PM_ROGUE, rog_abil },
903         { PM_SAMURAI, sam_abil },
904         { PM_TOURIST, tou_abil },
905         { PM_VALKYRIE, val_abil },
906         { PM_WIZARD, wiz_abil },
907         { 0, 0 }
908     };
909     int i;
910
911     for (i = 0; roleabils[i].abil && roleabils[i].role != r; i++)
912         continue;
913     return roleabils[i].abil;
914 }
915
916 STATIC_OVL const struct innate *
917 check_innate_abil(ability, frommask)
918 long *ability;
919 long frommask;
920 {
921     const struct innate *abil = 0;
922
923     if (frommask == FROMEXPER)
924         abil = role_abil(Role_switch);
925     else if (frommask == FROMRACE)
926         switch (Race_switch) {
927         case PM_DWARF:
928             abil = dwa_abil;
929             break;
930         case PM_ELF:
931             abil = elf_abil;
932             break;
933         case PM_GNOME:
934             abil = gno_abil;
935             break;
936         case PM_ORC:
937             abil = orc_abil;
938             break;
939         case PM_HUMAN:
940             abil = hum_abil;
941             break;
942         default:
943             break;
944         }
945
946     while (abil && abil->ability) {
947         if ((abil->ability == ability) && (u.ulevel >= abil->ulevel))
948             return abil;
949         abil++;
950     }
951     return (struct innate *) 0;
952 }
953
954 /* reasons for innate ability */
955 #define FROM_NONE 0
956 #define FROM_ROLE 1 /* from experience at level 1 */
957 #define FROM_RACE 2
958 #define FROM_INTR 3 /* intrinsically (eating some corpse or prayer reward) */
959 #define FROM_EXP  4 /* from experience for some level > 1 */
960 #define FROM_FORM 5
961 #define FROM_LYCN 6
962
963 /* check whether particular ability has been obtained via innate attribute */
964 STATIC_OVL int
965 innately(ability)
966 long *ability;
967 {
968     const struct innate *iptr;
969
970     if ((iptr = check_innate_abil(ability, FROMEXPER)) != 0)
971         return (iptr->ulevel == 1) ? FROM_ROLE : FROM_EXP;
972     if ((iptr = check_innate_abil(ability, FROMRACE)) != 0)
973         return FROM_RACE;
974     if ((*ability & FROMOUTSIDE) != 0L)
975         return FROM_INTR;
976     if ((*ability & FROMFORM) != 0L)
977         return FROM_FORM;
978     return FROM_NONE;
979 }
980
981 int
982 is_innate(propidx)
983 int propidx;
984 {
985     int innateness;
986
987     /* innately() would report FROM_FORM for this; caller wants specificity */
988     if (propidx == DRAIN_RES && u.ulycn >= LOW_PM)
989         return FROM_LYCN;
990     if (propidx == FAST && Very_fast)
991         return FROM_NONE; /* can't become very fast innately */
992     if ((innateness = innately(&u.uprops[propidx].intrinsic)) != FROM_NONE)
993         return innateness;
994     if (propidx == JUMPING && Role_if(PM_KNIGHT)
995         /* knight has intrinsic jumping, but extrinsic is more versatile so
996            ignore innateness if equipment is going to claim responsibility */
997         && !u.uprops[propidx].extrinsic)
998         return FROM_ROLE;
999     if (propidx == BLINDED && !haseyes(youmonst.data))
1000         return FROM_FORM;
1001     return FROM_NONE;
1002 }
1003
1004 char *
1005 from_what(propidx)
1006 int propidx; /* special cases can have negative values */
1007 {
1008     static char buf[BUFSZ];
1009
1010     buf[0] = '\0';
1011     /*
1012      * Restrict the source of the attributes just to debug mode for now
1013      */
1014 /*JP:\81u\82 \82È\82½\82Í\82 \82È\82½\82Ì\81c\82É\82æ\82Á\82Ä\81v\82Æ\82È\82é\82Æ\95s\8e©\91R\82È\82Ì\82Åsimpleonames()\82ð\8eg\82¤*/
1015 /*JP: \96{\97\88\82Íminimal_xname()\82ð\8eg\82¤\82×\82«\82¾\82ªstatic\82È\82Ì\82Å\91ã\97p*/
1016     if (wizard) {
1017 /*JP
1018         static NEARDATA const char because_of[] = " because of %s";
1019 */
1020         static NEARDATA const char because_of[] = "%s\82É\82æ\82Á\82Ä";
1021
1022         if (propidx >= 0) {
1023 #if 0 /*JP*/
1024             char *p;
1025 #endif
1026             struct obj *obj = (struct obj *) 0;
1027             int innateness = is_innate(propidx);
1028
1029             /*
1030              * Properties can be obtained from multiple sources and we
1031              * try to pick the most significant one.  Classification
1032              * priority is not set in stone; current precedence is:
1033              * "from the start" (from role or race at level 1),
1034              * "from outside" (eating corpse, divine reward, blessed potion),
1035              * "from experience" (from role or race at level 2+),
1036              * "from current form" (while polymorphed),
1037              * "from timed effect" (potion or spell),
1038              * "from worn/wielded equipment" (Firebrand, elven boots, &c),
1039              * "from carried equipment" (mainly quest artifacts).
1040              * There are exceptions.  Versatile jumping from spell or boots
1041              * takes priority over knight's innate but limited jumping.
1042              */
1043             if (propidx == BLINDED && u.uroleplay.blind)
1044 /*JP
1045                 Sprintf(buf, " from birth");
1046 */
1047                 Sprintf(buf, "\90\82Ü\82ê\82Ä\82©\82ç\82¸\82Á\82Æ");
1048             else if (innateness == FROM_ROLE || innateness == FROM_RACE)
1049 /*JP
1050                 Strcpy(buf, " innately");
1051 */
1052                 Strcpy(buf, "\90\82Ü\82ê\82È\82ª\82ç\82É");
1053             else if (innateness == FROM_INTR) /* [].intrinsic & FROMOUTSIDE */
1054 /*JP
1055                 Strcpy(buf, " intrinsically");
1056 */
1057                 Strcpy(buf, "\96{\8e¿\93I\82É");
1058             else if (innateness == FROM_EXP)
1059 /*JP
1060                 Strcpy(buf, " because of your experience");
1061 */
1062                 Strcpy(buf, "\8co\8c±\82É\82æ\82Á\82Ä");
1063             else if (innateness == FROM_LYCN)
1064 /*JP
1065                 Strcpy(buf, " due to your lycanthropy");
1066 */
1067                 Strcpy(buf, "\8fb\89»\95a\82É\82æ\82Á\82Ä");
1068             else if (innateness == FROM_FORM)
1069 /*JP
1070                 Strcpy(buf, " from current creature form");
1071 */
1072                 Strcpy(buf, "\8c»\8dÝ\82Ì\8ep\82É\82æ\82Á\82Ä");
1073             else if (propidx == FAST && Very_fast)
1074 #if 0 /*JP:T*/
1075                 Sprintf(buf, because_of,
1076                         ((HFast & TIMEOUT) != 0L) ? "a potion or spell"
1077                           : ((EFast & W_ARMF) != 0L && uarmf->dknown
1078                              && objects[uarmf->otyp].oc_name_known)
1079                               ? ysimple_name(uarmf) /* speed boots */
1080                                 : EFast ? "worn equipment"
1081                                   : something);
1082 #else
1083                 Sprintf(buf, because_of,
1084                         ((HFast & TIMEOUT) != 0L) ? "\96ò\82â\8eô\95¶"
1085                           : ((EFast & W_ARMF) != 0L && uarmf->dknown
1086                              && objects[uarmf->otyp].oc_name_known)
1087                               ? ysimple_name(uarmf) /* speed boots */
1088                                 : EFast ? "\91\95\94õ"
1089                                   : something);
1090 #endif
1091             else if (wizard
1092                      && (obj = what_gives(&u.uprops[propidx].extrinsic)) != 0)
1093                 Sprintf(buf, because_of, obj->oartifact
1094                                              ? bare_artifactname(obj)
1095 /*JP
1096                                              : ysimple_name(obj));
1097 */
1098                                              : simpleonames(obj));
1099             else if (propidx == BLINDED && Blindfolded_only)
1100 /*JP
1101                 Sprintf(buf, because_of, ysimple_name(ublindf));
1102 */
1103                 Sprintf(buf, because_of, simpleonames(ublindf));
1104
1105 #if 0 /*JP*//*\95s\97v*/
1106             /* remove some verbosity and/or redundancy */
1107             if ((p = strstri(buf, " pair of ")) != 0)
1108                 copynchars(p + 1, p + 9, BUFSZ); /* overlapping buffers ok */
1109             else if (propidx == STRANGLED
1110                      && (p = strstri(buf, " of strangulation")) != 0)
1111                 *p = '\0';
1112 #endif
1113
1114         } else { /* negative property index */
1115             /* if more blocking capabilities get implemented we'll need to
1116                replace this with what_blocks() comparable to what_gives() */
1117             switch (-propidx) {
1118             case BLINDED:
1119                 if (ublindf
1120                     && ublindf->oartifact == ART_EYES_OF_THE_OVERWORLD)
1121                     Sprintf(buf, because_of, bare_artifactname(ublindf));
1122                 break;
1123             case INVIS:
1124                 if (u.uprops[INVIS].blocked & W_ARMC)
1125 #if 0 /*JP*/
1126                     Sprintf(buf, because_of,
1127                             ysimple_name(uarmc)); /* mummy wrapping */
1128 #else
1129                     Sprintf(buf, because_of,
1130                             simpleonames(uarmc)); /* mummy wrapping */
1131 #endif
1132                 break;
1133             case CLAIRVOYANT:
1134                 if (wizard && (u.uprops[CLAIRVOYANT].blocked & W_ARMH))
1135 #if 0 /*JP*/
1136                     Sprintf(buf, because_of,
1137                             ysimple_name(uarmh)); /* cornuthaum */
1138 #else
1139                     Sprintf(buf, because_of,
1140                             simpleonames(uarmh)); /* cornuthaum */
1141 #endif
1142                 break;
1143             }
1144         }
1145
1146     } /*wizard*/
1147     return buf;
1148 }
1149
1150 void
1151 adjabil(oldlevel, newlevel)
1152 int oldlevel, newlevel;
1153 {
1154     register const struct innate *abil, *rabil;
1155     long prevabil, mask = FROMEXPER;
1156
1157     abil = role_abil(Role_switch);
1158
1159     switch (Race_switch) {
1160     case PM_ELF:
1161         rabil = elf_abil;
1162         break;
1163     case PM_ORC:
1164         rabil = orc_abil;
1165         break;
1166     case PM_HUMAN:
1167     case PM_DWARF:
1168     case PM_GNOME:
1169     default:
1170         rabil = 0;
1171         break;
1172     }
1173
1174     while (abil || rabil) {
1175         /* Have we finished with the intrinsics list? */
1176         if (!abil || !abil->ability) {
1177             /* Try the race intrinsics */
1178             if (!rabil || !rabil->ability)
1179                 break;
1180             abil = rabil;
1181             rabil = 0;
1182             mask = FROMRACE;
1183         }
1184         prevabil = *(abil->ability);
1185         if (oldlevel < abil->ulevel && newlevel >= abil->ulevel) {
1186             /* Abilities gained at level 1 can never be lost
1187              * via level loss, only via means that remove _any_
1188              * sort of ability.  A "gain" of such an ability from
1189              * an outside source is devoid of meaning, so we set
1190              * FROMOUTSIDE to avoid such gains.
1191              */
1192             if (abil->ulevel == 1)
1193                 *(abil->ability) |= (mask | FROMOUTSIDE);
1194             else
1195                 *(abil->ability) |= mask;
1196             if (!(*(abil->ability) & INTRINSIC & ~mask)) {
1197                 if (*(abil->gainstr))
1198 /*JP
1199                     You_feel("%s!", abil->gainstr);
1200 */
1201                     You("%s\82æ\82¤\82È\8bC\82ª\82µ\82½\81I", abil->gainstr);
1202             }
1203         } else if (oldlevel >= abil->ulevel && newlevel < abil->ulevel) {
1204             *(abil->ability) &= ~mask;
1205             if (!(*(abil->ability) & INTRINSIC)) {
1206                 if (*(abil->losestr))
1207 /*JP
1208                     You_feel("%s!", abil->losestr);
1209 */
1210                     You("%s\82æ\82¤\82È\8bC\82ª\82µ\82½\81I", abil->losestr);
1211 /*JP:\82±\82Ì\8fð\8c\8f\82Í\96\9e\82³\82È\82¢\82Í\82¸\81D*/
1212                 else if (*(abil->gainstr))
1213                     You_feel("less %s!", abil->gainstr);
1214             }
1215         }
1216         if (prevabil != *(abil->ability)) /* it changed */
1217             postadjabil(abil->ability);
1218         abil++;
1219     }
1220
1221     if (oldlevel > 0) {
1222         if (newlevel > oldlevel)
1223             add_weapon_skill(newlevel - oldlevel);
1224         else
1225             lose_weapon_skill(oldlevel - newlevel);
1226     }
1227 }
1228
1229 int
1230 newhp()
1231 {
1232     int hp, conplus;
1233
1234     if (u.ulevel == 0) {
1235         /* Initialize hit points */
1236         hp = urole.hpadv.infix + urace.hpadv.infix;
1237         if (urole.hpadv.inrnd > 0)
1238             hp += rnd(urole.hpadv.inrnd);
1239         if (urace.hpadv.inrnd > 0)
1240             hp += rnd(urace.hpadv.inrnd);
1241         if (moves <= 1L) { /* initial hero; skip for polyself to new man */
1242             /* Initialize alignment stuff */
1243             u.ualign.type = aligns[flags.initalign].value;
1244             u.ualign.record = urole.initrecord;
1245         }
1246         /* no Con adjustment for initial hit points */
1247     } else {
1248         if (u.ulevel < urole.xlev) {
1249             hp = urole.hpadv.lofix + urace.hpadv.lofix;
1250             if (urole.hpadv.lornd > 0)
1251                 hp += rnd(urole.hpadv.lornd);
1252             if (urace.hpadv.lornd > 0)
1253                 hp += rnd(urace.hpadv.lornd);
1254         } else {
1255             hp = urole.hpadv.hifix + urace.hpadv.hifix;
1256             if (urole.hpadv.hirnd > 0)
1257                 hp += rnd(urole.hpadv.hirnd);
1258             if (urace.hpadv.hirnd > 0)
1259                 hp += rnd(urace.hpadv.hirnd);
1260         }
1261         if (ACURR(A_CON) <= 3)
1262             conplus = -2;
1263         else if (ACURR(A_CON) <= 6)
1264             conplus = -1;
1265         else if (ACURR(A_CON) <= 14)
1266             conplus = 0;
1267         else if (ACURR(A_CON) <= 16)
1268             conplus = 1;
1269         else if (ACURR(A_CON) == 17)
1270             conplus = 2;
1271         else if (ACURR(A_CON) == 18)
1272             conplus = 3;
1273         else
1274             conplus = 4;
1275         hp += conplus;
1276     }
1277     if (hp <= 0)
1278         hp = 1;
1279     if (u.ulevel < MAXULEV)
1280         u.uhpinc[u.ulevel] = (xchar) hp;
1281     return hp;
1282 }
1283
1284 schar
1285 acurr(x)
1286 int x;
1287 {
1288     register int tmp = (u.abon.a[x] + u.atemp.a[x] + u.acurr.a[x]);
1289
1290     if (x == A_STR) {
1291         if (tmp >= 125 || (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER))
1292             return (schar) 125;
1293         else
1294 #ifdef WIN32_BUG
1295             return (x = ((tmp <= 3) ? 3 : tmp));
1296 #else
1297             return (schar) ((tmp <= 3) ? 3 : tmp);
1298 #endif
1299     } else if (x == A_CHA) {
1300         if (tmp < 18
1301             && (youmonst.data->mlet == S_NYMPH || u.umonnum == PM_SUCCUBUS
1302                 || u.umonnum == PM_INCUBUS))
1303             return (schar) 18;
1304     } else if (x == A_CON) {
1305         if (uwep && uwep->oartifact == ART_OGRESMASHER)
1306             return (schar) 25;
1307     } else if (x == A_INT || x == A_WIS) {
1308         /* yes, this may raise int/wis if player is sufficiently
1309          * stupid.  there are lower levels of cognition than "dunce".
1310          */
1311         if (uarmh && uarmh->otyp == DUNCE_CAP)
1312             return (schar) 6;
1313     }
1314 #ifdef WIN32_BUG
1315     return (x = ((tmp >= 25) ? 25 : (tmp <= 3) ? 3 : tmp));
1316 #else
1317     return (schar) ((tmp >= 25) ? 25 : (tmp <= 3) ? 3 : tmp);
1318 #endif
1319 }
1320
1321 /* condense clumsy ACURR(A_STR) value into value that fits into game formulas
1322  */
1323 schar
1324 acurrstr()
1325 {
1326     register int str = ACURR(A_STR);
1327
1328     if (str <= 18)
1329         return (schar) str;
1330     if (str <= 121)
1331         return (schar) (19 + str / 50); /* map to 19..21 */
1332     else
1333         return (schar) (min(str, 125) - 100); /* 22..25 */
1334 }
1335
1336 /* when wearing (or taking off) an unID'd item, this routine is used
1337    to distinguish between observable +0 result and no-visible-effect
1338    due to an attribute not being able to exceed maximum or minimum */
1339 boolean
1340 extremeattr(attrindx) /* does attrindx's value match its max or min? */
1341 int attrindx;
1342 {
1343     /* Fixed_abil and racial MINATTR/MAXATTR aren't relevant here */
1344     int lolimit = 3, hilimit = 25, curval = ACURR(attrindx);
1345
1346     /* upper limit for Str is 25 but its value is encoded differently */
1347     if (attrindx == A_STR) {
1348         hilimit = STR19(25); /* 125 */
1349         /* lower limit for Str can also be 25 */
1350         if (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER)
1351             lolimit = hilimit;
1352     } else if (attrindx == A_CON) {
1353         if (uwep && uwep->oartifact == ART_OGRESMASHER)
1354             lolimit = hilimit;
1355     }
1356     /* this exception is hypothetical; the only other worn item affecting
1357        Int or Wis is another helmet so can't be in use at the same time */
1358     if (attrindx == A_INT || attrindx == A_WIS) {
1359         if (uarmh && uarmh->otyp == DUNCE_CAP)
1360             hilimit = lolimit = 6;
1361     }
1362
1363     /* are we currently at either limit? */
1364     return (curval == lolimit || curval == hilimit) ? TRUE : FALSE;
1365 }
1366
1367 /* avoid possible problems with alignment overflow, and provide a centralized
1368    location for any future alignment limits */
1369 void
1370 adjalign(n)
1371 int n;
1372 {
1373     int newalign = u.ualign.record + n;
1374
1375     if (n < 0) {
1376         if (newalign < u.ualign.record)
1377             u.ualign.record = newalign;
1378     } else if (newalign > u.ualign.record) {
1379         u.ualign.record = newalign;
1380         if (u.ualign.record > ALIGNLIM)
1381             u.ualign.record = ALIGNLIM;
1382     }
1383 }
1384
1385 /* change hero's alignment type, possibly losing use of artifacts */
1386 void
1387 uchangealign(newalign, reason)
1388 int newalign;
1389 int reason; /* 0==conversion, 1==helm-of-OA on, 2==helm-of-OA off */
1390 {
1391     aligntyp oldalign = u.ualign.type;
1392
1393     u.ublessed = 0; /* lose divine protection */
1394     /* You/Your/pline message with call flush_screen(), triggering bot(),
1395        so the actual data change needs to come before the message */
1396     context.botl = TRUE; /* status line needs updating */
1397     if (reason == 0) {
1398         /* conversion via altar */
1399         u.ualignbase[A_CURRENT] = (aligntyp) newalign;
1400         /* worn helm of opposite alignment might block change */
1401         if (!uarmh || uarmh->otyp != HELM_OF_OPPOSITE_ALIGNMENT)
1402             u.ualign.type = u.ualignbase[A_CURRENT];
1403 #if 0 /*JP:T*/
1404         You("have a %ssense of a new direction.",
1405             (u.ualign.type != oldalign) ? "sudden " : "");
1406 #else
1407         You("%s\95Ê\82Ì\95û\8cü\90«\82É\82ß\82´\82ß\82½\81D",
1408             (u.ualign.type != oldalign) ? "\93Ë\91R" : "");
1409 #endif
1410     } else {
1411         /* putting on or taking off a helm of opposite alignment */
1412         u.ualign.type = (aligntyp) newalign;
1413         if (reason == 1)
1414 /*JP
1415             Your("mind oscillates %s.", Hallucination ? "wildly" : "briefly");
1416 */
1417             You("%s\90Q\95Ô\82Á\82½\81D", Hallucination ? "\8dr\82Á\82Û\82­" : "\82 \82Á\82³\82è\82Æ");
1418         else if (reason == 2)
1419 #if 0 /*JP:T*/
1420             Your("mind is %s.", Hallucination
1421                                     ? "much of a muchness"
1422                                     : "back in sync with your body");
1423 #else
1424             Your("\90S\82Í%s\81D", Hallucination
1425                                     ? "\8e\97\82½\82è\8añ\82Á\82½\82è\82É\82È\82Á\82½"
1426                                     : "\8dÄ\82Ñ\91Ì\82Æ\88ê\92v\82·\82é\82æ\82¤\82É\82È\82Á\82½");
1427 #endif
1428     }
1429     if (u.ualign.type != oldalign) {
1430         u.ualign.record = 0; /* slate is wiped clean */
1431         retouch_equipment(0);
1432     }
1433 }
1434
1435 /*attrib.c*/