ftp.nice.ch/pub/next/games/strategic/NetHack.s.tar.gz#/NetHackSource/src/mail.c

This is mail.c in view mode; [Download] [Up]

/*	SCCS Id: @(#)mail.c	3.0	89/07/07
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed.  See license for details. */

/* block some unused #defines to avoid overloading some cpp's */
#define MONATTK_H
#include "hack.h"	/* mainly for index() which depends on BSD */

#ifdef MAIL
static void FDECL(mdrush,(struct monst *,int,int));
static void FDECL(mdappear,(struct monst *,BOOLEAN_P));
static void NDECL(newmail);

# ifdef UNIX
#  include <sys/stat.h>
#  include <pwd.h>
# endif
# ifdef VMS
#  include <descrip.h>
#  include <ssdef.h>
# endif

/*
 * Notify user when new mail has arrived. [Idea from Merlyn Leroy, but
 * I don't know the details of his implementation.]
 * { Later note: he disliked my calling a general mailreader and felt that
 *   hack should do the paging itself. But when I get mail, I want to put it
 *   in some folder, reply, etc. - it would be unreasonable to put all these
 *   functions in hack. }
 *
 * The mail daemon can move with less than usual restraint.  It can:
 *	- move diagonally from a door
 *	- use secret doors
 *	- run thru a monster
 *
 * Its path should be longer when you are Telepat-hic and Blind.
 *
 * Possible extensions:
 *	- Open the file MAIL and do fstat instead of stat for efficiency.
 *	  (But sh uses stat, so this cannot be too bad.)
 *	- Examine the mail and produce a scroll of mail named "From somebody".
 *	- Invoke MAILREADER in such a way that only this single letter is read.
 *	- Do something to the text when the scroll is enchanted or cancelled.
 */

/*
 * { Note by Olaf Seibert: On the Amiga, we usually don't get mail.
 *   So we go through most of the effects at 'random' moments. }
 */

/*
 * I found many bugs in this code, some dating back to Hack.
 * Here are some minor problems i didn't fix:  -3.
 *
 *	- The code sometimes pops up the mail daemon next to you on
 *	  the corridor side of doorways when there are open spaces
 *	  within the room.
 *	- It may also do this with adjoining castle rooms.
 */

#ifdef OVL0

# if !defined(UNIX) && !defined(VMS)
int mustgetmail = -1;
# endif

#endif /* OVL0 */
#ifdef OVLB

# ifdef UNIX
extern struct passwd *getpwuid();
static struct stat omstat,nmstat;
static char *mailbox = NULL;
static long laststattime;

# ifdef AMS				/* Just a placeholder for AMS */
#   define MAILPATH "/dev/null"
# else
#  ifdef BSD
#   define MAILPATH "/usr/spool/mail/"
#  endif
#  ifdef SYSV
#   define MAILPATH "/usr/mail/"
#  endif
# endif /* AMS */

void
getmailstatus() {
	if(!mailbox && !(mailbox = getenv("MAIL"))) {
#  ifdef MAILPATH
#   ifdef AMS
	        struct passwd ppasswd;

		bcopy(getpwuid(getuid()), &ppasswd, sizeof(struct passwd));
		if (ppasswd.pw_dir) {
		     mailbox = (char *) alloc((unsigned) strlen(ppasswd.pw_dir)+sizeof(AMS_MAILBOX));
		     Strcpy(mailbox, ppasswd.pw_dir);
		     Strcat(mailbox, AMS_MAILBOX);
		} else
		  return;
#   else
		mailbox = (char *) alloc(sizeof(MAILPATH)+8);
		Strcpy(mailbox, MAILPATH);
		Strcat(mailbox, getpwuid(getuid())->pw_name);
#  endif /* AMS */
#  else
		return;
#  endif
	}
	if(stat(mailbox, &omstat)){
#  ifdef PERMANENT_MAILBOX
		pline("Cannot get status of MAIL=\"%s\".", mailbox);
		mailbox = 0;
#  else
		omstat.st_mtime = 0;
#  endif
	}
}
# endif /* UNIX */

# ifdef VMS
extern unsigned long pasteboard_id;
int broadcasts = 0;
#  define getmailstatus()
# endif /* VMS */


/* make mail daemon run through the dungeon */
static void
mdrush(md,fx,fy)
struct monst *md;
register int fx, fy;	/* origin, where the '&' is displayed */
{
	register int tx = md->mx, ty = md->my;
			/* real location, where the '&' is going */

	tmp_at(-1, md->data->mlet);	/* open call */
#ifdef TEXTCOLOR
	tmp_at(-3, (int)md->data->mcolor);
#endif

	while(fx != tx || fy != ty) {
		register int dx, dy,		/* direction counters */
			     nfx = fx, nfy = fy,/* next location */ 
			     d1, d2;		/* shortest dist, eval */

		/* display the '&' at (fx,fy) */
		tmp_at(fx,fy);

		/* find location next to (fx,fy) closest to (tx,ty) */
		d1 = dist2(fx,fy,tx,ty);
		for(dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++)
		    if((dx || dy) && 
		       !IS_STWALL(levl[fx+dx][fy+dy].typ)) {
			d2 = dist2(fx+dx,fy+dy,tx,ty);
			if(d2 < d1) {
			    d1 = d2;
			    nfx = fx+dx;
			    nfy = fy+dy;
			}
		    }

		/* set (fx,fy) to next location, unless it stopped */
		if(nfx != fx || nfy != fy) {
		    fx = nfx;
		    fy = nfy;
		} else break;
	}

	tmp_at(-1,-1);			/* close call */
}

