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. */
4 /* JNetHack Copyright */
5 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
6 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2022 */
7 /* JNetHack may be freely redistributed. See license for details. */
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 *));
16 * returns basecost of a scroll or a spellbook
20 register struct obj *otmp;
22 if (otmp->oclass == SPBOOK_CLASS)
23 return (10 * objects[otmp->otyp].oc_level);
31 case SCR_GOLD_DETECTION:
32 case SCR_FOOD_DETECTION:
33 case SCR_MAGIC_MAPPING:
38 case SCR_DESTROY_ARMOR:
39 case SCR_CREATE_MONSTER:
42 case SCR_CONFUSE_MONSTER:
46 case SCR_ENCHANT_ARMOR:
47 case SCR_REMOVE_CURSE:
48 case SCR_ENCHANT_WEAPON:
51 case SCR_SCARE_MONSTER:
52 case SCR_STINKING_CLOUD:
54 case SCR_TELEPORTATION:
60 impossible("You can't write such a weird scroll!");
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 */
70 label_known(scrolltype, objlist)
77 if (objects[scrolltype].oc_class != SCROLL_CLASS)
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)
83 /* check inventory, including carried containers with known contents */
84 for (otmp = objlist; otmp; otmp = otmp->nobj) {
85 if (otmp->otyp == scrolltype && otmp->dknown)
87 if (Has_contents(otmp) && otmp->cknown
88 && label_known(scrolltype, otmp->cobj))
95 static NEARDATA const char write_on[] = { SCROLL_CLASS, SPBOOK_CLASS, 0 };
97 /* write -- applying a magic marker */
100 register struct obj *pen;
102 register struct obj *paper;
104 char namebuf[BUFSZ] = DUMMY, *nm, *bp;
106 char namebuf[BUFSZ] = DUMMY, *nm;
108 register struct obj *new_obj;
109 int basecost, actualcost;
112 int first, last, i, deferred, deferralchance;
113 boolean by_descr = FALSE;
114 const char *typeword;
116 if (nohands(youmonst.data)) {
118 You("need hands to be able to write!");
120 You("
\8f\91\82
\82½
\82ß
\82É
\82Í
\8eè
\82ª
\95K
\97v
\82¾
\81I");
124 pline("%s from your %s.", Tobjnam(pen, "slip"),
125 fingers_or_gloves(FALSE));
127 pline("%s
\82ª%s
\82©
\82ç
\8a\8a\82è
\82¨
\82¿
\82½
\81D", xname(pen),
128 fingers_or_gloves(FALSE));
134 /* get paper to write on */
135 paper = getobj(write_on, "write on");
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" */
141 typeword = (paper->otyp == SPE_NOVEL)
143 : (paper->oclass == SPBOOK_CLASS)
147 typeword = (paper->otyp == SPE_NOVEL)
149 : (paper->oclass == SPBOOK_CLASS)
154 if (!paper->dknown) {
156 You("don't know if that %s is blank or not.", typeword);
158 You("%s
\82ª
\94\92\8e\86\82©
\82Ç
\82¤
\82©
\82í
\82©
\82ç
\82È
\82¢
\81I", typeword);
160 } else if (paper->oclass == SPBOOK_CLASS) {
161 /* can't write a magic book while blind */
163 pline("%s can't create braille text.",
165 pline("%s
\82Å
\82Í
\93_
\8e\9a\82ð
\8dì
\82ê
\82È
\82¢
\81D",
166 upstart(ysimple_name(pen)));
171 if (paper->otyp != SCR_BLANK_PAPER && paper->otyp != SPE_BLANK_PAPER) {
173 pline("That %s is not blank!", typeword);
175 pline("%s
\82Í
\94\92\8e\86\82¶
\82á
\82È
\82¢
\81I", typeword);
176 exercise(A_WIS, FALSE);
182 Sprintf(qbuf, "What type of %s do you want to write?", typeword);
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])
190 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
191 if (!strncmpi(nm, "scroll ", 7))
193 else if (!strncmpi(nm, "spellbook ", 10))
195 if (!strncmpi(nm, "of ", 3))
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 */
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]))
213 if (!strcmpi(OBJ_NAME(objects[i]), nm))
215 if (!strcmpi(OBJ_DESCR(objects[i]), nm)) {
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)
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.
234 && !rn2(++deferralchance))
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) */
247 There("is no such %s!", typeword);
249 pline("
\82»
\82Ì
\82æ
\82¤
\82È%s
\82Í
\82È
\82¢
\81I", typeword);
253 if (i == SCR_BLANK_PAPER || i == SPE_BLANK_PAPER) {
255 You_cant("write that!");
257 pline("
\94\92\8e\86\82É
\94\92\8e\86\82ð
\8f\91\82
\81H
\81I");
259 pline("It's obscene!");
261 pline("
\82»
\82¤
\82¢
\82¤
\82â
\82è
\82©
\82½
\82Í
\82¿
\82å
\82Á
\82Æ
\95s
\96ù
\89õ
\82¾
\82È
\81I");
263 } else if (i == SPE_BOOK_OF_THE_DEAD) {
265 pline("No mere dungeon adventurer could write that.");
267 pline("
\88ê
\89î
\82Ì
\96À
\8b{
\96`
\8c¯
\89Æ
\82É
\82Í
\8f\91\82¯
\82é
\82à
\82Ì
\82Å
\82Í
\82È
\82¢
\81D");
269 } else if (by_descr && paper->oclass == SPBOOK_CLASS
270 && !objects[i].oc_name_known) {
271 /* can't write unknown spellbooks by description */
273 pline("Unfortunately you don't have enough information to go on.");
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");
280 u.uconduct.literate++;
282 new_obj = mksobj(i, FALSE, FALSE);
283 new_obj->bknown = (paper->bknown && pen->bknown);
285 /* shk imposes a flat rate per use, not based on actual charges used */
288 /* see if there's enough ink */
289 basecost = cost(new_obj);
290 if (pen->spe < basecost / 2) {
292 Your("marker is too dry to write that!");
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);
299 /* we're really going to write now, so calculate cost
301 actualcost = rn1(basecost / 2, basecost / 2);
302 curseval = bcsign(pen) + bcsign(paper);
303 exercise(A_WIS, TRUE);
305 if (pen->spe < actualcost) {
308 Your("marker dries out!");
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) {
314 pline_The("spellbook is left unfinished and your writing fades.");
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 */
320 pline_The("scroll is now useless and disappears!");
322 pline_The("
\8aª
\95¨
\82Í
\8eg
\82¢
\82à
\82Ì
\82É
\82È
\82ç
\82È
\82
\82È
\82Á
\82Ä
\8fÁ
\96Å
\82µ
\82½
\81I");
325 obfree(new_obj, (struct obj *) 0);
328 pen->spe -= actualcost;
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.)
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.
350 * Normal requirements can be overridden if hero is Lucky.
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)) {
360 You("%s to write that.", by_descr ? "fail" : "don't know how");
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) {
367 "write in your best handwriting: \"My Diary\", but it quickly fades.");
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 */
373 Strcpy(namebuf, OBJ_DESCR(objects[new_obj->otyp]));
374 wipeout_text(namebuf, (6 + MAXULEV - u.ulevel) / 6, 0);
377 Sprintf(namebuf, "%s was here!", plname);
379 Sprintf(namebuf, "%s
\82Í
\82±
\82±
\82É
\82 \82è
\81I", plname);
381 You("write \"%s\" and the scroll disappears.", namebuf);
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);
386 obfree(new_obj, (struct obj *) 0);
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 */
398 You("fail to write the scroll correctly and it disappears.");
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");
402 obfree(new_obj, (struct obj *) 0);
406 /* useup old scroll / spellbook */
410 if (new_obj->oclass == SPBOOK_CLASS) {
411 /* acknowledge the change in the object's description... */
413 pline_The("spellbook warps strangely, then turns %s.",
414 new_book_description(new_obj->otyp, namebuf));
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));
420 new_obj->blessed = (curseval > 0);
421 new_obj->cursed = (curseval < 0);
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 */
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;
435 new_obj = hold_another_object(new_obj, "Oops! %s out of your grasp!",
436 The(aobjnam(new_obj, "slip")),
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);
443 nhUse(new_obj); /* try to avoid complaint about dead assignment */
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"!) */
455 new_book_description(booktype, outbuf)
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[] = {
467 "canvas", "hardcover", /* not used */
468 "papyrus", /* not applicable--can't be produced via writing */
472 const char *descr, *const *comp_p;
474 descr = OBJ_DESCR(objects[booktype]);
475 for (comp_p = compositions; *comp_p; ++comp_p)
476 if (!strcmpi(descr, *comp_p))
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]));