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 6STATIC_DCL int FDECL(cost,(struct obj *)); 7 8/* 9 * returns basecost of a scroll or a spellbook 10 */ 11STATIC_OVL int 12cost(otmp) 13register 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 67static NEARDATA const char write_on[] = { SCROLL_CLASS, SPBOOK_CLASS, 0 }; 68 69int 70dowrite(pen) 71register 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; 141found: 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*/ 242