OSDN Git Service

Initial Import
[nethackexpress/trunk.git] / src / write.c
1 /*      SCCS Id: @(#)write.c    3.4     2001/11/29      */
2 /* NetHack may be freely redistributed.  See license for details. */
3
4 #include "hack.h"
5
6 STATIC_DCL int FDECL(cost,(struct obj *));
7
8 /*
9  * returns basecost of a scroll or a spellbook
10  */
11 STATIC_OVL int
12 cost(otmp)
13 register struct obj *otmp;
14 {
15
16         if (otmp->oclass == SPBOOK_CLASS)
17                 return(10 * objects[otmp->otyp].oc_level);
18
19         switch (otmp->otyp) {
20 # ifdef MAIL
21         case SCR_MAIL:
22                 return(2);
23 /*              break; */
24 # endif
25         case SCR_LIGHT:
26         case SCR_GOLD_DETECTION:
27         case SCR_FOOD_DETECTION:
28         case SCR_MAGIC_MAPPING:
29         case SCR_AMNESIA:
30         case SCR_FIRE:
31         case SCR_EARTH:
32                 return(8);
33 /*              break; */
34         case SCR_DESTROY_ARMOR:
35         case SCR_CREATE_MONSTER:
36         case SCR_PUNISHMENT:
37                 return(10);
38 /*              break; */
39         case SCR_CONFUSE_MONSTER:
40                 return(12);
41 /*              break; */
42         case SCR_IDENTIFY:
43                 return(14);
44 /*              break; */
45         case SCR_ENCHANT_ARMOR:
46         case SCR_REMOVE_CURSE:
47         case SCR_ENCHANT_WEAPON:
48         case SCR_CHARGING:
49                 return(16);
50 /*              break; */
51         case SCR_SCARE_MONSTER:
52         case SCR_STINKING_CLOUD:
53         case SCR_TAMING:
54         case SCR_TELEPORTATION:
55                 return(20);
56 /*              break; */
57         case SCR_GENOCIDE:
58                 return(30);
59 /*              break; */
60         case SCR_BLANK_PAPER:
61         default:
62                 impossible("You can't write such a weird scroll!");
63         }
64         return(1000);
65 }
66
67 static NEARDATA const char write_on[] = { SCROLL_CLASS, SPBOOK_CLASS, 0 };
68
69 int
70 dowrite(pen)
71 register struct obj *pen;
72 {
73         register struct obj *paper;
74         char namebuf[BUFSZ], *nm, *bp;
75         register struct obj *new_obj;
76         int basecost, actualcost;
77         int curseval;
78         char qbuf[QBUFSZ];
79         int first, last, i;
80         boolean by_descr = FALSE;
81         const char *typeword;
82
83         if (nohands(youmonst.data)) {
84             You("need hands to be able to write!");
85             return 0;
86         } else if (Glib) {
87             pline("%s from your %s.",
88                   Tobjnam(pen, "slip"), makeplural(body_part(FINGER)));
89             dropx(pen);
90             return 1;
91         }
92
93         /* get paper to write on */
94         paper = getobj(write_on,"write on");
95         if(!paper)
96                 return(0);
97         typeword = (paper->oclass == SPBOOK_CLASS) ? "spellbook" : "scroll";
98         if(Blind && !paper->dknown) {
99                 You("don't know if that %s is blank or not!", typeword);
100                 return(1);
101         }
102         paper->dknown = 1;
103         if(paper->otyp != SCR_BLANK_PAPER && paper->otyp != SPE_BLANK_PAPER) {
104                 pline("That %s is not blank!", typeword);
105                 exercise(A_WIS, FALSE);
106                 return(1);
107         }
108
109         /* what to write */
110         Sprintf(qbuf, "What type of %s do you want to write?", typeword);
111         getlin(qbuf, namebuf);
112         (void)mungspaces(namebuf);      /* remove any excess whitespace */
113         if(namebuf[0] == '\033' || !namebuf[0])
114                 return(1);
115         nm = namebuf;
116         if (!strncmpi(nm, "scroll ", 7)) nm += 7;
117         else if (!strncmpi(nm, "spellbook ", 10)) nm += 10;
118         if (!strncmpi(nm, "of ", 3)) nm += 3;
119
120         if ((bp = strstri(nm, " armour")) != 0) {
121                 (void)strncpy(bp, " armor ", 7);        /* won't add '\0' */
122                 (void)mungspaces(bp + 1);       /* remove the extra space */
123         }
124
125         first = bases[(int)paper->oclass];
126         last = bases[(int)paper->oclass + 1] - 1;
127         for (i = first; i <= last; i++) {
128                 /* extra shufflable descr not representing a real object */
129                 if (!OBJ_NAME(objects[i])) continue;
130
131                 if (!strcmpi(OBJ_NAME(objects[i]), nm))
132                         goto found;
133                 if (!strcmpi(OBJ_DESCR(objects[i]), nm)) {
134                         by_descr = TRUE;
135                         goto found;
136                 }
137         }
138
139         There("is no such %s!", typeword);
140         return 1;
141 found:
142
143         if (i == SCR_BLANK_PAPER || i == SPE_BLANK_PAPER) {
144                 You_cant("write that!");
145                 pline("It's obscene!");
146                 return 1;
147         } else if (i == SPE_BOOK_OF_THE_DEAD) {
148                 pline("No mere dungeon adventurer could write that.");
149                 return 1;
150         } else if (by_descr && paper->oclass == SPBOOK_CLASS &&
151                     !objects[i].oc_name_known) {
152                 /* can't write unknown spellbooks by description */
153                 pline(
154                   "Unfortunately you don't have enough information to go on.");
155                 return 1;
156         }
157
158         /* KMH, conduct */
159         u.uconduct.literate++;
160
161         new_obj = mksobj(i, FALSE, FALSE);
162         new_obj->bknown = (paper->bknown && pen->bknown);
163
164         /* shk imposes a flat rate per use, not based on actual charges used */
165         check_unpaid(pen);
166
167         /* see if there's enough ink */
168         basecost = cost(new_obj);
169         if(pen->spe < basecost/2)  {
170                 Your("marker is too dry to write that!");
171                 obfree(new_obj, (struct obj *) 0);
172                 return(1);
173         }
174
175         /* we're really going to write now, so calculate cost
176          */
177         actualcost = rn1(basecost/2,basecost/2);
178         curseval = bcsign(pen) + bcsign(paper);
179         exercise(A_WIS, TRUE);
180         /* dry out marker */
181         if (pen->spe < actualcost) {
182                 pen->spe = 0;
183                 Your("marker dries out!");
184                 /* scrolls disappear, spellbooks don't */
185                 if (paper->oclass == SPBOOK_CLASS) {
186                         pline_The(
187                        "spellbook is left unfinished and your writing fades.");
188                         update_inventory();     /* pen charges */
189                 } else {
190                         pline_The("scroll is now useless and disappears!");
191                         useup(paper);
192                 }
193                 obfree(new_obj, (struct obj *) 0);
194                 return(1);
195         }
196         pen->spe -= actualcost;
197
198         /* can't write if we don't know it - unless we're lucky */
199         if(!(objects[new_obj->otyp].oc_name_known) &&
200            !(objects[new_obj->otyp].oc_uname) &&
201            (rnl(Role_if(PM_WIZARD) ? 3 : 15))) {
202                 You("%s to write that!", by_descr ? "fail" : "don't know how");
203                 /* scrolls disappear, spellbooks don't */
204                 if (paper->oclass == SPBOOK_CLASS) {
205                         You(
206        "write in your best handwriting:  \"My Diary\", but it quickly fades.");
207                         update_inventory();     /* pen charges */
208                 } else {
209                         if (by_descr) {
210                             Strcpy(namebuf, OBJ_DESCR(objects[new_obj->otyp]));
211                             wipeout_text(namebuf, (6+MAXULEV - u.ulevel)/6, 0);
212                         } else
213                             Sprintf(namebuf, "%s was here!", plname);
214                         You("write \"%s\" and the scroll disappears.", namebuf);
215                         useup(paper);
216                 }
217                 obfree(new_obj, (struct obj *) 0);
218                 return(1);
219         }
220
221         /* useup old scroll / spellbook */
222         useup(paper);
223
224         /* success */
225         if (new_obj->oclass == SPBOOK_CLASS) {
226                 /* acknowledge the change in the object's description... */
227                 pline_The("spellbook warps strangely, then turns %s.",
228                       OBJ_DESCR(objects[new_obj->otyp]));
229         }
230         new_obj->blessed = (curseval > 0);
231         new_obj->cursed = (curseval < 0);
232 #ifdef MAIL
233         if (new_obj->otyp == SCR_MAIL) new_obj->spe = 1;
234 #endif
235         new_obj = hold_another_object(new_obj, "Oops!  %s out of your grasp!",
236                                                The(aobjnam(new_obj, "slip")),
237                                                (const char *)0);
238         return(1);
239 }
240
241 /*write.c*/