static void
mdappear(md,away)
struct monst *md;
boolean away;
{
	static int fx, fy;			/* origin */
	int tx = md->mx, ty = md->my;		/* destination */
	register int uroom = inroom(u.ux, u.uy);/* room you're in */

	/* if mail daemon is in same room as you */
	if(uroom >= 0 && inroom(md->mx,md->my) == uroom && (!Blind || Telepat))
		if(away) {
			unpmon(md);
			remove_monster(tx, ty);

			/* fake "real" location to origin */
			md->mx = fx; md->my = fy;

			/* rush from destination */
			mdrush(md,tx,ty);
			return;
		} else {
			/* choose origin */
			register int cnt = rooms[uroom].doorct;
			register int tmp = rooms[uroom].fdoor;
			register int dd = 0;

			/* which door (or staircase) is farthest? */
			while (cnt--) {
				if(dd < dist(doors[tmp].x, doors[tmp].y)) {
					fx = doors[tmp].x;
					fy = doors[tmp].y;
					dd = dist(tx,ty);
				}
				tmp++;
			}
			if (has_dnstairs(&rooms[uroom]))
				if(dd < dist(xdnstair, ydnstair)) {
					fx = xdnstair;
					fy = ydnstair;
					dd = dist(xdnstair, ydnstair);
				}
			if (has_upstairs(&rooms[uroom]))
				if(dd < dist(xupstair, yupstair)) {
					fx = xupstair;
					fy = yupstair;
				}

			/* rush from origin */
			mdrush(md,fx,fy);
		}

	pmon(md);
}

static void
newmail() {
	/* deliver a scroll of mail */
	register boolean invload =
	((inv_weight() + (int)objects[SCR_MAIL].oc_weight) > 0 ||
	 inv_cnt() >= 52 || Fumbling);
	register struct monst *md = 
	makemon(&mons[PM_MAIL_DAEMON], u.ux, u.uy);

	if(!md)	return;

	mdappear(md,FALSE);

# ifdef VMS
	pline("\"Hello, %s!  I have a message for you.\"", plname);
# else
#  ifdef NO_MAILREADER
	pline("\"Hello, %s!  You have some mail in the outside world.\"", plname);
#  else
	pline("\"Hello, %s!  I have some mail for you.\"", plname);
# endif
# endif

# ifndef NO_MAILREADER
	if(dist(md->mx,md->my) > 2)
		verbalize("Catch!");
	more();
	if(invload) {
		struct obj *obj = mksobj_at(SCR_MAIL,u.ux,u.uy);
		obj->known = obj->dknown = TRUE;
		makeknown(SCR_MAIL);
		stackobj(fobj);		
		verbalize("Oops!");
	} else {
		/* set known and do prinv() */
		(void) identify(addinv(mksobj(SCR_MAIL,FALSE)));
	}

	/* disappear again */
	mdappear(md,TRUE);
	mongone(md);

	/* force the graphics character set off */
	nscr();
# ifdef VMS
	broadcasts--;
# endif
# endif /* NO_MAILREADER */
}

#endif /* OVLB */

# if !defined(UNIX) && !defined(VMS)

#ifdef OVL0

void
ckmailstatus() {
	if (mustgetmail < 0)
	    return;
	if (--mustgetmail <= 0) {
		newmail();
		mustgetmail = -1;
	}
}

#endif /* OVL0 */
#ifdef OVLB

void
readmail()
{
	pline("It says:  \"Please disregard previous letter.\"");
}

#endif /* OVLB */

# endif /* !UNIX && !VMS */

# ifdef UNIX

#ifdef OVL0

void
ckmailstatus() {
	if(!mailbox
#  ifdef MAILCKFREQ
		    || moves < laststattime + MAILCKFREQ
#  endif
							)
		return;

	laststattime = moves;
	if(stat(mailbox, &nmstat)){
#  ifdef PERMANENT_MAILBOX
		pline("Cannot get status of MAIL=\"%s\" anymore.", mailbox);
		mailbox = 0;
#  else
		nmstat.st_mtime = 0;
#  endif
	} else if(nmstat.st_mtime > omstat.st_mtime) {
		if(nmstat.st_size)
			newmail();
		getmailstatus();	/* might be too late ... */
	}
}

#endif /* OVL0 */
#ifdef OVLB

void
readmail() {
#  ifdef DEF_MAILREADER			/* This implies that UNIX is defined */
	register char *mr = 0;
	more();
	if(!(mr = getenv("MAILREADER")))
		mr = DEF_MAILREADER;
	if(child(1)){
		(void) execl(mr, mr, NULL);
		exit(1);
	}
#  else
#   ifndef AMS  			/* AMS mailboxes are directories */
	(void) page_file(mailbox, FALSE);
#   endif /* AMS */
#  endif /* DEF_MAILREADER */

	/* get new stat; not entirely correct: there is a small time
	   window where we do not see new mail */
	getmailstatus();
}

#endif /* OVLB */

# endif /* UNIX */

# ifdef VMS

#ifdef OVL0

void
ckmailstatus()
{
	if (broadcasts)
		newmail();
}

#endif /* OVL0 */
#ifdef OVLB

void
readmail()
{
	char buf[16384];	/* $BRKTHRU limits messages to 16350 bytes */
	$DESCRIPTOR(message, buf);
	short length;

	if (SMG$GET_BROADCAST_MESSAGE(&pasteboard_id, &message, &length)
	    == SS$_NORMAL && length != 0) {
		buf[length] = '\0';
		pline("%s", buf);
	}
}
# endif /* VMS */

#endif /* OVLB */

#endif /* MAIL */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.