mcgrew@aramis.rutgers.edu (Charles Mcgrew) (05/06/89)
Submitted-by: kent@wsl.dec.com Posting-number: Volume 1, Issue 2 Archive-name: mazewar/part03 #!/bin/sh sed 's/^X//' >./init.c << 'xxFUNNYxx' X/* $Header: init.c,v 1.13 88/09/07 14:37:21 kent Exp $ */ X X/* X * init.c - Initialization code for mazewar X * X * Author: Christopher A. Kent X * Western Research Laboratory X * Digital Equipment Corporation X * Date: Thu Oct 2 1986 X */ X X/*********************************************************** XCopyright 1986 by Digital Equipment Corporation, Maynard, Massachusetts, X X All Rights Reserved X XPermission to use, copy, modify, and distribute this software and its Xdocumentation for any purpose and without fee is hereby granted, Xprovided that the above copyright notice appear in all copies and that Xboth that copyright notice and this permission notice appear in Xsupporting documentation, and that the names of Digital not be Xused in advertising or publicity pertaining to disstribution of the Xsoftware without specific, written prior permission. X XDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL XDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS XSOFTWARE. X X******************************************************************/ X X/* X * $Log: init.c,v $ X * Revision 1.13 88/09/07 14:37:21 kent X * Portability changes for broadcasts. X * X * Revision 1.12 88/08/25 09:57:53 kent X * Copyright and changed to allow the broadcast address to be set in Makefile. X * X * Revision 1.11 88/06/15 16:36:31 kent X * Updated to use proper broadcast address. X * X * Revision 1.10 87/07/28 13:51:16 kent X * Fixed a problem in netInit(); didn't handle the case when gethostname() X * returned something that couldn't be found in the host table. X * X * Revision 1.9 87/03/31 14:42:14 kent X * Portability considerations, especially byteswapping to/from the net. X * X * Revision 1.8 86/12/04 17:48:05 kent X * findDuke's return value pointed to something on the stack! X * X * Revision 1.7 86/12/04 11:16:54 kent X * Handle name case when there's no comma in the gecos field. X * X * Revision 1.6 86/12/04 11:14:23 kent X * Clean up join, so you can specify any host in a game, not just the duke. X * X * Revision 1.5 86/12/03 13:31:25 kent X * X * X * Revision 1.4 86/12/03 10:00:45 kent X * Changes to allow multiple players per machine. X * X * Revision 1.3 86/12/01 23:44:25 kent X * Housecleaning and documentation pass. X * X * Revision 1.2 86/12/01 14:48:17 kent X * Changes for a realistic implementation of shooting. X * X * Revision 1.1 86/11/26 16:57:42 kent X * Initial revision X * X */ X X#ifndef lint Xstatic char rcs_ident[] = "$Header: init.c,v 1.13 88/09/07 14:37:21 kent Exp $"; X#endif X X#include <sys/types.h> X#include <sys/socket.h> X#include <sys/time.h> X X#include <netinet/in.h> X X#include <errno.h> X#include <netdb.h> X#include <pwd.h> X#include <stdio.h> X#include <strings.h> X X#include "mazewar.h" X Xint RV[VECTORSIZE] = { X 0031575, 0055455, 0147160, 0176745, 0173126, 0117426, 0033612, 0136020, X 0054013, 0167672, 0070252, 0033100, 0015700, 0113523, 0170465, 0024344, X 0175535, 0137325, 0126211, 0010207, 0173547, 0016071, 0056622, 0014433, X 0113225, 0047553, 0103024, 0110174, 0000124, 0173304, 0076700, 0104042, X 0135030, 0126234, 0175154, 0140123, 0167542, 0000405, 0035464, 0166537, X 0050260, 0167655, 0123715, 0176164, 0172206, 0140365, 0074606, 0075656, X 0176163, 0030017, 0022102, 0040051, 0154620, 0017144, 0073372 X}; X Xstatic MazeType mazeBits = { X { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, /* 0 */ X { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, X { 1,0,1,1,1,1,1,0,1,1,1,1,0,1,1,1}, X { 1,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1}, X X { 1,0,1,0,1,0,0,0,1,0,1,1,1,1,0,1}, /* 1 */ X { 1,0,1,1,1,0,1,0,1,0,1,0,0,0,0,1}, X { 1,0,0,0,0,0,1,0,0,0,1,0,1,1,0,1}, X { 1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1}, X X { 1,0,0,0,0,0,0,0,1,0,1,1,1,1,0,1}, /* 2 */ X { 1,0,1,1,1,1,1,0,1,0,1,0,0,0,0,1}, X { 1,0,0,0,0,0,1,0,0,0,1,0,1,1,1,1}, X { 1,0,1,1,1,0,1,0,1,0,1,0,0,0,0,1}, X X { 1,0,0,0,0,0,1,0,1,0,1,1,1,1,0,1}, /* 3 */ X { 1,0,1,1,1,1,1,0,1,0,1,1,0,1,0,1}, X { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, X { 1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,1}, X X { 1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1}, /* 4 */ X { 1,1,1,0,1,0,1,0,1,0,1,0,1,1,0,1}, X { 1,0,0,0,1,0,1,0,1,0,1,0,0,1,0,1}, X { 1,0,1,1,1,0,1,0,1,0,1,1,0,0,0,1}, X X { 1,0,0,0,0,0,0,0,1,0,1,0,0,1,0,1}, /* 5 */ X { 1,0,1,1,1,1,1,1,1,0,1,0,1,1,0,1}, X { 1,0,0,0,1,0,0,0,1,0,1,0,0,1,0,1}, X { 1,0,1,0,1,0,1,0,1,0,1,1,0,0,0,1}, X X { 1,0,1,0,1,0,1,0,1,0,0,0,0,1,0,1}, /* 6 */ X { 1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1}, X { 1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,1}, X { 1,0,1,0,0,0,1,0,1,0,1,1,0,1,0,1}, X X { 1,0,1,0,1,0,1,0,0,0,1,0,0,0,0,1}, /* 7 */ X { 1,0,1,0,1,0,1,0,1,0,1,1,1,1,0,1}, X { 1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,1}, X { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} X}; X Xstatic char *ratName = NULL; Xstatic char *dukeName = NULL; Xstatic Sockaddr dukeAddr; X XSockaddr *resolveHost(); X Xextern int errno; X XMazeInit(argc, argv) Xchar **argv; X{ X register RatId ratId; X X for (ratId = 0; ratId < MAXRATS; ratId++) { X bzero((char *) M.ratcb.rats[ratId].name, NAMESIZE); X M.ratcb.rats[ratId].playing = FALSE; X R2d2[ratId].visible = FALSE; X } X M.invincible = FALSE; X M.omniscient = FALSE; X RatKillQ = (RatKillQ_t) NULL; X X getMaze(); X X setRandom(); X InitRandom(); X X InitDisplay(argc, argv); X getNames(); X NewPosition(); X X /* X * We don't do ShowPosition() or ShowView() here, but let the update X * routine in the window handler do it for the first time when X * the window is exposed. X */ X X netInit(); X StartDisplay(); X RatCursor(); X} X X/* get the maze into memory */ XgetMaze() X{ X int i, j; X X for (i = 0; i < MAZEXMAX; i++) X for (j = 0; j < MAZEYMAX; j++) X if (mazeBits[i].y[MAZEYMAX-1 - j] == 1) X M.maze[i].y[j] = TRUE; X else X M.maze[i].y[j] = FALSE; X} X X/* initialize the random vector */ XsetRandom() X{ X register i; X X for (i = 0; i < VECTORSIZE; i++) X M.randomVector[i] = RV[i]; X} X X/* get player and duke host names */ XgetNames() X{ X char buf[128], *cp; X char *comma; X Sockaddr *duke; X char *getenv(); X struct passwd *getpwuid(); X X buf[0] = '\0'; X printf("Welcome to Alto MazeWar!\n\n"); X printf("Your Name: "); X gets(buf); X if (buf[0] == '\0') { X if ((cp = getenv("USERNAME")) != NULL) X strcpy(buf, cp); X else { X strcpy(buf, (getpwuid(getuid()))->pw_gecos); X comma = index(buf, ','); X if (comma != NULL) X *comma = '\0'; X } X } X ratName = malloc((unsigned) (strlen(buf) + 1)); X if (ratName == NULL) X MWError("no mem for ratName"); X strcpy(ratName, buf); X for (duke = NULL; duke == NULL; ) { X#ifndef NO_BROADCAST X printf("Duke Host (CR for any game): "); X#else X printf("Duke Host: "); X#endif NO_BROADCAST X gets(buf); X if (strlen(buf) == 0) X break; X dukeName = malloc((unsigned) (strlen(buf) + 1)); X if (dukeName == NULL) X MWError("no mem for dukeName"); X strcpy(dukeName, buf); X X /* check for valid duke name */ X duke = resolveHost(dukeName); X if (duke == (Sockaddr *) NULL) { X printf("Don't know host %s\n", dukeName); X free(dukeName); X dukeName = NULL; X } X } X if ((dukeName != NULL) && X (strlen(dukeName) != 0)) X bcopy((char *) duke, (char *) &dukeAddr, sizeof(Sockaddr)); X} X XnetInit() X{ X register RatId ratId; X Boolean joinGame(); X struct servent *mazeService; X u_short port; X Sockaddr nullAddr; X Sockaddr *thisHost; X char buf[128]; X X mazeService = getservbyname(MAZESERVICE, "udp"); X if (mazeService != (struct servent *) NULL) X M.mazePort = mazeService->s_port; X else X M.mazePort = htons(MAZEPORT); X X gethostname(buf, sizeof(buf)); X if ((thisHost = resolveHost(buf)) == (Sockaddr *) NULL) X MWError("who am I?"); X bcopy((caddr_t) thisHost, (caddr_t) &M.myAddr, sizeof(Sockaddr)); X nullAddr = M.myAddr; X bzero((char *)&nullAddr.sin_addr, sizeof(nullAddr.sin_addr)); X X /* X * Figure out which port I can use. Start at MAZEPORT and go X * up till there's a free one. We use nullAddr so that we X * can receive any incoming packet, in case there's some X * multi-homed nonsense. However, not binding may cause troubles X * if a specified duke is on a net that causes the source of the X * packets to be something other than what M.myAddr is... X * There also seems to be a problem with broadcasts not being X * accepted on sockets that have an address bound to them. X */ X X M.theSocket = socket(AF_INET, SOCK_DGRAM, 0); X if (M.theSocket < 0) X MWError("can't get socket"); X X for (port = ntohs(M.mazePort); ; port++) { X nullAddr.sin_port = htons(port); X if (bind(M.theSocket, &nullAddr, sizeof(nullAddr)) < 0) X if (errno != EADDRINUSE) X MWError("netInit binding"); X else X continue; X else X break; X } X M.myAddr.sin_port = nullAddr.sin_port; X X /* X * Now we can try to find a game to join; if none, start one. X */ X X if (!joinGame()) X startGame(); X printf("\n"); X X for (ratId = 0; ratId < MAXRATS; ratId++) X TokenVisible(ratId); /* oh oh say can we see? */ X X} X X/* X * Find a game. If the user specified a "duke" host, contact that X * duke. Otherwise broadcast to find a duke. Finally join that game. X */ X XBoolean XjoinGame() X{ X Sockaddr *duke, *findDuke(); X Boolean join(); X X if ((dukeName == NULL) || X (strlen(dukeName) == 0)) { X duke = findDuke(); X if (duke != NULL) X bcopy((char *) duke, (char *) &dukeAddr, X sizeof(Sockaddr)); X else X return FALSE; X } else X dukeAddr.sin_port = M.mazePort; X return join(dukeAddr); X} X X/* X * No game to join; set ourselves up as duke and wait for others to join. X */ X XstartGame() X{ X RatId i; X RatInfo rsp; X X printf("starting a new game"); X M.myRatId = 0; X M.score = 0; X SetMyRatId(0); X M.ratcb.dukeRat = M.myRatId; X M.ratcb.rats[M.myRatId].addr = M.myAddr; X rsp = &M.ratcb.rats[M.myRatId]; X rsp->playing = TRUE; X rsp->xLoc = M.xloc; X rsp->yLoc = M.yloc; X rsp->dir = M.dir; X rsp->score = M.score; X rsp->addr = M.myAddr; X strncpy(rsp->name, ratName, NAMESIZE); X for (i = 1; i < MAXRATS; i++) X M.ratcb.rats[i].playing = FALSE; X M.duke = TRUE; X} X X/* X * Join an existing game. Send a RAT_NEW packet and wait for a X * RAT_STATUS packet to come back with the other players. X */ X XBoolean Xjoin(addr) XSockaddr addr; X{ X RatPacket b, r; X RatNew ratNew; X RatId id; X RatStatus status; X int i, ret; X int fds; X struct timeval timeout; X Boolean retVal = FALSE; X X b.type = RAT_NEW; X ratNew = (RatNew) &b.body; X ratNew->pass = RAT_PASSWORD; X ratNew->xLoc = M.xloc; X ratNew->yLoc = M.yloc; X ratNew->dir = M.dir; X ratNew->addr = M.myAddr; X strncpy(ratNew->name, ratName, NAMESIZE); X free(ratName); X ConvertOutgoing(&b); X X for (i = 0; i < 5; i++) { X int fromlen; X struct sockaddr from; X X if (sendto(M.theSocket, (char *) &b, sizeof(b), 0, &addr, X sizeof(addr)) < 0) X MWError("join sendto"); X fds = (1<<M.theSocket); X timeout.tv_sec = 5; X timeout.tv_usec = 0; X ret = select(32, &fds, NULL, NULL, &timeout); X if (ret < 0) X MWError("join select"); X if (ret == 0) X continue; X if (recvfrom(M.theSocket, (char *) &r, sizeof(r), X 0, &from, &fromlen) < 0) X MWError("join status receive"); X ConvertIncoming(&r); X if (r.type != RAT_STATUS) X continue; X X /* see if I got into the game */ X status = &r.body; X for (id = 0; id < MAXRATS; id++) X if (status->rats[id].playing && X !bcmp(&status->rats[id].addr, &M.myAddr, X sizeof(M.myAddr))) { X M.myRatId = id; X break; X } X X /* X * Didn't find me; this guy must not really be the X * duke. Contact the duke of the game and get added. X */ X X if (id == MAXRATS) { X addr = status->rats[status->dukeRat].addr; X continue; X } X X bcopy((char *) status, (char *) &M.ratcb, sizeof(RatCb)); X retVal = TRUE; X break; X } X return retVal; X} X X/* X * Find a "duke" host. Broadcast a RAT_SURVEY packet to MAZEPORT. X * X * The broadcast is done just on the network that is associated X * with the name returned by gethostname(); for most workstations X * this is accurate, but multi-homed hosts may miss some games. Oh X * well. X * X * After the broadcast, collect responses. This goes on until no packets X * have been received for 5 seconds or the max number have been seen X * X * All players are supposed to respond. If a packet comes from a non-duke, X * the information is inspected to send a RAT_SURVEY directly to him. X * Otherwise, the answer is saved. When all the answers are in, the X * first game with an empty slot is chosen. X * X * If all players were listening on MAZEPORT, we could probably do X * without the resending nonsense. Since the duke might not be on X * MAZEPORT, this is necessary. It also adds a certain robustness, in X * case the duke drops the packet or somesuch. Care is taken elsewhere X * (ratLeft() and ratDoctor())to make sure there are always players X * listening on MAZEPORT. X */ X Xstruct answer { X Sockaddr source; X int srclen; X RatPacket packet; X}; X XSockaddr * XfindDuke() X{ X#ifndef NO_BROADCAST X register int i; X int cnt = 0; X int maxAnswers = 10; X static Sockaddr rmtAddr; X struct timeval timeout; X RatPacket *b = (RatPacket *) malloc(sizeof(RatPacket)); X struct answer *answers; X int fds, fd = M.theSocket; X int ret, cc; X Boolean duke(), freeSlot(); X struct in_addr inet_makeaddr(); X X printf("Checking out available games..."); fflush(stdout); X X#ifdef SO_BROADCAST X#ifdef BSD_43 X { X int one = 1; X X if (setsockopt(M.theSocket, SOL_SOCKET, SO_BROADCAST, X &one, sizeof one) < 0) X MWError("can't get broadcast permission"); X } X#else BSD_43 X if (setsockopt(M.theSocket, SOL_SOCKET, SO_BROADCAST, NULL, 0) < 0) X MWError("can't get broadcast permission"); X#endif BSD_43 X#endif SO_BROADCAST X X rmtAddr = M.myAddr; X rmtAddr.sin_addr = inet_makeaddr(inet_netof(M.myAddr.sin_addr), X BROAD_ADDR); /* from Makefile */ X rmtAddr.sin_port = M.mazePort; X X answers = (struct answer *) X malloc((unsigned) (maxAnswers * sizeof(*answers))); X X setupSurvey(b); X ConvertOutgoing(b); X if (sendto(fd, (char *) b, sizeof(*b), 0, &rmtAddr, sizeof(rmtAddr)) < 0) X fprintf(stderr, "findDuke survey can't broadcast\n"); X X while (1) { X fds = (1<<fd); X timeout.tv_sec = 5; X timeout.tv_usec = 0; X ret = select(32, &fds, NULL, NULL, &timeout); X if (ret < 0) X MWError("findDuke select"); X if (ret == 0) X break; X answers[cnt].srclen = sizeof(Sockaddr); X if (recvfrom(fd, &answers[cnt].packet, sizeof(RatPacket), 0, X &answers[cnt].source, &answers[cnt].srclen) < 0) X MWError("findDuke recv"); X ConvertIncoming(&answers[cnt].packet); X if (answers[cnt].packet.type != RAT_STATUS) X continue; X if (!duke(&answers[cnt])) { X RatStatus rs; X X rs = (RatStatus) &answers[cnt].packet.body; X setupSurvey(b); X ConvertOutgoing(b); X if (sendto(fd, b, sizeof(*b), 0, X &rs->rats[rs->dukeRat].addr, X sizeof(rs->rats[rs->dukeRat].addr)) < 0) X fprintf(stderr, X "findDuke resend can't broadcast"); X continue; X } X if (freeSlot(&answers[cnt])) X if (++cnt == maxAnswers) X break; X } X X for (i = 0; i < cnt; i++) X if (duke(&answers[i])) { X rmtAddr = answers[i].source; X break; X } X free((char *) answers); X free((char *) b); X if (i == cnt) X return (Sockaddr *) NULL; X else X return &rmtAddr; X#else NO_BROADCAST X return (Sockaddr *) NULL; X#endif NO_BROADCAST X} X X/* X * See if the game contains any empty slots for players. X */ X XBoolean XfreeSlot(a) Xstruct answer *a; X{ X RatStatus test; X RatId id; X X test = (RatStatus) &a->packet.body; X for (id = 0; id < MAXRATS; id++) X if (!test->rats[id].playing) X return TRUE; X return FALSE; X} X X/* X * Fill in the RAT_SURVEY packet. X */ X XsetupSurvey(b) XRatPacket *b; X{ X RatNew ratSurvey; X X b->type = RAT_SURVEY; X ratSurvey = (RatNew) &b->body; X ratSurvey->pass = RAT_PASSWORD; X} X X/* X * Check if this guy's the duke of his game. X */ X XBoolean Xduke(a) Xstruct answer *a; X{ X RatStatus test; X X test = (RatStatus) &a->packet.body; X return !bcmp((char *) &test->rats[test->dukeRat].addr.sin_addr, X (char *) &a->source.sin_addr, sizeof(struct in_addr)); X} X X/* X * Resolve the specified host name into an internet address. The "name" may X * be either a character string name, or an address in the form a.b.c.d where X * the pieces are octal, decimal, or hex numbers. Returns a pointer to a X * sockaddr_in struct (note this structure is statically allocated and must X * be copied), or NULL if the name is unknown. X */ X XSockaddr * XresolveHost(name) Xregister char *name; X{ X register struct hostent *fhost; X struct in_addr fadd; X static Sockaddr sa; X X if ((fhost = gethostbyname(name)) != NULL) { X sa.sin_family = fhost->h_addrtype; X sa.sin_port = 0; X bcopy(fhost->h_addr, &sa.sin_addr, fhost->h_length); X } else { X fadd.s_addr = inet_addr(name); X if (fadd.s_addr != -1) { X sa.sin_family = AF_INET; /* grot */ X sa.sin_port = 0; X sa.sin_addr.s_addr = fadd.s_addr; X } else X return(NULL); X } X return(&sa); X} xxFUNNYxx sed 's/^X//' >./mazefind.6 << 'xxFUNNYxx' X.TH MAZEFIND 6 X.SH NAME Xmazefind \- discover current MazeWar games X.SH SYNTAX X.B /usr/games/mazefind X.SH DESCRIPTION X.I Mazefind Xbroadcasts a query on the net to discover what MazeWar games are being Xplayed, and prints out useful information about them. XIt's useful for discovering what games might be interesting to connect to Xon a distant network. X.SH "SEE ALSO" Xmazewar(6) xxFUNNYxx sed 's/^X//' >./mazewar.h << 'xxFUNNYxx' X/* $Header: mazewar.h,v 1.7 88/08/25 09:59:51 kent Exp $ */ X X/* X * mazewar.h - Definitions for MazeWar X * X * Author: Christopher A. Kent X * Western Research Laboratory X * Digital Equipment Corporation X * Date: Wed Sep 24 1986 X */ X X/*********************************************************** XCopyright 1986 by Digital Equipment Corporation, Maynard, Massachusetts, X X All Rights Reserved X XPermission to use, copy, modify, and distribute this software and its Xdocumentation for any purpose and without fee is hereby granted, Xprovided that the above copyright notice appear in all copies and that Xboth that copyright notice and this permission notice appear in Xsupporting documentation, and that the names of Digital not be Xused in advertising or publicity pertaining to disstribution of the Xsoftware without specific, written prior permission. X XDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL XDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS XSOFTWARE. X X******************************************************************/ X X/* X * $Log: mazewar.h,v $ X * Revision 1.7 88/08/25 09:59:51 kent X * Copyright. X * X * Revision 1.6 88/08/11 11:37:59 kent X * Fix a type clash with X11 include files. We need a Boolean to be a short X * for alignment purposes, but X11 typedefs it to be a char. X * X * Revision 1.5 87/03/31 14:42:32 kent X * Portability considerations, especially byteswapping to/from the net. X * X * Revision 1.4 86/12/03 10:00:54 kent X * Changes to allow multiple players per machine. X * X * Revision 1.3 86/12/01 23:45:53 kent X * Housecleaning and documentation pass. X * X * Revision 1.2 86/12/01 14:47:52 kent X * Changes for a realistic implementation of shooting. X * X * Revision 1.1 86/11/26 16:58:19 kent X * Initial revision X * X * Revision 1.1 86/11/26 16:56:33 kent X * Initial revision X * X */ X X/* fundamental constants */ X X#ifndef TRUE X#define TRUE 1 X#define FALSE 0 X#endif TRUE X X#define MAZEXMAX 32 X#define MAZEYMAX 16 X#define MAXRATS 8 X#define VECTORSIZE 55 X#define NAMESIZE 20 X#define NDIRECTION 4 X#define NORTH 0 X#define SOUTH 1 X#define EAST 2 X#define WEST 3 X#define NVIEW 4 X#define LEFT 0 X#define RIGHT 1 X#define REAR 2 X#define FRONT 3 X X/* types */ X Xtypedef struct sockaddr_in Sockaddr; X#define Boolean short /* don't clash with X11 toolkit */ Xtypedef struct {Boolean y[MAZEYMAX];} MazeRow; Xtypedef MazeRow MazeType X [MAZEXMAX]; Xtypedef MazeRow *MazeTypePtr; Xtypedef short Direction; Xtypedef struct {short x, y; } XYpoint; Xtypedef struct {XYpoint p1, p2;} XYpair; Xtypedef struct {short xcor, ycor;} XY; X Xtypedef struct {short bits[16];} BitCell; X Xtypedef short Loc; Xtypedef unsigned long Score; Xtypedef char RatName X [NAMESIZE]; Xtypedef long RatId; X Xtypedef struct { X RatId ratId; X Score score; X Loc xLoc, yLoc; X Direction dir; X} AqRatLocation; Xtypedef AqRatLocation * RatLocation; X Xtypedef struct { X RatId ratId; X Loc xLoc, yLoc; X Direction dir; X} AqRatKill; Xtypedef AqRatKill * RatKill; X Xstruct _AqRatKillQ { X AqRatKill thisOne; X struct _AqRatKillQ *nextOne; X struct timeval shotHits; X}; Xtypedef struct _AqRatKillQ AqRatKillQ; Xtypedef AqRatKillQ * RatKillQ_t; X Xtypedef struct { X RatId ratId; X RatId killedBy; X} AqRatDead; Xtypedef AqRatDead * RatDead; X Xtypedef struct { X Sockaddr addr; X short pass; X Loc xLoc, yLoc; X Direction dir; X RatName name; X} AqRatNew; Xtypedef AqRatNew * RatNew; X Xtypedef struct { X RatId ratId; X} AqRatGone; Xtypedef AqRatGone * RatGone; X Xtypedef struct { X RatId ratId; X} AqRatQuery; Xtypedef AqRatQuery * RatQuery; X Xtypedef struct { X RatId ratId; X} AqRatAlive; Xtypedef AqRatAlive * RatAlive; X Xtypedef struct { X RatId ratId; X} AqRatMove; Xtypedef AqRatMove * RatMove; X Xtypedef struct { X Sockaddr addr; X Score score; X Boolean playing; X Loc xLoc, yLoc; X Direction dir; X RatName name; X} RatObject; Xtypedef RatObject * RatInfo; X Xtypedef struct { X RatId dukeRat; X RatObject rats[MAXRATS]; X} RatCb; Xtypedef RatCb * RatStatus; X Xtypedef long TokenId; X Xtypedef struct { X Boolean visible; X Loc x, y; X short distance; X TokenId tokenId; X} RatAppearance; Xtypedef RatAppearance R2d2_t X [MAXRATS]; Xtypedef RatAppearance * RatLook; X Xtypedef struct {TokenId t[NDIRECTION];} RelativeTokens X [NDIRECTION]; X Xtypedef struct { X Boolean send; X Boolean rcvd; X short count; X} RatNetHealth; Xtypedef RatNetHealth RatHealth X [MAXRATS]; X X/* network stuff */ X X#define MAZEPORT 1111 X#define MAZESERVICE "mazewar" X X#define RAT_LOCATION 1 X#define RAT_KILL 2 X#define RAT_DEAD 3 X#define RAT_STATUS 4 X#define RAT_NEW 5 X#define RAT_GOING 6 X#define RAT_QUERY 7 X#define RAT_ALIVE 8 X#define RAT_SURVEY 9 X#define RAT_MOVE 10 X#define RAT_PASSWORD 032610 X Xtypedef struct { X long type; X RatCb body; /* largest type above */ X} RatPacket; X X/* variables "exported" by the mazewar "module" */ X Xstruct _mazewar { X Direction dir; /* which way am I looking? */ X Direction dirPeek; /* direction for peek display */ X Boolean duke; /* I am the duke */ X Sockaddr dukeAddr; /* where is the duke? */ X Boolean invincible; /* can I be killed? */ X MazeType maze; /* the maze in bits */ X long mazePort; /* the port to keep busy */ X Sockaddr myAddr; /* my net address */ X RatId myRatId; /* my index into the ratcb */ X Boolean omniscient; /* can I see everyone? */ X Boolean peeking; /* peeking in progress */ X int theSocket; /* the main socket */ X short randomVector[VECTORSIZE]; X RatCb ratcb; /* my copy of the world */ X Score score; /* my total so far */ X Loc xloc; /* current x location */ X Loc yloc; /* current y location */ X Loc xPeek; /* x for peek display */ X Loc yPeek; /* y for peek display */ X}M; /* expediency wins out */ X X/* events */ X X#define EVENT_A 1 /* user pressed "A" */ X#define EVENT_S 2 /* user pressed "S" */ X#define EVENT_D 3 /* user pressed "D" */ X#define EVENT_F 4 /* user pressed "F" */ X#define EVENT_BAR 5 /* user pressed space bar */ X#define EVENT_I 6 /* user pressed "I" */ X#define EVENT_K 7 /* user pressed "K" */ X#define EVENT_O 8 /* user pressed "O" */ X#define EVENT_L 9 /* user pressed "L" */ X#define EVENT_LEFT_D 10 /* user pressed left mouse button */ X#define EVENT_LEFT_U 11 /* user released l.m.b */ X#define EVENT_MIDDLE_D 12 /* user pressed middle button */ X#define EVENT_RIGHT_D 13 /* user pressed right button */ X#define EVENT_RIGHT_U 14 /* user released r.m.b */ X#define EVENT_NETWORK 15 /* incoming network packet */ X#define EVENT_INT 16 /* user pressed interrupt key */ X#define EVENT_TIMEOUT 17 /* nothing happened! */ X Xtypedef struct { X short eventType; X RatPacket *eventDetail; /* for incoming data */ X Sockaddr eventSource; X} MWEvent; X XR2d2_t R2d2; XRatKillQ_t RatKillQ; X Xvoid NextEvent(); X Xchar *malloc(); xxFUNNYxx