OSDN Git Service

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