Source:NetHack 3.0.0/mail.c

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

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

1.   /*	SCCS Id: @(#)mail.c	3.0	89/07/07 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    /* block some unused #defines to avoid overloading some cpp's */ 6.   #define MONATTK_H 7.   #include "hack.h"	/* mainly for index which depends on BSD */ 8.    9.    #ifdef MAIL 10.   11.   # ifdef UNIX 12.  #include   13. # endif 14.   15.   /*  16.    * Notify user when new mail has arrived. [Idea from Merlyn Leroy, but 17.   * I don't know the details of his implementation.] 18.   * { Later note: he disliked my calling a general mailreader and felt that 19.   *   hack should do the paging itself. But when I get mail, I want to put it 20. *  in some folder, reply, etc. - it would be unreasonable to put all these 21.   *   functions in hack. } 22.    * The motion of the mail daemon is less restrained than usual: 23.   * diagonal moves from a DOOR are possible. He might also use SDOOR's. Also, 24.   * the mail daemon is visible in a ROOM, even when you are Blind. 25.   * Its path should be longer when you are Telepat-hic and Blind. 26.   *  27.    * Possible extensions: 28.   *	- Open the file MAIL and do fstat instead of stat for efficiency. 29.   *	  (But sh uses stat, so this cannot be too bad.) 30.   *	- Examine the mail and produce a scroll of mail named "From somebody". 31.   *	- Invoke MAILREADER in such a way that only this single letter is read. 32.   *	- Do something to the text when the scroll is enchanted or cancelled. 33.   */  34.    35.   /*  36.    * { Note by Olaf Seibert: On the Amiga, we usually don't get mail. 37.   *   So we go through most of the effects at 'random' moments. } 38.    */  39.    40.   /*  41.    * I found many bugs in this code, some dating back to Hack. 42.   * Here are some minor problems i didn't fix:  -3. 43.   *  44.    *	- The code sometimes pops up the mail daemon next to you on  45. *	 the corridor side of doorways when there are open spaces in  46. *	 the room. 47.   *	- It may also do this with adjoining castle rooms. 48.   */  49.    50.   # ifdef AMIGA 51.  int mustgetmail = -1; 52.  # endif 53.   54.   # ifdef UNIX 55.  static struct stat omstat,nmstat; 56.  static char *mailbox; 57.  static long laststattime; 58.   59.   void 60.  getmailstatus { 61.  	if(!(mailbox = getenv("MAIL"))) 62.  		return; 63.  	if(stat(mailbox, &omstat)){ 64.  #  ifdef PERMANENT_MAILBOX 65.  		pline("Cannot get status of MAIL=%s .", mailbox); 66.  		mailbox = 0; 67.  #  else 68.  		omstat.st_mtime = 0; 69.  #  endif 70.  	}  71.   }  72.   # endif /* UNIX */ 73.   74.   /* make md run through the cave */ 75.  static void 76.  mdrush(md,away) 77.  register struct monst *md; 78.  boolean away; 79.  {  80.   	register int uroom = inroom(u.ux, u.uy); 81.  	if(uroom >= 0 && inroom(md->mx,md->my) == uroom) { 82.  		register int tmp = rooms[uroom].fdoor; 83.  		register int cnt = rooms[uroom].doorct; 84.  		register int fx = u.ux, fy = u.uy; 85.  		while(cnt--) { 86.  			if(dist(fx,fy) < dist(doors[tmp].x, doors[tmp].y)){ 87.  				fx = doors[tmp].x;  88. fy = doors[tmp].y; 89. } 90.   			tmp++; 91.  		}  92.   		if (has_dnstairs(&rooms[uroom])) 93.  			if(dist(fx,fy) < dist(xdnstair, ydnstair)){ 94.  				fx = xdnstair; 95.  				fy = ydnstair; 96.  			}  97.   		if (has_upstairs(&rooms[uroom])) 98.  			if(dist(fx,fy) < dist(xupstair, yupstair)){ 99.  				fx = xupstair; 100. 				fy = yupstair; 101. 			}  102.  		tmp_at(-1, md->data->mlet);	/* open call */ 103. 		tmp_at(-3, (int)AT_MON); 104. 		if(away) {	/* interchange origin and destination */ 105. 			unpmon(md); 106. 			levl[md->mx][md->my].mmask = 0; 107. 			levl[fx][fy].mmask = 1; 108. 			tmp = fx; fx = md->mx; md->mx = tmp; 109. 			tmp = fy; fy = md->my; md->my = tmp; 110. 		}  111.  		while(fx != md->mx || fy != md->my) { 112. 			register int dx,dy,nfx = fx,nfy = fy,d1,d2; 113.  114.  			tmp_at(fx,fy); 115. 			d1 = dist2(fx,fy,md->mx,md->my); 116. 			for(dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++) 117. 			    if((dx || dy) &&  118.  			       !IS_STWALL(levl[fx+dx][fy+dy].typ)) { 119. 				d2 = dist2(fx+dx,fy+dy,md->mx,md->my); 120. 				if(d2 < d1) { 121. 				    d1 = d2; 122. 				    nfx = fx+dx; 123. 				    nfy = fy+dy; 124. 				}  125.  			    }  126.  			if(nfx != fx || nfy != fy) { 127. 			    fx = nfx; 128. 			    fy = nfy; 129. 			} else { 130. 			    if(!away) { 131. 				levl[md->mx][md->my].mmask = 0; 132. 				levl[fx][fy].mmask = 1; 133. 				md->mx = fx; 134. 				md->my = fy; 135. 			    }  136.  			    break; 137. 			}  138.  		}  139.  		tmp_at(-1,-1);			/* close call */ 140. 	}  141.  	if(!away) 142. 		pmon(md); 143. }  144.   145.  static void 146. newmail { 147. 	/* deliver a scroll of mail */ 148. 	register boolean invload = 149. 	((inv_weight + (int)objects[SCR_MAIL].oc_weight) > 0 ||  150.  	 inv_cnt >= 52 || Fumbling); 151. 	register struct monst *md = 152. 	makemon(&mons[PM_MAIL_DAEMON], u.ux, u.uy); 153.  154.  	if(!md)	return; 155.  156.  	mdrush(md,0); 157.  158.  	pline("\"Hello, %s!  I have some mail for you.\"", plname); 159.  160.  	if(dist(md->mx,md->my) > 2) 161. 		verbalize("Catch!"); 162. 	more; 163. 	if(invload) { 164. 		struct obj *obj = mksobj_at(SCR_MAIL,u.ux,u.uy); 165. 		obj->known = obj->dknown = TRUE; 166. 		makeknown(SCR_MAIL); 167. 		stackobj(fobj); 168. 		verbalize("Oops!"); 169. 		more; 170. 	} else { 171. 		/* set known and do prinv */ 172. 		(void) identify(addinv(mksobj(SCR_MAIL,FALSE))); 173. 	}  174.   175.  	/* disappear again */ 176. 	mdrush(md,1); 177. 	mongone(md); 178.  179.  	/* force the graphics character set off */ 180. 	nscr; 181. }  182.   183.  # ifdef AMIGA 184. void 185. ckmailstatus { 186. 	if (mustgetmail < 0) 187. 	    return; 188. 	if (--mustgetmail <= 0) { 189. 		newmail; 190. 		mustgetmail = -1; 191. 	}  192.  }  193.   194.  void 195. readmail 196. {  197.  	pline("It says: \"How nice to get a letter down here!\""); 198. }  199.  # endif /* AMIGA */ 200.  201.  # ifdef UNIX 202. void 203. ckmailstatus { 204. 	if(!mailbox  205.  #  ifdef MAILCKFREQ  206.  		    || moves < laststattime + MAILCKFREQ  207.  #  endif  208.  							) 209. 		return; 210.  211.  	laststattime = moves; 212. 	if(stat(mailbox, &nmstat)){ 213. #  ifdef PERMANENT_MAILBOX 214. 		pline("Cannot get status of MAIL=%s anymore.", mailbox); 215. 		mailbox = 0; 216. #  else 217. 		nmstat.st_mtime = 0; 218. #  endif 219. 	} else if(nmstat.st_mtime > omstat.st_mtime) { 220. 		if(nmstat.st_size) 221. 			newmail; 222. 		getmailstatus;	/* might be too late ... */ 223.  	}  224.  }  225.   226.  void 227. readmail { 228. #  ifdef DEF_MAILREADER			/* This implies that UNIX is defined */ 229. 	register char *mr = 0; 230. 	more; 231. 	if(!(mr = getenv("MAILREADER"))) 232. 		mr = DEF_MAILREADER; 233. 	if(child(1)){ 234. 		(void) execl(mr, mr, NULL); 235. 		exit(1); 236. 	}  237.  #  else 238. 	(void) page_file(mailbox, FALSE); 239. #  endif 240. 	/* get new stat; not entirely correct: there is a small time 241. 	   window where we do not see new mail */ 242. 	getmailstatus; 243. }  244.  # endif /* UNIX */ 245.  246.  #endif /* MAIL */