OSDN Git Service

update year to 2020
[jnethack/source.git] / src / engrave.c
1 /* NetHack 3.6  engrave.c       $NHDT-Date: 1570318925 2019/10/05 23:42:05 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.75 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2012. */
4 /* NetHack may be freely redistributed.  See license for details. */
5
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020            */
9 /* JNetHack may be freely redistributed.  See license for details. */
10
11 #include "hack.h"
12 #include "lev.h"
13
14 STATIC_VAR NEARDATA struct engr *head_engr;
15 STATIC_DCL const char *NDECL(blengr);
16
17 char *
18 random_engraving(outbuf)
19 char *outbuf;
20 {
21     const char *rumor;
22
23     /* a random engraving may come from the "rumors" file,
24        or from the "engrave" file (formerly in an array here) */
25     if (!rn2(4) || !(rumor = getrumor(0, outbuf, TRUE)) || !*rumor)
26         (void) get_rnd_text(ENGRAVEFILE, outbuf, rn2);
27
28     wipeout_text(outbuf, (int) (strlen(outbuf) / 4), 0);
29     return outbuf;
30 }
31
32 /* Partial rubouts for engraving characters. -3. */
33 static const struct {
34     char wipefrom;
35     const char *wipeto;
36 } rubouts[] = { { 'A', "^" },
37                 { 'B', "Pb[" },
38                 { 'C', "(" },
39                 { 'D', "|)[" },
40                 { 'E', "|FL[_" },
41                 { 'F', "|-" },
42                 { 'G', "C(" },
43                 { 'H', "|-" },
44                 { 'I', "|" },
45                 { 'K', "|<" },
46                 { 'L', "|_" },
47                 { 'M', "|" },
48                 { 'N', "|\\" },
49                 { 'O', "C(" },
50                 { 'P', "F" },
51                 { 'Q', "C(" },
52                 { 'R', "PF" },
53                 { 'T', "|" },
54                 { 'U', "J" },
55                 { 'V', "/\\" },
56                 { 'W', "V/\\" },
57                 { 'Z', "/" },
58                 { 'b', "|" },
59                 { 'd', "c|" },
60                 { 'e', "c" },
61                 { 'g', "c" },
62                 { 'h', "n" },
63                 { 'j', "i" },
64                 { 'k', "|" },
65                 { 'l', "|" },
66                 { 'm', "nr" },
67                 { 'n', "r" },
68                 { 'o', "c" },
69                 { 'q', "c" },
70                 { 'w', "v" },
71                 { 'y', "v" },
72                 { ':', "." },
73                 { ';', ",:" },
74                 { ',', "." },
75                 { '=', "-" },
76                 { '+', "-|" },
77                 { '*', "+" },
78                 { '@', "0" },
79                 { '0', "C(" },
80                 { '1', "|" },
81                 { '6', "o" },
82                 { '7', "/" },
83                 { '8', "3o" } };
84
85 /* degrade some of the characters in a string */
86 void
87 wipeout_text(engr, cnt, seed)
88 char *engr;
89 int cnt;
90 unsigned seed; /* for semi-controlled randomization */
91 {
92 #if 0 /*JP*/
93     char *s;
94 #else
95     unsigned char *s;
96 #endif
97     int i, j, nxt, use_rubout, lth = (int) strlen(engr);
98
99     if (lth && cnt > 0) {
100         while (cnt--) {
101             /* pick next character */
102             if (!seed) {
103                 /* random */
104                 nxt = rn2(lth);
105                 use_rubout = rn2(4);
106             } else {
107                 /* predictable; caller can reproduce the same sequence by
108                    supplying the same arguments later, or a pseudo-random
109                    sequence by varying any of them */
110                 nxt = seed % lth;
111                 seed *= 31, seed %= (BUFSZ - 1);
112                 use_rubout = seed & 3;
113             }
114 #if 0 /*JP*/
115             s = &engr[nxt];
116 #else /*JP: \93ú\96{\8cê\82Ì\8fê\8d\87\82Íjrubout()\82ð\8eg\82Á\82Ä\8fÁ\82·*/
117             if (!seed)
118                 j = rn2(2);
119             else {
120                 seed *= 31,  seed %= (BUFSZ-1);
121                 j = seed % 2;
122             }
123
124             if(jrubout(engr, nxt, use_rubout, j)){
125                 continue;
126             }
127
128             s = (unsigned char *)&engr[nxt];
129 #endif
130             if (*s == ' ')
131                 continue;
132
133             /* rub out unreadable & small punctuation marks */
134             if (index("?.,'`-|_", *s)) {
135                 *s = ' ';
136                 continue;
137             }
138
139             if (!use_rubout)
140                 i = SIZE(rubouts);
141             else
142                 for (i = 0; i < SIZE(rubouts); i++)
143                     if (*s == rubouts[i].wipefrom) {
144                         /*
145                          * Pick one of the substitutes at random.
146                          */
147                         if (!seed)
148                             j = rn2(strlen(rubouts[i].wipeto));
149                         else {
150                             seed *= 31, seed %= (BUFSZ - 1);
151                             j = seed % (strlen(rubouts[i].wipeto));
152                         }
153                         *s = rubouts[i].wipeto[j];
154                         break;
155                     }
156
157             /* didn't pick rubout; use '?' for unreadable character */
158             if (i == SIZE(rubouts))
159                 *s = '?';
160         }
161     }
162
163     /* trim trailing spaces */
164     while (lth && engr[lth - 1] == ' ')
165         engr[--lth] = '\0';
166 }
167
168 /* check whether hero can reach something at ground level */
169 boolean
170 can_reach_floor(check_pit)
171 boolean check_pit;
172 {
173     struct trap *t;
174
175     if (u.uswallow)
176         return FALSE;
177     /* Restricted/unskilled riders can't reach the floor */
178     if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
179         return FALSE;
180     if (check_pit && !Flying
181         && (t = t_at(u.ux, u.uy)) != 0
182         && (uteetering_at_seen_pit(t) || uescaped_shaft(t)))
183         return FALSE;
184
185     return (boolean) ((!Levitation || Is_airlevel(&u.uz)
186                        || Is_waterlevel(&u.uz))
187                       && (!u.uundetected || !is_hider(youmonst.data)
188                           || u.umonnum == PM_TRAPPER));
189 }
190
191 /* give a message after caller has determined that hero can't reach */
192 void
193 cant_reach_floor(x, y, up, check_pit)
194 int x, y;
195 boolean up, check_pit;
196 {
197 #if 0 /*JP:T*/
198     You("can't reach the %s.",
199         up ? ceiling(x, y)
200            : (check_pit && can_reach_floor(FALSE))
201                ? "bottom of the pit"
202                : surface(x, y));
203 #else
204     You("%s\82É\93Í\82©\82È\82¢\81D",
205         up ? ceiling(x, y)
206            : (check_pit && can_reach_floor(FALSE))
207                ? "\97\8e\82µ\8c\8a\82Ì\92ê"
208                : surface(x, y));
209 #endif
210 }
211
212 const char *
213 surface(x, y)
214 register int x, y;
215 {
216     register struct rm *lev = &levl[x][y];
217
218     if (x == u.ux && y == u.uy && u.uswallow && is_animal(u.ustuck->data))
219 /*JP
220         return "maw";
221 */
222         return "\88Ý\91Ü";
223     else if (IS_AIR(lev->typ) && Is_airlevel(&u.uz))
224 /*JP
225         return "air";
226 */
227         return "\8bó\92\86";
228     else if (is_pool(x, y))
229 #if 0 /*JP:T*/
230         return (Underwater && !Is_waterlevel(&u.uz))
231             ? "bottom" : hliquid("water");
232 #else
233         return (Underwater && !Is_waterlevel(&u.uz))
234             ? "\90\85\82Ì\92ê" : hliquid("\90\85\92\86");
235 #endif
236     else if (is_ice(x, y))
237 /*JP
238         return "ice";
239 */
240         return "\95X";
241     else if (is_lava(x, y))
242 /*JP
243         return hliquid("lava");
244 */
245         return hliquid("\97n\8aâ");
246     else if (lev->typ == DRAWBRIDGE_DOWN)
247 /*JP
248         return "bridge";
249 */
250         return "\8b´";
251     else if (IS_ALTAR(levl[x][y].typ))
252 /*JP
253         return "altar";
254 */
255         return "\8dÕ\92d";
256     else if (IS_GRAVE(levl[x][y].typ))
257 /*JP
258         return "headstone";
259 */
260         return "\95æ\90Î";
261     else if (IS_FOUNTAIN(levl[x][y].typ))
262 /*JP
263         return "fountain";
264 */
265         return "\90ò";
266     else if ((IS_ROOM(lev->typ) && !Is_earthlevel(&u.uz))
267              || IS_WALL(lev->typ) || IS_DOOR(lev->typ) || lev->typ == SDOOR)
268 /*JP
269         return "floor";
270 */
271         return "\8f°";
272     else
273 /*JP
274         return "ground";
275 */
276         return "\92n\96Ê";
277 }
278
279 const char *
280 ceiling(x, y)
281 register int x, y;
282 {
283     register struct rm *lev = &levl[x][y];
284     const char *what;
285
286     /* other room types will no longer exist when we're interested --
287      * see check_special_room()
288      */
289     if (*in_rooms(x, y, VAULT))
290 /*JP
291         what = "vault's ceiling";
292 */
293         what = "\91q\8cÉ\82Ì\93V\88ä";
294     else if (*in_rooms(x, y, TEMPLE))
295 /*JP
296         what = "temple's ceiling";
297 */
298         what = "\8e\9b\89@\82Ì\93V\88ä";
299     else if (*in_rooms(x, y, SHOPBASE))
300 /*JP
301         what = "shop's ceiling";
302 */
303         what = "\93X\82Ì\93V\88ä";
304     else if (Is_waterlevel(&u.uz))
305         /* water plane has no surface; its air bubbles aren't below sky */
306 /*JP
307         what = "water above";
308 */
309         what = "\90\85\82Ì\8fã\95û";
310     else if (IS_AIR(lev->typ))
311 /*JP
312         what = "sky";
313 */
314         what = "\8bó";
315     else if (Underwater)
316 /*JP
317         what = "water's surface";
318 */
319         what = "\90\85\96Ê";
320     else if ((IS_ROOM(lev->typ) && !Is_earthlevel(&u.uz))
321              || IS_WALL(lev->typ) || IS_DOOR(lev->typ) || lev->typ == SDOOR)
322 /*JP
323         what = "ceiling";
324 */
325         what = "\93V\88ä";
326     else
327 /*JP
328         what = "rock cavern";
329 */
330         what = "\93´\8cA\82Ì\93V\88ä";
331
332     return what;
333 }
334
335 struct engr *
336 engr_at(x, y)
337 xchar x, y;
338 {
339     register struct engr *ep = head_engr;
340
341     while (ep) {
342         if (x == ep->engr_x && y == ep->engr_y)
343             return ep;
344         ep = ep->nxt_engr;
345     }
346     return (struct engr *) 0;
347 }
348
349 /* Decide whether a particular string is engraved at a specified
350  * location; a case-insensitive substring match is used.
351  * Ignore headstones, in case the player names herself "Elbereth".
352  *
353  * If strict checking is requested, the word is only considered to be
354  * present if it is intact and is the entire content of the engraving.
355  */
356 int
357 sengr_at(s, x, y, strict)
358 const char *s;
359 xchar x, y;
360 boolean strict;
361 {
362     register struct engr *ep = engr_at(x, y);
363
364     if (ep && ep->engr_type != HEADSTONE && ep->engr_time <= moves) {
365         return strict ? (fuzzymatch(ep->engr_txt, s, "", TRUE))
366                       : (strstri(ep->engr_txt, s) != 0);
367     }
368
369     return FALSE;
370 }
371
372 void
373 u_wipe_engr(cnt)
374 int cnt;
375 {
376     if (can_reach_floor(TRUE))
377         wipe_engr_at(u.ux, u.uy, cnt, FALSE);
378 }
379
380 void
381 wipe_engr_at(x, y, cnt, magical)
382 xchar x, y, cnt;
383 boolean magical;
384 {
385     register struct engr *ep = engr_at(x, y);
386
387     /* Headstones are indelible */
388     if (ep && ep->engr_type != HEADSTONE) {
389         debugpline1("asked to erode %d characters", cnt);
390         if (ep->engr_type != BURN || is_ice(x, y) || (magical && !rn2(2))) {
391             if (ep->engr_type != DUST && ep->engr_type != ENGR_BLOOD) {
392                 cnt = rn2(1 + 50 / (cnt + 1)) ? 0 : 1;
393                 debugpline1("actually eroding %d characters", cnt);
394             }
395             wipeout_text(ep->engr_txt, (int) cnt, 0);
396             while (ep->engr_txt[0] == ' ')
397                 ep->engr_txt++;
398             if (!ep->engr_txt[0])
399                 del_engr(ep);
400         }
401     }
402 }
403
404 void
405 read_engr_at(x, y)
406 int x, y;
407 {
408     register struct engr *ep = engr_at(x, y);
409     int sensed = 0;
410
411     /* Sensing an engraving does not require sight,
412      * nor does it necessarily imply comprehension (literacy).
413      */
414     if (ep && ep->engr_txt[0]) {
415         switch (ep->engr_type) {
416         case DUST:
417             if (!Blind) {
418                 sensed = 1;
419 #if 0 /*JP:T*/
420                 pline("%s is written here in the %s.", Something,
421                       is_ice(x, y) ? "frost" : "dust");
422 #else
423                 pline("\89½\82©\82Ì\95\8e\9a\82ª%s\82É\8f\91\82¢\82Ä\82 \82é\81D",
424                       is_ice(x, y) ? "\91\9a" : "\82Ù\82±\82è");
425 #endif
426             }
427             break;
428         case ENGRAVE:
429         case HEADSTONE:
430             if (!Blind || can_reach_floor(TRUE)) {
431                 sensed = 1;
432 /*JP
433                 pline("%s is engraved here on the %s.", Something,
434 */
435                 pline("\89½\82©\82Ì\95\8e\9a\82ª%s\82É\8d\8f\82Ü\82ê\82Ä\82¢\82é\81D",
436                       surface(x, y));
437             }
438             break;
439         case BURN:
440             if (!Blind || can_reach_floor(TRUE)) {
441                 sensed = 1;
442 #if 0 /*JP:T*/
443                 pline("Some text has been %s into the %s here.",
444                       is_ice(x, y) ? "melted" : "burned", surface(x, y));
445 #else
446                 pline("\89½\82©\82Ì\95\8e\9a\82ª%s%s\82¢\82é\81D",
447                       surface(x,y),
448                       is_ice(x,y) ? "\82É\8d\8f\82Ü\82ê\82Ä" : "\82É\8fÄ\82«\95t\82¯\82ç\82ê\82Ä");
449 #endif
450             }
451             break;
452         case MARK:
453             if (!Blind) {
454                 sensed = 1;
455 /*JP
456                 pline("There's some graffiti on the %s here.", surface(x, y));
457 */
458                 pline("%s\82É\97\8e\8f\91\82ª\82 \82é\81D", surface(x,y));
459             }
460             break;
461         case ENGR_BLOOD:
462             /* "It's a message!  Scrawled in blood!"
463              * "What's it say?"
464              * "It says... `See you next Wednesday.'" -- Thriller
465              */
466             if (!Blind) {
467                 sensed = 1;
468 /*JP
469                 You_see("a message scrawled in blood here.");
470 */
471                 You("\8c\8c\95\8e\9a\82ª\82È\82®\82è\8f\91\82«\82³\82ê\82Ä\82¢\82é\82Ì\82ð\8c©\82Â\82¯\82½\81D");
472             }
473             break;
474         default:
475             impossible("%s is written in a very strange way.", Something);
476             sensed = 1;
477         }
478
479         if (sensed) {
480             char *et, buf[BUFSZ];
481             int maxelen = (int) (sizeof buf
482                                  /* sizeof "literal" counts terminating \0 */
483 /*JP
484                                  - sizeof "You feel the words: \"\".");
485 */
486                                  - sizeof "\82 \82È\82½\82Í\8e\9f\82Ì\82æ\82¤\82É\8a´\82\82½\81F\81u\81v");
487
488             if ((int) strlen(ep->engr_txt) > maxelen) {
489                 (void) strncpy(buf, ep->engr_txt, maxelen);
490                 buf[maxelen] = '\0';
491                 et = buf;
492             } else {
493                 et = ep->engr_txt;
494             }
495 /*JP
496             You("%s: \"%s\".", (Blind) ? "feel the words" : "read", et);
497 */
498             You("%s\81F\81u%s\81v", (Blind) ? "\8e\9f\82Ì\82æ\82¤\82É\8a´\82\82½" : "\93Ç\82ñ\82¾",  et);
499             if (context.run > 0)
500                 nomul(0);
501         }
502     }
503 }
504
505 void
506 make_engr_at(x, y, s, e_time, e_type)
507 int x, y;
508 const char *s;
509 long e_time;
510 xchar e_type;
511 {
512     struct engr *ep;
513     unsigned smem = strlen(s) + 1;
514
515     if ((ep = engr_at(x, y)) != 0)
516         del_engr(ep);
517     ep = newengr(smem);
518     (void) memset((genericptr_t)ep, 0, smem + sizeof(struct engr));
519     ep->nxt_engr = head_engr;
520     head_engr = ep;
521     ep->engr_x = x;
522     ep->engr_y = y;
523     ep->engr_txt = (char *) (ep + 1);
524     Strcpy(ep->engr_txt, s);
525     /* engraving Elbereth shows wisdom */
526     if (!in_mklev && !strcmp(s, "Elbereth"))
527         exercise(A_WIS, TRUE);
528     ep->engr_time = e_time;
529     ep->engr_type = e_type > 0 ? e_type : rnd(N_ENGRAVE - 1);
530     ep->engr_lth = smem;
531 }
532
533 /* delete any engraving at location <x,y> */
534 void
535 del_engr_at(x, y)
536 int x, y;
537 {
538     register struct engr *ep = engr_at(x, y);
539
540     if (ep)
541         del_engr(ep);
542 }
543
544 /*
545  * freehand - returns true if player has a free hand
546  */
547 int
548 freehand()
549 {
550     return (!uwep || !welded(uwep)
551             || (!bimanual(uwep) && (!uarms || !uarms->cursed)));
552 }
553
554 static NEARDATA const char styluses[] = { ALL_CLASSES, ALLOW_NONE,
555                                           TOOL_CLASS,  WEAPON_CLASS,
556                                           WAND_CLASS,  GEM_CLASS,
557                                           RING_CLASS,  0 };
558
559 /* Mohs' Hardness Scale:
560  *  1 - Talc             6 - Orthoclase
561  *  2 - Gypsum           7 - Quartz
562  *  3 - Calcite          8 - Topaz
563  *  4 - Fluorite         9 - Corundum
564  *  5 - Apatite         10 - Diamond
565  *
566  * Since granite is an igneous rock hardness ~ 7, anything >= 8 should
567  * probably be able to scratch the rock.
568  * Devaluation of less hard gems is not easily possible because obj struct
569  * does not contain individual oc_cost currently. 7/91
570  *
571  * steel      - 5-8.5   (usu. weapon)
572  * diamond    - 10                      * jade       -  5-6      (nephrite)
573  * ruby       -  9      (corundum)      * turquoise  -  5-6
574  * sapphire   -  9      (corundum)      * opal       -  5-6
575  * topaz      -  8                      * glass      - ~5.5
576  * emerald    -  7.5-8  (beryl)         * dilithium  -  4-5??
577  * aquamarine -  7.5-8  (beryl)         * iron       -  4-5
578  * garnet     -  7.25   (var. 6.5-8)    * fluorite   -  4
579  * agate      -  7      (quartz)        * brass      -  3-4
580  * amethyst   -  7      (quartz)        * gold       -  2.5-3
581  * jasper     -  7      (quartz)        * silver     -  2.5-3
582  * onyx       -  7      (quartz)        * copper     -  2.5-3
583  * moonstone  -  6      (orthoclase)    * amber      -  2-2.5
584  */
585
586 /* return 1 if action took 1 (or more) moves, 0 if error or aborted */
587 int
588 doengrave()
589 {
590     boolean dengr = FALSE;    /* TRUE if we wipe out the current engraving */
591     boolean doblind = FALSE;  /* TRUE if engraving blinds the player */
592     boolean doknown = FALSE;  /* TRUE if we identify the stylus */
593     boolean eow = FALSE;      /* TRUE if we are overwriting oep */
594     boolean jello = FALSE;    /* TRUE if we are engraving in slime */
595     boolean ptext = TRUE;     /* TRUE if we must prompt for engrave text */
596     boolean teleengr = FALSE; /* TRUE if we move the old engraving */
597     boolean zapwand = FALSE;  /* TRUE if we remove a wand charge */
598     xchar type = DUST;        /* Type of engraving made */
599     xchar oetype = 0;         /* will be set to type of current engraving */
600     char buf[BUFSZ];          /* Buffer for final/poly engraving text */
601     char ebuf[BUFSZ];         /* Buffer for initial engraving text */
602     char fbuf[BUFSZ];         /* Buffer for "your fingers" */
603     char qbuf[QBUFSZ];        /* Buffer for query text */
604     char post_engr_text[BUFSZ]; /* Text displayed after engraving prompt */
605     const char *everb;          /* Present tense of engraving type */
606     const char *eloc; /* Where the engraving is (ie dust/floor/...) */
607     char *sp;         /* Place holder for space count of engr text */
608     int len;          /* # of nonspace chars of new engraving text */
609     int maxelen;      /* Max allowable length of engraving text */
610     struct engr *oep = engr_at(u.ux, u.uy);
611     /* The current engraving */
612     struct obj *otmp; /* Object selected with which to engrave */
613     char *writer;
614
615     multi = 0;              /* moves consumed */
616     nomovemsg = (char *) 0; /* occupation end message */
617
618     buf[0] = (char) 0;
619     ebuf[0] = (char) 0;
620     post_engr_text[0] = (char) 0;
621     maxelen = BUFSZ - 1;
622     if (oep)
623         oetype = oep->engr_type;
624     if (is_demon(youmonst.data) || youmonst.data->mlet == S_VAMPIRE)
625         type = ENGR_BLOOD;
626
627     /* Can the adventurer engrave at all? */
628
629     if (u.uswallow) {
630         if (is_animal(u.ustuck->data)) {
631 /*JP
632             pline("What would you write?  \"Jonah was here\"?");
633 */
634             pline("\89½\82ð\8f\91\82­\82ñ\82¾\82¢\81H\81u\83\88\83i\82Í\82±\82±\82É\82¢\82é\81v\81H");
635             return 0;
636         } else if (is_whirly(u.ustuck->data)) {
637             cant_reach_floor(u.ux, u.uy, FALSE, FALSE);
638             return 0;
639         } else
640             jello = TRUE;
641     } else if (is_lava(u.ux, u.uy)) {
642 /*JP
643         You_cant("write on the %s!", surface(u.ux, u.uy));
644 */
645         You("%s\82É\93Í\82©\82È\82¢\81D", surface(u.ux,u.uy));
646         return 0;
647     } else if (is_pool(u.ux, u.uy) || IS_FOUNTAIN(levl[u.ux][u.uy].typ)) {
648 /*JP
649         You_cant("write on the %s!", surface(u.ux, u.uy));
650 */
651         You("%s\82É\82Í\8f\91\82¯\82È\82¢\81I", surface(u.ux, u.uy));
652         return 0;
653     }
654     if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) /* in bubble */) {
655 /*JP
656         You_cant("write in thin air!");
657 */
658         You("\8bó\92\86\82É\82Í\8f\91\82¯\82È\82¢\81I");
659         return 0;
660     } else if (!accessible(u.ux, u.uy)) {
661         /* stone, tree, wall, secret corridor, pool, lava, bars */
662 /*JP
663         You_cant("write here.");
664 */
665         You_cant("\82±\82±\82É\82Í\8f\91\82¯\82È\82¢\81D");
666         return 0;
667     }
668     if (cantwield(youmonst.data)) {
669 /*JP
670         You_cant("even hold anything!");
671 */
672         You("\89½\82©\82ð\8e\9d\82Â\82±\82Æ\82·\82ç\82Å\82«\82È\82¢\81I");
673         return 0;
674     }
675     if (check_capacity((char *) 0))
676         return 0;
677
678     /* One may write with finger, or weapon, or wand, or..., or...
679      * Edited by GAN 10/20/86 so as not to change weapon wielded.
680      */
681
682     otmp = getobj(styluses, "write with");
683     if (!otmp) /* otmp == zeroobj if fingers */
684         return 0;
685
686     if (otmp == &zeroobj) {
687 /*JP
688         Strcat(strcpy(fbuf, "your "), body_part(FINGERTIP));
689 */
690         Strcat(strcpy(fbuf, "\82 \82È\82½\82Ì"), body_part(FINGERTIP));
691         writer = fbuf;
692     } else
693         writer = yname(otmp);
694
695     /* There's no reason you should be able to write with a wand
696      * while both your hands are tied up.
697      */
698     if (!freehand() && otmp != uwep && !otmp->owornmask) {
699 /*JP
700         You("have no free %s to write with!", body_part(HAND));
701 */
702         pline("%s\82Ì\8e©\97R\82ª\8cø\82©\82È\82¢\82Ì\82Å\8f\91\82¯\82È\82¢\81I", body_part(HAND));
703         return 0;
704     }
705
706     if (jello) {
707 /*JP
708         You("tickle %s with %s.", mon_nam(u.ustuck), writer);
709 */
710         You("%s\82Å%s\82ð\82­\82·\82®\82Á\82½\81D", writer, mon_nam(u.ustuck));
711 /*JP
712         Your("message dissolves...");
713 */
714         Your("\83\81\83b\83Z\81[\83W\82Í\8fÁ\82¦\82½\81D\81D\81D");
715         return 0;
716     }
717     if (otmp->oclass != WAND_CLASS && !can_reach_floor(TRUE)) {
718         cant_reach_floor(u.ux, u.uy, FALSE, TRUE);
719         return 0;
720     }
721     if (IS_ALTAR(levl[u.ux][u.uy].typ)) {
722 /*JP
723         You("make a motion towards the altar with %s.", writer);
724 */
725         You("%s\82ð\8eg\82Á\82Ä\8dÕ\92d\82É\8f\91\82±\82¤\82Æ\82µ\82½\81D", writer);
726         altar_wrath(u.ux, u.uy);
727         return 0;
728     }
729     if (IS_GRAVE(levl[u.ux][u.uy].typ)) {
730         if (otmp == &zeroobj) { /* using only finger */
731 /*JP
732             You("would only make a small smudge on the %s.",
733 */
734             You("%s\82ð\8f­\82µ\82æ\82²\82·\82±\82Æ\82µ\82©\82Å\82«\82È\82©\82Á\82½\81D",
735                 surface(u.ux, u.uy));
736             return 0;
737         } else if (!levl[u.ux][u.uy].disturbed) {
738 /*JP
739             You("disturb the undead!");
740 */
741             You("\95s\8e\80\82Ì\8eÒ\82Ì\96°\82è\82ð\96W\82°\82½\81I");
742             levl[u.ux][u.uy].disturbed = 1;
743             (void) makemon(&mons[PM_GHOUL], u.ux, u.uy, NO_MM_FLAGS);
744             exercise(A_WIS, FALSE);
745             return 1;
746         }
747     }
748
749     /* SPFX for items */
750
751     switch (otmp->oclass) {
752     default:
753     case AMULET_CLASS:
754     case CHAIN_CLASS:
755     case POTION_CLASS:
756     case COIN_CLASS:
757         break;
758     case RING_CLASS:
759         /* "diamond" rings and others should work */
760     case GEM_CLASS:
761         /* diamonds & other hard gems should work */
762         if (objects[otmp->otyp].oc_tough) {
763             type = ENGRAVE;
764             break;
765         }
766         break;
767     case ARMOR_CLASS:
768         if (is_boots(otmp)) {
769             type = DUST;
770             break;
771         }
772         /*FALLTHRU*/
773     /* Objects too large to engrave with */
774     case BALL_CLASS:
775     case ROCK_CLASS:
776 /*JP
777         You_cant("engrave with such a large object!");
778 */
779         pline("\82»\82ñ\82È\91å\82«\82È\82à\82Ì\82ð\8eg\82Á\82Ä\95\8e\9a\82ð\8d\8f\82ß\82È\82¢\81I");
780         ptext = FALSE;
781         break;
782     /* Objects too silly to engrave with */
783     case FOOD_CLASS:
784     case SCROLL_CLASS:
785     case SPBOOK_CLASS:
786 #if 0 /*JP:T*/
787         pline("%s would get %s.", Yname2(otmp),
788               is_ice(u.ux, u.uy) ? "all frosty" : "too dirty");
789 #else
790         Your("%s\82Í%s\82È\82Á\82½\81D", xname(otmp),
791              is_ice(u.ux,u.uy) ? "\91\9a\82¾\82ç\82¯\82É" : "\89\98\82È\82­");
792 #endif
793         ptext = FALSE;
794         break;
795     case RANDOM_CLASS: /* This should mean fingers */
796         break;
797
798     /* The charge is removed from the wand before prompting for
799      * the engraving text, because all kinds of setup decisions
800      * and pre-engraving messages are based upon knowing what type
801      * of engraving the wand is going to do.  Also, the player
802      * will have potentially seen "You wrest .." message, and
803      * therefore will know they are using a charge.
804      */
805     case WAND_CLASS:
806         if (zappable(otmp)) {
807             check_unpaid(otmp);
808             if (otmp->cursed && !rn2(WAND_BACKFIRE_CHANCE)) {
809                 wand_explode(otmp, 0);
810                 return 1;
811             }
812             zapwand = TRUE;
813             if (!can_reach_floor(TRUE))
814                 ptext = FALSE;
815
816             switch (otmp->otyp) {
817             /* DUST wands */
818             default:
819                 break;
820             /* NODIR wands */
821             case WAN_LIGHT:
822             case WAN_SECRET_DOOR_DETECTION:
823             case WAN_CREATE_MONSTER:
824             case WAN_WISHING:
825             case WAN_ENLIGHTENMENT:
826                 zapnodir(otmp);
827                 break;
828             /* IMMEDIATE wands */
829             /* If wand is "IMMEDIATE", remember to affect the
830              * previous engraving even if turning to dust.
831              */
832             case WAN_STRIKING:
833                 Strcpy(post_engr_text,
834 /*JP
835                     "The wand unsuccessfully fights your attempt to write!");
836 */
837                     "\82 \82È\82½\82ª\8f\91\82±\82¤\82Æ\82·\82é\82Æ\8fñ\82Í\92ï\8dR\82µ\82½\81I");
838                 break;
839             case WAN_SLOW_MONSTER:
840                 if (!Blind) {
841 /*JP
842                     Sprintf(post_engr_text, "The bugs on the %s slow down!",
843 */
844                     Sprintf(post_engr_text, "%s\82Ì\8fã\82Ì\92\8e\82Ì\93®\82«\82ª\92x\82­\82È\82Á\82½\81I",
845                             surface(u.ux, u.uy));
846                 }
847                 break;
848             case WAN_SPEED_MONSTER:
849                 if (!Blind) {
850 /*JP
851                     Sprintf(post_engr_text, "The bugs on the %s speed up!",
852 */
853                     Sprintf(post_engr_text, "%s\82Ì\8fã\82Ì\92\8e\82Ì\93®\82«\82ª\91¬\82­\82È\82Á\82½\81I",
854                             surface(u.ux, u.uy));
855                 }
856                 break;
857             case WAN_POLYMORPH:
858                 if (oep) {
859                     if (!Blind) {
860                         type = (xchar) 0; /* random */
861                         (void) random_engraving(buf);
862                     } else {
863                         /* keep the same type so that feels don't
864                            change and only the text is altered,
865                            but you won't know anyway because
866                            you're a _blind writer_ */
867                         if (oetype)
868                             type = oetype;
869                         xcrypt(blengr(), buf);
870                     }
871                     dengr = TRUE;
872                 }
873                 break;
874             case WAN_NOTHING:
875             case WAN_UNDEAD_TURNING:
876             case WAN_OPENING:
877             case WAN_LOCKING:
878             case WAN_PROBING:
879                 break;
880             /* RAY wands */
881             case WAN_MAGIC_MISSILE:
882                 ptext = TRUE;
883                 if (!Blind) {
884                     Sprintf(post_engr_text,
885 /*JP
886                             "The %s is riddled by bullet holes!",
887 */
888                             "%s\82Í\8eU\92e\82Å\8d×\82©\82¢\8c\8a\82¾\82ç\82¯\82É\82È\82Á\82½\81I",
889                             surface(u.ux, u.uy));
890                 }
891                 break;
892             /* can't tell sleep from death - Eric Backus */
893             case WAN_SLEEP:
894             case WAN_DEATH:
895                 if (!Blind) {
896 /*JP
897                     Sprintf(post_engr_text, "The bugs on the %s stop moving!",
898 */
899                     Sprintf(post_engr_text, "%s\82Ì\8fã\82Ì\92\8e\82Ì\93®\82«\82ª\8e~\82Ü\82Á\82½\81I",
900                             surface(u.ux, u.uy));
901                 }
902                 break;
903             case WAN_COLD:
904                 if (!Blind)
905                     Strcpy(post_engr_text,
906 /*JP
907                            "A few ice cubes drop from the wand.");
908 */
909                            "\95X\82Ì\82©\82¯\82ç\82ª\8fñ\82©\82ç\82±\82Ú\82ê\97\8e\82¿\82½\81D");
910                 if (!oep || (oep->engr_type != BURN))
911                     break;
912                 /*FALLTHRU*/
913             case WAN_CANCELLATION:
914             case WAN_MAKE_INVISIBLE:
915                 if (oep && oep->engr_type != HEADSTONE) {
916                     if (!Blind)
917 /*JP
918                         pline_The("engraving on the %s vanishes!",
919 */
920                         pline("%s\82Ì\8fã\82Ì\95\8e\9a\82Í\8fÁ\82¦\82½\81I",
921                                   surface(u.ux, u.uy));
922                     dengr = TRUE;
923                 }
924                 break;
925             case WAN_TELEPORTATION:
926                 if (oep && oep->engr_type != HEADSTONE) {
927                     if (!Blind)
928 /*JP
929                         pline_The("engraving on the %s vanishes!",
930 */
931                         pline("%s\82Ì\8fã\82Ì\95\8e\9a\82Í\8fÁ\82¦\82½\81I",
932                                   surface(u.ux, u.uy));
933                     teleengr = TRUE;
934                 }
935                 break;
936             /* type = ENGRAVE wands */
937             case WAN_DIGGING:
938                 ptext = TRUE;
939                 type = ENGRAVE;
940                 if (!objects[otmp->otyp].oc_name_known) {
941                     if (flags.verbose)
942 /*JP
943                         pline("This %s is a wand of digging!", xname(otmp));
944 */
945                         pline("\82±\82ê\82Í\8c\8a\8c@\82è\82Ì\8fñ\82¾\81I");
946                     doknown = TRUE;
947                 }
948 #if 0 /*JP:T*/
949                 Strcpy(post_engr_text,
950                        (Blind && !Deaf)
951                           ? "You hear drilling!"    /* Deaf-aware */
952                           : Blind
953                              ? "You feel tremors."
954                              : IS_GRAVE(levl[u.ux][u.uy].typ)
955                                  ? "Chips fly out from the headstone."
956                                  : is_ice(u.ux, u.uy)
957                                     ? "Ice chips fly up from the ice surface!"
958                                     : (level.locations[u.ux][u.uy].typ
959                                        == DRAWBRIDGE_DOWN)
960                                        ? "Splinters fly up from the bridge."
961                                        : "Gravel flies up from the floor.");
962 #else
963                 Strcpy(post_engr_text,
964                        (Blind && !Deaf)
965                           ? "\8c\8a\82ª\8aJ\82­\89¹\82ð\95·\82¢\82½\81I"    /* Deaf-aware */
966                           : Blind
967                              ? "\90U\93®\82ð\8a´\82\82½\81D"
968                              : IS_GRAVE(levl[u.ux][u.uy].typ)
969                                 ? "\95æ\90Î\82©\82ç\94j\95Ð\82ª\94ò\82Ñ\8eU\82Á\82½\81D"
970                                 : is_ice(u.ux,u.uy)
971                                    ? "\95X\82Ì\95\\96Ê\82©\82ç\95X\82Ì\82©\82¯\82ç\82ª\94ò\82Ñ\8eU\82Á\82½\81D"
972                                    : (level.locations[u.ux][u.uy].typ
973                                       == DRAWBRIDGE_DOWN)
974                                       ? "\94j\95Ð\82ª\8b´\82©\82ç\95\91\82¢\82 \82ª\82Á\82½\81D"
975                                       : "\8d»\97\98\82ª\8f°\82©\82ç\94ò\82Ñ\8eU\82Á\82½\81D");
976 #endif
977                 break;
978             /* type = BURN wands */
979             case WAN_FIRE:
980                 ptext = TRUE;
981                 type = BURN;
982                 if (!objects[otmp->otyp].oc_name_known) {
983                     if (flags.verbose)
984 /*JP
985                         pline("This %s is a wand of fire!", xname(otmp));
986 */
987                         pline("\82±\82ê\82Í\89\8a\82Ì\8fñ\82¾\81I");
988                     doknown = TRUE;
989                 }
990 #if 0 /*JP:T*/
991                 Strcpy(post_engr_text, Blind ? "You feel the wand heat up."
992                                              : "Flames fly from the wand.");
993 #else
994                 Strcpy(post_engr_text, Blind ? "\8fñ\82ª\92g\82©\82­\82È\82Á\82½\82æ\82¤\82È\8bC\82ª\82µ\82½\81D"
995                                              : "\89\8a\82ª\8fñ\82©\82ç\94ò\82Ñ\8eU\82Á\82½\81D");
996 #endif
997                 break;
998             case WAN_LIGHTNING:
999                 ptext = TRUE;
1000                 type = BURN;
1001                 if (!objects[otmp->otyp].oc_name_known) {
1002                     if (flags.verbose)
1003 /*JP
1004                         pline("This %s is a wand of lightning!", xname(otmp));
1005 */
1006                         pline("\82±\82ê\82Í\97\8b\82Ì\8fñ\82¾\81I");
1007                     doknown = TRUE;
1008                 }
1009                 if (!Blind) {
1010 /*JP
1011                     Strcpy(post_engr_text, "Lightning arcs from the wand.");
1012 */
1013                     Strcpy(post_engr_text, "\89Î\89Ô\82ª\8fñ\82©\82ç\94ò\82Ñ\8eU\82Á\82½\81D");
1014                     doblind = TRUE;
1015                 } else
1016 #if 0 /*JP:T*/
1017                     Strcpy(post_engr_text, !Deaf
1018                                 ? "You hear crackling!"  /* Deaf-aware */
1019                                 : "Your hair stands up!");
1020 #else
1021                     Strcpy(post_engr_text, !Deaf
1022                                 ? "\83p\83`\83p\83`\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81I"  /* Deaf-aware */
1023                                 : "\83]\83b\82Æ\82µ\82½\81I");
1024 #endif
1025                 break;
1026
1027             /* type = MARK wands */
1028             /* type = ENGR_BLOOD wands */
1029             }
1030         } else { /* end if zappable */
1031             /* failing to wrest one last charge takes time */
1032             ptext = FALSE; /* use "early exit" below, return 1 */
1033             /* give feedback here if we won't be getting the
1034                "can't reach floor" message below */
1035             if (can_reach_floor(TRUE)) {
1036                 /* cancelled wand turns to dust */
1037                 if (otmp->spe < 0)
1038                     zapwand = TRUE;
1039                 /* empty wand just doesn't write */
1040                 else
1041 /*JP
1042                     pline_The("wand is too worn out to engrave.");
1043 */
1044                     pline_The("\8fñ\82Í\95\8e\9a\82ð\8d\8f\82Þ\82É\82Í\8eg\82¢\82·\82¬\82Ä\82¢\82é\81D");
1045             }
1046         }
1047         break;
1048
1049     case WEAPON_CLASS:
1050         if (is_blade(otmp)) {
1051             if ((int) otmp->spe > -3)
1052                 type = ENGRAVE;
1053             else
1054 /*JP
1055                 pline("%s too dull for engraving.", Yobjnam2(otmp, "are"));
1056 */
1057                 pline("%s\82Í\90n\82ª\83{\83\8d\83{\83\8d\82Å\81C\95\8e\9a\82ð\92¤\82ê\82È\82¢\81D", xname(otmp));
1058         }
1059         break;
1060
1061     case TOOL_CLASS:
1062         if (otmp == ublindf) {
1063             pline(
1064 /*JP
1065                 "That is a bit difficult to engrave with, don't you think?");
1066 */
1067                 "\82¿\82å\82Á\82Æ\82»\82ê\82Å\92¤\82é\82Ì\82Í\91å\95Ï\82¾\82ë\82¤\81C\82»\82¤\8ev\82í\82È\82¢\81H");
1068             return 0;
1069         }
1070         switch (otmp->otyp) {
1071         case MAGIC_MARKER:
1072             if (otmp->spe <= 0)
1073 /*JP
1074                 Your("marker has dried out.");
1075 */
1076                 Your("\83}\81[\83J\82Í\8a£\82«\82«\82Á\82½\81D");
1077             else
1078                 type = MARK;
1079             break;
1080         case TOWEL:
1081             /* Can't really engrave with a towel */
1082             ptext = FALSE;
1083             if (oep)
1084                 if (oep->engr_type == DUST
1085                     || oep->engr_type == ENGR_BLOOD
1086                     || oep->engr_type == MARK) {
1087                     if (is_wet_towel(otmp))
1088                         dry_a_towel(otmp, -1, TRUE);
1089                     if (!Blind)
1090 /*JP
1091                         You("wipe out the message here.");
1092 */
1093                         You("\83\81\83b\83Z\81[\83W\82ð\90@\82«\82Æ\82Á\82½\81D");
1094                     else
1095 #if 0 /*JP:T*/
1096                         pline("%s %s.", Yobjnam2(otmp, "get"),
1097                               is_ice(u.ux, u.uy) ? "frosty" : "dusty");
1098 #else
1099                         pline("%s\82Í%s\82É\82È\82Á\82½\81D", xname(otmp),
1100                               is_ice(u.ux,u.uy) ? "\91\9a\82¾\82ç\82¯" : "\82Ù\82±\82è\82Ü\82Ý\82ê");
1101 #endif
1102                     dengr = TRUE;
1103                 } else
1104 /*JP
1105                     pline("%s can't wipe out this engraving.", Yname2(otmp));
1106 */
1107                     pline("\82±\82Ì\95\8e\9a\82Í%s\82Å\82Í\90@\82«\82Æ\82ê\82È\82¢\81D", xname(otmp));
1108             else
1109 #if 0 /*JP:T*/
1110                 pline("%s %s.", Yobjnam2(otmp, "get"),
1111                       is_ice(u.ux, u.uy) ? "frosty" : "dusty");
1112 #else
1113                 pline("%s\82Í%s\82É\82È\82Á\82½\81D", xname(otmp),
1114                       is_ice(u.ux,u.uy) ? "\91\9a\82¾\82ç\82¯" : "\82Ù\82±\82è\82Ü\82Ý\82ê");
1115 #endif
1116             break;
1117         default:
1118             break;
1119         }
1120         break;
1121
1122     case VENOM_CLASS:
1123         if (wizard) {
1124 /*JP
1125             pline("Writing a poison pen letter??");
1126 */
1127             pline("\82Ó\82Þ\81D\82±\82ê\82±\82»\96{\93\96\82Ì\93Å\90ã\82¾\81D");
1128             break;
1129         }
1130         /*FALLTHRU*/
1131     case ILLOBJ_CLASS:
1132         impossible("You're engraving with an illegal object!");
1133         break;
1134     }
1135
1136     if (IS_GRAVE(levl[u.ux][u.uy].typ)) {
1137         if (type == ENGRAVE || type == 0) {
1138             type = HEADSTONE;
1139         } else {
1140             /* ensures the "cannot wipe out" case */
1141             type = DUST;
1142             dengr = FALSE;
1143             teleengr = FALSE;
1144             buf[0] = '\0';
1145         }
1146     }
1147
1148     /*
1149      * End of implement setup
1150      */
1151
1152     /* Identify stylus */
1153     if (doknown) {
1154         learnwand(otmp);
1155         if (objects[otmp->otyp].oc_name_known)
1156             more_experienced(0, 10);
1157     }
1158     if (teleengr) {
1159         rloc_engr(oep);
1160         oep = (struct engr *) 0;
1161     }
1162     if (dengr) {
1163         del_engr(oep);
1164         oep = (struct engr *) 0;
1165     }
1166     /* Something has changed the engraving here */
1167     if (*buf) {
1168         make_engr_at(u.ux, u.uy, buf, moves, type);
1169         if (!Blind)
1170 /*JP
1171             pline_The("engraving now reads: \"%s\".", buf);
1172 */
1173             pline("\8d\8f\82Ü\82ê\82½\95\8e\9a\82ð\93Ç\82ñ\82¾\81F\81u%s\81v\81D", buf);
1174         ptext = FALSE;
1175     }
1176     if (zapwand && (otmp->spe < 0)) {
1177 #if 0 /*JP:T*/
1178         pline("%s %sturns to dust.", The(xname(otmp)),
1179               Blind ? "" : "glows violently, then ");
1180 #else
1181         pline("%s\82Í%s\82¿\82è\82Æ\82È\82Á\82½\81D", xname(otmp),
1182               Blind ? "" : "\8c\83\82µ\82­\8bP\82«\81C");
1183 #endif
1184         if (!IS_GRAVE(levl[u.ux][u.uy].typ))
1185 #if 0 /*JP:T*/
1186             You(
1187     "are not going to get anywhere trying to write in the %s with your dust.",
1188                 is_ice(u.ux, u.uy) ? "frost" : "dust");
1189 #else
1190             You(
1191                 "\90o\82Å%s\82É\89½\82©\8f\91\82±\82¤\82Æ\82µ\82½\82ª\81C\82Å\82«\82È\82©\82Á\82½\81D",
1192                 is_ice(u.ux,u.uy) ? "\95X" : "\82Ù\82±\82è");
1193 #endif
1194         useup(otmp);
1195         otmp = 0; /* wand is now gone */
1196         ptext = FALSE;
1197     }
1198     /* Early exit for some implements. */
1199     if (!ptext) {
1200         if (otmp && otmp->oclass == WAND_CLASS && !can_reach_floor(TRUE))
1201             cant_reach_floor(u.ux, u.uy, FALSE, TRUE);
1202         return 1;
1203     }
1204     /*
1205      * Special effects should have deleted the current engraving (if
1206      * possible) by now.
1207      */
1208     if (oep) {
1209         register char c = 'n';
1210
1211         /* Give player the choice to add to engraving. */
1212         if (type == HEADSTONE) {
1213             /* no choice, only append */
1214             c = 'y';
1215         } else if (type == oep->engr_type
1216                    && (!Blind || oep->engr_type == BURN
1217                        || oep->engr_type == ENGRAVE)) {
1218 /*JP
1219             c = yn_function("Do you want to add to the current engraving?",
1220 */
1221             c = yn_function("\89½\82©\8f\91\82«\89Á\82¦\82Ü\82·\82©\81H",
1222                             ynqchars, 'y');
1223             if (c == 'q') {
1224                 pline1(Never_mind);
1225                 return 0;
1226             }
1227         }
1228
1229         if (c == 'n' || Blind) {
1230             if (oep->engr_type == DUST
1231                 || oep->engr_type == ENGR_BLOOD
1232                 || oep->engr_type == MARK) {
1233                 if (!Blind) {
1234 #if 0 /*JP:T*/
1235                     You("wipe out the message that was %s here.",
1236                         (oep->engr_type == DUST)
1237                             ? "written in the dust"
1238                             : (oep->engr_type == ENGR_BLOOD)
1239                                 ? "scrawled in blood"
1240                                 : "written");
1241 #else
1242                     You("%s\83\81\83b\83Z\81[\83W\82ð\90@\82«\82Æ\82Á\82½\81D",
1243                         (oep->engr_type == DUST)
1244                             ? "\82Ù\82±\82è\82É\8f\91\82©\82ê\82Ä\82¢\82é"
1245                             : (oep->engr_type == BLOOD)
1246                                 ? "\8c\8c\95\8e\9a\82Å\82È\82®\82è\8f\91\82«\82³\82ê\82Ä\82¢\82é"
1247                                 : "\8f\91\82©\82ê\82Ä\82¢\82é");
1248 #endif
1249                     del_engr(oep);
1250                     oep = (struct engr *) 0;
1251                 } else
1252                     /* Don't delete engr until after we *know* we're engraving
1253                      */
1254                     eow = TRUE;
1255             } else if (type == DUST || type == MARK || type == ENGR_BLOOD) {
1256 #if 0 /*JP:T*/
1257                 You("cannot wipe out the message that is %s the %s here.",
1258                     oep->engr_type == BURN
1259                         ? (is_ice(u.ux, u.uy) ? "melted into" : "burned into")
1260                         : "engraved in",
1261                     surface(u.ux, u.uy));
1262 #else
1263                 You("%s\83\81\83b\83Z\81[\83W\82ð\90@\82«\82Æ\82ê\82È\82©\82Á\82½\81D",
1264                     oep->engr_type == BURN
1265                         ? (is_ice(u.ux, u.uy) ? "\8d\8f\82Ü\82ê\82Ä\82¢\82é" : "\8fÄ\82«\95t\82¯\82ç\82ê\82Ä\82¢\82é")
1266                         : "\8d\8f\82Ü\82ê\82Ä\82¢\82é");
1267 #endif
1268                 return 1;
1269             } else if (type != oep->engr_type || c == 'n') {
1270                 if (!Blind || can_reach_floor(TRUE))
1271 /*JP
1272                     You("will overwrite the current message.");
1273 */
1274                     You("\83\81\83b\83Z\81[\83W\82ð\8fã\8f\91\82«\82µ\82æ\82¤\82Æ\82µ\82½\81D");
1275                 eow = TRUE;
1276             }
1277         }
1278     }
1279
1280     eloc = surface(u.ux, u.uy);
1281     switch (type) {
1282     default:
1283 /*JP
1284         everb = (oep && !eow ? "add to the weird writing on"
1285 */
1286         everb = (oep && !eow ? "\8aï\96­\82È\95\8e\9a\97ñ\82É\8f\91\82«\89Á\82¦\82é"
1287 /*JP
1288                              : "write strangely on");
1289 */
1290                              : "\8aï\96­\82È\95\8e\9a\97ñ\82ð\8f\91\82­");
1291         break;
1292     case DUST:
1293 /*JP
1294         everb = (oep && !eow ? "add to the writing in" : "write in");
1295 */
1296         everb = (oep && !eow ? "\8f\91\82«\89Á\82¦\82é" : "\8f\91\82­");
1297 /*JP
1298         eloc = is_ice(u.ux, u.uy) ? "frost" : "dust";
1299 */
1300         eloc = is_ice(u.ux,u.uy) ? "\91\9a" : "\82Ù\82±\82è";
1301         break;
1302     case HEADSTONE:
1303 /*JP
1304         everb = (oep && !eow ? "add to the epitaph on" : "engrave on");
1305 */
1306         everb = (oep && !eow ? "\95æ\94è\96Á\82ð\8d\8f\82Ý\89Á\82¦\82é" : "\95æ\94è\96Á\82ð\8d\8f\82Þ");
1307         break;
1308     case ENGRAVE:
1309 /*JP
1310         everb = (oep && !eow ? "add to the engraving in" : "engrave in");
1311 */
1312         everb = (oep && !eow ? "\8d\8f\82Ý\89Á\82¦\82é" : "\8d\8f\82Þ");
1313         break;
1314     case BURN:
1315 #if 0 /*JP:T*/
1316         everb = (oep && !eow
1317                      ? (is_ice(u.ux, u.uy) ? "add to the text melted into"
1318                                            : "add to the text burned into")
1319                      : (is_ice(u.ux, u.uy) ? "melt into" : "burn into"));
1320 #else
1321         everb = (oep && !eow
1322                  ? ( is_ice(u.ux,u.uy) ? "\8d\8f\82Ý\89Á\82¦\82é"
1323                                        : "\94R\82¦\82Ä\82¢\82é\95\8e\9a\82É\8f\91\82«\89Á\82¦\82é")
1324                  : ( is_ice(u.ux,u.uy) ? "\8d\8f\82Þ" : "\8fÄ\88ó\82ð\82¢\82ê\82é"));
1325 #endif
1326         break;
1327     case MARK:
1328 /*JP
1329         everb = (oep && !eow ? "add to the graffiti on" : "scribble on");
1330 */
1331         everb = (oep && !eow ? "\97\8e\8f\91\82É\8f\91\82«\89Á\82¦\82é" : "\82Í\82µ\82è\8f\91\82«\82·\82é");
1332         break;
1333     case ENGR_BLOOD:
1334 /*JP
1335         everb = (oep && !eow ? "add to the scrawl on" : "scrawl on");
1336 */
1337         everb = (oep && !eow ? "\82È\82®\82è\8f\91\82«\82É\8f\91\82«\89Á\82¦\82é" : "\82È\82®\82è\8f\91\82«\82·\82é");
1338         break;
1339     }
1340
1341     /* Tell adventurer what is going on */
1342     if (otmp != &zeroobj)
1343 /*JP
1344         You("%s the %s with %s.", everb, eloc, doname(otmp));
1345 */
1346         You("%s\82Å%s\82É%s\81D", doname(otmp), eloc, jpast(everb));
1347     else
1348 #if 0 /*JP:T*/
1349         You("%s the %s with your %s.", everb, eloc, body_part(FINGERTIP));
1350 #else
1351         You("%s\82Å%s\82É%s\81D", body_part(FINGER), eloc, jpast(everb));
1352 #endif
1353
1354     /* Prompt for engraving! */
1355 /*JP
1356     Sprintf(qbuf, "What do you want to %s the %s here?", everb, eloc);
1357 */
1358     Sprintf(qbuf,"%s\82É\89½\82Æ%s\82©\81H", eloc, jpolite(everb));
1359     getlin(qbuf, ebuf);
1360     /* convert tabs to spaces and condense consecutive spaces to one */
1361     mungspaces(ebuf);
1362
1363     /* Count the actual # of chars engraved not including spaces */
1364     len = strlen(ebuf);
1365     for (sp = ebuf; *sp; sp++)
1366         if (*sp == ' ')
1367             len -= 1;
1368
1369     if (len == 0 || index(ebuf, '\033')) {
1370         if (zapwand) {
1371             if (!Blind)
1372 #if 0 /*JP:T*/
1373                 pline("%s, then %s.", Tobjnam(otmp, "glow"),
1374                       otense(otmp, "fade"));
1375 #else
1376                 pline("%s\82Í\8bP\82¢\82½\82ª\81C\82·\82®\82É\8fÁ\82¦\82½\81D", xname(otmp));
1377 #endif
1378             return 1;
1379         } else {
1380             pline1(Never_mind);
1381             return 0;
1382         }
1383     }
1384
1385     /* A single `x' is the traditional signature of an illiterate person */
1386     if (len != 1 || (!index(ebuf, 'x') && !index(ebuf, 'X')))
1387         u.uconduct.literate++;
1388
1389     /* Mix up engraving if surface or state of mind is unsound.
1390        Note: this won't add or remove any spaces. */
1391     for (sp = ebuf; *sp; sp++) {
1392         if (*sp == ' ')
1393             continue;
1394         if (((type == DUST || type == ENGR_BLOOD) && !rn2(25))
1395             || (Blind && !rn2(11)) || (Confusion && !rn2(7))
1396             || (Stunned && !rn2(4)) || (Hallucination && !rn2(2)))
1397 #if 0 /*JP*/
1398             *sp = ' ' + rnd(96 - 2); /* ASCII '!' thru '~'
1399                                         (excludes ' ' and DEL) */
1400 #else /*JP:\93ú\96{\8cê\82Å\83\89\83\93\83_\83\80\89» */
1401             {
1402                 if(is_kanji1(ebuf, sp-ebuf))
1403                     jrndm_replace(sp);
1404                 else if(is_kanji2(ebuf, sp-ebuf))
1405                     jrndm_replace(sp-1);
1406                 else
1407                     *sp = '!' + rn2(93); /* ASCII-code only */
1408             }
1409 #endif
1410     }
1411
1412     /* Previous engraving is overwritten */
1413     if (eow) {
1414         del_engr(oep);
1415         oep = (struct engr *) 0;
1416     }
1417
1418     /* Figure out how long it took to engrave, and if player has
1419      * engraved too much.
1420      */
1421     switch (type) {
1422     default:
1423         multi = -(len / 10);
1424         if (multi)
1425 /*JP
1426             nomovemsg = "You finish your weird engraving.";
1427 */
1428             nomovemsg = "\82 \82È\82½\82Í\8aï\96­\82È\8d\8f\82Ý\82ð\8fI\82¦\82½\81D";
1429         break;
1430     case DUST:
1431         multi = -(len / 10);
1432         if (multi)
1433 /*JP
1434             nomovemsg = "You finish writing in the dust.";
1435 */
1436             nomovemsg = "\82 \82È\82½\82Í\82Ù\82±\82è\82É\8f\91\82«\8fI\82¦\82½\81D";
1437         break;
1438     case HEADSTONE:
1439     case ENGRAVE:
1440         multi = -(len / 10);
1441         if (otmp->oclass == WEAPON_CLASS
1442             && (otmp->otyp != ATHAME || otmp->cursed)) {
1443             multi = -len;
1444             maxelen = ((otmp->spe + 3) * 2) + 1;
1445             /* -2 => 3, -1 => 5, 0 => 7, +1 => 9, +2 => 11
1446              * Note: this does not allow a +0 anything (except an athame)
1447              * to engrave "Elbereth" all at once.
1448              * However, you can engrave "Elb", then "ere", then "th".
1449              */
1450 /*JP
1451             pline("%s dull.", Yobjnam2(otmp, "get"));
1452 */
1453             Your("%s\82Í\90n\82±\82Ú\82ê\82µ\82½\81D", xname(otmp));
1454             costly_alteration(otmp, COST_DEGRD);
1455             if (len > maxelen) {
1456                 multi = -maxelen;
1457                 otmp->spe = -3;
1458             } else if (len > 1)
1459                 otmp->spe -= len >> 1;
1460             else
1461                 otmp->spe -= 1; /* Prevent infinite engraving */
1462         } else if (otmp->oclass == RING_CLASS || otmp->oclass == GEM_CLASS) {
1463             multi = -len;
1464         }
1465         if (multi)
1466 /*JP
1467             nomovemsg = "You finish engraving.";
1468 */
1469             nomovemsg = "\82 \82È\82½\82Í\8d\8f\82Ý\8fI\82¦\82½\81D";
1470         break;
1471     case BURN:
1472         multi = -(len / 10);
1473         if (multi)
1474             nomovemsg = is_ice(u.ux, u.uy)
1475 /*JP
1476                           ? "You finish melting your message into the ice."
1477 */
1478                           ? "\95X\82Ö\83\81\83b\83Z\81[\83W\82ð\8d\8f\82Ý\8fI\82¦\82½\81D"
1479 /*JP
1480                           : "You finish burning your message into the floor.";
1481 */
1482                           : "\8f°\82Ö\83\81\83b\83Z\81[\83W\82ð\8fÄ\82«\82¢\82ê\8fI\82¦\82½\81D";
1483         break;
1484     case MARK:
1485         multi = -(len / 10);
1486         if (otmp->otyp == MAGIC_MARKER) {
1487             maxelen = otmp->spe * 2; /* one charge / 2 letters */
1488             if (len > maxelen) {
1489 /*JP
1490                 Your("marker dries out.");
1491 */
1492                 Your("\83}\81[\83J\82Í\8a£\82«\82«\82Á\82½\81D");
1493                 otmp->spe = 0;
1494                 multi = -(maxelen / 10);
1495             } else if (len > 1)
1496                 otmp->spe -= len >> 1;
1497             else
1498                 otmp->spe -= 1; /* Prevent infinite graffiti */
1499         }
1500         if (multi)
1501 /*JP
1502             nomovemsg = "You finish defacing the dungeon.";
1503 */
1504             nomovemsg = "\82 \82È\82½\82Í\96À\8b{\82Ö\82Ì\97\8e\8f\91\82ð\8f\91\82«\8fI\82¦\82½\81D";
1505         break;
1506     case ENGR_BLOOD:
1507         multi = -(len / 10);
1508         if (multi)
1509 /*JP
1510             nomovemsg = "You finish scrawling.";
1511 */
1512             nomovemsg = "\82Í\82µ\82è\8f\91\82«\82ð\8f\91\82«\8fI\82¦\82½\81D";
1513         break;
1514     }
1515
1516     /* Chop engraving down to size if necessary */
1517     if (len > maxelen) {
1518         for (sp = ebuf; maxelen && *sp; sp++)
1519             if (*sp == ' ')
1520                 maxelen--;
1521         if (!maxelen && *sp) {
1522 #if 1 /*JP*//*\8a¿\8e\9a\82Ì1\83o\83C\83g\96Ú\82¾\82¯\82ª\8ec\82ç\82È\82¢\82æ\82¤\82É*/
1523             if(is_kanji2(ebuf, sp - ebuf))
1524                 --sp;
1525 #endif
1526             *sp = '\0';
1527             if (multi)
1528 /*JP
1529                 nomovemsg = "You cannot write any more.";
1530 */
1531                 nomovemsg = "\82±\82ê\88È\8fã\89½\82à\8f\91\82¯\82È\82©\82Á\82½\81D";
1532 /*JP
1533             You("are only able to write \"%s\".", ebuf);
1534 */
1535             You("\81u%s\81v\82Æ\82Ü\82Å\82µ\82©\8f\91\82¯\82È\82©\82Á\82½\81D", ebuf);
1536         }
1537     }
1538
1539     if (oep) /* add to existing engraving */
1540         Strcpy(buf, oep->engr_txt);
1541     (void) strncat(buf, ebuf, BUFSZ - (int) strlen(buf) - 1);
1542     /* Put the engraving onto the map */
1543     make_engr_at(u.ux, u.uy, buf, moves - multi, type);
1544
1545     if (post_engr_text[0])
1546         pline("%s", post_engr_text);
1547     if (doblind && !resists_blnd(&youmonst)) {
1548 /*JP
1549         You("are blinded by the flash!");
1550 */
1551         You("\82Ü\82Î\82ä\82¢\8cõ\82Å\96Ú\82ª\82­\82ç\82ñ\82¾\81I");
1552         make_blinded((long) rnd(50), FALSE);
1553         if (!Blind)
1554             Your1(vision_clears);
1555     }
1556     return 1;
1557 }
1558
1559 /* while loading bones, clean up text which might accidentally
1560    or maliciously disrupt player's terminal when displayed */
1561 void
1562 sanitize_engravings()
1563 {
1564     struct engr *ep;
1565
1566     for (ep = head_engr; ep; ep = ep->nxt_engr) {
1567         sanitize_name(ep->engr_txt);
1568     }
1569 }
1570
1571 void
1572 save_engravings(fd, mode)
1573 int fd, mode;
1574 {
1575     struct engr *ep, *ep2;
1576     unsigned no_more_engr = 0;
1577
1578     for (ep = head_engr; ep; ep = ep2) {
1579         ep2 = ep->nxt_engr;
1580         if (ep->engr_lth && ep->engr_txt[0] && perform_bwrite(mode)) {
1581             bwrite(fd, (genericptr_t) &ep->engr_lth, sizeof ep->engr_lth);
1582             bwrite(fd, (genericptr_t) ep, sizeof (struct engr) + ep->engr_lth);
1583         }
1584         if (release_data(mode))
1585             dealloc_engr(ep);
1586     }
1587     if (perform_bwrite(mode))
1588         bwrite(fd, (genericptr_t) &no_more_engr, sizeof no_more_engr);
1589     if (release_data(mode))
1590         head_engr = 0;
1591 }
1592
1593 void
1594 rest_engravings(fd)
1595 int fd;
1596 {
1597     struct engr *ep;
1598     unsigned lth;
1599
1600     head_engr = 0;
1601     while (1) {
1602         mread(fd, (genericptr_t) &lth, sizeof lth);
1603         if (lth == 0)
1604             return;
1605         ep = newengr(lth);
1606         mread(fd, (genericptr_t) ep, sizeof (struct engr) + lth);
1607         ep->nxt_engr = head_engr;
1608         head_engr = ep;
1609         ep->engr_txt = (char *) (ep + 1); /* Andreas Bormann */
1610         /* Mark as finished for bones levels -- no problem for
1611          * normal levels as the player must have finished engraving
1612          * to be able to move again.
1613          */
1614         ep->engr_time = moves;
1615     }
1616 }
1617
1618 /* to support '#stats' wizard-mode command */
1619 void
1620 engr_stats(hdrfmt, hdrbuf, count, size)
1621 const char *hdrfmt;
1622 char *hdrbuf;
1623 long *count, *size;
1624 {
1625     struct engr *ep;
1626
1627     Sprintf(hdrbuf, hdrfmt, (long) sizeof (struct engr));
1628     *count = *size = 0L;
1629     for (ep = head_engr; ep; ep = ep->nxt_engr) {
1630         ++*count;
1631         *size += (long) sizeof *ep + (long) ep->engr_lth;
1632     }
1633 }
1634
1635 void
1636 del_engr(ep)
1637 register struct engr *ep;
1638 {
1639     if (ep == head_engr) {
1640         head_engr = ep->nxt_engr;
1641     } else {
1642         register struct engr *ept;
1643
1644         for (ept = head_engr; ept; ept = ept->nxt_engr)
1645             if (ept->nxt_engr == ep) {
1646                 ept->nxt_engr = ep->nxt_engr;
1647                 break;
1648             }
1649         if (!ept) {
1650             impossible("Error in del_engr?");
1651             return;
1652         }
1653     }
1654     dealloc_engr(ep);
1655 }
1656
1657 /* randomly relocate an engraving */
1658 void
1659 rloc_engr(ep)
1660 struct engr *ep;
1661 {
1662     int tx, ty, tryct = 200;
1663
1664     do {
1665         if (--tryct < 0)
1666             return;
1667         tx = rn1(COLNO - 3, 2);
1668         ty = rn2(ROWNO);
1669     } while (engr_at(tx, ty) || !goodpos(tx, ty, (struct monst *) 0, 0));
1670
1671     ep->engr_x = tx;
1672     ep->engr_y = ty;
1673 }
1674
1675 /* Create a headstone at the given location.
1676  * The caller is responsible for newsym(x, y).
1677  */
1678 void
1679 make_grave(x, y, str)
1680 int x, y;
1681 const char *str;
1682 {
1683     char buf[BUFSZ];
1684
1685     /* Can we put a grave here? */
1686     if ((levl[x][y].typ != ROOM && levl[x][y].typ != GRAVE) || t_at(x, y))
1687         return;
1688     /* Make the grave */
1689     levl[x][y].typ = GRAVE;
1690     /* Engrave the headstone */
1691     del_engr_at(x, y);
1692     if (!str)
1693         str = get_rnd_text(EPITAPHFILE, buf, rn2);
1694     make_engr_at(x, y, str, 0L, HEADSTONE);
1695     return;
1696 }
1697
1698 static const char blind_writing[][21] = {
1699     {0x44, 0x66, 0x6d, 0x69, 0x62, 0x65, 0x22, 0x45, 0x7b, 0x71,
1700      0x65, 0x6d, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
1701     {0x51, 0x67, 0x60, 0x7a, 0x7f, 0x21, 0x40, 0x71, 0x6b, 0x71,
1702      0x6f, 0x67, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
1703     {0x49, 0x6d, 0x73, 0x69, 0x62, 0x65, 0x22, 0x4c, 0x61, 0x7c,
1704      0x6d, 0x67, 0x24, 0x42, 0x7f, 0x69, 0x6c, 0x77, 0x67, 0x7e, 0x00},
1705     {0x4b, 0x6d, 0x6c, 0x66, 0x30, 0x4c, 0x6b, 0x68, 0x7c, 0x7f,
1706      0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
1707     {0x51, 0x67, 0x70, 0x7a, 0x7f, 0x6f, 0x67, 0x68, 0x64, 0x71,
1708      0x21, 0x4f, 0x6b, 0x6d, 0x7e, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00},
1709     {0x4c, 0x63, 0x76, 0x61, 0x71, 0x21, 0x48, 0x6b, 0x7b, 0x75,
1710      0x67, 0x63, 0x24, 0x45, 0x65, 0x6b, 0x6b, 0x65, 0x00, 0x00, 0x00},
1711     {0x4c, 0x67, 0x68, 0x6b, 0x78, 0x68, 0x6d, 0x76, 0x7a, 0x75,
1712      0x21, 0x4f, 0x71, 0x7a, 0x75, 0x6f, 0x77, 0x00, 0x00, 0x00, 0x00},
1713     {0x44, 0x66, 0x6d, 0x7c, 0x78, 0x21, 0x50, 0x65, 0x66, 0x65,
1714      0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
1715     {0x44, 0x66, 0x73, 0x69, 0x62, 0x65, 0x22, 0x56, 0x7d, 0x63,
1716      0x69, 0x76, 0x6b, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
1717 };
1718
1719 STATIC_OVL const char *
1720 blengr(VOID_ARGS)
1721 {
1722     return blind_writing[rn2(SIZE(blind_writing))];
1723 }
1724
1725 /*engrave.c*/