OSDN Git Service

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