Source:NetHack 3.4.0/write.c

Below is the full text to write.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/write.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

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.  	    dropx(pen); 88.  	    pline("%s from your %s.",  89.   		  Tobjnam(pen, "slip"), makeplural(body_part(FINGER))); 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*/