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. */
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. */
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 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 */
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;
103 char namebuf[BUFSZ], *nm, *bp;
104 register struct obj *new_obj;
105 int basecost, actualcost;
108 int first, last, i, deferred, deferralchance;
109 boolean by_descr = FALSE;
110 const char *typeword;
112 if (nohands(youmonst.data)) {
114 You("need hands to be able to write!");
116 You("
\8f\91\82
\82½
\82ß
\82É
\82Í
\8eè
\82ª
\95K
\97v
\82¾
\81I");
120 pline("%s from your %s.", Tobjnam(pen, "slip"),
121 makeplural(body_part(FINGER)));
123 pline("%s
\82ª%s
\82©
\82ç
\8a\8a\82è
\82¨
\82¿
\82½
\81D", xname(pen),
130 /* get paper to write on */
131 paper = getobj(write_on, "write on");
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" */
137 typeword = (paper->otyp == SPE_NOVEL)
139 : (paper->oclass == SPBOOK_CLASS)
143 typeword = (paper->otyp == SPE_NOVEL)
145 : (paper->oclass == SPBOOK_CLASS)
150 if (!paper->dknown) {
152 You("don't know if that %s is blank or not.", typeword);
154 You("%s
\82ª
\94\92\8e\86\82©
\82Ç
\82¤
\82©
\82í
\82©
\82ç
\82È
\82¢
\81I", typeword);
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)));
164 if (paper->otyp != SCR_BLANK_PAPER && paper->otyp != SPE_BLANK_PAPER) {
166 pline("That %s is not blank!", typeword);
168 pline("%s
\82Í
\94\92\8e\86\82¶
\82á
\82È
\82¢
\81I", typeword);
169 exercise(A_WIS, FALSE);
175 Sprintf(qbuf, "What type of %s do you want to write?", typeword);
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])
183 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
184 if (!strncmpi(nm, "scroll ", 7))
186 else if (!strncmpi(nm, "spellbook ", 10))
188 if (!strncmpi(nm, "of ", 3))
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 */
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]))
206 if (!strcmpi(OBJ_NAME(objects[i]), nm))
208 if (!strcmpi(OBJ_DESCR(objects[i]), nm)) {
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)
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.
227 && !rn2(++deferralchance))
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) */
240 There("is no such %s!", typeword);
242 pline("
\82»
\82Ì
\82æ
\82¤
\82È%s
\82Í
\82È
\82¢
\81I", typeword);
246 if (i == SCR_BLANK_PAPER || i == SPE_BLANK_PAPER) {
248 You_cant("write that!");
250 pline("
\94\92\8e\86\82É
\94\92\8e\86\82ð
\8f\91\82
\81H
\81I");
252 pline("It's obscene!");
254 pline("
\82»
\82¤
\82¢
\82¤
\82â
\82è
\82©
\82½
\82Í
\82¿
\82å
\82Á
\82Æ
\95s
\96ù
\89õ
\82¾
\82È
\81I");
256 } else if (i == SPE_BOOK_OF_THE_DEAD) {
258 pline("No mere dungeon adventurer could write that.");
260 pline("
\88ê
\89î
\82Ì
\96À
\8b{
\96`
\8c¯
\89Æ
\82É
\82Í
\8f\91\82¯
\82é
\82à
\82Ì
\82Å
\82Í
\82È
\82¢
\81D");
262 } else if (by_descr && paper->oclass == SPBOOK_CLASS
263 && !objects[i].oc_name_known) {
264 /* can't write unknown spellbooks by description */
266 pline("Unfortunately you don't have enough information to go on.");
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");
273 u.uconduct.literate++;
275 new_obj = mksobj(i, FALSE, FALSE);
276 new_obj->bknown = (paper->bknown && pen->bknown);
278 /* shk imposes a flat rate per use, not based on actual charges used */
281 /* see if there's enough ink */
282 basecost = cost(new_obj);
283 if (pen->spe < basecost / 2) {
285 Your("marker is too dry to write that!");
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);
292 /* we're really going to write now, so calculate cost
294 actualcost = rn1(basecost / 2, basecost / 2);
295 curseval = bcsign(pen) + bcsign(paper);
296 exercise(A_WIS, TRUE);
298 if (pen->spe < actualcost) {
301 Your("marker dries out!");
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) {
307 pline_The("spellbook is left unfinished and your writing fades.");
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 */
313 pline_The("scroll is now useless and disappears!");
315 pline_The("
\8aª
\95¨
\82Í
\8eg
\82¢
\82à
\82Ì
\82É
\82È
\82ç
\82È
\82
\82È
\82Á
\82Ä
\8fÁ
\96Å
\82µ
\82½
\81I");
318 obfree(new_obj, (struct obj *) 0);
321 pen->spe -= actualcost;
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.)
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.
343 * Normal requirements can be overridden if hero is Lucky.
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)) {
353 You("%s to write that.", by_descr ? "fail" : "don't know how");
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) {
360 "write in your best handwriting: \"My Diary\", but it quickly fades.");
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 */
366 Strcpy(namebuf, OBJ_DESCR(objects[new_obj->otyp]));
367 wipeout_text(namebuf, (6 + MAXULEV - u.ulevel) / 6, 0);
370 Sprintf(namebuf, "%s was here!", plname);
372 Sprintf(namebuf, "%s
\82Í
\82±
\82±
\82É
\82 \82è
\81I", plname);
374 You("write \"%s\" and the scroll disappears.", namebuf);
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);
379 obfree(new_obj, (struct obj *) 0);
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.");
392 obfree(new_obj, (struct obj *) 0);
396 /* useup old scroll / spellbook */
400 if (new_obj->oclass == SPBOOK_CLASS) {
401 /* acknowledge the change in the object's description... */
403 pline_The("spellbook warps strangely, then turns %s.",
404 new_book_description(new_obj->otyp, namebuf));
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));
410 new_obj->blessed = (curseval > 0);
411 new_obj->cursed = (curseval < 0);
413 if (new_obj->otyp == SCR_MAIL)
418 hold_another_object(new_obj, "Oops! %s out of your grasp!",
419 The(aobjnam(new_obj, "slip")), (const char *) 0);
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);
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"!) */
436 new_book_description(booktype, outbuf)
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[] = {
447 "canvas", "hardcover", /* not used */
448 "papyrus", /* not applicable--can't be produced via writing */
452 const char *descr, *const *comp_p;
454 descr = OBJ_DESCR(objects[booktype]);
455 for (comp_p = compositions; *comp_p; ++comp_p)
456 if (!strcmpi(descr, *comp_p))
459 Sprintf(outbuf, "%s%s", *comp_p ? "into " : "", descr);