Below is the full text to src/write.c from NetHack 3.4.3. To link to a particular line, write [[write.c#line123]], for example.
Top of file[]
1. /* SCCS Id: @(#)write.c 3.4 2001/11/29 */ 2. /* NetHack may be freely redistributed. See license for details. */ 3.
| The NetHack General Public License applies to screenshots, source code and other content from NetHack. |
4. #include "hack.h" 5. 6. STATIC_DCL int FDECL(cost,(struct obj *)); 7.
cost[]
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.
dowrite[]
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*/