OSDN Git Service

update year to 2020
[jnethack/source.git] / src / write.c
1 /* NetHack 3.6  write.c $NHDT-Date: 1573346194 2019/11/10 00:36:34 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.20 $ */
2 /* NetHack may be freely redistributed.  See license for details. */
3
4 /* JNetHack Copyright */
5 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
6 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020            */
7 /* JNetHack may be freely redistributed.  See license for details. */
8
9 #include "hack.h"
10
11 STATIC_DCL int FDECL(cost, (struct obj *));
12 STATIC_DCL boolean FDECL(label_known, (int, struct obj *));
13 STATIC_DCL char *FDECL(new_book_description, (int, char *));
14
15 /*
16  * returns basecost of a scroll or a spellbook
17  */
18 STATIC_OVL int
19 cost(otmp)
20 register struct obj *otmp;
21 {
22     if (otmp->oclass == SPBOOK_CLASS)
23         return (10 * objects[otmp->otyp].oc_level);
24
25     switch (otmp->otyp) {
26 #ifdef MAIL
27     case SCR_MAIL:
28         return 2;
29 #endif
30     case SCR_LIGHT:
31     case SCR_GOLD_DETECTION:
32     case SCR_FOOD_DETECTION:
33     case SCR_MAGIC_MAPPING:
34     case SCR_AMNESIA:
35     case SCR_FIRE:
36     case SCR_EARTH:
37         return 8;
38     case SCR_DESTROY_ARMOR:
39     case SCR_CREATE_MONSTER:
40     case SCR_PUNISHMENT:
41         return 10;
42     case SCR_CONFUSE_MONSTER:
43         return 12;
44     case SCR_IDENTIFY:
45         return 14;
46     case SCR_ENCHANT_ARMOR:
47     case SCR_REMOVE_CURSE:
48     case SCR_ENCHANT_WEAPON:
49     case SCR_CHARGING:
50         return 16;
51     case SCR_SCARE_MONSTER:
52     case SCR_STINKING_CLOUD:
53     case SCR_TAMING:
54     case SCR_TELEPORTATION:
55         return 20;
56     case SCR_GENOCIDE:
57         return 30;
58     case SCR_BLANK_PAPER:
59     default:
60         impossible("You can't write such a weird scroll!");
61     }
62     return 1000;
63 }
64
65 /* decide whether the hero knowns a particular scroll's label;
66    unfortunately, we can't track things that haven't been added to
67    the discoveries list and aren't present in current inventory,
68    so some scrolls with ought to yield True will end up False */
69 STATIC_OVL boolean
70 label_known(scrolltype, objlist)
71 int scrolltype;
72 struct obj *objlist;
73 {
74     struct obj *otmp;
75
76     /* only scrolls */
77     if (objects[scrolltype].oc_class != SCROLL_CLASS)
78         return FALSE;
79     /* type known implies full discovery; otherwise,
80        user-assigned name implies partial discovery */
81     if (objects[scrolltype].oc_name_known || objects[scrolltype].oc_uname)
82         return TRUE;
83     /* check inventory, including carried containers with known contents */
84     for (otmp = objlist; otmp; otmp = otmp->nobj) {
85         if (otmp->otyp == scrolltype && otmp->dknown)
86             return TRUE;
87         if (Has_contents(otmp) && otmp->cknown
88             && label_known(scrolltype, otmp->cobj))
89             return TRUE;
90     }
91     /* not found */
92     return FALSE;
93 }
94
95 static NEARDATA const char write_on[] = { SCROLL_CLASS, SPBOOK_CLASS, 0 };
96
97 /* write -- applying a magic marker */
98 int
99 dowrite(pen)
100 register struct obj *pen;
101 {
102     register struct obj *paper;
103 #if 0 /*JP*/
104     char namebuf[BUFSZ] = DUMMY, *nm, *bp;
105 #else
106     char namebuf[BUFSZ] = DUMMY, *nm;
107 #endif
108     register struct obj *new_obj;
109     int basecost, actualcost;
110     int curseval;
111     char qbuf[QBUFSZ];
112     int first, last, i, deferred, deferralchance;
113     boolean by_descr = FALSE;
114     const char *typeword;
115
116     if (nohands(youmonst.data)) {
117 /*JP
118         You("need hands to be able to write!");
119 */
120         You("\8f\91\82­\82½\82ß\82É\82Í\8eè\82ª\95K\97v\82¾\81I");
121         return 0;
122     } else if (Glib) {
123 #if 0 /*JP:T*/
124         pline("%s from your %s.", Tobjnam(pen, "slip"),
125               fingers_or_gloves(FALSE));
126 #else
127         pline("%s\82ª%s\82©\82ç\8a\8a\82è\82¨\82¿\82½\81D", xname(pen),
128               fingers_or_gloves(FALSE));
129 #endif
130         dropx(pen);
131         return 1;
132     }
133
134     /* get paper to write on */
135     paper = getobj(write_on, "write on");
136     if (!paper)
137         return 0;
138     /* can't write on a novel (unless/until it's been converted into a blank
139        spellbook), but we want messages saying so to avoid "spellbook" */
140 #if 0 /*JP:T*/
141     typeword = (paper->otyp == SPE_NOVEL)
142                   ? "book"
143                   : (paper->oclass == SPBOOK_CLASS)
144                      ? "spellbook"
145                      : "scroll";
146 #else
147     typeword = (paper->otyp == SPE_NOVEL)
148                   ? "\96{"
149                   : (paper->oclass == SPBOOK_CLASS)
150                      ? "\96\82\96@\8f\91"
151                      : "\8aª\95¨";
152 #endif
153     if (Blind) {
154         if (!paper->dknown) {
155 /*JP
156             You("don't know if that %s is blank or not.", typeword);
157 */
158             You("%s\82ª\94\92\8e\86\82©\82Ç\82¤\82©\82í\82©\82ç\82È\82¢\81I", typeword);
159             return 0;
160         } else if (paper->oclass == SPBOOK_CLASS) {
161             /* can't write a magic book while blind */
162 /*JP
163             pline("%s can't create braille text.",
164 */
165             pline("%s\82Å\82Í\93_\8e\9a\82ð\8dì\82ê\82È\82¢\81D",
166                   upstart(ysimple_name(pen)));
167             return 0;
168         }
169     }
170     paper->dknown = 1;
171     if (paper->otyp != SCR_BLANK_PAPER && paper->otyp != SPE_BLANK_PAPER) {
172 /*JP
173         pline("That %s is not blank!", typeword);
174 */
175         pline("%s\82Í\94\92\8e\86\82\82á\82È\82¢\81I", typeword);
176         exercise(A_WIS, FALSE);
177         return 1;
178     }
179
180     /* what to write */
181 /*JP
182     Sprintf(qbuf, "What type of %s do you want to write?", typeword);
183 */
184     Sprintf(qbuf, "\82Ç\82Ì\8eí\82Ì%s\82Ì\8eô\95\82ð\8f\91\82«\82Ü\82·\82©\81H", typeword);
185     getlin(qbuf, namebuf);
186     (void) mungspaces(namebuf); /* remove any excess whitespace */
187     if (namebuf[0] == '\033' || !namebuf[0])
188         return 1;
189     nm = namebuf;
190 #if 0 /*JP*//*\93ú\96{\8cê\82Å\82Í\95s\97v*/
191     if (!strncmpi(nm, "scroll ", 7))
192         nm += 7;
193     else if (!strncmpi(nm, "spellbook ", 10))
194         nm += 10;
195     if (!strncmpi(nm, "of ", 3))
196         nm += 3;
197
198     if ((bp = strstri(nm, " armour")) != 0) {
199         (void) strncpy(bp, " armor ", 7); /* won't add '\0' */
200         (void) mungspaces(bp + 1);        /* remove the extra space */
201     }
202 #endif
203
204     deferred = 0;       /* not any scroll or book */
205     deferralchance = 0; /* incremented for each oc_uname match */
206     first = bases[(int) paper->oclass];
207     last = bases[(int) paper->oclass + 1] - 1;
208     for (i = first; i <= last; i++) {
209         /* extra shufflable descr not representing a real object */
210         if (!OBJ_NAME(objects[i]))
211             continue;
212
213         if (!strcmpi(OBJ_NAME(objects[i]), nm))
214             goto found;
215         if (!strcmpi(OBJ_DESCR(objects[i]), nm)) {
216             by_descr = TRUE;
217             goto found;
218         }
219         /* user-assigned name might match real name of a later
220            entry, so we don't simply use first match with it;
221            also, player might assign same name multiple times
222            and if so, we choose one of those matches randomly */
223         if (objects[i].oc_uname && !strcmpi(objects[i].oc_uname, nm)
224             /*
225              * First match: chance incremented to 1,
226              *   !rn2(1) is 1, we remember i;
227              * second match: chance incremented to 2,
228              *   !rn2(2) has 1/2 chance to replace i;
229              * third match: chance incremented to 3,
230              *   !rn2(3) has 1/3 chance to replace i
231              *   and 2/3 chance to keep previous 50:50
232              *   choice; so on for higher match counts.
233              */
234             && !rn2(++deferralchance))
235             deferred = i;
236     }
237     /* writing by user-assigned name is same as by description:
238        fails for books, works for scrolls (having an assigned
239        type name guarantees presence on discoveries list) */
240     if (deferred) {
241         i = deferred;
242         by_descr = TRUE;
243         goto found;
244     }
245
246 /*JP
247     There("is no such %s!", typeword);
248 */
249     pline("\82»\82Ì\82æ\82¤\82È%s\82Í\82È\82¢\81I", typeword);
250     return 1;
251 found:
252
253     if (i == SCR_BLANK_PAPER || i == SPE_BLANK_PAPER) {
254 /*JP
255         You_cant("write that!");
256 */
257         pline("\94\92\8e\86\82É\94\92\8e\86\82ð\8f\91\82­\81H\81I");
258 /*JP
259         pline("It's obscene!");
260 */
261         pline("\82»\82¤\82¢\82¤\82â\82è\82©\82½\82Í\82¿\82å\82Á\82Æ\95s\96ù\89õ\82¾\82È\81I");
262         return 1;
263     } else if (i == SPE_BOOK_OF_THE_DEAD) {
264 /*JP
265         pline("No mere dungeon adventurer could write that.");
266 */
267         pline("\88ê\89î\82Ì\96À\8b{\96`\8c¯\89Æ\82É\82Í\8f\91\82¯\82é\82à\82Ì\82Å\82Í\82È\82¢\81D");
268         return 1;
269     } else if (by_descr && paper->oclass == SPBOOK_CLASS
270                && !objects[i].oc_name_known) {
271         /* can't write unknown spellbooks by description */
272 /*JP
273         pline("Unfortunately you don't have enough information to go on.");
274 */
275         pline("\8ec\94O\82È\82ª\82ç\82»\82ê\82ð\8f\91\82­\82¾\82¯\82Ì\8f\\95ª\82È\92m\8e¯\82ª\82È\82¢\81D");
276         return 1;
277     }
278
279     /* KMH, conduct */
280     u.uconduct.literate++;
281
282     new_obj = mksobj(i, FALSE, FALSE);
283     new_obj->bknown = (paper->bknown && pen->bknown);
284
285     /* shk imposes a flat rate per use, not based on actual charges used */
286     check_unpaid(pen);
287
288     /* see if there's enough ink */
289     basecost = cost(new_obj);
290     if (pen->spe < basecost / 2) {
291 /*JP
292         Your("marker is too dry to write that!");
293 */
294         Your("\83}\81[\83J\82Í\8a£\82«\82·\82¬\82Ä\82¨\82è\82¤\82Ü\82­\8f\91\82¯\82È\82©\82Á\82½\81I");
295         obfree(new_obj, (struct obj *) 0);
296         return 1;
297     }
298
299     /* we're really going to write now, so calculate cost
300      */
301     actualcost = rn1(basecost / 2, basecost / 2);
302     curseval = bcsign(pen) + bcsign(paper);
303     exercise(A_WIS, TRUE);
304     /* dry out marker */
305     if (pen->spe < actualcost) {
306         pen->spe = 0;
307 /*JP
308         Your("marker dries out!");
309 */
310         pline("\8f\91\82¢\82Ä\82¢\82é\93r\92\86\82Å\83}\81[\83J\82Í\8a£\82«\82«\82Á\82½\81I");
311         /* scrolls disappear, spellbooks don't */
312         if (paper->oclass == SPBOOK_CLASS) {
313 /*JP
314             pline_The("spellbook is left unfinished and your writing fades.");
315 */
316             pline_The("\96\82\96@\8f\91\82É\82Í\8f\91\82«\82«\82ê\82È\82©\82Á\82½\81D\82»\82µ\82Ä\8f\91\82¢\82½\95\8e\9a\82Í\8fÁ\82¦\82Ä\82µ\82Ü\82Á\82½\81D");
317             update_inventory(); /* pen charges */
318         } else {
319 /*JP
320             pline_The("scroll is now useless and disappears!");
321 */
322             pline_The("\8aª\95¨\82Í\8eg\82¢\82à\82Ì\82É\82È\82ç\82È\82­\82È\82Á\82Ä\8fÁ\96Å\82µ\82½\81I");
323             useup(paper);
324         }
325         obfree(new_obj, (struct obj *) 0);
326         return 1;
327     }
328     pen->spe -= actualcost;
329
330     /*
331      * Writing by name requires that the hero knows the scroll or
332      * book type.  One has previously been read (and its effect
333      * was evident) or been ID'd via scroll/spell/throne and it
334      * will be on the discoveries list.
335      * (Previous versions allowed scrolls and books to be written
336      * by type name if they were on the discoveries list via being
337      * given a user-assigned name, even though doing the latter
338      * doesn't--and shouldn't--make the actual type become known.)
339      *
340      * Writing by description requires that the hero knows the
341      * description (a scroll's label, that is, since books by_descr
342      * are rejected above).  BUG:  We can only do this for known
343      * scrolls and for the case where the player has assigned a
344      * name to put it onto the discoveries list; we lack a way to
345      * track other scrolls which have been seen closely enough to
346      * read the label without then being ID'd or named.  The only
347      * exception is for currently carried inventory, where we can
348      * check for one [with its dknown bit set] of the same type.
349      *
350      * Normal requirements can be overridden if hero is Lucky.
351      */
352
353     /* if known, then either by-name or by-descr works */
354     if (!objects[new_obj->otyp].oc_name_known
355         /* else if named, then only by-descr works */
356         && !(by_descr && label_known(new_obj->otyp, invent))
357         /* and Luck might override after both checks have failed */
358         && rnl(Role_if(PM_WIZARD) ? 5 : 15)) {
359 /*JP
360         You("%s to write that.", by_descr ? "fail" : "don't know how");
361 */
362         You("%s\81I", by_descr ? "\8f\91\82­\82Ì\82É\8e¸\94s\82µ\82½" : "\82Ç\82¤\82â\82Á\82Ä\8f\91\82­\82Ì\82©\92m\82ç\82È\82¢");
363         /* scrolls disappear, spellbooks don't */
364         if (paper->oclass == SPBOOK_CLASS) {
365             You(
366 /*JP
367       "write in your best handwriting:  \"My Diary\", but it quickly fades.");
368 */
369       "\92\9a\94J\82É\8f\91\82¢\82½\81F\81u\89ä\82ª\93ú\8bL\81v\81D\82µ\82©\82µ\82 \82Á\82Æ\8c¾\82¤\8aÔ\82É\8fÁ\82¦\82Ä\82µ\82Ü\82Á\82½\81D");
370             update_inventory(); /* pen charges */
371         } else {
372             if (by_descr) {
373                 Strcpy(namebuf, OBJ_DESCR(objects[new_obj->otyp]));
374                 wipeout_text(namebuf, (6 + MAXULEV - u.ulevel) / 6, 0);
375             } else
376 /*JP
377                 Sprintf(namebuf, "%s was here!", plname);
378 */
379                 Sprintf(namebuf, "%s\82Í\82±\82±\82É\82 \82è\81I", plname);
380 /*JP
381             You("write \"%s\" and the scroll disappears.", namebuf);
382 */
383             You("\81u%s\81v\82Æ\8f\91\82¢\82½\81D\82·\82é\82Æ\8aª\95¨\82Í\8fÁ\82¦\82Ä\82µ\82Ü\82Á\82½\81D", namebuf);
384             useup(paper);
385         }
386         obfree(new_obj, (struct obj *) 0);
387         return 1;
388     }
389     /* can write scrolls when blind, but requires luck too;
390        attempts to write books when blind are caught above */
391     if (Blind && rnl(3)) {
392         /* writing while blind usually fails regardless of
393            whether the target scroll is known; even if we
394            have passed the write-an-unknown scroll test
395            above we can still fail this one, so it's doubly
396            hard to write an unknown scroll while blind */
397 /*JP
398         You("fail to write the scroll correctly and it disappears.");
399 */
400         You("\8aª\95¨\82É\90³\82µ\82­\8f\91\82­\82Ì\82É\8e¸\94s\82µ\82½\81D\8aª\95¨\82Í\8fÁ\82¦\82½\81D");
401         useup(paper);
402         obfree(new_obj, (struct obj *) 0);
403         return 1;
404     }
405
406     /* useup old scroll / spellbook */
407     useup(paper);
408
409     /* success */
410     if (new_obj->oclass == SPBOOK_CLASS) {
411         /* acknowledge the change in the object's description... */
412 #if 0 /*JP:T*/
413         pline_The("spellbook warps strangely, then turns %s.",
414                   new_book_description(new_obj->otyp, namebuf));
415 #else
416         pline("\96\82\96@\8f\91\82Í\96­\82É\94½\82è\82©\82¦\82è\81C\82»\82µ\82Ä%s\82É\82È\82Á\82½\81D",
417                   new_book_description(new_obj->otyp, namebuf));
418 #endif
419     }
420     new_obj->blessed = (curseval > 0);
421     new_obj->cursed = (curseval < 0);
422 #ifdef MAIL
423     if (new_obj->otyp == SCR_MAIL)
424         /* 0: delivered in-game via external event (or randomly for fake mail);
425            1: from bones or wishing; 2: written with marker */
426         new_obj->spe = 2;
427 #endif
428     /* unlike alchemy, for example, a successful result yields the
429        specifically chosen item so hero recognizes it even if blind;
430        the exception is for being lucky writing an undiscovered scroll,
431        where the label associated with the type-name isn't known yet */
432     new_obj->dknown = label_known(new_obj->otyp, invent) ? 1 : 0;
433
434 #if 0 /*JP*/
435     new_obj = hold_another_object(new_obj, "Oops!  %s out of your grasp!",
436                                   The(aobjnam(new_obj, "slip")),
437                                   (const char *) 0);
438 #else
439     new_obj =
440         hold_another_object(new_obj, "\82¨\82Á\82Æ\81I%s\82Í\82 \82È\82½\82Ì\8eè\82©\82ç\8a\8a\82è\97\8e\82¿\82½\81I",
441                             xname(new_obj), (const char *) 0);
442 #endif
443     nhUse(new_obj); /* try to avoid complaint about dead assignment */
444     return 1;
445 }
446
447 /* most book descriptions refer to cover appearance, so we can issue a
448    message for converting a plain book into one of those with something
449    like "the spellbook turns red" or "the spellbook turns ragged";
450    but some descriptions refer to composition and "the book turns vellum"
451    looks funny, so we want to insert "into " prior to such descriptions;
452    even that's rather iffy, indicating that such descriptions probably
453    ought to be eliminated (especially "cloth"!) */
454 STATIC_OVL char *
455 new_book_description(booktype, outbuf)
456 int booktype;
457 char *outbuf;
458 {
459 #if 0 /*JP*//*\93ú\96{\8cê\82Å\82Í\95s\97v*/
460     /* subset of description strings from objects.c; if it grows
461        much, we may need to add a new flag field to objects[] instead */
462     static const char *const compositions[] = {
463         "parchment",
464         "vellum",
465         "cloth",
466 #if 0
467         "canvas", "hardcover", /* not used */
468         "papyrus", /* not applicable--can't be produced via writing */
469 #endif /*0*/
470         0
471     };
472     const char *descr, *const *comp_p;
473
474     descr = OBJ_DESCR(objects[booktype]);
475     for (comp_p = compositions; *comp_p; ++comp_p)
476         if (!strcmpi(descr, *comp_p))
477             break;
478
479     Sprintf(outbuf, "%s%s", *comp_p ? "into " : "", descr);
480 #else /*JP:\92P\8f\83\82É\83R\83s\81[*/
481     Strcpy(outbuf, OBJ_DESCR(objects[booktype]));
482 #endif
483     return outbuf;
484 }
485
486 /*write.c*/