OSDN Git Service

add translation
[jnethack/source.git] / src / spell.c
1 /* NetHack 3.6  spell.c $NHDT-Date: 1546565814 2019/01/04 01:36:54 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.88 $ */
2 /*      Copyright (c) M. Stephenson 1988                          */
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-2019            */
8 /* JNetHack may be freely redistributed.  See license for details. */
9
10 #include "hack.h"
11
12 /* spellmenu arguments; 0 thru n-1 used as spl_book[] index when swapping */
13 #define SPELLMENU_CAST (-2)
14 #define SPELLMENU_VIEW (-1)
15 #define SPELLMENU_SORT (MAXSPELL) /* special menu entry */
16
17 /* spell retention period, in turns; at 10% of this value, player becomes
18    eligible to reread the spellbook and regain 100% retention (the threshold
19    used to be 1000 turns, which was 10% of the original 10000 turn retention
20    period but didn't get adjusted when that period got doubled to 20000) */
21 #define KEEN 20000
22 /* x: need to add 1 when used for reading a spellbook rather than for hero
23    initialization; spell memory is decremented at the end of each turn,
24    including the turn on which the spellbook is read; without the extra
25    increment, the hero used to get cheated out of 1 turn of retention */
26 #define incrnknow(spell, x) (spl_book[spell].sp_know = KEEN + (x))
27
28 #define spellev(spell) spl_book[spell].sp_lev
29 #define spellname(spell) OBJ_NAME(objects[spellid(spell)])
30 #define spellet(spell) \
31     ((char) ((spell < 26) ? ('a' + spell) : ('A' + spell - 26)))
32
33 STATIC_DCL int FDECL(spell_let_to_idx, (CHAR_P));
34 STATIC_DCL boolean FDECL(cursed_book, (struct obj * bp));
35 STATIC_DCL boolean FDECL(confused_book, (struct obj *));
36 STATIC_DCL void FDECL(deadbook, (struct obj *));
37 STATIC_PTR int NDECL(learn);
38 STATIC_DCL boolean NDECL(rejectcasting);
39 STATIC_DCL boolean FDECL(getspell, (int *));
40 STATIC_PTR int FDECL(CFDECLSPEC spell_cmp, (const genericptr,
41                                             const genericptr));
42 STATIC_DCL void NDECL(sortspells);
43 STATIC_DCL boolean NDECL(spellsortmenu);
44 STATIC_DCL boolean FDECL(dospellmenu, (const char *, int, int *));
45 STATIC_DCL int FDECL(percent_success, (int));
46 STATIC_DCL char *FDECL(spellretention, (int, char *));
47 STATIC_DCL int NDECL(throwspell);
48 STATIC_DCL void NDECL(cast_protection);
49 STATIC_DCL void FDECL(spell_backfire, (int));
50 STATIC_DCL const char *FDECL(spelltypemnemonic, (int));
51 STATIC_DCL boolean FDECL(spell_aim_step, (genericptr_t, int, int));
52
53 /* The roles[] table lists the role-specific values for tuning
54  * percent_success().
55  *
56  * Reasoning:
57  *   spelbase, spelheal:
58  *      Arc are aware of magic through historical research
59  *      Bar abhor magic (Conan finds it "interferes with his animal instincts")
60  *      Cav are ignorant to magic
61  *      Hea are very aware of healing magic through medical research
62  *      Kni are moderately aware of healing from Paladin training
63  *      Mon use magic to attack and defend in lieu of weapons and armor
64  *      Pri are very aware of healing magic through theological research
65  *      Ran avoid magic, preferring to fight unseen and unheard
66  *      Rog are moderately aware of magic through trickery
67  *      Sam have limited magical awareness, preferring meditation to conjuring
68  *      Tou are aware of magic from all the great films they have seen
69  *      Val have limited magical awareness, preferring fighting
70  *      Wiz are trained mages
71  *
72  *      The arms penalty is lessened for trained fighters Bar, Kni, Ran,
73  *      Sam, Val -- the penalty is its metal interference, not encumbrance.
74  *      The `spelspec' is a single spell which is fundamentally easier
75  *      for that role to cast.
76  *
77  *  spelspec, spelsbon:
78  *      Arc map masters (SPE_MAGIC_MAPPING)
79  *      Bar fugue/berserker (SPE_HASTE_SELF)
80  *      Cav born to dig (SPE_DIG)
81  *      Hea to heal (SPE_CURE_SICKNESS)
82  *      Kni to turn back evil (SPE_TURN_UNDEAD)
83  *      Mon to preserve their abilities (SPE_RESTORE_ABILITY)
84  *      Pri to bless (SPE_REMOVE_CURSE)
85  *      Ran to hide (SPE_INVISIBILITY)
86  *      Rog to find loot (SPE_DETECT_TREASURE)
87  *      Sam to be At One (SPE_CLAIRVOYANCE)
88  *      Tou to smile (SPE_CHARM_MONSTER)
89  *      Val control the cold (SPE_CONE_OF_COLD)
90  *      Wiz all really, but SPE_MAGIC_MISSILE is their party trick
91  *
92  *      See percent_success() below for more comments.
93  *
94  *  uarmbon, uarmsbon, uarmhbon, uarmgbon, uarmfbon:
95  *      Fighters find body armour & shield a little less limiting.
96  *      Headgear, Gauntlets and Footwear are not role-specific (but
97  *      still have an effect, except helm of brilliance, which is designed
98  *      to permit magic-use).
99  */
100
101 #define uarmhbon 4 /* Metal helmets interfere with the mind */
102 #define uarmgbon 6 /* Casting channels through the hands */
103 #define uarmfbon 2 /* All metal interferes to some degree */
104
105 /* since the spellbook itself doesn't blow up, don't say just "explodes" */
106 #if 0 /*JP*/
107 static const char explodes[] = "radiates explosive energy";
108 #endif
109
110 /* convert a letter into a number in the range 0..51, or -1 if not a letter */
111 STATIC_OVL int
112 spell_let_to_idx(ilet)
113 char ilet;
114 {
115     int indx;
116
117     indx = ilet - 'a';
118     if (indx >= 0 && indx < 26)
119         return indx;
120     indx = ilet - 'A';
121     if (indx >= 0 && indx < 26)
122         return indx + 26;
123     return -1;
124 }
125
126 /* TRUE: book should be destroyed by caller */
127 STATIC_OVL boolean
128 cursed_book(bp)
129 struct obj *bp;
130 {
131     boolean was_in_use;
132     int lev = objects[bp->otyp].oc_level;
133     int dmg = 0;
134
135     switch (rn2(lev)) {
136     case 0:
137 /*JP
138         You_feel("a wrenching sensation.");
139 */
140         You("\82Ë\82\82ç\82ê\82½\82æ\82¤\82È\8a´\8ao\82ð\8a´\82\82½\81D");
141         tele(); /* teleport him */
142         break;
143     case 1:
144 /*JP
145         You_feel("threatened.");
146 */
147         You("\82¨\82Ç\82³\82ê\82Ä\82¢\82é\82æ\82¤\82È\8bC\82ª\82µ\82½\81D");
148         aggravate();
149         break;
150     case 2:
151         make_blinded(Blinded + rn1(100, 250), TRUE);
152         break;
153     case 3:
154         take_gold();
155         break;
156     case 4:
157 /*JP
158         pline("These runes were just too much to comprehend.");
159 */
160         pline("\82±\82Ì\83\8b\81[\83\93\95\8e\9a\82ð\97\9d\89ð\82·\82é\82Ì\82Í\8d¢\93ï\82¾\81D");
161         make_confused(HConfusion + rn1(7, 16), FALSE);
162         break;
163     case 5:
164 /*JP
165         pline_The("book was coated with contact poison!");
166 */
167         pline("\82±\82Ì\96{\82Í\90Ú\90G\8c^\82Ì\93Å\82Å\95¢\82í\82ê\82Ä\82¢\82é\81I");
168         if (uarmg) {
169 #if 0 /*JP*/
170             erode_obj(uarmg, "gloves", ERODE_CORRODE, EF_GREASE | EF_VERBOSE);
171 #else
172             erode_obj(uarmg, "\8f¬\8eè", ERODE_CORRODE, EF_GREASE | EF_VERBOSE);
173 #endif
174             break;
175         }
176         /* temp disable in_use; death should not destroy the book */
177         was_in_use = bp->in_use;
178         bp->in_use = FALSE;
179         losestr(Poison_resistance ? rn1(2, 1) : rn1(4, 3));
180 #if 0 /*JP*/
181         losehp(rnd(Poison_resistance ? 6 : 10), "contact-poisoned spellbook",
182                KILLED_BY_AN);
183 #else
184         losehp(rnd(Poison_resistance ? 6 : 10), "\90Ú\90G\93Å\82Ì\96\82\96@\8f\91\82Å",
185                KILLED_BY_AN);
186 #endif
187         bp->in_use = was_in_use;
188         break;
189     case 6:
190         if (Antimagic) {
191             shieldeff(u.ux, u.uy);
192 /*JP
193             pline_The("book %s, but you are unharmed!", explodes);
194 */
195             pline("\96{\82Í\8b­\97Í\82È\83G\83l\83\8b\83M\81[\82ð\95ú\8fo\82µ\82½\81C\82µ\82©\82µ\82 \82È\82½\82Í\8f\9d\82Â\82©\82È\82¢\81I");
196         } else {
197 /*JP
198             pline("As you read the book, it %s in your %s!", explodes,
199 */
200             pline("\96{\82Í\8b­\97Í\82È\83G\83l\83\8b\83M\81[\82ð\82 \82È\82½\82Ì%s\82É\95ú\8fo\82µ\82½\81I",
201                   body_part(FACE));
202             dmg = 2 * rnd(10) + 5;
203 /*JP
204             losehp(Maybe_Half_Phys(dmg), "exploding rune", KILLED_BY_AN);
205 */
206             losehp(Maybe_Half_Phys(dmg), "\8b­\97Í\82È\83\8b\81[\83\93\95\8e\9a\82Ì\83G\83l\83\8b\83M\81[\82Å", KILLED_BY_AN);
207         }
208         return TRUE;
209     default:
210         rndcurse();
211         break;
212     }
213     return FALSE;
214 }
215
216 /* study while confused: returns TRUE if the book is destroyed */
217 STATIC_OVL boolean
218 confused_book(spellbook)
219 struct obj *spellbook;
220 {
221     boolean gone = FALSE;
222
223     if (!rn2(3) && spellbook->otyp != SPE_BOOK_OF_THE_DEAD) {
224         spellbook->in_use = TRUE; /* in case called from learn */
225         pline(
226 /*JP
227          "Being confused you have difficulties in controlling your actions.");
228 */
229          "\8d¬\97\90\82µ\82Ä\82¢\82é\82Ì\82Å\81C\82»\82¤\82¢\82¤\82±\82Æ\82ð\82·\82é\82Ì\82Í\93ï\82µ\82¢\81D");
230         display_nhwindow(WIN_MESSAGE, FALSE);
231 /*JP
232         You("accidentally tear the spellbook to pieces.");
233 */
234         You("\82¤\82Á\82©\82è\81C\96\82\96@\8f\91\82ð\88ø\82«\82³\82¢\82Ä\82µ\82Ü\82Á\82½\81D");
235         if (!objects[spellbook->otyp].oc_name_known
236             && !objects[spellbook->otyp].oc_uname)
237             docall(spellbook);
238         useup(spellbook);
239         gone = TRUE;
240     } else {
241 #if 0 /*JP*/
242         You("find yourself reading the %s line over and over again.",
243             spellbook == context.spbook.book ? "next" : "first");
244 #else
245         You("%s\82Ì\8ds\82ð\89½\93x\82à\8cJ\82è\95Ô\82µ\82Ä\93Ç\82ñ\82Å\82¢\82½\82±\82Æ\82É\8bC\95t\82¢\82½\81D",
246             spellbook == context.spbook.book ? "\8e\9f" : "\8dÅ\8f\89");
247 #endif
248     }
249     return gone;
250 }
251
252 /* special effects for The Book of the Dead */
253 STATIC_OVL void
254 deadbook(book2)
255 struct obj *book2;
256 {
257     struct monst *mtmp, *mtmp2;
258     coord mm;
259
260 /*JP
261     You("turn the pages of the Book of the Dead...");
262 */
263     You("\8e\80\8eÒ\82Ì\8f\91\82Ì\83y\81[\83W\82ð\82ß\82­\82Á\82½\81D\81D\81D");
264     makeknown(SPE_BOOK_OF_THE_DEAD);
265     /* KMH -- Need ->known to avoid "_a_ Book of the Dead" */
266     book2->known = 1;
267     if (invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
268         register struct obj *otmp;
269         register boolean arti1_primed = FALSE, arti2_primed = FALSE,
270                          arti_cursed = FALSE;
271
272         if (book2->cursed) {
273 /*JP
274             pline_The("runes appear scrambled.  You can't read them!");
275 */
276             pline("\83\8b\81[\83\93\95\8e\9a\82Í\82²\82¿\82á\82Ü\82º\82É\82È\82Á\82Ä\82¨\82è\81C\93Ç\82Þ\82±\82Æ\82ª\82Å\82«\82È\82©\82Á\82½\81I");
277             return;
278         }
279
280         if (!u.uhave.bell || !u.uhave.menorah) {
281 /*JP
282             pline("A chill runs down your %s.", body_part(SPINE));
283 */
284             Your("%s\82É\8a¦\82¯\82ª\91\96\82Á\82½\81D", body_part(SPINE));
285             if (!u.uhave.bell)
286 /*JP
287                 You_hear("a faint chime...");
288 */
289                 You_hear("\82©\82·\82©\82È\83x\83\8b\82Ì\89¹\82ð\95·\82¢\82½\81D\81D\81D");
290             if (!u.uhave.menorah)
291 /*JP
292                 pline("Vlad's doppelganger is amused.");
293 */
294                 pline("\83\94\83\89\83h\82Ì\90\97ì\82Í\8fÎ\82Á\82½\81D");
295             return;
296         }
297
298         for (otmp = invent; otmp; otmp = otmp->nobj) {
299             if (otmp->otyp == CANDELABRUM_OF_INVOCATION && otmp->spe == 7
300                 && otmp->lamplit) {
301                 if (!otmp->cursed)
302                     arti1_primed = TRUE;
303                 else
304                     arti_cursed = TRUE;
305             }
306             if (otmp->otyp == BELL_OF_OPENING
307                 && (moves - otmp->age) < 5L) { /* you rang it recently */
308                 if (!otmp->cursed)
309                     arti2_primed = TRUE;
310                 else
311                     arti_cursed = TRUE;
312             }
313         }
314
315         if (arti_cursed) {
316 /*JP
317             pline_The("invocation fails!");
318 */
319             pline("\93Á\8eê\94\\97Í\82Í\94­\8aö\82³\82ê\82È\82©\82Á\82½\81I");
320 /*JP
321             pline("At least one of your artifacts is cursed...");
322 */
323             pline("\8f­\82È\82­\82Æ\82à\90¹\8aí\82Ì\82Ð\82Æ\82Â\82ª\8eô\82í\82ê\82Ä\82¢\82é\81D\81D\81D");
324         } else if (arti1_primed && arti2_primed) {
325             unsigned soon =
326                 (unsigned) d(2, 6); /* time til next intervene() */
327
328             /* successful invocation */
329             mkinvokearea();
330             u.uevent.invoked = 1;
331             /* in case you haven't killed the Wizard yet, behave as if
332                you just did */
333             u.uevent.udemigod = 1; /* wizdead() */
334             if (!u.udg_cnt || u.udg_cnt > soon)
335                 u.udg_cnt = soon;
336         } else { /* at least one artifact not prepared properly */
337 /*JP
338             You("have a feeling that %s is amiss...", something);
339 */
340             You("\89½\82©\82ª\8aÔ\88á\82Á\82Ä\82¢\82é\82æ\82¤\82È\8bC\82ª\82µ\82½\81D\81D\81D");
341             goto raise_dead;
342         }
343         return;
344     }
345
346     /* when not an invocation situation */
347     if (book2->cursed) {
348     raise_dead:
349
350 /*JP
351         You("raised the dead!");
352 */
353         You("\8e\80\8eÒ\82ð\91h\82ç\82¹\82½\81I");
354         /* first maybe place a dangerous adversary */
355         if (!rn2(3) && ((mtmp = makemon(&mons[PM_MASTER_LICH], u.ux, u.uy,
356                                         NO_MINVENT)) != 0
357                         || (mtmp = makemon(&mons[PM_NALFESHNEE], u.ux, u.uy,
358                                            NO_MINVENT)) != 0)) {
359             mtmp->mpeaceful = 0;
360             set_malign(mtmp);
361         }
362         /* next handle the affect on things you're carrying */
363         (void) unturn_dead(&youmonst);
364         /* last place some monsters around you */
365         mm.x = u.ux;
366         mm.y = u.uy;
367         mkundead(&mm, TRUE, NO_MINVENT);
368     } else if (book2->blessed) {
369         for (mtmp = fmon; mtmp; mtmp = mtmp2) {
370             mtmp2 = mtmp->nmon; /* tamedog() changes chain */
371             if (DEADMONSTER(mtmp))
372                 continue;
373
374             if ((is_undead(mtmp->data) || is_vampshifter(mtmp))
375                 && cansee(mtmp->mx, mtmp->my)) {
376                 mtmp->mpeaceful = TRUE;
377                 if (sgn(mtmp->data->maligntyp) == sgn(u.ualign.type)
378                     && distu(mtmp->mx, mtmp->my) < 4)
379                     if (mtmp->mtame) {
380                         if (mtmp->mtame < 20)
381                             mtmp->mtame++;
382                     } else
383                         (void) tamedog(mtmp, (struct obj *) 0);
384                 else
385                     monflee(mtmp, 0, FALSE, TRUE);
386             }
387         }
388     } else {
389         switch (rn2(3)) {
390         case 0:
391 /*JP
392             Your("ancestors are annoyed with you!");
393 */
394             Your("\90æ\91c\82Í\82 \82È\82½\82ª\8c\99\82¢\82È\82æ\82¤\82¾\81I");
395             break;
396         case 1:
397 /*JP
398             pline_The("headstones in the cemetery begin to move!");
399 */
400             pline("\95æ\92n\82Ì\95æ\90Î\82ª\93®\82«\82Í\82\82ß\82½\81I");
401             break;
402         default:
403 /*JP
404             pline("Oh my!  Your name appears in the book!");
405 */
406             pline("\82È\82ñ\82Ä\82±\82Á\82½\82¢\81I\82 \82È\82½\82Ì\96¼\91O\82ª\96{\82É\8f\91\82¢\82Ä\82 \82é\81I");
407         }
408     }
409     return;
410 }
411
412 /* 'book' has just become cursed; if we're reading it and realize it is
413    now cursed, interrupt */
414 void
415 book_cursed(book)
416 struct obj *book;
417 {
418     if (occupation == learn && context.spbook.book == book
419         && book->cursed && book->bknown && multi >= 0)
420         stop_occupation();
421 }
422
423 STATIC_PTR int
424 learn(VOID_ARGS)
425 {
426     int i;
427     short booktype;
428     char splname[BUFSZ];
429     boolean costly = TRUE;
430     struct obj *book = context.spbook.book;
431
432     /* JDS: lenses give 50% faster reading; 33% smaller read time */
433     if (context.spbook.delay && ublindf && ublindf->otyp == LENSES && rn2(2))
434         context.spbook.delay++;
435     if (Confusion) { /* became confused while learning */
436         (void) confused_book(book);
437         context.spbook.book = 0; /* no longer studying */
438         context.spbook.o_id = 0;
439         nomul(context.spbook.delay); /* remaining delay is uninterrupted */
440 /*JP
441         multi_reason = "reading a book";
442 */
443         multi_reason = "\96{\82ð\93Ç\82ñ\82Å\82¢\82é\8e\9e\82É";
444         nomovemsg = 0;
445         context.spbook.delay = 0;
446         return 0;
447     }
448     if (context.spbook.delay) {
449         /* not if (context.spbook.delay++), so at end delay == 0 */
450         context.spbook.delay++;
451         return 1; /* still busy */
452     }
453     exercise(A_WIS, TRUE); /* you're studying. */
454     booktype = book->otyp;
455     if (booktype == SPE_BOOK_OF_THE_DEAD) {
456         deadbook(book);
457         return 0;
458     }
459
460 #if 0 /*JP*/
461     Sprintf(splname,
462             objects[booktype].oc_name_known ? "\"%s\"" : "the \"%s\" spell",
463             OBJ_NAME(objects[booktype]));
464 #else
465     Sprintf(splname,
466             objects[booktype].oc_name_known ? "\"%s\"" : "\"%s\"",
467             OBJ_NAME(objects[booktype]));
468 #endif
469     for (i = 0; i < MAXSPELL; i++)
470         if (spellid(i) == booktype || spellid(i) == NO_SPELL)
471             break;
472
473     if (i == MAXSPELL) {
474         impossible("Too many spells memorized!");
475     } else if (spellid(i) == booktype) {
476         /* normal book can be read and re-read a total of 4 times */
477         if (book->spestudied > MAX_SPELL_STUDY) {
478 /*JP
479             pline("This spellbook is too faint to be read any more.");
480 */
481             pline("\82±\82Ì\96\82\96@\8f\91\82Ì\95\8e\9a\82Í\94\96\82·\82¬\82Ä\82±\82ê\88È\8fã\93Ç\82ß\82È\82¢\81D");
482             book->otyp = booktype = SPE_BLANK_PAPER;
483             /* reset spestudied as if polymorph had taken place */
484             book->spestudied = rn2(book->spestudied);
485         } else if (spellknow(i) > KEEN / 10) {
486 /*JP
487             You("know %s quite well already.", splname);
488 */
489             You("\82·\82Å\82É%s\82ð\8fn\92m\82µ\82Ä\82¢\82é\81D", splname);
490             costly = FALSE;
491         } else { /* spellknow(i) <= KEEN/10 */
492 #if 0 /*JP*/
493             Your("knowledge of %s is %s.", splname,
494                  spellknow(i) ? "keener" : "restored");
495 #else
496             Your("%s\82É\91Î\82·\82é\92m\8e¯\82Í%s\82³\82ê\82½\81D", splname,
497                  spellknow(i) ? "\82³\82ç\82É\8c¤\82¬\82·\82Ü" : "\95\9c\8c³");
498 #endif
499             incrnknow(i, 1);
500             book->spestudied++;
501             exercise(A_WIS, TRUE); /* extra study */
502         }
503         /* make book become known even when spell is already
504            known, in case amnesia made you forget the book */
505         makeknown((int) booktype);
506     } else { /* (spellid(i) == NO_SPELL) */
507         /* for a normal book, spestudied will be zero, but for
508            a polymorphed one, spestudied will be non-zero and
509            one less reading is available than when re-learning */
510         if (book->spestudied >= MAX_SPELL_STUDY) {
511             /* pre-used due to being the product of polymorph */
512 /*JP
513             pline("This spellbook is too faint to read even once.");
514 */
515             pline("\82±\82Ì\96\82\96@\8f\91\82Ì\95\8e\9a\82Í\94\96\82·\82¬\82Ä\82±\82ê\88È\8fã\93Ç\82ß\82È\82¢\81D");
516             book->otyp = booktype = SPE_BLANK_PAPER;
517             /* reset spestudied as if polymorph had taken place */
518             book->spestudied = rn2(book->spestudied);
519         } else {
520             spl_book[i].sp_id = booktype;
521             spl_book[i].sp_lev = objects[booktype].oc_level;
522             incrnknow(i, 1);
523             book->spestudied++;
524 /*JP
525             You(i > 0 ? "add %s to your repertoire." : "learn %s.", splname);
526 */
527             You(i > 0 ? "%s\82ð\83\8c\83p\81[\83g\83\8a\81[\82É\89Á\82¦\82½\81D" : "%s\82ð\8fK\93¾\82µ\82½\81D", splname);
528         }
529         makeknown((int) booktype);
530     }
531
532     if (book->cursed) { /* maybe a demon cursed it */
533         if (cursed_book(book)) {
534             useup(book);
535             context.spbook.book = 0;
536             context.spbook.o_id = 0;
537             return 0;
538         }
539     }
540     if (costly)
541         check_unpaid(book);
542     context.spbook.book = 0;
543     context.spbook.o_id = 0;
544     return 0;
545 }
546
547 int
548 study_book(spellbook)
549 register struct obj *spellbook;
550 {
551     int booktype = spellbook->otyp;
552     boolean confused = (Confusion != 0);
553     boolean too_hard = FALSE;
554
555     /* attempting to read dull book may make hero fall asleep */
556     if (!confused && !Sleep_resistance
557 /*JP
558         && !strcmp(OBJ_DESCR(objects[booktype]), "dull")) {
559 */
560         && !strcmp(OBJ_DESCR(objects[booktype]), "\89\94\90F\82Ì\96\82\96@\8f\91")) {
561         const char *eyes;
562         int dullbook = rnd(25) - ACURR(A_WIS);
563
564         /* adjust chance if hero stayed awake, got interrupted, retries */
565         if (context.spbook.delay && spellbook == context.spbook.book)
566             dullbook -= rnd(objects[booktype].oc_level);
567
568         if (dullbook > 0) {
569             eyes = body_part(EYE);
570             if (eyecount(youmonst.data) > 1)
571                 eyes = makeplural(eyes);
572 /*JP
573             pline("This book is so dull that you can't keep your %s open.",
574 */
575             pline("\82±\82Ì\96{\82Í\91Þ\8bü\82·\82¬\82Ä%s\82ð\8aJ\82¯\82Ä\82¢\82ç\82ê\82È\82¢\81D",
576                   eyes);
577             dullbook += rnd(2 * objects[booktype].oc_level);
578             fall_asleep(-dullbook, TRUE);
579             return 1;
580         }
581     }
582
583     if (context.spbook.delay && !confused && spellbook == context.spbook.book
584         /* handle the sequence: start reading, get interrupted, have
585            context.spbook.book become erased somehow, resume reading it */
586         && booktype != SPE_BLANK_PAPER) {
587 #if 0 /*JP*/
588         You("continue your efforts to %s.",
589             (booktype == SPE_NOVEL) ? "read the novel" : "memorize the spell");
590 #else
591         You("%s\82ð\8dÄ\8aJ\82µ\82½\81D",
592             (booktype == SPE_NOVEL) ? "\93Ç\8f\91" : "\96\82\96@\82Ì\8aw\8fK");
593 #endif
594     } else {
595         /* KMH -- Simplified this code */
596         if (booktype == SPE_BLANK_PAPER) {
597 /*JP
598             pline("This spellbook is all blank.");
599 */
600             pline("\82±\82Ì\96\82\96@\8f\91\82Í\90^\82Á\94\92\82¾\81D");
601             makeknown(booktype);
602             return 1;
603         }
604
605         /* 3.6 tribute */
606         if (booktype == SPE_NOVEL) {
607             /* Obtain current Terry Pratchett book title */
608             const char *tribtitle = noveltitle(&spellbook->novelidx);
609
610             if (read_tribute("books", tribtitle, 0, (char *) 0, 0,
611                              spellbook->o_id)) {
612                 u.uconduct.literate++;
613                 check_unpaid(spellbook);
614                 makeknown(booktype);
615                 if (!u.uevent.read_tribute) {
616                     /* give bonus of 20 xp and 4*20+0 pts */
617                     more_experienced(20, 0);
618                     newexplevel();
619                     u.uevent.read_tribute = 1; /* only once */
620                 }
621             }
622             return 1;
623         }
624
625         switch (objects[booktype].oc_level) {
626         case 1:
627         case 2:
628             context.spbook.delay = -objects[booktype].oc_delay;
629             break;
630         case 3:
631         case 4:
632             context.spbook.delay = -(objects[booktype].oc_level - 1)
633                                    * objects[booktype].oc_delay;
634             break;
635         case 5:
636         case 6:
637             context.spbook.delay =
638                 -objects[booktype].oc_level * objects[booktype].oc_delay;
639             break;
640         case 7:
641             context.spbook.delay = -8 * objects[booktype].oc_delay;
642             break;
643         default:
644             impossible("Unknown spellbook level %d, book %d;",
645                        objects[booktype].oc_level, booktype);
646             return 0;
647         }
648
649         /* Books are often wiser than their readers (Rus.) */
650         spellbook->in_use = TRUE;
651         if (!spellbook->blessed && spellbook->otyp != SPE_BOOK_OF_THE_DEAD) {
652             if (spellbook->cursed) {
653                 too_hard = TRUE;
654             } else {
655                 /* uncursed - chance to fail */
656                 int read_ability = ACURR(A_INT) + 4 + u.ulevel / 2
657                                    - 2 * objects[booktype].oc_level
658                              + ((ublindf && ublindf->otyp == LENSES) ? 2 : 0);
659
660                 /* only wizards know if a spell is too difficult */
661                 if (Role_if(PM_WIZARD) && read_ability < 20 && !confused) {
662                     char qbuf[QBUFSZ];
663
664 #if 0 /*JP*/
665                     Sprintf(qbuf,
666                     "This spellbook is %sdifficult to comprehend.  Continue?",
667                             (read_ability < 12 ? "very " : ""));
668 #else
669                     Sprintf(qbuf,
670                     "\82±\82Ì\96\82\96@\8f\91\82ð\97\9d\89ð\82·\82é\82Ì\82Í%s\8d¢\93ï\82¾\81D\91±\82¯\82Ü\82·\82©\81H",
671                             (read_ability < 12 ? "\82Æ\82Ä\82à" : ""));
672 #endif
673                     if (yn(qbuf) != 'y') {
674                         spellbook->in_use = FALSE;
675                         return 1;
676                     }
677                 }
678                 /* its up to random luck now */
679                 if (rnd(20) > read_ability) {
680                     too_hard = TRUE;
681                 }
682             }
683         }
684
685         if (too_hard) {
686             boolean gone = cursed_book(spellbook);
687
688             nomul(context.spbook.delay); /* study time */
689 /*JP
690             multi_reason = "reading a book";
691 */
692             multi_reason = "\96{\82ð\93Ç\82ñ\82Å\82¢\82é\8e\9e\82É";
693             nomovemsg = 0;
694             context.spbook.delay = 0;
695             if (gone || !rn2(3)) {
696                 if (!gone)
697 /*JP
698                     pline_The("spellbook crumbles to dust!");
699 */
700                     pline("\96\82\96@\8f\91\82Í\90o\82Æ\82È\82Á\82½\81I");
701                 if (!objects[spellbook->otyp].oc_name_known
702                     && !objects[spellbook->otyp].oc_uname)
703                     docall(spellbook);
704                 useup(spellbook);
705             } else
706                 spellbook->in_use = FALSE;
707             return 1;
708         } else if (confused) {
709             if (!confused_book(spellbook)) {
710                 spellbook->in_use = FALSE;
711             }
712             nomul(context.spbook.delay);
713 /*JP
714             multi_reason = "reading a book";
715 */
716             multi_reason = "\96{\82ð\93Ç\82ñ\82Å\82¢\82é\8e\9e\82É";
717             nomovemsg = 0;
718             context.spbook.delay = 0;
719             return 1;
720         }
721         spellbook->in_use = FALSE;
722
723 #if 0 /*JP*/
724         You("begin to %s the runes.",
725             spellbook->otyp == SPE_BOOK_OF_THE_DEAD ? "recite" : "memorize");
726 #else
727         You("\83\8b\81[\83\93\95\8e\9a\82ð%s\82µ\82Í\82\82ß\82½\81D",
728             spellbook->otyp == SPE_BOOK_OF_THE_DEAD ? "\88Ã\8f¥" : "\8bL\89¯");
729 #endif
730     }
731
732     context.spbook.book = spellbook;
733     if (context.spbook.book)
734         context.spbook.o_id = context.spbook.book->o_id;
735 /*JP
736     set_occupation(learn, "studying", 0);
737 */
738     set_occupation(learn, "\8aw\82Ô", 0);
739     return 1;
740 }
741
742 /* a spellbook has been destroyed or the character has changed levels;
743    the stored address for the current book is no longer valid */
744 void
745 book_disappears(obj)
746 struct obj *obj;
747 {
748     if (obj == context.spbook.book) {
749         context.spbook.book = (struct obj *) 0;
750         context.spbook.o_id = 0;
751     }
752 }
753
754 /* renaming an object usually results in it having a different address;
755    so the sequence start reading, get interrupted, name the book, resume
756    reading would read the "new" book from scratch */
757 void
758 book_substitution(old_obj, new_obj)
759 struct obj *old_obj, *new_obj;
760 {
761     if (old_obj == context.spbook.book) {
762         context.spbook.book = new_obj;
763         if (context.spbook.book)
764             context.spbook.o_id = context.spbook.book->o_id;
765     }
766 }
767
768 /* called from moveloop() */
769 void
770 age_spells()
771 {
772     int i;
773     /*
774      * The time relative to the hero (a pass through move
775      * loop) causes all spell knowledge to be decremented.
776      * The hero's speed, rest status, conscious status etc.
777      * does not alter the loss of memory.
778      */
779     for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++)
780         if (spellknow(i))
781             decrnknow(i);
782     return;
783 }
784
785 /* return True if spellcasting is inhibited;
786    only covers a small subset of reasons why casting won't work */
787 STATIC_OVL boolean
788 rejectcasting()
789 {
790     /* rejections which take place before selecting a particular spell */
791     if (Stunned) {
792 /*JP
793         You("are too impaired to cast a spell.");
794 */
795         You("\82­\82ç\82­\82ç\82µ\82Ä\82¢\82Ä\96\82\96@\82ð\8eg\82¦\82È\82¢\81D");
796         return TRUE;
797     } else if (!can_chant(&youmonst)) {
798 /*JP
799         You("are unable to chant the incantation.");
800 */
801         You("\8eô\95\82ð\8f¥\82¦\82é\82±\82Æ\82ª\82Å\82«\82È\82¢\81D");
802         return TRUE;
803     } else if (!freehand()) {
804         /* Note: !freehand() occurs when weapon and shield (or two-handed
805          * weapon) are welded to hands, so "arms" probably doesn't need
806          * to be makeplural(bodypart(ARM)).
807          *
808          * But why isn't lack of free arms (for gesturing) an issue when
809          * poly'd hero has no limbs?
810          */
811 /*JP
812         Your("arms are not free to cast!");
813 */
814         pline("\96\82\96@\82ð\8f¥\82¦\82æ\82¤\82É\82à\98r\82Ì\8e©\97R\82ª\8cø\82©\82È\82¢\81I");
815         return TRUE;
816     }
817     return FALSE;
818 }
819
820 /*
821  * Return TRUE if a spell was picked, with the spell index in the return
822  * parameter.  Otherwise return FALSE.
823  */
824 STATIC_OVL boolean
825 getspell(spell_no)
826 int *spell_no;
827 {
828     int nspells, idx;
829     char ilet, lets[BUFSZ], qbuf[QBUFSZ];
830
831     if (spellid(0) == NO_SPELL) {
832 /*JP
833         You("don't know any spells right now.");
834 */
835         You("\8d¡\82Ì\82Æ\82±\82ë\89½\82Ì\96\82\96@\82à\92m\82ç\82È\82¢\81D");
836         return FALSE;
837     }
838     if (rejectcasting())
839         return FALSE; /* no spell chosen */
840
841     if (flags.menu_style == MENU_TRADITIONAL) {
842         /* we know there is at least 1 known spell */
843         for (nspells = 1; nspells < MAXSPELL && spellid(nspells) != NO_SPELL;
844              nspells++)
845             continue;
846
847         if (nspells == 1)
848             Strcpy(lets, "a");
849         else if (nspells < 27)
850             Sprintf(lets, "a-%c", 'a' + nspells - 1);
851         else if (nspells == 27)
852             Sprintf(lets, "a-zA");
853         /* this assumes that there are at most 52 spells... */
854         else
855             Sprintf(lets, "a-zA-%c", 'A' + nspells - 27);
856
857         for (;;) {
858 /*JP
859             Sprintf(qbuf, "Cast which spell? [%s *?]", lets);
860 */
861             Sprintf(qbuf, "\82Ç\82Ì\96\82\96@\82ð\8f¥\82¦\82é\81H[%s ?]", lets);
862             ilet = yn_function(qbuf, (char *) 0, '\0');
863             if (ilet == '*' || ilet == '?')
864                 break; /* use menu mode */
865             if (index(quitchars, ilet))
866                 return FALSE;
867
868             idx = spell_let_to_idx(ilet);
869             if (idx < 0 || idx >= nspells) {
870 /*JP
871                 You("don't know that spell.");
872 */
873                 You("\82»\82ñ\82È\96\82\96@\82Í\92m\82ç\82È\82¢\81D");
874                 continue; /* ask again */
875             }
876             *spell_no = idx;
877             return TRUE;
878         }
879     }
880 /*JP
881     return dospellmenu("Choose which spell to cast", SPELLMENU_CAST,
882 */
883     return dospellmenu("\82Ç\82Ì\96\82\96@\82ð\8f¥\82¦\82é\81H", SPELLMENU_CAST,
884                        spell_no);
885 }
886
887 /* the 'Z' command -- cast a spell */
888 int
889 docast()
890 {
891     int spell_no;
892
893     if (getspell(&spell_no))
894         return spelleffects(spell_no, FALSE);
895     return 0;
896 }
897
898 STATIC_OVL const char *
899 spelltypemnemonic(skill)
900 int skill;
901 {
902     switch (skill) {
903     case P_ATTACK_SPELL:
904 /*JP
905         return "attack";
906 */
907         return "\8dU\8c\82";
908     case P_HEALING_SPELL:
909 /*JP
910         return "healing";
911 */
912         return "\8e¡\96ü";
913     case P_DIVINATION_SPELL:
914 /*JP
915         return "divination";
916 */
917         return "\97\\92m";
918     case P_ENCHANTMENT_SPELL:
919 /*JP
920         return "enchantment";
921 */
922         return "\95â\8f\95";
923     case P_CLERIC_SPELL:
924 /*JP
925         return "clerical";
926 */
927         return "\91m\97µ";
928     case P_ESCAPE_SPELL:
929 /*JP
930         return "escape";
931 */
932         return "\92E\8fo";
933     case P_MATTER_SPELL:
934 /*JP
935         return "matter";
936 */
937         return "\95¨\8e¿";
938     default:
939         impossible("Unknown spell skill, %d;", skill);
940         return "";
941     }
942 }
943
944 int
945 spell_skilltype(booktype)
946 int booktype;
947 {
948     return objects[booktype].oc_skill;
949 }
950
951 STATIC_OVL void
952 cast_protection()
953 {
954     int l = u.ulevel, loglev = 0,
955         gain, natac = u.uac + u.uspellprot;
956     /* note: u.uspellprot is subtracted when find_ac() factors it into u.uac,
957        so adding here factors it back out
958        (versions prior to 3.6 had this backwards) */
959
960     /* loglev=log2(u.ulevel)+1 (1..5) */
961     while (l) {
962         loglev++;
963         l /= 2;
964     }
965
966     /* The more u.uspellprot you already have, the less you get,
967      * and the better your natural ac, the less you get.
968      *
969      *  LEVEL AC    SPELLPROT from successive SPE_PROTECTION casts
970      *      1     10    0,  1,  2,  3,  4
971      *      1      0    0,  1,  2,  3
972      *      1    -10    0,  1,  2
973      *      2-3   10    0,  2,  4,  5,  6,  7,  8
974      *      2-3    0    0,  2,  4,  5,  6
975      *      2-3  -10    0,  2,  3,  4
976      *      4-7   10    0,  3,  6,  8,  9, 10, 11, 12
977      *      4-7    0    0,  3,  5,  7,  8,  9
978      *      4-7  -10    0,  3,  5,  6
979      *      7-15 -10    0,  3,  5,  6
980      *      8-15  10    0,  4,  7, 10, 12, 13, 14, 15, 16
981      *      8-15   0    0,  4,  7,  9, 10, 11, 12
982      *      8-15 -10    0,  4,  6,  7,  8
983      *     16-30  10    0,  5,  9, 12, 14, 16, 17, 18, 19, 20
984      *     16-30   0    0,  5,  9, 11, 13, 14, 15
985      *     16-30 -10    0,  5,  8,  9, 10
986      */
987     natac = (10 - natac) / 10; /* convert to positive and scale down */
988     gain = loglev - (int) u.uspellprot / (4 - min(3, natac));
989
990     if (gain > 0) {
991         if (!Blind) {
992             int rmtyp;
993             const char *hgolden = hcolor(NH_GOLDEN), *atmosphere;
994
995             if (u.uspellprot) {
996 /*JP
997                 pline_The("%s haze around you becomes more dense.", hgolden);
998 */
999                 pline("\82 \82È\82½\82Ì\82Ü\82í\82è\82Ì%s\89à\82ª\94Z\82­\82È\82Á\82½\81D", hgolden);
1000             } else {
1001                 rmtyp = levl[u.ux][u.uy].typ;
1002                 atmosphere = u.uswallow
1003                                 ? ((u.ustuck->data == &mons[PM_FOG_CLOUD])
1004 /*JP
1005                                    ? "mist"
1006 */
1007                                    ? "\96¶"
1008                                    : is_whirly(u.ustuck->data)
1009 /*JP
1010                                       ? "maelstrom"
1011 */
1012                                       ? "\89Q"
1013                                       : is_animal(u.ustuck->data)
1014 /*JP
1015                                          ? "maw"
1016 */
1017                                          ? "\88Ý"
1018 /*JP
1019                                          : "ooze")
1020 */
1021                                          : "\82Ë\82Î\82Ë\82Î")
1022                                 : (u.uinwater
1023 /*JP
1024                                    ? hliquid("water")
1025 */
1026                                    ? hliquid("\90\85")
1027                                    : (rmtyp == CLOUD)
1028 /*JP
1029                                       ? "cloud"
1030 */
1031                                       ? "\89_"
1032                                       : IS_TREE(rmtyp)
1033 /*JP
1034                                          ? "vegetation"
1035 */
1036                                          ? "\96Ø"
1037                                          : IS_STWALL(rmtyp)
1038 /*JP
1039                                             ? "stone"
1040 */
1041                                             ? "\90Î"
1042 /*JP
1043                                             : "air");
1044 */
1045                                             : "\8bó\8bC");
1046 #if 0 /*JP*/
1047                 pline_The("%s around you begins to shimmer with %s haze.",
1048                           atmosphere, an(hgolden));
1049 #else
1050                 pline("\82 \82È\82½\82Ì\82Ü\82í\82è\82Ì%s\82ª%s\96\82Å\83L\83\89\83L\83\89\82Æ\8cõ\82è\82Í\82\82ß\82½\81D",
1051                           atmosphere, hgolden);
1052 #endif
1053             }
1054         }
1055         u.uspellprot += gain;
1056         u.uspmtime = (P_SKILL(spell_skilltype(SPE_PROTECTION)) == P_EXPERT)
1057                         ? 20 : 10;
1058         if (!u.usptime)
1059             u.usptime = u.uspmtime;
1060         find_ac();
1061     } else {
1062 /*JP
1063         Your("skin feels warm for a moment.");
1064 */
1065         Your("\94§\82Í\88ê\8fu\83|\83J\83|\83J\82µ\82½\81D");
1066     }
1067 }
1068
1069 /* attempting to cast a forgotten spell will cause disorientation */
1070 STATIC_OVL void
1071 spell_backfire(spell)
1072 int spell;
1073 {
1074     long duration = (long) ((spellev(spell) + 1) * 3), /* 6..24 */
1075          old_stun = (HStun & TIMEOUT), old_conf = (HConfusion & TIMEOUT);
1076
1077     /* Prior to 3.4.1, only effect was confusion; it still predominates.
1078      *
1079      * 3.6.0: this used to override pre-existing confusion duration
1080      * (cases 0..8) and pre-existing stun duration (cases 4..9);
1081      * increase them instead.   (Hero can no longer cast spells while
1082      * Stunned, so the potential increment to stun duration here is
1083      * just hypothetical.)
1084      */
1085     switch (rn2(10)) {
1086     case 0:
1087     case 1:
1088     case 2:
1089     case 3:
1090         make_confused(old_conf + duration, FALSE); /* 40% */
1091         break;
1092     case 4:
1093     case 5:
1094     case 6:
1095         make_confused(old_conf + 2L * duration / 3L, FALSE); /* 30% */
1096         make_stunned(old_stun + duration / 3L, FALSE);
1097         break;
1098     case 7:
1099     case 8:
1100         make_stunned(old_stun + 2L * duration / 3L, FALSE); /* 20% */
1101         make_confused(old_conf + duration / 3L, FALSE);
1102         break;
1103     case 9:
1104         make_stunned(old_stun + duration, FALSE); /* 10% */
1105         break;
1106     }
1107     return;
1108 }
1109
1110 int
1111 spelleffects(spell, atme)
1112 int spell;
1113 boolean atme;
1114 {
1115     int energy, damage, chance, n, intell;
1116     int otyp, skill, role_skill, res = 0;
1117     boolean confused = (Confusion != 0);
1118     boolean physical_damage = FALSE;
1119     struct obj *pseudo;
1120     coord cc;
1121
1122     /*
1123      * Reject attempting to cast while stunned or with no free hands.
1124      * Already done in getspell() to stop casting before choosing
1125      * which spell, but duplicated here for cases where spelleffects()
1126      * gets called directly for ^T without intrinsic teleport capability
1127      * or #turn for non-priest/non-knight.
1128      * (There's no duplication of messages; when the rejection takes
1129      * place in getspell(), we don't get called.)
1130      */
1131     if (rejectcasting()) {
1132         return 0; /* no time elapses */
1133     }
1134
1135     /*
1136      * Spell casting no longer affects knowledge of the spell. A
1137      * decrement of spell knowledge is done every turn.
1138      */
1139     if (spellknow(spell) <= 0) {
1140 /*JP
1141         Your("knowledge of this spell is twisted.");
1142 */
1143         Your("\82±\82Ì\96\82\96@\82É\8aÖ\82·\82é\92m\8e¯\82Í\82æ\82\82ê\82½\81D");
1144 /*JP
1145         pline("It invokes nightmarish images in your mind...");
1146 */
1147         pline("\82»\82ê\82Í\88«\96²\82ð\90S\82É\95\82\82Î\82¹\82½\81D\81D\81D");
1148         spell_backfire(spell);
1149         return 1;
1150     } else if (spellknow(spell) <= KEEN / 200) { /* 100 turns left */
1151 /*JP
1152         You("strain to recall the spell.");
1153 */
1154         You("\96\82\96@\82ð\8ev\82¢\82¾\82·\82Ì\82É\8bê\98J\82µ\82½\81D");
1155     } else if (spellknow(spell) <= KEEN / 40) { /* 500 turns left */
1156 /*JP
1157         You("have difficulty remembering the spell.");
1158 */
1159         You("\8eô\95\82ð\8ev\82¢\8fo\82·\82Ì\82ª\93ï\82µ\82­\82È\82Á\82Ä\82«\82½\81D");
1160     } else if (spellknow(spell) <= KEEN / 20) { /* 1000 turns left */
1161 /*JP
1162         Your("knowledge of this spell is growing faint.");
1163 */
1164         Your("\82±\82Ì\96\82\96@\82É\8aÖ\82·\82é\92m\8e¯\82ª\82¨\82Ú\82ë\82°\82É\82È\82Á\82Ä\82«\82½\81D");
1165     } else if (spellknow(spell) <= KEEN / 10) { /* 2000 turns left */
1166 /*JP
1167         Your("recall of this spell is gradually fading.");
1168 */
1169         Your("\82±\82Ì\96\82\96@\82É\8aÖ\82·\82é\92m\8e¯\82ª\8f\99\81X\82É\94\96\82ê\82Ä\82«\82½\81D");
1170     }
1171     /*
1172      *  Note: dotele() also calculates energy use and checks nutrition
1173      *  and strength requirements; it any of these change, update it too.
1174      */
1175     energy = (spellev(spell) * 5); /* 5 <= energy <= 35 */
1176
1177     if (u.uhunger <= 10 && spellid(spell) != SPE_DETECT_FOOD) {
1178 /*JP
1179         You("are too hungry to cast that spell.");
1180 */
1181         pline("\95 \82ª\8c¸\82è\82·\82¬\82Ä\96\82\96@\82ð\8f¥\82¦\82ç\82ê\82È\82¢\81D");
1182         return 0;
1183     } else if (ACURR(A_STR) < 4 && spellid(spell) != SPE_RESTORE_ABILITY) {
1184 /*JP
1185         You("lack the strength to cast spells.");
1186 */
1187         pline("\8b­\82³\82ª\8f­\82È\82·\82¬\82Ä\96\82\96@\82ð\8f¥\82¦\82ç\82ê\82È\82¢\81D");
1188         return 0;
1189     } else if (check_capacity(
1190 /*JP
1191                 "Your concentration falters while carrying so much stuff.")) {
1192 */
1193                 "\82½\82­\82³\82ñ\82à\82Ì\82ð\8e\9d\82¿\82·\82¬\82Ä\8fW\92\86\82Å\82«\82È\82¢\81D")){
1194         return 1;
1195     }
1196
1197     /* if the cast attempt is already going to fail due to insufficient
1198        energy (ie, u.uen < energy), the Amulet's drain effect won't kick
1199        in and no turn will be consumed; however, when it does kick in,
1200        the attempt may fail due to lack of energy after the draining, in
1201        which case a turn will be used up in addition to the energy loss */
1202     if (u.uhave.amulet && u.uen >= energy) {
1203 /*JP
1204         You_feel("the amulet draining your energy away.");
1205 */
1206         pline("\96\82\8f\9c\82¯\82ª\82 \82È\82½\82Ì\83G\83l\83\8b\83M\81[\82ð\8bz\82¢\82Æ\82Á\82Ä\82¢\82é\82æ\82¤\82È\8bC\82ª\82µ\82½\81D");
1207         /* this used to be 'energy += rnd(2 * energy)' (without 'res'),
1208            so if amulet-induced cost was more than u.uen, nothing
1209            (except the "don't have enough energy" message) happened
1210            and player could just try again (and again and again...);
1211            now we drain some energy immediately, which has a
1212            side-effect of not increasing the hunger aspect of casting */
1213         u.uen -= rnd(2 * energy);
1214         if (u.uen < 0)
1215             u.uen = 0;
1216         context.botl = 1;
1217         res = 1; /* time is going to elapse even if spell doesn't get cast */
1218     }
1219
1220     if (energy > u.uen) {
1221 /*JP
1222         You("don't have enough energy to cast that spell.");
1223 */
1224         pline("\96\82\96@\82ð\8f¥\82¦\82é\82¾\82¯\82Ì\8f\\95ª\82È\83G\83l\83\8b\83M\81[\82ª\82È\82¢\81D");
1225         return res;
1226     } else {
1227         if (spellid(spell) != SPE_DETECT_FOOD) {
1228             int hungr = energy * 2;
1229
1230             /* If hero is a wizard, their current intelligence
1231              * (bonuses + temporary + current)
1232              * affects hunger reduction in casting a spell.
1233              * 1. int = 17-18 no reduction
1234              * 2. int = 16    1/4 hungr
1235              * 3. int = 15    1/2 hungr
1236              * 4. int = 1-14  normal reduction
1237              * The reason for this is:
1238              * a) Intelligence affects the amount of exertion
1239              * in thinking.
1240              * b) Wizards have spent their life at magic and
1241              * understand quite well how to cast spells.
1242              */
1243             intell = acurr(A_INT);
1244             if (!Role_if(PM_WIZARD))
1245                 intell = 10;
1246             switch (intell) {
1247             case 25:
1248             case 24:
1249             case 23:
1250             case 22:
1251             case 21:
1252             case 20:
1253             case 19:
1254             case 18:
1255             case 17:
1256                 hungr = 0;
1257                 break;
1258             case 16:
1259                 hungr /= 4;
1260                 break;
1261             case 15:
1262                 hungr /= 2;
1263                 break;
1264             }
1265             /* don't put player (quite) into fainting from
1266              * casting a spell, particularly since they might
1267              * not even be hungry at the beginning; however,
1268              * this is low enough that they must eat before
1269              * casting anything else except detect food
1270              */
1271             if (hungr > u.uhunger - 3)
1272                 hungr = u.uhunger - 3;
1273             morehungry(hungr);
1274         }
1275     }
1276
1277     chance = percent_success(spell);
1278     if (confused || (rnd(100) > chance)) {
1279 /*JP
1280         You("fail to cast the spell correctly.");
1281 */
1282         You("\96\82\96@\82ð\90³\82µ\82­\8f¥\82¦\82é\82±\82Æ\82ª\82Å\82«\82È\82©\82Á\82½\81D");
1283         u.uen -= energy / 2;
1284         context.botl = 1;
1285         return 1;
1286     }
1287
1288     u.uen -= energy;
1289     context.botl = 1;
1290     exercise(A_WIS, TRUE);
1291     /* pseudo is a temporary "false" object containing the spell stats */
1292     pseudo = mksobj(spellid(spell), FALSE, FALSE);
1293     pseudo->blessed = pseudo->cursed = 0;
1294     pseudo->quan = 20L; /* do not let useup get it */
1295     /*
1296      * Find the skill the hero has in a spell type category.
1297      * See spell_skilltype for categories.
1298      */
1299     otyp = pseudo->otyp;
1300     skill = spell_skilltype(otyp);
1301     role_skill = P_SKILL(skill);
1302
1303     switch (otyp) {
1304     /*
1305      * At first spells act as expected.  As the hero increases in skill
1306      * with the appropriate spell type, some spells increase in their
1307      * effects, e.g. more damage, further distance, and so on, without
1308      * additional cost to the spellcaster.
1309      */
1310     case SPE_FIREBALL:
1311     case SPE_CONE_OF_COLD:
1312         if (role_skill >= P_SKILLED) {
1313             if (throwspell()) {
1314                 cc.x = u.dx;
1315                 cc.y = u.dy;
1316                 n = rnd(8) + 1;
1317                 while (n--) {
1318                     if (!u.dx && !u.dy && !u.dz) {
1319                         if ((damage = zapyourself(pseudo, TRUE)) != 0) {
1320                             char buf[BUFSZ];
1321 #if 0 /*JP*/
1322                             Sprintf(buf, "zapped %sself with a spell",
1323                                     uhim());
1324                             losehp(damage, buf, NO_KILLER_PREFIX);
1325 #else
1326                             Strcpy(buf, "\8e©\95ª\8e©\90g\82Ì\96\82\96@\82ð\97\81\82Ñ\82Ä");
1327                             losehp(damage, buf, KILLED_BY);
1328 #endif
1329                         }
1330                     } else {
1331                         explode(u.dx, u.dy,
1332                                 otyp - SPE_MAGIC_MISSILE + 10,
1333                                 spell_damage_bonus(u.ulevel / 2 + 1), 0,
1334                                 (otyp == SPE_CONE_OF_COLD)
1335                                    ? EXPL_FROSTY
1336                                    : EXPL_FIERY);
1337                     }
1338                     u.dx = cc.x + rnd(3) - 2;
1339                     u.dy = cc.y + rnd(3) - 2;
1340                     if (!isok(u.dx, u.dy) || !cansee(u.dx, u.dy)
1341                         || IS_STWALL(levl[u.dx][u.dy].typ) || u.uswallow) {
1342                         /* Spell is reflected back to center */
1343                         u.dx = cc.x;
1344                         u.dy = cc.y;
1345                     }
1346                 }
1347             }
1348             break;
1349         } /* else */
1350         /*FALLTHRU*/
1351
1352     /* these spells are all duplicates of wand effects */
1353     case SPE_FORCE_BOLT:
1354         physical_damage = TRUE;
1355     /*FALLTHRU*/
1356     case SPE_SLEEP:
1357     case SPE_MAGIC_MISSILE:
1358     case SPE_KNOCK:
1359     case SPE_SLOW_MONSTER:
1360     case SPE_WIZARD_LOCK:
1361     case SPE_DIG:
1362     case SPE_TURN_UNDEAD:
1363     case SPE_POLYMORPH:
1364     case SPE_TELEPORT_AWAY:
1365     case SPE_CANCELLATION:
1366     case SPE_FINGER_OF_DEATH:
1367     case SPE_LIGHT:
1368     case SPE_DETECT_UNSEEN:
1369     case SPE_HEALING:
1370     case SPE_EXTRA_HEALING:
1371     case SPE_DRAIN_LIFE:
1372     case SPE_STONE_TO_FLESH:
1373         if (objects[otyp].oc_dir != NODIR) {
1374             if (otyp == SPE_HEALING || otyp == SPE_EXTRA_HEALING) {
1375                 /* healing and extra healing are actually potion effects,
1376                    but they've been extended to take a direction like wands */
1377                 if (role_skill >= P_SKILLED)
1378                     pseudo->blessed = 1;
1379             }
1380             if (atme) {
1381                 u.dx = u.dy = u.dz = 0;
1382             } else if (!getdir((char *) 0)) {
1383                 /* getdir cancelled, re-use previous direction */
1384                 /*
1385                  * FIXME:  reusing previous direction only makes sense
1386                  * if there is an actual previous direction.  When there
1387                  * isn't one, the spell gets cast at self which is rarely
1388                  * what the player intended.  Unfortunately, the way
1389                  * spelleffects() is organized means that aborting with
1390                  * "nevermind" is not an option.
1391                  */
1392 /*JP
1393                 pline_The("magical energy is released!");
1394 */
1395                 pline("\96\82\96@\82Ì\83G\83l\83\8b\83M\81[\82ª\89ð\95ú\82³\82ê\82½\81I");
1396             }
1397             if (!u.dx && !u.dy && !u.dz) {
1398                 if ((damage = zapyourself(pseudo, TRUE)) != 0) {
1399                     char buf[BUFSZ];
1400
1401 /*JP
1402                     Sprintf(buf, "zapped %sself with a spell", uhim());
1403 */
1404                     Strcpy(buf, "\8e©\95ª\8e©\90g\82Ì\96\82\96@\82ð\97\81\82Ñ\82Ä");
1405                     if (physical_damage)
1406                         damage = Maybe_Half_Phys(damage);
1407 #if 0 /*JP*/
1408                     losehp(damage, buf, NO_KILLER_PREFIX);
1409 #else
1410                     losehp(damage, buf, KILLED_BY);
1411 #endif
1412                 }
1413             } else
1414                 weffects(pseudo);
1415         } else
1416             weffects(pseudo);
1417         update_inventory(); /* spell may modify inventory */
1418         break;
1419
1420     /* these are all duplicates of scroll effects */
1421     case SPE_REMOVE_CURSE:
1422     case SPE_CONFUSE_MONSTER:
1423     case SPE_DETECT_FOOD:
1424     case SPE_CAUSE_FEAR:
1425     case SPE_IDENTIFY:
1426         /* high skill yields effect equivalent to blessed scroll */
1427         if (role_skill >= P_SKILLED)
1428             pseudo->blessed = 1;
1429     /*FALLTHRU*/
1430     case SPE_CHARM_MONSTER:
1431     case SPE_MAGIC_MAPPING:
1432     case SPE_CREATE_MONSTER:
1433         (void) seffects(pseudo);
1434         break;
1435
1436     /* these are all duplicates of potion effects */
1437     case SPE_HASTE_SELF:
1438     case SPE_DETECT_TREASURE:
1439     case SPE_DETECT_MONSTERS:
1440     case SPE_LEVITATION:
1441     case SPE_RESTORE_ABILITY:
1442         /* high skill yields effect equivalent to blessed potion */
1443         if (role_skill >= P_SKILLED)
1444             pseudo->blessed = 1;
1445     /*FALLTHRU*/
1446     case SPE_INVISIBILITY:
1447         (void) peffects(pseudo);
1448         break;
1449     /* end of potion-like spells */
1450
1451     case SPE_CURE_BLINDNESS:
1452         healup(0, 0, FALSE, TRUE);
1453         break;
1454     case SPE_CURE_SICKNESS:
1455         if (Sick)
1456 /*JP
1457             You("are no longer ill.");
1458 */
1459             Your("\95a\8bC\82Í\92¼\82Á\82½\81D");
1460         if (Slimed)
1461 /*JP
1462             make_slimed(0L, "The slime disappears!");
1463 */
1464             make_slimed(0L, "\83X\83\89\83C\83\80\82Í\8fÁ\82¦\82½\81I");
1465         healup(0, 0, TRUE, FALSE);
1466         break;
1467     case SPE_CREATE_FAMILIAR:
1468         (void) make_familiar((struct obj *) 0, u.ux, u.uy, FALSE);
1469         break;
1470     case SPE_CLAIRVOYANCE:
1471         if (!BClairvoyant) {
1472             if (role_skill >= P_SKILLED)
1473                 pseudo->blessed = 1; /* detect monsters as well as map */
1474             do_vicinity_map(pseudo);
1475         /* at present, only one thing blocks clairvoyance */
1476         } else if (uarmh && uarmh->otyp == CORNUTHAUM)
1477 /*JP
1478             You("sense a pointy hat on top of your %s.", body_part(HEAD));
1479 */
1480             You("\82Æ\82ª\82Á\82½\96X\8eq\82ð%s\82Ì\8fã\82É\94­\8c©\82µ\82½\81D", body_part(HEAD));
1481         break;
1482     case SPE_PROTECTION:
1483         cast_protection();
1484         break;
1485     case SPE_JUMPING:
1486         if (!jump(max(role_skill, 1)))
1487             pline1(nothing_happens);
1488         break;
1489     default:
1490         impossible("Unknown spell %d attempted.", spell);
1491         obfree(pseudo, (struct obj *) 0);
1492         return 0;
1493     }
1494
1495     /* gain skill for successful cast */
1496     use_skill(skill, spellev(spell));
1497
1498     obfree(pseudo, (struct obj *) 0); /* now, get rid of it */
1499     return 1;
1500 }
1501
1502 /*ARGSUSED*/
1503 STATIC_OVL boolean
1504 spell_aim_step(arg, x, y)
1505 genericptr_t arg UNUSED;
1506 int x, y;
1507 {
1508     if (!isok(x,y))
1509         return FALSE;
1510     if (!ZAP_POS(levl[x][y].typ)
1511         && !(IS_DOOR(levl[x][y].typ) && (levl[x][y].doormask & D_ISOPEN)))
1512         return FALSE;
1513     return TRUE;
1514 }
1515
1516 /* Choose location where spell takes effect. */
1517 STATIC_OVL int
1518 throwspell()
1519 {
1520     coord cc, uc;
1521     struct monst *mtmp;
1522
1523     if (u.uinwater) {
1524 /*JP
1525         pline("You're joking!  In this weather?");
1526 */
1527         pline("\90\85\92\86\82Å\89½\82ð\82µ\82æ\82¤\82Á\82Ä\82¢\82¤\82ñ\82¾\82¢\81H");
1528         return 0;
1529     } else if (Is_waterlevel(&u.uz)) {
1530 /*JP
1531         You("had better wait for the sun to come out.");
1532 */
1533         You("\91¾\97z\82ª\8c»\82ê\82é\82Ü\82Å\91Ò\82Á\82½\82Ù\82¤\82ª\82æ\82¢\82¾\82ë\82¤\81D");
1534         return 0;
1535     }
1536
1537 /*JP
1538     pline("Where do you want to cast the spell?");
1539 */
1540     pline("\82Ç\82±\82É\8cü\82©\82Á\82Ä\96\82\96@\82ð\8f¥\82¦\82é\81H");
1541     cc.x = u.ux;
1542     cc.y = u.uy;
1543 /*JP
1544     if (getpos(&cc, TRUE, "the desired position") < 0)
1545 */
1546     if (getpos(&cc, TRUE, "\96]\82Ý\82Ì\8fê\8f\8a") < 0)
1547         return 0; /* user pressed ESC */
1548     /* The number of moves from hero to where the spell drops.*/
1549     if (distmin(u.ux, u.uy, cc.x, cc.y) > 10) {
1550 /*JP
1551         pline_The("spell dissipates over the distance!");
1552 */
1553         pline("\89\93\82·\82¬\82é\81I");
1554         return 0;
1555     } else if (u.uswallow) {
1556 /*JP
1557         pline_The("spell is cut short!");
1558 */
1559         pline("\82¾\82ß\82¾\81I\8bß\82·\82¬\82é\81I");
1560         exercise(A_WIS, FALSE); /* What were you THINKING! */
1561         u.dx = 0;
1562         u.dy = 0;
1563         return 1;
1564     } else if ((!cansee(cc.x, cc.y)
1565                 && (!(mtmp = m_at(cc.x, cc.y)) || !canspotmon(mtmp)))
1566                || IS_STWALL(levl[cc.x][cc.y].typ)) {
1567 /*JP
1568         Your("mind fails to lock onto that location!");
1569 */
1570         You("\82»\82±\82É\8cü\82©\82Á\82Ä\8fW\92\86\82µ\82½\82ª\8e¸\94s\82µ\82½\81I");
1571         return 0;
1572     }
1573
1574     uc.x = u.ux;
1575     uc.y = u.uy;
1576
1577     walk_path(&uc, &cc, spell_aim_step, (genericptr_t) 0);
1578
1579     u.dx = cc.x;
1580     u.dy = cc.y;
1581     return 1;
1582 }
1583
1584 /* add/hide/remove/unhide teleport-away on behalf of dotelecmd() to give
1585    more control to behavior of ^T when used in wizard mode */
1586 int
1587 tport_spell(what)
1588 int what;
1589 {
1590     static struct tport_hideaway {
1591         struct spell savespell;
1592         int tport_indx;
1593     } save_tport;
1594     int i;
1595 /* also defined in teleport.c */
1596 #define NOOP_SPELL  0
1597 #define HIDE_SPELL  1
1598 #define ADD_SPELL   2
1599 #define UNHIDESPELL 3
1600 #define REMOVESPELL 4
1601
1602     for (i = 0; i < MAXSPELL; i++)
1603         if (spellid(i) == SPE_TELEPORT_AWAY || spellid(i) == NO_SPELL)
1604             break;
1605     if (i == MAXSPELL) {
1606         impossible("tport_spell: spellbook full");
1607         /* wizard mode ^T is not able to honor player's menu choice */
1608     } else if (spellid(i) == NO_SPELL) {
1609         if (what == HIDE_SPELL || what == REMOVESPELL) {
1610             save_tport.tport_indx = MAXSPELL;
1611         } else if (what == UNHIDESPELL) {
1612             /*assert( save_tport.savespell.sp_id == SPE_TELEPORT_AWAY );*/
1613             spl_book[save_tport.tport_indx] = save_tport.savespell;
1614             save_tport.tport_indx = MAXSPELL; /* burn bridge... */
1615         } else if (what == ADD_SPELL) {
1616             save_tport.savespell = spl_book[i];
1617             save_tport.tport_indx = i;
1618             spl_book[i].sp_id = SPE_TELEPORT_AWAY;
1619             spl_book[i].sp_lev = objects[SPE_TELEPORT_AWAY].oc_level;
1620             spl_book[i].sp_know = KEEN;
1621             return REMOVESPELL; /* operation needed to reverse */
1622         }
1623     } else { /* spellid(i) == SPE_TELEPORT_AWAY */
1624         if (what == ADD_SPELL || what == UNHIDESPELL) {
1625             save_tport.tport_indx = MAXSPELL;
1626         } else if (what == REMOVESPELL) {
1627             /*assert( i == save_tport.tport_indx );*/
1628             spl_book[i] = save_tport.savespell;
1629             save_tport.tport_indx = MAXSPELL;
1630         } else if (what == HIDE_SPELL) {
1631             save_tport.savespell = spl_book[i];
1632             save_tport.tport_indx = i;
1633             spl_book[i].sp_id = NO_SPELL;
1634             return UNHIDESPELL; /* operation needed to reverse */
1635         }
1636     }
1637     return NOOP_SPELL;
1638 }
1639
1640 /* forget a random selection of known spells due to amnesia;
1641    they used to be lost entirely, as if never learned, but now we
1642    just set the memory retention to zero so that they can't be cast */
1643 void
1644 losespells()
1645 {
1646     int n, nzap, i;
1647
1648     /* in case reading has been interrupted earlier, discard context */
1649     context.spbook.book = 0;
1650     context.spbook.o_id = 0;
1651     /* count the number of known spells */
1652     for (n = 0; n < MAXSPELL; ++n)
1653         if (spellid(n) == NO_SPELL)
1654             break;
1655
1656     /* lose anywhere from zero to all known spells;
1657        if confused, use the worse of two die rolls */
1658     nzap = rn2(n + 1);
1659     if (Confusion) {
1660         i = rn2(n + 1);
1661         if (i > nzap)
1662             nzap = i;
1663     }
1664     /* good Luck might ameliorate spell loss */
1665     if (nzap > 1 && !rnl(7))
1666         nzap = rnd(nzap);
1667
1668     /*
1669      * Forget 'nzap' out of 'n' known spells by setting their memory
1670      * retention to zero.  Every spell has the same probability to be
1671      * forgotten, even if its retention is already zero.
1672      *
1673      * Perhaps we should forget the corresponding book too?
1674      *
1675      * (3.4.3 removed spells entirely from the list, but always did
1676      * so from its end, so the 'nzap' most recently learned spells
1677      * were the ones lost by default.  Player had sort control over
1678      * the list, so could move the most useful spells to front and
1679      * only lose them if 'nzap' turned out to be a large value.
1680      *
1681      * Discarding from the end of the list had the virtue of making
1682      * casting letters for lost spells become invalid and retaining
1683      * the original letter for the ones which weren't lost, so there
1684      * was no risk to the player of accidentally casting the wrong
1685      * spell when using a letter that was in use prior to amnesia.
1686      * That wouldn't be the case if we implemented spell loss spread
1687      * throughout the list of known spells; every spell located past
1688      * the first lost spell would end up with new letter assigned.)
1689      */
1690     for (i = 0; nzap > 0; ++i) {
1691         /* when nzap is small relative to the number of spells left,
1692            the chance to lose spell [i] is small; as the number of
1693            remaining candidates shrinks, the chance per candidate
1694            gets bigger; overall, exactly nzap entries are affected */
1695         if (rn2(n - i) < nzap) {
1696             /* lose access to spell [i] */
1697             spellknow(i) = 0;
1698 #if 0
1699             /* also forget its book */
1700             forget_single_object(spellid(i));
1701 #endif
1702             /* and abuse wisdom */
1703             exercise(A_WIS, FALSE);
1704             /* there's now one less spell slated to be forgotten */
1705             --nzap;
1706         }
1707     }
1708 }
1709
1710 /*
1711  * Allow player to sort the list of known spells.  Manually swapping
1712  * pairs of them becomes very tedious once the list reaches two pages.
1713  *
1714  * Possible extensions:
1715  *      provide means for player to control ordering of skill classes;
1716  *      provide means to supply value N such that first N entries stick
1717  *      while rest of list is being sorted;
1718  *      make chosen sort order be persistent such that when new spells
1719  *      are learned, they get inserted into sorted order rather than be
1720  *      appended to the end of the list?
1721  */
1722 enum spl_sort_types {
1723     SORTBY_LETTER = 0,
1724     SORTBY_ALPHA,
1725     SORTBY_LVL_LO,
1726     SORTBY_LVL_HI,
1727     SORTBY_SKL_AL,
1728     SORTBY_SKL_LO,
1729     SORTBY_SKL_HI,
1730     SORTBY_CURRENT,
1731     SORTRETAINORDER,
1732
1733     NUM_SPELL_SORTBY
1734 };
1735
1736 static const char *spl_sortchoices[NUM_SPELL_SORTBY] = {
1737 /*JP
1738     "by casting letter",
1739 */
1740     "\91I\91ð\82·\82é\95\8e\9a\8f\87",
1741 /*JP
1742     "alphabetically",
1743 */
1744     "\95\8e\9a\83R\81[\83h\8f\87",
1745 /*JP
1746     "by level, low to high",
1747 */
1748     "\83\8c\83x\83\8b\8f¸\8f\87",
1749 /*JP
1750     "by level, high to low",
1751 */
1752     "\83\8c\83x\83\8b\8d~\8f\87",
1753 /*JP
1754     "by skill group, alphabetized within each group",
1755 */
1756     "\83X\83L\83\8b\83O\83\8b\81[\83v\96\88\82É\95\8e\9a\83R\81[\83h\8f\87",
1757 /*JP
1758     "by skill group, low to high level within group",
1759 */
1760     "\83X\83L\83\8b\83O\83\8b\81[\83v\96\88\82É\83\8c\83x\83\8b\8f¸\8f\87",
1761 /*JP
1762     "by skill group, high to low level within group",
1763 */
1764     "\83X\83L\83\8b\83O\83\8b\81[\83v\96\88\82É\83\8c\83x\83\8b\8d~\8f\87",
1765 /*JP
1766     "maintain current ordering",
1767 */
1768     "\8c»\8dÝ\82Ì\8f\87\8f\98\82ð\88Û\8e\9d",
1769     /* a menu choice rather than a sort choice */
1770 /*JP
1771     "reassign casting letters to retain current order",
1772 */
1773     "\8c»\8dÝ\82Ì\8f\87\8f\98\82ð\95Ï\82¦\82¸\82É\91I\91ð\82·\82é\95\8e\9a\82ð\8dÄ\8a\84\82è\93\96\82Ä",
1774 };
1775 static int spl_sortmode = 0;   /* index into spl_sortchoices[] */
1776 static int *spl_orderindx = 0; /* array of spl_book[] indices */
1777
1778 /* qsort callback routine */
1779 STATIC_PTR int CFDECLSPEC
1780 spell_cmp(vptr1, vptr2)
1781 const genericptr vptr1;
1782 const genericptr vptr2;
1783 {
1784     /*
1785      * gather up all of the possible parameters except spell name
1786      * in advance, even though some might not be needed:
1787      *  indx. = spl_orderindx[] index into spl_book[];
1788      *  otyp. = spl_book[] index into objects[];
1789      *  levl. = spell level;
1790      *  skil. = skill group aka spell class.
1791      */
1792     int indx1 = *(int *) vptr1, indx2 = *(int *) vptr2,
1793         otyp1 = spl_book[indx1].sp_id, otyp2 = spl_book[indx2].sp_id,
1794         levl1 = objects[otyp1].oc_level, levl2 = objects[otyp2].oc_level,
1795         skil1 = objects[otyp1].oc_skill, skil2 = objects[otyp2].oc_skill;
1796
1797     switch (spl_sortmode) {
1798     case SORTBY_LETTER:
1799         return indx1 - indx2;
1800     case SORTBY_ALPHA:
1801         break;
1802     case SORTBY_LVL_LO:
1803         if (levl1 != levl2)
1804             return levl1 - levl2;
1805         break;
1806     case SORTBY_LVL_HI:
1807         if (levl1 != levl2)
1808             return levl2 - levl1;
1809         break;
1810     case SORTBY_SKL_AL:
1811         if (skil1 != skil2)
1812             return skil1 - skil2;
1813         break;
1814     case SORTBY_SKL_LO:
1815         if (skil1 != skil2)
1816             return skil1 - skil2;
1817         if (levl1 != levl2)
1818             return levl1 - levl2;
1819         break;
1820     case SORTBY_SKL_HI:
1821         if (skil1 != skil2)
1822             return skil1 - skil2;
1823         if (levl1 != levl2)
1824             return levl2 - levl1;
1825         break;
1826     case SORTBY_CURRENT:
1827     default:
1828         return (vptr1 < vptr2) ? -1
1829                                : (vptr1 > vptr2); /* keep current order */
1830     }
1831     /* tie-breaker for most sorts--alphabetical by spell name */
1832     return strcmpi(OBJ_NAME(objects[otyp1]), OBJ_NAME(objects[otyp2]));
1833 }
1834
1835 /* sort the index used for display order of the "view known spells"
1836    list (sortmode == SORTBY_xxx), or sort the spellbook itself to make
1837    the current display order stick (sortmode == SORTRETAINORDER) */
1838 STATIC_OVL void
1839 sortspells()
1840 {
1841     int i;
1842 #if defined(SYSV) || defined(DGUX)
1843     unsigned n;
1844 #else
1845     int n;
1846 #endif
1847
1848     if (spl_sortmode == SORTBY_CURRENT)
1849         return;
1850     for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; ++n)
1851         continue;
1852     if (n < 2)
1853         return; /* not enough entries to need sorting */
1854
1855     if (!spl_orderindx) {
1856         /* we haven't done any sorting yet; list is in casting order */
1857         if (spl_sortmode == SORTBY_LETTER /* default */
1858             || spl_sortmode == SORTRETAINORDER)
1859             return;
1860         /* allocate enough for full spellbook rather than just N spells */
1861         spl_orderindx = (int *) alloc(MAXSPELL * sizeof(int));
1862         for (i = 0; i < MAXSPELL; i++)
1863             spl_orderindx[i] = i;
1864     }
1865
1866     if (spl_sortmode == SORTRETAINORDER) {
1867         struct spell tmp_book[MAXSPELL];
1868
1869         /* sort spl_book[] rather than spl_orderindx[];
1870            this also updates the index to reflect the new ordering (we
1871            could just free it since that ordering becomes the default) */
1872         for (i = 0; i < MAXSPELL; i++)
1873             tmp_book[i] = spl_book[spl_orderindx[i]];
1874         for (i = 0; i < MAXSPELL; i++)
1875             spl_book[i] = tmp_book[i], spl_orderindx[i] = i;
1876         spl_sortmode = SORTBY_LETTER; /* reset */
1877         return;
1878     }
1879
1880     /* usual case, sort the index rather than the spells themselves */
1881     qsort((genericptr_t) spl_orderindx, n, sizeof *spl_orderindx, spell_cmp);
1882     return;
1883 }
1884
1885 /* called if the [sort spells] entry in the view spells menu gets chosen */
1886 STATIC_OVL boolean
1887 spellsortmenu()
1888 {
1889     winid tmpwin;
1890     menu_item *selected;
1891     anything any;
1892     char let;
1893     int i, n, choice;
1894
1895     tmpwin = create_nhwindow(NHW_MENU);
1896     start_menu(tmpwin);
1897     any = zeroany; /* zero out all bits */
1898
1899     for (i = 0; i < SIZE(spl_sortchoices); i++) {
1900         if (i == SORTRETAINORDER) {
1901             let = 'z'; /* assumes fewer than 26 sort choices... */
1902             /* separate final choice from others with a blank line */
1903             any.a_int = 0;
1904             add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "",
1905                      MENU_UNSELECTED);
1906         } else {
1907             let = 'a' + i;
1908         }
1909         any.a_int = i + 1;
1910         add_menu(tmpwin, NO_GLYPH, &any, let, 0, ATR_NONE, spl_sortchoices[i],
1911                  (i == spl_sortmode) ? MENU_SELECTED : MENU_UNSELECTED);
1912     }
1913     end_menu(tmpwin, "View known spells list sorted");
1914
1915     n = select_menu(tmpwin, PICK_ONE, &selected);
1916     destroy_nhwindow(tmpwin);
1917     if (n > 0) {
1918         choice = selected[0].item.a_int - 1;
1919         /* skip preselected entry if we have more than one item chosen */
1920         if (n > 1 && choice == spl_sortmode)
1921             choice = selected[1].item.a_int - 1;
1922         free((genericptr_t) selected);
1923         spl_sortmode = choice;
1924         return TRUE;
1925     }
1926     return FALSE;
1927 }
1928
1929 /* the '+' command -- view known spells */
1930 int
1931 dovspell()
1932 {
1933     char qbuf[QBUFSZ];
1934     int splnum, othnum;
1935     struct spell spl_tmp;
1936
1937     if (spellid(0) == NO_SPELL) {
1938 /*JP
1939         You("don't know any spells right now.");
1940 */
1941         You("\96\82\96@\82ð\92m\82ç\82È\82¢\81D");
1942     } else {
1943 /*JP
1944         while (dospellmenu("Currently known spells",
1945 */
1946         while (dospellmenu("\8c»\8dÝ\92m\82Á\82Ä\82¢\82é\96\82\96@\88ê\97\97",
1947                            SPELLMENU_VIEW, &splnum)) {
1948             if (splnum == SPELLMENU_SORT) {
1949                 if (spellsortmenu())
1950                     sortspells();
1951             } else {
1952 /*JP
1953                 Sprintf(qbuf, "Reordering spells; swap '%c' with",
1954 */
1955                 Sprintf(qbuf, "'%c'\82Æ\95À\82Ñ\95Ï\82¦\82é\96\82\96@\82Í\81H",
1956                         spellet(splnum));
1957                 if (!dospellmenu(qbuf, splnum, &othnum))
1958                     break;
1959
1960                 spl_tmp = spl_book[splnum];
1961                 spl_book[splnum] = spl_book[othnum];
1962                 spl_book[othnum] = spl_tmp;
1963             }
1964         }
1965     }
1966     if (spl_orderindx) {
1967         free((genericptr_t) spl_orderindx);
1968         spl_orderindx = 0;
1969     }
1970     spl_sortmode = SORTBY_LETTER; /* 0 */
1971     return 0;
1972 }
1973
1974 STATIC_OVL boolean
1975 dospellmenu(prompt, splaction, spell_no)
1976 const char *prompt;
1977 int splaction; /* SPELLMENU_CAST, SPELLMENU_VIEW, or spl_book[] index */
1978 int *spell_no;
1979 {
1980     winid tmpwin;
1981     int i, n, how, splnum;
1982     char buf[BUFSZ], retentionbuf[24];
1983     const char *fmt;
1984     menu_item *selected;
1985     anything any;
1986
1987     tmpwin = create_nhwindow(NHW_MENU);
1988     start_menu(tmpwin);
1989     any = zeroany; /* zero out all bits */
1990
1991     /*
1992      * The correct spacing of the columns when not using
1993      * tab separation depends on the following:
1994      * (1) that the font is monospaced, and
1995      * (2) that selection letters are pre-pended to the
1996      * given string and are of the form "a - ".
1997      */
1998     if (!iflags.menu_tab_sep) {
1999 #if 0 /*JP*/
2000         Sprintf(buf, "%-20s     Level %-12s Fail Retention", "    Name",
2001                 "Category");
2002 #else
2003         Sprintf(buf, "%-20s     Level  %-12s \90¬\8c÷\97¦", "    Name", "\95ª\97Þ");
2004 #endif
2005         fmt = "%-20s  %2d   %-12s %3d%% %9s";
2006     } else {
2007 /*JP
2008         Sprintf(buf, "Name\tLevel\tCategory\tFail\tRetention");
2009 */
2010         Sprintf(buf, "\96¼\91O\t\83\8c\83x\83\8b\t\95ª\97Þ\t\90¬\8c÷\97¦");
2011         fmt = "%s\t%-d\t%s\t%-d%%\t%s";
2012     }
2013     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings, buf,
2014              MENU_UNSELECTED);
2015     for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++) {
2016         splnum = !spl_orderindx ? i : spl_orderindx[i];
2017         Sprintf(buf, fmt, spellname(splnum), spellev(splnum),
2018                 spelltypemnemonic(spell_skilltype(spellid(splnum))),
2019                 100 - percent_success(splnum),
2020                 spellretention(splnum, retentionbuf));
2021
2022         any.a_int = splnum + 1; /* must be non-zero */
2023         add_menu(tmpwin, NO_GLYPH, &any, spellet(splnum), 0, ATR_NONE, buf,
2024                  (splnum == splaction) ? MENU_SELECTED : MENU_UNSELECTED);
2025     }
2026     how = PICK_ONE;
2027     if (splaction == SPELLMENU_VIEW) {
2028         if (spellid(1) == NO_SPELL) {
2029             /* only one spell => nothing to swap with */
2030             how = PICK_NONE;
2031         } else {
2032             /* more than 1 spell, add an extra menu entry */
2033             any.a_int = SPELLMENU_SORT + 1;
2034             add_menu(tmpwin, NO_GLYPH, &any, '+', 0, ATR_NONE,
2035                      "[sort spells]", MENU_UNSELECTED);
2036         }
2037     }
2038     end_menu(tmpwin, prompt);
2039
2040     n = select_menu(tmpwin, how, &selected);
2041     destroy_nhwindow(tmpwin);
2042     if (n > 0) {
2043         *spell_no = selected[0].item.a_int - 1;
2044         /* menu selection for `PICK_ONE' does not
2045            de-select any preselected entry */
2046         if (n > 1 && *spell_no == splaction)
2047             *spell_no = selected[1].item.a_int - 1;
2048         free((genericptr_t) selected);
2049         /* default selection of preselected spell means that
2050            user chose not to swap it with anything */
2051         if (*spell_no == splaction)
2052             return FALSE;
2053         return TRUE;
2054     } else if (splaction >= 0) {
2055         /* explicit de-selection of preselected spell means that
2056            user is still swapping but not for the current spell */
2057         *spell_no = splaction;
2058         return TRUE;
2059     }
2060     return FALSE;
2061 }
2062
2063 STATIC_OVL int
2064 percent_success(spell)
2065 int spell;
2066 {
2067     /* Intrinsic and learned ability are combined to calculate
2068      * the probability of player's success at cast a given spell.
2069      */
2070     int chance, splcaster, special, statused;
2071     int difficulty;
2072     int skill;
2073
2074     /* Calculate intrinsic ability (splcaster) */
2075
2076     splcaster = urole.spelbase;
2077     special = urole.spelheal;
2078     statused = ACURR(urole.spelstat);
2079
2080     if (uarm && is_metallic(uarm))
2081         splcaster += (uarmc && uarmc->otyp == ROBE) ? urole.spelarmr / 2
2082                                                     : urole.spelarmr;
2083     else if (uarmc && uarmc->otyp == ROBE)
2084         splcaster -= urole.spelarmr;
2085     if (uarms)
2086         splcaster += urole.spelshld;
2087
2088     if (uarmh && is_metallic(uarmh) && uarmh->otyp != HELM_OF_BRILLIANCE)
2089         splcaster += uarmhbon;
2090     if (uarmg && is_metallic(uarmg))
2091         splcaster += uarmgbon;
2092     if (uarmf && is_metallic(uarmf))
2093         splcaster += uarmfbon;
2094
2095     if (spellid(spell) == urole.spelspec)
2096         splcaster += urole.spelsbon;
2097
2098     /* `healing spell' bonus */
2099     if (spellid(spell) == SPE_HEALING || spellid(spell) == SPE_EXTRA_HEALING
2100         || spellid(spell) == SPE_CURE_BLINDNESS
2101         || spellid(spell) == SPE_CURE_SICKNESS
2102         || spellid(spell) == SPE_RESTORE_ABILITY
2103         || spellid(spell) == SPE_REMOVE_CURSE)
2104         splcaster += special;
2105
2106     if (splcaster > 20)
2107         splcaster = 20;
2108
2109     /* Calculate learned ability */
2110
2111     /* Players basic likelihood of being able to cast any spell
2112      * is based of their `magic' statistic. (Int or Wis)
2113      */
2114     chance = 11 * statused / 2;
2115
2116     /*
2117      * High level spells are harder.  Easier for higher level casters.
2118      * The difficulty is based on the hero's level and their skill level
2119      * in that spell type.
2120      */
2121     skill = P_SKILL(spell_skilltype(spellid(spell)));
2122     skill = max(skill, P_UNSKILLED) - 1; /* unskilled => 0 */
2123     difficulty =
2124         (spellev(spell) - 1) * 4 - ((skill * 6) + (u.ulevel / 3) + 1);
2125
2126     if (difficulty > 0) {
2127         /* Player is too low level or unskilled. */
2128         chance -= isqrt(900 * difficulty + 2000);
2129     } else {
2130         /* Player is above level.  Learning continues, but the
2131          * law of diminishing returns sets in quickly for
2132          * low-level spells.  That is, a player quickly gains
2133          * no advantage for raising level.
2134          */
2135         int learning = 15 * -difficulty / spellev(spell);
2136         chance += learning > 20 ? 20 : learning;
2137     }
2138
2139     /* Clamp the chance: >18 stat and advanced learning only help
2140      * to a limit, while chances below "hopeless" only raise the
2141      * specter of overflowing 16-bit ints (and permit wearing a
2142      * shield to raise the chances :-).
2143      */
2144     if (chance < 0)
2145         chance = 0;
2146     if (chance > 120)
2147         chance = 120;
2148
2149     /* Wearing anything but a light shield makes it very awkward
2150      * to cast a spell.  The penalty is not quite so bad for the
2151      * player's role-specific spell.
2152      */
2153     if (uarms && weight(uarms) > (int) objects[SMALL_SHIELD].oc_weight) {
2154         if (spellid(spell) == urole.spelspec) {
2155             chance /= 2;
2156         } else {
2157             chance /= 4;
2158         }
2159     }
2160
2161     /* Finally, chance (based on player intell/wisdom and level) is
2162      * combined with ability (based on player intrinsics and
2163      * encumbrances).  No matter how intelligent/wise and advanced
2164      * a player is, intrinsics and encumbrance can prevent casting;
2165      * and no matter how able, learning is always required.
2166      */
2167     chance = chance * (20 - splcaster) / 15 - splcaster;
2168
2169     /* Clamp to percentile */
2170     if (chance > 100)
2171         chance = 100;
2172     if (chance < 0)
2173         chance = 0;
2174
2175     return chance;
2176 }
2177
2178 STATIC_OVL char *
2179 spellretention(idx, outbuf)
2180 int idx;
2181 char *outbuf;
2182 {
2183     long turnsleft, percent, accuracy;
2184     int skill;
2185
2186     skill = P_SKILL(spell_skilltype(spellid(idx)));
2187     skill = max(skill, P_UNSKILLED); /* restricted same as unskilled */
2188     turnsleft = spellknow(idx);
2189     *outbuf = '\0'; /* lint suppression */
2190
2191     if (turnsleft < 1L) {
2192         /* spell has expired; hero can't successfully cast it anymore */
2193 /*JP
2194         Strcpy(outbuf, "(gone)");
2195 */
2196         Strcpy(outbuf, "(\96Y\8bp)");
2197     } else if (turnsleft >= (long) KEEN) {
2198         /* full retention, first turn or immediately after reading book */
2199         Strcpy(outbuf, "100%");
2200     } else {
2201         /*
2202          * Retention is displayed as a range of percentages of
2203          * amount of time left until memory of the spell expires;
2204          * the precision of the range depends upon hero's skill
2205          * in this spell.
2206          *    expert:  2% intervals; 1-2,   3-4,  ...,   99-100;
2207          *   skilled:  5% intervals; 1-5,   6-10, ...,   95-100;
2208          *     basic: 10% intervals; 1-10, 11-20, ...,   91-100;
2209          * unskilled: 25% intervals; 1-25, 26-50, 51-75, 76-100.
2210          *
2211          * At the low end of each range, a value of N% really means
2212          * (N-1)%+1 through N%; so 1% is "greater than 0, at most 200".
2213          * KEEN is a multiple of 100; KEEN/100 loses no precision.
2214          */
2215         percent = (turnsleft - 1L) / ((long) KEEN / 100L) + 1L;
2216         accuracy =
2217             (skill == P_EXPERT) ? 2L : (skill == P_SKILLED)
2218                                            ? 5L
2219                                            : (skill == P_BASIC) ? 10L : 25L;
2220         /* round up to the high end of this range */
2221         percent = accuracy * ((percent - 1L) / accuracy + 1L);
2222         Sprintf(outbuf, "%ld%%-%ld%%", percent - accuracy + 1L, percent);
2223     }
2224     return outbuf;
2225 }
2226
2227 /* Learn a spell during creation of the initial inventory */
2228 void
2229 initialspell(obj)
2230 struct obj *obj;
2231 {
2232     int i, otyp = obj->otyp;
2233
2234     for (i = 0; i < MAXSPELL; i++)
2235         if (spellid(i) == NO_SPELL || spellid(i) == otyp)
2236             break;
2237
2238     if (i == MAXSPELL) {
2239         impossible("Too many spells memorized!");
2240     } else if (spellid(i) != NO_SPELL) {
2241         /* initial inventory shouldn't contain duplicate spellbooks */
2242         impossible("Spell %s already known.", OBJ_NAME(objects[otyp]));
2243     } else {
2244         spl_book[i].sp_id = otyp;
2245         spl_book[i].sp_lev = objects[otyp].oc_level;
2246         incrnknow(i, 0);
2247     }
2248     return;
2249 }
2250
2251 /*spell.c*/