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 */
159 pline("%s can't create braille text.",
161 pline("%s
\82Å
\82Í
\93_
\8e\9a\82ð
\8dì
\82ê
\82È
\82¢
\81D",
162 upstart(ysimple_name(pen)));
167 if (paper->otyp != SCR_BLANK_PAPER && paper->otyp != SPE_BLANK_PAPER) {
169 pline("That %s is not blank!", typeword);
171 pline("%s
\82Í
\94\92\8e\86\82¶
\82á
\82È
\82¢
\81I", typeword);
172 exercise(A_WIS, FALSE);
178 Sprintf(qbuf, "What type of %s do you want to write?", typeword);
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])
186 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
187 if (!strncmpi(nm, "scroll ", 7))
189 else if (!strncmpi(nm, "spellbook ", 10))
191 if (!strncmpi(nm, "of ", 3))
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 */
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]))
209 if (!strcmpi(OBJ_NAME(objects[i]), nm))
211 if (!strcmpi(OBJ_DESCR(objects[i]), nm)) {
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)
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.
230 && !rn2(++deferralchance))
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) */
243 There("is no such %s!", typeword);
245 pline("
\82»
\82Ì
\82æ
\82¤
\82È%s
\82Í
\82È
\82¢
\81I", typeword);
249 if (i == SCR_BLANK_PAPER || i == SPE_BLANK_PAPER) {
251 You_cant("write that!");
253 pline("
\94\92\8e\86\82É
\94\92\8e\86\82ð
\8f\91\82
\81H
\81I");
255 pline("It's obscene!");
257 pline("
\82»
\82¤
\82¢
\82¤
\82â
\82è
\82©
\82½
\82Í
\82¿
\82å
\82Á
\82Æ
\95s
\96ù
\89õ
\82¾
\82È
\81I");
259 } else if (i == SPE_BOOK_OF_THE_DEAD) {
261 pline("No mere dungeon adventurer could write that.");
263 pline("
\88ê
\89î
\82Ì
\96À
\8b{
\96`
\8c¯
\89Æ
\82É
\82Í
\8f\91\82¯
\82é
\82à
\82Ì
\82Å
\82Í
\82È
\82¢
\81D");
265 } else if (by_descr && paper->oclass == SPBOOK_CLASS
266 && !objects[i].oc_name_known) {
267 /* can't write unknown spellbooks by description */
269 pline("Unfortunately you don't have enough information to go on.");
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");
276 u.uconduct.literate++;
278 new_obj = mksobj(i, FALSE, FALSE);
279 new_obj->bknown = (paper->bknown && pen->bknown);
281 /* shk imposes a flat rate per use, not based on actual charges used */
284 /* see if there's enough ink */
285 basecost = cost(new_obj);
286 if (pen->spe < basecost / 2) {
288 Your("marker is too dry to write that!");
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);
295 /* we're really going to write now, so calculate cost
297 actualcost = rn1(basecost / 2, basecost / 2);
298 curseval = bcsign(pen) + bcsign(paper);
299 exercise(A_WIS, TRUE);
301 if (pen->spe < actualcost) {
304 Your("marker dries out!");
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) {
310 pline_The("spellbook is left unfinished and your writing fades.");
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 */
316 pline_The("scroll is now useless and disappears!");
318 pline_The("
\8aª
\95¨
\82Í
\8eg
\82¢
\82à
\82Ì
\82É
\82È
\82ç
\82È
\82
\82È
\82Á
\82Ä
\8fÁ
\96Å
\82µ
\82½
\81I");
321 obfree(new_obj, (struct obj *) 0);
324 pen->spe -= actualcost;
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.)
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.
346 * Normal requirements can be overridden if hero is Lucky.
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)) {
356 You("%s to write that.", by_descr ? "fail" : "don't know how");
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) {
363 "write in your best handwriting: \"My Diary\", but it quickly fades.");
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 */
369 Strcpy(namebuf, OBJ_DESCR(objects[new_obj->otyp]));
370 wipeout_text(namebuf, (6 + MAXULEV - u.ulevel) / 6, 0);
373 Sprintf(namebuf, "%s was here!", plname);
375 Sprintf(namebuf, "%s
\82Í
\82±
\82±
\82É
\82 \82è
\81I", plname);
377 You("write \"%s\" and the scroll disappears.", namebuf);
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);
382 obfree(new_obj, (struct obj *) 0);
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 */
394 You("fail to write the scroll correctly and it disappears.");
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");
398 obfree(new_obj, (struct obj *) 0);
402 /* useup old scroll / spellbook */
406 if (new_obj->oclass == SPBOOK_CLASS) {
407 /* acknowledge the change in the object's description... */
409 pline_The("spellbook warps strangely, then turns %s.",
410 new_book_description(new_obj->otyp, namebuf));
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));
416 new_obj->blessed = (curseval > 0);
417 new_obj->cursed = (curseval < 0);
419 if (new_obj->otyp == SCR_MAIL)
424 hold_another_object(new_obj, "Oops! %s out of your grasp!",
425 The(aobjnam(new_obj, "slip")), (const char *) 0);
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);
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"!) */
442 new_book_description(booktype, outbuf)
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[] = {
454 "canvas", "hardcover", /* not used */
455 "papyrus", /* not applicable--can't be produced via writing */
459 const char *descr, *const *comp_p;
461 descr = OBJ_DESCR(objects[booktype]);
462 for (comp_p = compositions; *comp_p; ++comp_p)
463 if (!strcmpi(descr, *comp_p))
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]));