home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!news.tek.com!master!saab!billr
- From: billr@saab.CNA.TEK.COM (Bill Randle)
- Newsgroups: comp.sources.games
- Subject: v15i030: xtb - multi-player X11 tank game and server, Part02/02
- Message-ID: <4040@master.CNA.TEK.COM>
- Date: 8 Dec 92 17:39:04 GMT
- Sender: news@master.CNA.TEK.COM
- Lines: 1399
- Approved: billr@saab.CNA.TEK.COM
- Xref: uunet comp.sources.games:1529
-
- Submitted-by: bmh@terminus.ericsson.se (Bernard Hatt)
- Posting-number: Volume 15, Issue 30
- Archive-name: xtb/Part02
- Environment: X11, UDP Sockets
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 2)."
- # Contents: Makefile TODO comms.h defs.h dgram.c xtb.6 xtbd.c
- # Wrapped by billr@saab on Tue Dec 8 09:35:46 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(938 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X# Makefile for XTankBattle
- X
- Xall : xtb xtbd rtb
- X
- XCFLAGS = -O2
- XCC = cc
- X# wherever your X11 include files are
- XXINCS = -I/usr/openwin/include
- X
- XSOURCES = xtb.c rtb.c xtbd.c dgram.c common.c
- XINCLUDES = defs.h comms.h
- XMISC = xtb.6 README TODO
- X
- Xrtb : rtb.o dgram.o common.o
- X $(CC) -o rtb rtb.o dgram.o common.o -lm
- X
- Xxtb : xtb.o dgram.o common.o
- X $(CC) -o xtb xtb.o dgram.o common.o -lX11 -lm
- X
- Xxtbd : xtbd.o dgram.o common.o
- X $(CC) -o xtbd xtbd.o dgram.o common.o -lm
- X
- Xxtb.o : xtb.c $(INCLUDES)
- X cc -c xtb.c $(XINCS)
- X
- Xrtb.o : rtb.c $(INCLUDES)
- Xxtbd.o: xtbd.c $(INCLUDES)
- Xdgram.o : dgram.c $(INCLUDES)
- X
- Xcommon.o : common.c $(INCLUDES)
- X cc -c common.c -DBSD
- X
- Xshar: $(SOURCES) $(INCLUDES) Makefile $(MISC)
- X shar $(SOURCES) $(INCLUDES) Makefile $(MISC) >xtb.shar
- X
- Xtar: $(SOURCES) $(INCLUDES) Makefile $(MISC)
- X tar cvf xtb.tar $(SOURCES) $(INCLUDES) Makefile $(MISC)
- X
- Xshu: tar
- X compress xtb.tar
- X uuencode xtb.tar.Z xtb.tar.Z >xtb.shu
- X rm xtb.tar.Z
- END_OF_FILE
- if test 938 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'TODO' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'TODO'\"
- else
- echo shar: Extracting \"'TODO'\" \(848 characters\)
- sed "s/^X//" >'TODO' <<'END_OF_FILE'
- X
- XEnhancement Ideas
- X=================
- X
- XRestart option when killed.
- XShootable blocks.
- XDifferent tank types (heavy/light armour, high/low speed, short/long range).
- XRecognise teams.
- XMore than 24 players ?
- XBar new entrants to a game, (ie. allow n to start, game ends when n-1 are dead).
- XNew players to start with average (or worst) damage of existing players?
- XLimited shells/ammo dumps ?
- XAutomatic invoicing of players at 10p per game!
- XUse UDP broadcast to cut down traffic ?
- XTime bar to prevent playing during working hours ?
- XClients able to get score list from server ?
- X3D view (like Battlezone) ?
- XScrolling using copy rather than repaint ?
- X
- XDone
- X====
- X
- XTwo button mouse support (Any key (without auto-repeat) pressed reverses
- X motion, any key released un-reverses).
- XFixed refresh on startup (failed only occasionly).
- XProper restart for robot tanks.
- X
- END_OF_FILE
- if test 848 -ne `wc -c <'TODO'`; then
- echo shar: \"'TODO'\" unpacked with wrong size!
- fi
- # end of 'TODO'
- fi
- if test -f 'comms.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'comms.h'\"
- else
- echo shar: Extracting \"'comms.h'\" \(3413 characters\)
- sed "s/^X//" >'comms.h' <<'END_OF_FILE'
- X/* comms and common data structures */
- X
- X/*
- X * $Header: /morpork/home/bmh/xtest2/RCS/comms.h,v 1.18 92/10/19 15:34:38 bmh Exp Locker: bmh $
- X *
- X * Bernard Hatt
- X * Camtec Electronics (Ericsson), Leicester, England, LE1 4SA
- X * bmh@terminus.ericsson.se
- X *
- X */
- X
- X /* types of message */
- X#define T_SIGNON 1 /* signon request to server */
- X#define T_ACCEPT 2 /* accept of signon from server */
- X#define T_REJECT 3 /* rejection of signon from server */
- X#define T_MOVE 4 /* move made sent to server */
- X#define T_REPLY 5 /* reply from server (once moves have been made) */
- X#define T_SIGNOFF 6 /* signoff to server */
- X#define T_FIELDDATA 7 /* battlefield data (from server) */
- X#define T_DATAREQ 8 /* request for battlefield data (to server) */
- X#define T_EXPLOSION 9 /* explosion on battlefield */
- X#define T_MESSAGE 10 /* message from server */
- X#define T_ALIVE 11 /* check if client is alive */
- X
- X /* match byte orders of differing machines */
- X#define INSWAP(x) ((int)(htonl((long)(x))))
- X#define OUTSWAP(x) ((int)(ntohl((long)(x))))
- X
- X
- Xtypedef struct struct_userinfo
- X{
- X int id;
- X char username[NAMELEN];
- X char hostname[HOSTLEN]; /* sending hostname */
- X} USER;
- X
- Xtypedef struct struct_position
- X{
- X int x; /* x position on battlefield */
- X int y; /* y */
- X int rot; /* rotation */
- X int scx; /* x distance scrolled */
- X int scy; /* y */
- X} POSITION;
- X
- Xtypedef struct signon_struct
- X{
- X int port; /* callback port no. */
- X int version; /* program version */
- X char hostname[HOSTLEN]; /* sending hostname */
- X char username[NAMELEN];
- X} SIGNON;
- X
- Xtypedef struct accept_struct
- X{
- X int id; /* your player id. */
- X USER players[MAXUSERS];
- X int kills[MAXUSERS]; /* no. of kills made */
- X int killed[MAXUSERS]; /* no of times killed */
- X} ACCEPT;
- X
- Xtypedef struct reject_struct
- X{
- X int reason; /* unused */
- X char text[BUFLEN]; /* textual reason for rejection */
- X} REJECT;
- X
- Xtypedef struct move_struct
- X{
- X int rot; /* rotation */
- X int linear; /* linear movement */
- X int fire; /* file button */
- X} MOVE;
- X
- Xtypedef struct reply_struct
- X{
- X POSITION pos[MAXUSERS]; /* positions of players */
- X} REPLY;
- X
- Xtypedef struct field_struct
- X{
- X int lineno; /* line no of field */
- X char object[OBJECTSIZE]; /* data */
- X} FIELD;
- X
- Xtypedef struct datareq_struct
- X{
- X int lineno; /* requested reason */
- X} DATAREQ;
- X
- Xtypedef struct signoff_struct
- X{
- X int reason;
- X} SIGNOFF;
- X
- Xtypedef struct explosion_struct
- X{
- X int x; /* x and y of explosion */
- X int y;
- X int damage[MAXUSERS]; /* damage sustained by players */
- X} EXPLOSION;
- X
- Xtypedef struct message_struct
- X{
- X char text[BUFLEN];
- X} MESSAGE;
- X
- Xtypedef union extra_union
- X{
- X SIGNON signon;
- X ACCEPT accept;
- X REJECT reject;
- X MOVE move;
- X REPLY reply;
- X FIELD field;
- X DATAREQ datareq;
- X EXPLOSION explosion;
- X MESSAGE message;
- X SIGNOFF signoff;
- X} EXTRA;
- X
- Xtypedef struct data_struct
- X{
- X int type; /* type of message */
- X int id; /* id of sending machine */
- X EXTRA extra;
- X} DATA;
- X
- Xtypedef struct player_struct
- X{
- X int ssd; /* socket descripter */
- X int t; /* last time a move was made */
- X int restime; /* time of last response */
- X int firetime; /* last time the player fired */
- X int damage; /* damage a player has sustained */
- X int kills; /* kills made by a player */
- X int killed; /* times killed */
- X USER user; /* data about user */
- X POSITION pos; /* current position */
- X MOVE move; /* status */
- X} PLAYER;
- X
- Xtypedef struct score_struct
- X{
- X int kills; /* kills made by a player */
- X int killed; /* times killed */
- X USER user; /* data about user */
- X} SCORE;
- END_OF_FILE
- if test 3413 -ne `wc -c <'comms.h'`; then
- echo shar: \"'comms.h'\" unpacked with wrong size!
- fi
- # end of 'comms.h'
- fi
- if test -f 'defs.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'defs.h'\"
- else
- echo shar: Extracting \"'defs.h'\" \(2767 characters\)
- sed "s/^X//" >'defs.h' <<'END_OF_FILE'
- X/* common defines */
- X/*
- X * $Header: /morpork/home/bmh/xtest2/RCS/defs.h,v 1.20 92/10/19 15:34:40 bmh Exp Locker: bmh $
- X *
- X * Bernard Hatt
- X * Camtec Electronics (Ericsson), Leicester, England, LE1 4SA
- X * bmh@terminus.ericsson.se
- X *
- X */
- X
- X /* increment this version no. if the client/server protocol is */
- X /* changed in any way */
- X#define VERSION 7
- X
- X#define DEFSPORT 1622 /* default server UDP port no. */
- X#define DEFCPORT 1623 /* default client UDP port no. */
- X#define DEFRPORT 1650 /* default base for robot players */
- X
- X#define MAXUSERS 10 /* max no of users. */
- X
- X#if MAXUSERS >10
- X#define BASECHAR 'A' /* use letters if more than 10 users */
- X#else
- X#define BASECHAR '0' /* use digits if less than 10 users */
- X#endif
- X
- X#define MAXROBOTS (MAXUSERS/2) /* max no. of robots */
- X
- X#define SCORES (MAXUSERS*3) /* max number of users in score table */
- X
- X#define MAINX 768 /* X and Y of main battlefield */
- X#define MAINY 768
- X
- X#define HOSTLEN 16 /* max chars in hostname */
- X#define NAMELEN 16 /* max chars in username */
- X#define BUFLEN 128 /* general purpose char buffer */
- X
- X#define MAINSIZE 2048 /* size of field in pixels */
- X
- X#define OBJECTSIZE 32 /* size of object grid */
- X#define OBJECTSCALE (MAINSIZE/OBJECTSIZE)
- X#define OBJX (MAINX/OBJECTSCALE)
- X#define OBJY (MAINY/OBJECTSCALE)
- X
- X
- X#define RADARSIZE 256 /* size of radar screen (pixels) */
- X#define RADARSCALE (MAINSIZE/RADARSIZE)
- X#define ROSCALE (RADARSIZE/OBJECTSIZE) /* radar/object scale */
- X
- X#define SCROLLBAR 8 /* width of scroll bar */
- X#define SBX (MAINX/OBJECTSIZE)
- X#define SBY (MAINY/OBJECTSIZE)
- X
- X#define MESSAGESIZE 24
- X#define DAMAGEBAR 48
- X
- X#define TANKROT 128 /* number of different tank rotations */
- X#define TGRID 6 /* size of grid defining tank */
- X#define T TGRID
- X
- X
- X#define CLEAR 0 /* types of ground */
- X#define ROUGH 1
- X#define UNSET 64
- X#define BLOCKED 127
- X
- X#define QUIT 0 /* user quit */
- X#define KILLED 1 /* killed */
- X#define TIMEOUT 2 /* timeout after no responce */
- X#define DESTROYED 3 /* DestroyWindow event */
- X
- X#define MAXDAMAGE 128
- X#define DAMAGESCALE (RADARSIZE/MAXDAMAGE)
- X#define EXPSIZE 192 /* size of explosion (pixels dia.) */
- X#define EXPTIME 60 /* time for explosion (cs) */
- X#define EXPCONST 100 /* power of explosions */
- X#define EXPRANGE (32*32) /* range for which explosions count as direct hits */
- X
- X#define STDMOVE 64 /* standard move in pixels/sec */
- X#define MSTDMOVE (-1*STDMOVE) /* minus standard move in pixels/sec */
- X#define STDROT 32 /* standard rotation in pixels/sec */
- X#define MSTDROT (-1*STDROT) /* minus standard rotation in pixels/sec */
- X
- X
- X#define PI 3.14159265358979323846264338327950
- X
- X/* function type defs. */
- X
- Xextern char *getenv();
- X
- X /* functions in common.c */
- Xint gettime(),rnd(),GetAngle();
- Xvoid myualarm();
- X
- X#define SIZE(x) ((x>0)?x:(0-x))
- END_OF_FILE
- if test 2767 -ne `wc -c <'defs.h'`; then
- echo shar: \"'defs.h'\" unpacked with wrong size!
- fi
- # end of 'defs.h'
- fi
- if test -f 'dgram.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dgram.c'\"
- else
- echo shar: Extracting \"'dgram.c'\" \(1486 characters\)
- sed "s/^X//" >'dgram.c' <<'END_OF_FILE'
- X/*
- X * Comms.
- X *
- X * $Header: /morpork/home/bmh/xtest2/RCS/dgram.c,v 1.10 92/10/19 15:34:27 bmh Exp Locker: bmh $
- X *
- X * Bernard Hatt
- X * Camtec Electronics (Ericsson), Leicester, England, LE1 4SA
- X * bmh@terminus.ericsson.se
- X *
- X */
- X
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <netdb.h>
- X#include <stdio.h>
- X
- X#include "defs.h"
- X#include "comms.h"
- X
- X#define STREAM_TYPE SOCK_DGRAM
- X
- Xstruct hostent *gethostbyname();
- X
- Xint
- Xopenread(port)
- Xint port;
- X{
- X int sd;
- X struct sockaddr_in name;
- X
- X sd=socket(AF_INET,STREAM_TYPE,0);
- X if(sd==-1)
- X {
- X perror("openread()/socket()");
- X return(-1);
- X }
- X name.sin_family=AF_INET;
- X name.sin_addr.s_addr=INADDR_ANY;
- X name.sin_port=htons(port);
- X
- X if(bind(sd,&name,sizeof(name)))
- X {
- X perror("openread()/bind()");
- X return(-1);
- X }
- X return(sd);
- X}
- X
- Xint
- Xreaddata(sd,data)
- Xint sd;
- XDATA *data;
- X{
- X return(read(sd,data,sizeof(DATA)));
- X}
- X
- Xint
- Xopensend(host,port)
- Xchar *host;
- Xint port;
- X{
- X int ret,sd;
- X struct sockaddr_in name;
- X struct hostent *hent;
- X
- X sd=socket(AF_INET,STREAM_TYPE,0);
- X if(sd==-1)
- X {
- X perror("opensend()/socket()");
- X return(-1);
- X }
- X
- X hent=gethostbyname(host);
- X if(hent==NULL)
- X return(-1);
- X
- X bcopy(hent->h_addr,&name.sin_addr,hent->h_length);
- X name.sin_family=AF_INET;
- X name.sin_port=htons(port);
- X
- X /* connect port */
- X ret=connect(sd,&name,sizeof(name));
- X if(ret==-1)
- X {
- X perror("opensend()/connect()");
- X return(-1);
- X }
- X return(sd);
- X}
- X
- Xint
- Xsenddata(sd,data)
- Xint sd;
- XDATA *data;
- X{
- X return(write(sd,data,sizeof(DATA)));
- X}
- END_OF_FILE
- if test 1486 -ne `wc -c <'dgram.c'`; then
- echo shar: \"'dgram.c'\" unpacked with wrong size!
- fi
- # end of 'dgram.c'
- fi
- if test -f 'xtb.6' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'xtb.6'\"
- else
- echo shar: Extracting \"'xtb.6'\" \(4450 characters\)
- sed "s/^X//" >'xtb.6' <<'END_OF_FILE'
- X.TH XTB 6 "13 January 1991"
- X.SH NAME
- Xxtb, xtbd \- X11 Tank battle program and server
- X.SH SYNOPSIS
- X.B xtb
- X[
- X.B \-ic
- X] [
- X.IR portno
- X] [
- X.B \-os
- X] [
- X.IR portno
- X]
- X.B \-h
- X.IR hostname
- X[
- X.B \-w
- X]
- X[
- X.B \-p
- X]
- X[
- X.B \-b
- X]
- X.LP
- X.B xtbd
- X.B \-p
- X[
- X.IR portno
- X]
- X.LP
- X.B rtb
- X[
- X.B \-ic
- X] [
- X.IR portno
- X] [
- X.B \-os
- X] [
- X.IR portno
- X]
- X.B \-h
- X.IR hostname
- X[
- X.B \-n
- X.IR robots
- X]
- X.LP
- X.SH DESCRIPTION
- XMulti player, multi workstation tank battle game.
- X.SH OPTIONS
- X.B \-h
- X Server hostname to contact.
- X.br
- X.B \-w
- X Turns on warping of the mouse cursor on scrolling.
- XThe default is for the mouse cursor not to be moved when the screen is
- Xscrolled (With \fB-w\fR the square under the cursor remains the same.)
- X(Use what you find intuitive)
- X.br
- X.B "\-c\fR or \fB\-i"
- X Client (input) port number for client to use.
- X.br
- X.B "\-s\fR or \fB\-o"
- X Server (output) port number for client to use.
- X.br
- X.B "\-p"
- X Server port number for server to use (xtbd).
- X.br
- X.B "\-p"
- X Use polygons for drawing tanks (xtb).
- X.br
- X.B "\-b"
- X Use bitmaps for drawing tanks (default) (xtb).
- XSome X servers may not have sufficient storage for 128 bitmaps or may find
- Xdrawing polygons quicker than copying pixmaps, if so use \fB-b\fR.
- X.br
- X.B "\-n"
- X Number of robot tanks for rtb to produce.
- X.br
- X.SH STARTUP
- XPick a node (can be any machine with or without X) and run the server (xtbd).
- X.ti +1i
- X\fIhostname\fR% xtbd
- X.LP
- XFor each player at a workstation run the client (xtb).
- X.ti +1i
- Xworkstation% xtb -h \fIhostname\fR
- X.br
- X(ignore messages about datagrams and fielddata)
- X.LP
- XFor second and further players \fBon the same node\fR, each should pick
- Xdifferent port numbers to the default (and each other). eg
- Xthe second player might type
- X.ti +1i
- Xworkstation% xtb -h \fIhostname\fR -i 1624
- X.LP
- XTo run two or more servers on the same node, use a different port number
- Xto the default. eg.
- X.ti +1i
- X\fIhostname\fR% xtbd -p 1627
- X.br
- Xto contact this server the player would need to type
- X.ti +1i
- Xworkstation% xtb -h \fIhostname\fR -o 1627
- X.LP
- XTo start robot tanks, run rtb as you would xtb, adding the -n option for
- Xthe number of robots. Robots restart when killed after a 5 second delay.
- X.SH PLAYING
- XThe display has several areas, the main battlefield, (you appear as a
- Xsolid black tank, all others display their id) the radar, a damage
- Xdisplay, a message window, a quit button and a list of players and their
- Xid's. There are also scroll indicators, for the main and radar windows,
- Xshowing the portion of the battlefield that is on display.
- X.LP
- XThe controls are simple.
- X.br
- XLeft button -> Fire (in the direction the tank is facing)
- X.br
- XMiddle button -> Reverse
- X.br
- XRight button -> Forward
- X.LP
- XIf you only have a two button mouse, you can use the keyboard to reverse
- Xthe tank motion, any key press causes the motion to be reversed, any key
- Xrelease returns to normal. If you have auto-repeat on your keyboard
- X(most do), use a key that does not auto repeat (ie. shift,control etc)
- XThis will not work for a window manager that does not implement the
- Xinput (push-focus) window manager hint (olwm and twm are known to work).
- X.LP
- XThe tank will rotate towards the mouse cursor when the cursor is in the
- Xmain field.
- X.LP
- XThe solid black squares are obstacles, and cannot be moved through or
- Xfired through.
- X.LP
- XThe hatched areas are rough ground, you can only move at half speed
- Xacross these.
- X.LP
- XThe shells have a range of about four squares, you cannot fire again for
- X2.5 sec after firing.
- X.LP
- XExplosions do damage according to the (inverse square of the) distance
- Xfrom the explosion. Two direct hits is sufficient for a kill, near
- Xmisses cause smaller amounts of damage.
- X.LP
- XKilling another player clears your own damage (to encourage friendly play!).
- X.LP
- XQuitting should be done using the quit button (NOT the window manager
- Xframe)
- X.LP
- XIt is possible to shoot through the diagonal of two blocks.
- X.LP
- XThe battle ground is set for an invocation of the server, each time the
- Xserver is started a new battle ground is generated. (Scores are also set
- Xto zero when a server is re-started.)
- X.LP
- X.SH ENVIRONMENT
- X.B XTB_SERVER
- X- name of server to contact by default
- X.br
- X.B XTB_INPORT
- X- port number for input (client) (-i or -c)
- X.br
- X.B XTB_OUTPORT
- X- port number for output (server) (-o or -s)
- X.br
- X.SH BUGS
- XI don't currently know of any major bugs (that make the game
- Xunplayable/stop/core dump), though it is a bit flaky in a few places.
- X.SH AUTHOR
- XBernard Hatt
- X.br
- XCamtec Electronics (Ericsson), Leicester, England.
- X.br
- Xbmh@terminus.ericsson.se
- END_OF_FILE
- if test 4450 -ne `wc -c <'xtb.6'`; then
- echo shar: \"'xtb.6'\" unpacked with wrong size!
- fi
- # end of 'xtb.6'
- fi
- if test -f 'xtbd.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'xtbd.c'\"
- else
- echo shar: Extracting \"'xtbd.c'\" \(15465 characters\)
- sed "s/^X//" >'xtbd.c' <<'END_OF_FILE'
- X/*
- X * Server
- X *
- X * $Header: /morpork/home/bmh/xtest2/RCS/xtbd.c,v 1.28 92/10/19 15:34:36 bmh Exp Locker: bmh $
- X *
- X * Bernard Hatt
- X * Camtec Electronics (Ericsson), Leicester, England, LE1 4SA
- X * bmh@terminus.ericsson.se
- X *
- X */
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include <sys/time.h>
- X#include <sys/types.h>
- X#include <netinet/in.h>
- X#include <signal.h>
- X#include <errno.h>
- X
- X#include "defs.h"
- X#include "comms.h"
- X
- XPLAYER player[MAXUSERS]; /* players tanks */
- Xchar field[OBJECTSIZE][OBJECTSIZE];
- XSCORE score[SCORES]; /* score table */
- Xint noscores=0; /* number of scores in score table */
- X
- Xint sintable[TANKROT];
- Xint costable[TANKROT];
- X
- X
- XDATA pdata;
- X
- XDATA rdata,sdata;
- Xint rsd,ssd;
- Xchar mbuf[BUFLEN];
- Xint lastsend=0;
- X
- Xchar *progname;
- X
- Xint debug=0;
- Xint scoreflag=1;
- X
- Xint
- Xisuseron(name,host)
- Xchar *name,*host;
- X{
- X int i;
- X for(i=0;i<MAXUSERS;i++)
- X {
- X if(strcmp(player[i].user.username,name))
- X continue;
- X if(strcmp(player[i].user.hostname,host))
- X continue;
- X return(i);
- X }
- X return(-1);
- X}
- X
- Xvoid
- Xgetscore(id) /* get score for player[id] */
- Xint id;
- X{
- X int i;
- X for(i=0;i<noscores;i++)
- X {
- X if(strcmp(player[id].user.username,score[i].user.username))
- X continue;
- X if(strcmp(player[id].user.hostname,score[i].user.hostname))
- X continue;
- X player[id].killed=score[i].killed;
- X player[id].kills=score[i].kills;
- X return;
- X }
- X player[id].killed=0;
- X player[id].kills=0;
- X if(i==SCORES)
- X {
- X fprintf(stderr,"Run out of score table entries\n");
- X }
- X else
- X {
- X strcpy(score[noscores].user.username,player[id].user.username);
- X strcpy(score[noscores].user.hostname,player[id].user.hostname);
- X noscores++;
- X }
- X}
- X
- Xvoid
- Xdumpscores() /* dump all scores */
- X{
- X int i;
- X int killed,kills,total;
- X int on;
- X char ch;
- X for(i=0;i<noscores;i++)
- X {
- X ch=' ';
- X kills=score[i].kills;
- X killed=score[i].killed;
- X on=isuseron(score[i].user.username,score[i].user.hostname);
- X if(on!=(-1))
- X {
- X ch='*';
- X kills=player[on].kills;
- X killed=player[on].killed;
- X }
- X total=kills+killed;
- X if(total==0)
- X total=1;
- X printf("%12s@%-12s %c games %-4d, kills %-4d (%3d%%), killed %-4d (%3d%%)\n",score[i].user.username,score[i].user.hostname,ch,total,kills,((100*kills)/total),killed,((100*killed)/total));
- X }
- X}
- X
- Xvoid
- Xsetscore(id) /* set score for player[id] */
- Xint id;
- X{
- X int i;
- X for(i=0;i<noscores;i++)
- X {
- X if(strcmp(player[id].user.username,score[i].user.username))
- X continue;
- X if(strcmp(player[id].user.hostname,score[i].user.hostname))
- X continue;
- X score[i].killed=player[id].killed;
- X score[i].kills=player[id].kills;
- X printf("Score for %s@%s is %d/%d\n",score[i].user.username,score[i].user.hostname,player[id].kills,player[id].killed);
- X return;
- X }
- X fprintf(stderr,"User not in score table!\n");
- X}
- X
- Xint
- Xsqdist(x1,y1,x2,y2) /* square of distance between (x1,y1) and (x2,y2) */
- Xint x1,y1,x2,y2;
- X{
- X int dx,dy;
- X dx=(x1-x2);
- X dy=(y1-y2);
- X return(dx*dx+dy*dy);
- X}
- X
- Xvoid
- Xsendplayers() /* send all players their positions */
- X{
- X int i;
- X pdata.type=OUTSWAP(T_REPLY);
- X
- X for(i=0;i<MAXUSERS;i++)
- X {
- X pdata.extra.reply.pos[i].x=OUTSWAP(player[i].pos.x);
- X pdata.extra.reply.pos[i].y=OUTSWAP(player[i].pos.y);
- X pdata.extra.reply.pos[i].rot=OUTSWAP(player[i].pos.rot);
- X }
- X
- X for(i=0;i<MAXUSERS;i++)
- X if(player[i].pos.x!=-1)
- X senddata(player[i].ssd,&pdata);
- X}
- X
- Xvoid
- Xsendmessage(str) /* send a message to all players */
- Xchar *str;
- X{
- X int i;
- X sdata.type=OUTSWAP(T_MESSAGE);
- X strcpy(sdata.extra.message.text,str);
- X for(i=0;i<MAXUSERS;i++)
- X if(player[i].pos.x!=-1)
- X senddata(player[i].ssd,&sdata);
- X}
- X
- Xvoid
- Xfireshell(id) /* player (id) has fired */
- Xint id;
- X{
- X int newtime,i,j;
- X int srot,dist;
- X int sx,sy;
- X int dx,dy;
- X int hflag=0,kflag=0,killed;
- X
- X newtime=gettime();
- X if((newtime>(250+player[id].firetime))&&(player[id].damage<MAXDAMAGE))
- X {
- X player[id].firetime=newtime;
- X srot=player[id].pos.rot;
- X sx=player[id].pos.x;
- X sy=player[id].pos.y;
- X dx=costable[srot]/4;
- X dy=sintable[srot]/4;
- X for(i=0;i<16;i++)
- X {
- X sx-=dx;
- X sy-=dy;
- X if((sx>MAINSIZE)||(sy>MAINSIZE)||(sx<0)||(sy<0))
- X break;
- X if(field[sx/OBJECTSCALE][sy/OBJECTSCALE]==BLOCKED)
- X break;
- X for(j=0;j<MAXUSERS;j++)
- X {
- X if(id==j)
- X continue;
- X if(player[j].pos.x==(-1))
- X continue;
- X if(sqdist(sx,sy,player[j].pos.x,player[j].pos.y)<(TGRID*TGRID*6*6))
- X {
- X hflag++;
- X break;
- X }
- X }
- X if(hflag)
- X break;
- X }
- X /* sx,sy is position of shell hit */
- X sdata.type=OUTSWAP(T_EXPLOSION);
- X sdata.extra.explosion.x=OUTSWAP(sx);
- X sdata.extra.explosion.y=OUTSWAP(sy);
- X for(i=0;i<MAXUSERS;i++)
- X {
- X if(player[i].pos.x==(-1))
- X continue;
- X if(player[i].damage>=MAXDAMAGE)
- X continue;
- X dist=sqdist(sx,sy,player[i].pos.x,player[i].pos.y);
- X if(dist<EXPRANGE)
- X player[i].damage+=MAXDAMAGE/2;
- X else
- X player[i].damage+=(EXPCONST*(MAXDAMAGE/2)/((dist-EXPRANGE)+EXPCONST));
- X if(player[i].damage>=MAXDAMAGE)
- X {
- X killed=i;
- X kflag++;
- X }
- X sdata.extra.explosion.damage[i]=OUTSWAP(player[i].damage);
- X }
- X
- X if(kflag&&(killed!=id))
- X {
- X player[id].damage=0;
- X player[id].kills++;
- X }
- X
- X for(i=0;i<MAXUSERS;i++)
- X {
- X if(player[i].pos.x==(-1))
- X continue;
- X senddata(player[i].ssd,&sdata);
- X }
- X
- X if(kflag)
- X {
- X if(killed==id)
- X sprintf(mbuf,"%s@%s committed suicide",player[killed].user.username,player[killed].user.hostname);
- X else
- X sprintf(mbuf,"%s@%s killed by %s@%s",player[killed].user.username,player[killed].user.hostname,player[id].user.username,player[id].user.hostname);
- X sendmessage(mbuf);
- X }
- X
- X }
- X}
- X
- Xvoid
- Xdosignon() /* deal with signon from user */
- X{
- X int rndx,rndy;
- X int id,ssd,i,cflag,attempts;
- X /* find free slot */
- X id=(-1);
- X for(i=0;i<MAXUSERS;i++)
- X if(player[i].pos.x==(-1))
- X {
- X id=i;
- X break;
- X }
- X ssd=opensend(rdata.extra.signon.hostname,INSWAP(rdata.extra.signon.port));
- X if(ssd==(-1))
- X {
- X fprintf(stderr,"%s: Connecting to %s/%d failed\n",progname,rdata.extra.signon.hostname,INSWAP(rdata.extra.signon.port));
- X }
- X else
- X {
- X sdata.type=OUTSWAP(T_ACCEPT);
- X if(INSWAP(rdata.extra.signon.version)!=VERSION)
- X {
- X sdata.type=OUTSWAP(T_REJECT);
- X sprintf(sdata.extra.reject.text,"Client/Server version no. mismatch (%d,%d)",INSWAP(rdata.extra.signon.version),VERSION);
- X }
- X if(id==(-1))
- X {
- X sdata.type=OUTSWAP(T_REJECT);
- X strcpy(sdata.extra.reject.text,"Too many users");
- X }
- X if(isuseron(rdata.extra.signon.username,rdata.extra.signon.hostname)!=(-1))
- X {
- X sdata.type=OUTSWAP(T_REJECT);
- X strcpy(sdata.extra.reject.text,"User already signed on");
- X }
- X if(sdata.type==OUTSWAP(T_REJECT))
- X {
- X senddata(ssd,&sdata);
- X printf("Sent reject \"%s\"\n",sdata.extra.reject.text);
- X close(ssd);
- X return;
- X }
- X attempts=0;
- X player[id].ssd=ssd;
- X do
- X {
- X attempts++;
- X cflag=0;
- X rndx=rnd(OBJECTSIZE);
- X rndy=rnd(OBJECTSIZE);
- X for(i=0;i<MAXUSERS;i++)
- X {
- X if(i==id)
- X continue;
- X if(player[i].pos.x==(-1))
- X continue;
- X if(sqdist(rndx*OBJECTSCALE+(OBJECTSCALE/2),rndy*OBJECTSCALE+(OBJECTSCALE/2),player[i].pos.x,player[i].pos.y)<(OBJECTSCALE*OBJECTSCALE*49))
- X {
- X if(attempts<5)
- X cflag++;
- X break;
- X }
- X }
- X }
- X while(((field[rndx][rndy]!=CLEAR)||(cflag))&&(attempts<10));
- X
- X player[id].pos.x=rndx*OBJECTSCALE+(OBJECTSCALE/2);
- X player[id].pos.y=rndy*OBJECTSCALE+(OBJECTSCALE/2);
- X player[id].pos.rot=0;
- X player[id].move.rot=0;
- X player[id].move.linear=0;
- X player[id].t=gettime();
- X player[id].restime=gettime();
- X player[id].damage=0;
- X strcpy(player[id].user.username,rdata.extra.signon.username);
- X strcpy(player[id].user.hostname,rdata.extra.signon.hostname);
- X getscore(id);
- X printf("Sent accept (id=%d)\n",id);
- X sdata.extra.accept.id=OUTSWAP(id);
- X for(i=0;i<MAXUSERS;i++)
- X {
- X strcpy(sdata.extra.accept.players[i].username,player[i].user.username);
- X strcpy(sdata.extra.accept.players[i].hostname,player[i].user.hostname);
- X sdata.extra.accept.killed[i]=OUTSWAP(player[i].killed);
- X sdata.extra.accept.kills[i]=OUTSWAP(player[i].kills);
- X }
- X for(i=0;i<MAXUSERS;i++)
- X if(player[i].pos.x!=-1)
- X senddata(player[i].ssd,&sdata);
- X sprintf(mbuf,"Signon from %s@%s",player[id].user.username,player[id].user.hostname);
- X sendmessage(mbuf);
- X }
- X}
- X
- Xvoid
- Xdosignoff(thisid,reason) /* deal with signoff from user */
- Xint thisid,reason;
- X{
- X int i;
- X
- X switch(reason)
- X {
- X case QUIT:
- X printf("signoff (QUIT) from %d\n",thisid);
- X if(player[thisid].damage>(MAXDAMAGE/2))
- X player[thisid].killed++;
- X break;
- X case KILLED:
- X printf("signoff (KILLED) from %d\n",thisid);
- X player[thisid].killed++;
- X break;
- X case TIMEOUT:
- X printf("signoff (TIMEOUT) from %d\n",thisid);
- X break;
- X case DESTROYED:
- X printf("signoff (DESTROYED) from %d\n",thisid);
- X break;
- X }
- X if((reason!=KILLED)&&(reason!=DESTROYED))
- X {
- X sprintf(mbuf,"Signoff from %s@%s",player[thisid].user.username,player[thisid].user.hostname);
- X sendmessage(mbuf);
- X }
- X setscore(thisid);
- X
- X *(player[thisid].user.username)='\0';
- X *(player[thisid].user.hostname)='\0';
- X
- X if(scoreflag)
- X dumpscores();
- X
- X sdata.type=OUTSWAP(T_ACCEPT);
- X for(i=0;i<MAXUSERS;i++)
- X {
- X strcpy(sdata.extra.accept.players[i].username,player[i].user.username);
- X strcpy(sdata.extra.accept.players[i].hostname,player[i].user.hostname);
- X sdata.extra.accept.killed[i]=OUTSWAP(player[i].killed);
- X sdata.extra.accept.kills[i]=OUTSWAP(player[i].kills);
- X }
- X for(i=0;i<MAXUSERS;i++)
- X if(player[i].pos.x!=-1)
- X senddata(player[i].ssd,&sdata);
- X
- X player[thisid].pos.x=(-1);
- X close(player[thisid].ssd);
- X}
- X
- Xvoid
- Xmoveplayers() /* move all players */
- X{
- X int i,j,newtime,diff,td,max;
- X int testx,testy,testrot,scale;
- X int dx,dy,cflag=0;
- X int stage;
- X
- X for(i=0;i<MAXUSERS;i++)
- X {
- X stage=0;
- X if(player[i].pos.x==(-1))
- X continue;
- X newtime=gettime();
- X td=newtime-player[i].t;
- X player[i].t=newtime;
- X if((gettime()-player[i].restime)>500)
- X {
- X sdata.type=OUTSWAP(T_ALIVE);
- X senddata(player[i].ssd,&sdata);
- X }
- X
- X if((gettime()-player[i].restime)>1000)
- X {
- X dosignoff(i,TIMEOUT);
- X }
- X
- X scale=100;
- X
- X diff=player[i].move.rot-player[i].pos.rot;
- X
- X
- X testx=player[i].pos.x/OBJECTSCALE;
- X testy=player[i].pos.y/OBJECTSCALE;
- X if(field[testx][testy]==ROUGH)
- X scale=200;
- X if(diff>(TANKROT/2))
- X diff-=TANKROT;
- X
- X if(diff<(TANKROT/(-2)))
- X diff+=TANKROT;
- X
- X max=((td*STDROT)/scale)+1;
- X
- X if(diff<0)
- X diff=((td*diff-99)/100);
- X else
- X if(diff>0)
- X diff=((td*diff+99)/100);
- X
- X if(diff>max)
- X diff=max;
- X if(diff<(max*-1))
- X diff=(max*-1);
- X
- X player[i].pos.rot=(player[i].pos.rot+diff+TANKROT)%TANKROT;
- X
- X testrot=player[i].pos.rot;
- X dx=((TGRID*6)*costable[testrot])/STDMOVE;
- X dy=((TGRID*6)*sintable[testrot])/STDMOVE;
- X testx=(player[i].pos.x+player[i].move.linear*dx);
- X testy=(player[i].pos.y+player[i].move.linear*dy);
- X
- X stage=1;
- X if((testx>MAINSIZE)||(testy>MAINSIZE)||(testx<0)||(testy<0))
- X goto loopend;
- X stage=2;
- X if(field[testx/OBJECTSCALE][testy/OBJECTSCALE]==BLOCKED)
- X goto loopend;
- X
- X testrot=(player[i].pos.rot+TANKROT/14)%TANKROT;
- X dx=((TGRID*6)*costable[testrot])/STDMOVE;
- X dy=((TGRID*6)*sintable[testrot])/STDMOVE;
- X testx=(player[i].pos.x+player[i].move.linear*dx);
- X testy=(player[i].pos.y+player[i].move.linear*dy);
- X
- X stage=3;
- X if((testx>MAINSIZE)||(testy>MAINSIZE)||(testx<0)||(testy<0))
- X goto loopend;
- X stage=4;
- X if(field[testx/OBJECTSCALE][testy/OBJECTSCALE]==BLOCKED)
- X goto loopend;
- X
- X testrot=(player[i].pos.rot-(TANKROT/14)+TANKROT)%TANKROT;
- X
- X dx=((TGRID*6)*costable[testrot])/STDMOVE;
- X dy=((TGRID*6)*sintable[testrot])/STDMOVE;
- X testx=(player[i].pos.x+player[i].move.linear*dx);
- X testy=(player[i].pos.y+player[i].move.linear*dy);
- X
- X stage=5;
- X if((testx>MAINSIZE)||(testy>MAINSIZE)||(testx<0)||(testy<0))
- X goto loopend;
- X stage=6;
- X if(field[testx/OBJECTSCALE][testy/OBJECTSCALE]==BLOCKED)
- X goto loopend;
- X
- X testx=player[i].pos.x+(player[i].move.linear*td*costable[player[i].pos.rot])/scale;
- X testy=player[i].pos.y+(player[i].move.linear*td*sintable[player[i].pos.rot])/scale;
- X
- X for(j=0;j<MAXUSERS;j++)
- X {
- X if(i==j)
- X continue;
- X if(player[j].pos.x==(-1))
- X continue;
- X if(sqdist(testx,testy,player[j].pos.x,player[j].pos.y)<(TGRID*TGRID*6*6*2))
- X {
- X if(debug)
- X printf("Collision %d->%d\n",i,j);
- X cflag++;
- X break;
- X }
- X }
- X
- X if(!cflag)
- X {
- X player[i].pos.x=testx;
- X player[i].pos.y=testy;
- X stage=0;
- X }
- X
- X
- Xloopend: if(debug)
- X if(stage!=0)
- X printf("Tank %d blocked at stage %d\n",i,stage);
- X }
- X}
- X
- Xvoid
- Xdoalarm() /* what to do when alarm expires */
- X{
- X int i;
- X for(i=0;i<MAXUSERS;i++)
- X {
- X if(player[i].pos.x==(-1))
- X continue;
- X if(player[i].move.fire)
- X fireshell(i);
- X
- X }
- X moveplayers();
- X sendplayers();
- X myualarm(100000); /* reset 1/10th sec alarm */
- X}
- X
- Xmain(argc,argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int i,j,rn,thisid,reason;
- X int port=DEFSPORT;
- X char *p;
- X
- X srand(time(0));
- X
- X progname=argv[0];
- X
- X for(i=1;i<argc;i++)
- X {
- X p=argv[i];
- X if(*p++=='-')
- X {
- X switch(*p++)
- X {
- X case 'p':
- X if(*p=='\0')
- X port=atoi(argv[++i]);
- X else
- X port=atoi(p);
- X break;
- X case 'd':
- X debug=(!debug);
- X break;
- X case 's':
- X scoreflag=(!scoreflag);
- X break;
- X default:
- X fprintf(stderr,"Usage: %s -p portno\n",argv[0]);
- X }
- X }
- X }
- X
- X fprintf(stderr,"%s: XTankBattle server, datagram size is %d (V%d)\n",progname,sizeof(DATA),VERSION);
- X
- X srand(time(0));
- X for(i=0;i<MAXUSERS;i++)
- X {
- X player[i].pos.x=(-1);
- X player[i].user.username[0]='\0';
- X player[i].user.hostname[0]='\0';
- X }
- X
- X for(i=0;i<TANKROT;i++)
- X {
- X sintable[i]=(int)(0.5+(double)STDMOVE*sin(((double)i*2.0*PI)/TANKROT));
- X costable[i]=(int)(0.5+(double)STDMOVE*cos(((double)i*2.0*PI)/TANKROT));
- X }
- X
- X for(i=0;i<OBJECTSIZE;i++)
- X for(j=0;j<OBJECTSIZE;j++)
- X {
- X field[i][j]=CLEAR;
- X rn=rnd(8);
- X if(rn==1)
- X field[i][j]=BLOCKED;
- X if((rn==4)||(rn==6))
- X field[i][j]=ROUGH;
- X }
- X
- X signal(SIGALRM,doalarm);
- X
- X rsd=openread(port);
- X if(rsd==-1)
- X {
- X fprintf(stderr,"%s: Unable to open port %d for reading\n",argv[0],port);
- X exit(1);
- X }
- X while(1)
- X {
- X fflush(stdout);
- X myualarm(100000); /* 1/10th sec alarm */
- X if(readdata(rsd,&rdata)!=sizeof(DATA))
- X {
- X if(errno!=EINTR)
- X printf("Bad data (Config mismatch?)\n");
- X }
- X else
- X {
- X myualarm(0); /* turn off alarm */
- X switch(INSWAP(rdata.type))
- X {
- X case T_SIGNON:
- X printf("signon\n");
- X printf("host %s/%d\n",rdata.extra.signon.hostname,INSWAP(rdata.extra.signon.port));
- X printf("user %s\n",rdata.extra.signon.username);
- X
- X dosignon();
- X break;
- X case T_DATAREQ:
- X i=INSWAP(rdata.extra.datareq.lineno);
- X ssd=player[INSWAP(rdata.id)].ssd;
- X sdata.type=OUTSWAP(T_FIELDDATA);
- X sdata.extra.field.lineno=OUTSWAP(i);
- X memcpy(sdata.extra.field.object,&field[i][0],OBJECTSIZE);
- X senddata(ssd,&sdata);
- X break;
- X case T_ACCEPT:
- X printf("accept\n");
- X break;
- X case T_REJECT:
- X printf("reject\n");
- X break;
- X case T_MOVE:
- X thisid=INSWAP(rdata.id);
- X player[thisid].move.rot=INSWAP(rdata.extra.move.rot);
- X player[thisid].move.linear=INSWAP(rdata.extra.move.linear);
- X player[thisid].move.fire=INSWAP(rdata.extra.move.fire);
- X player[thisid].restime=gettime();
- X
- X if(player[thisid].move.fire)
- X fireshell(thisid);
- X
- X moveplayers();
- X if((gettime()-lastsend)>4)
- X {
- X sendplayers();
- X lastsend=gettime();
- X }
- X
- X break;
- X case T_REPLY:
- X printf("reply\n");
- X break;
- X case T_SIGNOFF:
- X thisid=INSWAP(rdata.id);
- X reason=INSWAP(rdata.extra.signoff.reason);
- X if(player[thisid].pos.x!=(-1))
- X dosignoff(thisid,reason);
- X break;
- X case T_ALIVE:
- X thisid=INSWAP(rdata.id);
- X player[thisid].restime=gettime();
- X/* printf("%d is alive\n",thisid);*/
- X break;
- X default:
- X printf("Unknown datagram type %d (0x%x)\n",INSWAP(rdata.type),INSWAP(rdata.type));
- X }
- X }
- X }
- X}
- END_OF_FILE
- if test 15465 -ne `wc -c <'xtbd.c'`; then
- echo shar: \"'xtbd.c'\" unpacked with wrong size!
- fi
- # end of 'xtbd.c'
- fi
- echo shar: End of archive 2 \(of 2\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked both archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-