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: v15i029: xtb - multi-player X11 tank game and server, Part01/02
- Message-ID: <4039@master.CNA.TEK.COM>
- Date: 8 Dec 92 17:38:36 GMT
- Sender: news@master.CNA.TEK.COM
- Lines: 2445
- Approved: billr@saab.CNA.TEK.COM
- Xref: uunet comp.sources.games:1528
-
- Submitted-by: bmh@terminus.ericsson.se (Bernard Hatt)
- Posting-number: Volume 15, Issue 29
- Archive-name: xtb/Part01
- Environment: X11, UDP Sockets
-
- [This is not only multi-player, but the players can be on different
- hosts, as well. It also has robot tanks in case you can't find anyone
- else to play against. Compiled and ran fine on a Sun SS-2. -br]
-
- #! /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 1 (of 2)."
- # Contents: README MANIFEST common.c rtb.c xtb.c
- # Wrapped by billr@saab on Tue Dec 8 09:35:46 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(5557 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- X
- XWHAT YOU NEED TO HAVE
- X=====================
- X
- XAn X11R3 or greater X server. (It might work on earlier X11 releases,
- Xbut I havn't tried)
- X
- XA display of at least 1024(W)*800(H) pixels. (1080 pixels wide is better)
- X
- XA three button mouse (It's playable with a two button mouse).
- X
- XA fastish (and unloaded) CPU and reasonable drawing speed.
- X
- XA fastish network.
- X
- XNothing better to do.
- X
- XSoftware that supports the following system/library calls and UDP sockets.
- X Socket/network related
- X socket(), bind(), connect() ,gethostbyname() ,htonl() ,ntohl()
- X Timing related
- X gettimeofday(), setitimer()
- X General
- X gethostname(), getpwuid()
- X
- XMachines with non 32-bit int's could be a problem (Sorry).
- X
- XTwo or more players. (The more the better).
- X
- XThe program works on mono, greyscale and colour displays, and looks
- Xexactly the same on each (I havn't got a colour node :-( ).
- X
- XCOMPILATION OPTIONS
- X===================
- X
- XIf you have more than 10 people wanting to play, try increasing the
- Xvalue if MAXUSERS in "defs.h" up to a maximum of 24. This should work,
- Xbut is untested.
- X
- XCOMPILING
- X=========
- X
- XType
- X make
- X
- XThis should create three programs, xtb, xtbd and rtb.
- X
- XSTARTING THE GAME
- X=================
- X
- XPick a node (can be any machine with or without X) and run the server (xtbd).
- X
- X hostname% xtbd
- X
- XFor each player at a workstation run the client (xtb).
- X
- X workstation% xtb -h hostname
- X (ignore messages about datagrams and fielddata)
- X
- XRUNNING TWO (OR MORE) PLAYERS ON THE SAME NODE
- X==============================================
- X
- XThe second and further players, should pick different port numbers to
- Xthe default (and each other). eg the second player might type
- X
- X workstation% xtb -h hostname -i 1624
- X
- XTo run two or more servers on the same node, use a different port number
- Xto the default. eg.
- X
- X hostname% xtbd -p 1627
- X
- Xto contact this server the player would need to type
- X workstation% xtb -h hostname -o 1627
- X
- XROBOT TANKS
- X===========
- X
- XIf you are short of people or want to practice, the program rtb adds
- Xrobot tanks. To create 4 robot tanks type
- X
- X robothost% rtb -h hostname -n4
- X
- XRobots re-start when killed after a 5 second delay. The -i and -o flags
- Xfor xtb that change the port numbers used are also valid for rtb. For
- X'n' robots 'n' port numbers are used.
- X
- XNote: Robot tanks can use a lot more network bandwidth than human players.
- X
- XSHELL VARIABLES
- X===============
- X
- XThe shell variables are overridden by the command line options.
- X
- XXTB_SERVER The hostname of the server to contact by default.
- XXTB_INPORT The input (client) port number to use.
- XXTB_OUTPORT The output (server) port number to use.
- X
- XKNOWN TO WORK
- X=============
- X
- XKnown to work as a server
- X Sun 4, DecStation 3100, Microvax 2, Sun 3, HP 9000s827
- X
- XKnown to work as a client (display)
- X Sun 4, DecStation 3100, HP9000s710 (With X dev. kit)
- X
- XWorks as a client with only a small number of players
- X Sun 3
- X
- XOPTIONS
- X=======
- X
- XThe -w flag turns on warping of the mouse cursor on scrolling. The
- Xdefault is for the mouse cursor not to be moved when the screen is
- Xscrolled (ie. the square under the cursor remains the same.) (Use what
- Xyou find intuitive)
- X
- XFor xtb the -p and -b flags change the method used to draw tanks.
- X-p uses polygons (as per previous versions)
- X-b (default) uses bitmaps (pixmaps), this takes much more X server memory,
- Xbut seems faster on most machines.
- X
- XPLAYING
- X=======
- X
- 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.
- X
- XThe controls are simple.
- X
- XLeft button -> Fire (in the direction the tank is facing)
- XMiddle button -> Reverse
- XRight button -> Forward
- X
- 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.
- X
- XThe tank will rotate towards the mouse cursor when the cursor is in the
- Xmain field.
- X
- XThe solid black squares are obstacles, and cannot be moved through or
- Xfired through.
- X
- XThe hatched areas are rough ground, you can only move at half speed
- Xacross these.
- X
- XThe shells have a range of about four squares, you cannot fire again for
- X2.5 sec after firing.
- X
- 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
- XKilling another player clears your own damage (to encourage friendly
- Xplay!).
- X
- XQuitting should be done using the quit button (NOT the window manager
- Xframe)
- X
- XIt is possible to shoot through the diagonal of two blocks.
- X
- XNOTES
- X=====
- X
- XThis was only my third ever X11 program, initially written only with the
- Xon-line manuals for reference. If I were to re-write it, I'd probably
- Xdo it differently.
- X
- XOne of the design specifications was that the program should be easy to
- Xinstall, configure and run, so it does not use any files (other than the
- Xexecutables) or require require root permissions to install/run.
- X
- XThe program is entirely mouse controlled (unless you only have a two
- Xbutton mouse)
- X
- XThe program comes with no warranty. I would like the conditions that
- Xapply to GNU software to apply to this software.
- X
- XGood Luck!
- X
- XBernard Hatt
- Xbmh@terminus.ericsson.se
- XCamtec Electronics (Ericsson), Leicester, England, LE1 4SA.
- END_OF_FILE
- if test 5557 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'MANIFEST' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'MANIFEST'\"
- else
- echo shar: Extracting \"'MANIFEST'\" \(486 characters\)
- sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
- X File Name Archive # Description
- X-----------------------------------------------------------
- X MANIFEST 1 This shipping list
- X Makefile 2
- X README 1
- X TODO 2
- X common.c 1
- X comms.h 2
- X defs.h 2
- X dgram.c 2
- X rtb.c 1
- X xtb.6 2
- X xtb.c 1
- X xtbd.c 2
- END_OF_FILE
- if test 486 -ne `wc -c <'MANIFEST'`; then
- echo shar: \"'MANIFEST'\" unpacked with wrong size!
- fi
- # end of 'MANIFEST'
- fi
- if test -f 'common.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'common.c'\"
- else
- echo shar: Extracting \"'common.c'\" \(1685 characters\)
- sed "s/^X//" >'common.c' <<'END_OF_FILE'
- X/*
- X * Common code.
- X *
- X * $Header: /morpork/home/bmh/xtest2/RCS/common.c,v 1.2 92/10/19 15:34:25 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
- X
- X#ifdef BSD
- X#include <sys/time.h>
- X#include <sys/types.h>
- X#include <fcntl.h>
- X#else
- X#include <sys/types.h>
- X#include <sys/timeb.h>
- X#include <sys/stat.h>
- X#include <fcntl.h>
- X
- X#endif
- X
- X#include <math.h>
- X#include "defs.h"
- X#include "comms.h"
- X
- X#ifdef BSD
- X
- Xstruct timezone tz={0,0};
- Xstruct timeval tv;
- Xlong lastsec=0;
- X /* return time in cs ( will fail if test runs for more than */
- X /* 240 days (2^31/(60*60*24*100)) */
- X
- Xint
- Xgettime()
- X{
- X gettimeofday(&tv,&tz);
- X if(lastsec==0)
- X lastsec=tv.tv_sec;
- X return((tv.tv_sec-lastsec)*100+(tv.tv_usec/10000));
- X}
- X
- X#else
- X
- Xstruct timeb tb;
- Xlong lastsec=0;
- X
- Xint
- Xgettime()
- X{
- X ftime(&tb);
- X if(lastsec==0)
- X lastsec=tb.time;
- X return((tb.time-lastsec)*100+tb.millitm/10);
- X}
- X
- X#endif
- X
- Xint
- Xrnd(n) /* a random no. between 0 and n-1 */
- Xint n;
- X{
- X return((rand()/153)%n);
- X}
- X
- Xvoid /* because Ultrix doesn't provide the nice SunOS ualarm() */
- Xmyualarm(val)
- Xint val;
- X{
- X struct itimerval itv;
- X itv.it_interval.tv_sec=0;
- X itv.it_interval.tv_usec=0;
- X itv.it_value.tv_sec=0;
- X itv.it_value.tv_usec=val;
- X setitimer(ITIMER_REAL,&itv,NULL);
- X}
- X
- Xint
- XGetAngle(x1,y1,x2,y2) /* return an angle between two points */
- Xint x1,y1,x2,y2;
- X{
- X double xc,yc,theta;
- X int ang;
- X xc=(double)(x1-x2);
- X yc=(double)(y1-y2);
- X if(xc==0.0)
- X {
- X if(yc>0)
- X theta=(PI/2.0);
- X else
- X theta=(-PI/2.0);
- X }
- X else
- X {
- X theta=atan2(yc,xc);
- X }
- X theta=(TANKROT*(theta/(2.0*PI)));
- X ang=(int)(theta+0.5+TANKROT)%TANKROT;
- X return(ang);
- X}
- X
- X
- END_OF_FILE
- if test 1685 -ne `wc -c <'common.c'`; then
- echo shar: \"'common.c'\" unpacked with wrong size!
- fi
- # end of 'common.c'
- fi
- if test -f 'rtb.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rtb.c'\"
- else
- echo shar: Extracting \"'rtb.c'\" \(11632 characters\)
- sed "s/^X//" >'rtb.c' <<'END_OF_FILE'
- X/*
- X * Robot tank
- X *
- X * $Header: /morpork/home/bmh/xtest2/RCS/rtb.c,v 1.7 92/10/19 15:34:30 bmh Exp Locker: bmh $
- X *
- X * Bernard Hatt
- X * Camtec Electronics (Ericsson), Leicester, England, LE1 4SA
- X * bmh@terminus.ericsson.se
- X *
- X */
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/wait.h>
- X#include <sys/ioctl.h>
- X#include <sys/time.h>
- X#include <netinet/in.h>
- X#include <unistd.h>
- X#include <fcntl.h>
- X#include <signal.h>
- X#include <ctype.h>
- X#include <math.h>
- X#include <pwd.h>
- X
- X#include "defs.h"
- X#include "comms.h"
- X
- Xint debug=0;
- X
- XPLAYER player[MAXUSERS]; /* players tanks */
- Xchar field[OBJECTSIZE][OBJECTSIZE];
- Xchar radar[OBJECTSIZE][OBJECTSIZE];
- X
- Xint distance=0;
- X
- Xint fire=0; /* fire button pressed */
- Xint motion=0; /* tank linear motion */
- Xint mrot=0; /* mouse pointer rotation */
- Xint damage=0; /* damage sustained */
- Xchar message[BUFLEN]=""; /* message for message window */
- Xchar *server=NULL;
- X
- XPOSITION cur={0,300,100,0,0};
- XPOSITION last;
- X
- Xint myid;
- Xint rsd,ssd;
- XDATA rdata,sdata;
- Xint savedx=(-1),savedy=(-1);
- Xint sfx=(-1),sfy=(-1);
- Xint lastsend=0;
- X
- Xint robots=0; /* attack other robots */
- Xint humans=1; /* attack humans */
- X
- X
- Xint ex[MAXUSERS],ey[MAXUSERS],exptime[MAXUSERS];
- X
- Xtypedef struct child_struct
- X{
- X int pid;
- X int portno;
- X} CHILD;
- X
- XCHILD child[MAXROBOTS];
- X
- Xchar *progname;
- Xint stuck=0;
- X
- Xvoid
- Xsignoff(t,reason) /* send signoff to server and exit */
- Xint t,reason;
- X{
- X sdata.id=OUTSWAP(myid);
- X sdata.type=OUTSWAP(T_SIGNOFF);
- X sdata.extra.signoff.reason=OUTSWAP(reason);
- X senddata(ssd,&sdata);
- X if(t!=0)
- X sleep(t);
- X exit(0);
- X}
- X
- Xvoid
- Xdointr() /* action on interrupt */
- X{
- X signoff(0,DESTROYED);
- X}
- X
- Xvoid
- XdoXio()
- X{
- X signoff(0,QUIT);
- X}
- X
- Xvoid
- Xtimeout() /* timeout on connect */
- X{
- X fprintf(stderr,"%s: No response from server \"%s\" (not running/busy?)\n",progname,server);
- X exit(1);
- X}
- X
- X
- Xvoid
- Xsendstatus() /* send our status to the server */
- X{
- X sdata.type=OUTSWAP(T_MOVE);
- X sdata.id=OUTSWAP(myid);
- X sdata.extra.move.rot=OUTSWAP(mrot);
- X sdata.extra.move.linear=OUTSWAP(motion);
- X sdata.extra.move.fire=OUTSWAP(fire);
- X senddata(ssd,&sdata);
- X lastsend=gettime();
- X}
- X
- X
- Xint
- Xisclear(x1,y1,x2,y2) /* is it clear between (x1,y1) and (x2,y2) */
- Xint x1,y1,x2,y2;
- X{
- X int i;
- X int x,y;
- X int fx,fy;
- X if((x1<0)||(x1>=MAINSIZE))
- X return(0);
- X if((y1<0)||(y1>=MAINSIZE))
- X return(0);
- X
- X for(i=0;i<16;i++)
- X {
- X x=x1+(((x2-x1)*i)/16);
- X y=y1+(((y2-y1)*i)/16);
- X fx=x/OBJECTSCALE;
- X fy=y/OBJECTSCALE;
- X if(field[fx][fy]==BLOCKED)
- X return(0);
- X }
- X return(1);
- X}
- X
- Xvoid
- Xdomymove()
- X{
- X int i;
- X int sqdist,ang;
- X int dx,dy,cansee,offset;
- X int cang,cdist=(-1),cid;
- X int omotion,ofire,omrot,cx,cy;
- X int sid=(-1),sang,sdist;
- X
- X ofire=fire;
- X omotion=motion;
- X omrot=mrot;
- X for(i=0;i<MAXUSERS;i++)
- X {
- X if(i==myid)
- X continue;
- X if(*player[i].user.username=='\0')
- X continue;
- X if(*player[i].user.username=='R')
- X {
- X if(!robots)
- X continue;
- X }
- X else
- X {
- X if(!humans)
- X continue;
- X }
- X dx=player[i].pos.x-cur.x;
- X dy=player[i].pos.y-cur.y;
- X sqdist=(dx*dx)+(dy*dy);
- X ang=GetAngle(0,0,dx,dy);
- X if(sqdist<(OBJECTSCALE*OBJECTSCALE*16))
- X {
- X if(isclear(cur.x,cur.y,player[i].pos.x,player[i].pos.y))
- X {
- X sid=i;
- X sang=ang;
- X sdist=sqdist;
- X }
- X }
- X if((cdist>sqdist)||(cdist==(-1)))
- X {
- X cang=ang;
- X cdist=sqdist;
- X cid=i;
- X }
- X }
- X fire=0;
- X if(cdist!=-1)
- X {
- X if(debug)
- X printf("Closest id %d ang %3d\t",cid,cang);
- X if(sid!=(-1))
- X {
- X mrot=sang;
- X distance=0;
- X if(sang==cur.rot)
- X {
- X fire=1;
- X if(sdist<(OBJECTSCALE*OBJECTSCALE*14))
- X motion=1;
- X }
- X if(debug)
- X {
- X putchar('F');
- X }
- X }
- X else
- X {
- X if(distance!=0)
- X distance--;
- X else
- X mrot=cang;
- X cx=player[cid].pos.x;
- X cy=player[cid].pos.y;
- X if((last.x!=cur.x)||(last.y!=cur.y)||(mrot!=cur.rot))
- X {
- X motion=(-1);
- X if(isclear(cur.x,cur.y,cx,cy))
- X {
- X if(debug)
- X putchar('V');
- X mrot=cang;
- X }
- X else
- X {
- X if(distance==0)
- X {
- X if(debug)
- X putchar('M');
- X mrot=cang;
- X }
- X else
- X {
- X if(debug)
- X printf("D%d",distance);
- X }
- X }
- X }
- X else
- X {
- X if(distance==0)
- X {
- X if(stuck>32)
- X stuck=0;
- X stuck++;
- X offset=(stuck*OBJECTSCALE/2);
- X if(isclear(cur.x-offset,cur.y,cx,cy))
- X {
- X mrot=0;
- X motion=(-1);
- X if(debug)
- X putchar('W');
- X distance=stuck*2;
- X }
- X else
- X if(isclear(cur.x+offset,cur.y,cx,cy))
- X {
- X mrot=64;
- X motion=(-1);
- X if(debug)
- X putchar('E');
- X distance=stuck*2;
- X }
- X else
- X if(isclear(cur.x,cur.y-offset,cx,cy))
- X {
- X mrot=32;
- X motion=(-1);
- X if(debug)
- X putchar('N');
- X distance=stuck*2;
- X }
- X else
- X if(isclear(cur.x,cur.y+offset,cx,cy))
- X {
- X mrot=96;
- X motion=(-1);
- X if(debug)
- X putchar('S');
- X distance=stuck*2;
- X }
- X }
- X if((last.x==cur.x)&&(last.y==cur.y)&&(mrot==cur.rot)&&(motion!=0)&&(!fire))
- X { /* stuck */
- X distance=rnd(20)+10;
- X motion==(-1);
- X mrot=rnd(TANKROT);
- X if(debug)
- X putchar('R');
- X }
- X }
- X }
- X if(debug)
- X printf("\tang=%2d motion=%2d %s\n",mrot,motion,fire?"FIRE":"");
- X }
- X if((fire!=ofire)||(motion!=omotion)||(mrot!=omrot))
- X {
- X sendstatus();
- X }
- X last.x=cur.x;
- X last.y=cur.y;
- X last.rot=cur.rot;
- X}
- X
- Xint
- XSocketHandle() /* handle data from the server incomming on the socket */
- X{
- X int i,j;
- X
- X if(readdata(rsd,&rdata)!=sizeof(DATA))
- X {
- X fprintf(stderr,"%s: Recieved bad data\n");
- X exit(1);
- X }
- X switch(INSWAP(rdata.type))
- X {
- X case T_REPLY:
- X for(i=0;i<MAXUSERS;i++)
- X {
- X if(INSWAP(rdata.extra.reply.pos[i].x)==-1)
- X continue;
- X player[i].pos.x=INSWAP(rdata.extra.reply.pos[i].x);
- X player[i].pos.y=INSWAP(rdata.extra.reply.pos[i].y);
- X player[i].pos.rot=INSWAP(rdata.extra.reply.pos[i].rot);
- X }
- X /* update current position */
- X cur.x=player[myid].pos.x;
- X cur.y=player[myid].pos.y;
- X cur.rot=player[myid].pos.rot;
- X break;
- X case T_ACCEPT:
- X for(i=0;i<MAXUSERS;i++)
- X {
- X strcpy(player[i].user.username,rdata.extra.accept.players[i].username);
- X strcpy(player[i].user.hostname,rdata.extra.accept.players[i].hostname);
- X player[i].kills=INSWAP(rdata.extra.accept.kills[i]);
- X player[i].killed=INSWAP(rdata.extra.accept.killed[i]);
- X }
- X break;
- X case T_EXPLOSION:
- X damage=INSWAP(rdata.extra.explosion.damage[myid]);
- X if(debug)
- X printf("Explosion: damage is %d\n",damage);
- X if(damage>=MAXDAMAGE)
- X {
- X if(debug)
- X printf("Explosion: killed\n");
- X signoff(5,KILLED);
- X }
- X break;
- X case T_MESSAGE:
- X if(debug)
- X printf("Message: %s\n",rdata.extra.message.text);
- X break;
- X case T_ALIVE:
- X sdata.type=OUTSWAP(T_ALIVE);
- X senddata(ssd,&sdata);
- X break;
- X default:
- X if(debug)
- X printf("Unexpected datagram type %d (0x%x)\n",INSWAP(rdata.type),INSWAP(rdata.type));
- X }
- X if((gettime()-lastsend)>20)
- X domymove();
- X}
- X
- Xmain(argc,argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int i,j;
- X int n=1,cpid,ppid,cstatus;
- X int restart;
- X char *p;
- X
- X int inport,outport;
- X int fieldok;
- X progname=argv[0];
- X
- X server=getenv("XTB_SERVER");
- X
- X p=getenv("XTB_INPORT");
- X if(p!=NULL)
- X inport=atoi(p);
- X else
- X inport=DEFRPORT;
- X
- X p=getenv("XTB_OUTPORT");
- X if(p!=NULL)
- X outport=atoi(p);
- X else
- X outport=DEFSPORT;
- X
- X for(i=1;i<argc;i++)
- X {
- X p=argv[i];
- X if(*p++=='-')
- X {
- X switch(*p++)
- X {
- X case 'i': /* input/client port */
- X case 'c':
- X if(*p=='\0')
- X inport=atoi(argv[++i]);
- X else
- X inport=atoi(p);
- X break;
- X case 'o': /* output/server port */
- X case 's':
- X if(*p=='\0')
- X outport=atoi(argv[++i]);
- X else
- X outport=atoi(p);
- X break;
- X case 'h':
- X if(*p=='\0')
- X server=argv[++i];
- X else
- X server=p;
- X break;
- X case 'n': /* number of robots */
- X if(*p=='\0')
- X n=atoi(argv[++i]);
- X else
- X n=atoi(p);
- X if(n<0)
- X n=1;
- X if(n>MAXROBOTS)
- X n=MAXROBOTS;
- X break;
- X case 'r': /* restart if killed */
- X break;
- X case 'v': /* viciousness */
- X break;
- X case 'd': /* debug */
- X debug++;
- X break;
- X case 'R':
- X robots=!robots;
- X break;
- X case 'H':
- X humans=!humans;
- X break;
- X default:
- X fprintf(stderr,"Usage: %s [-h server_host] [-c client_portno] [-s server_portno] \n",argv[0]);
- X }
- X }
- X }
- X
- X if(server==NULL)
- X {
- X fprintf(stderr,"%s: No server host (-h or $XTB_SERVER) defined\n",argv[0]);
- X exit(1);
- X }
- X
- X ppid=getpid();
- X /* fork off children, recording port number and pid */
- X for(j=0;j<n;j++)
- X {
- X cpid=fork();
- X if(cpid==0)
- X break;
- X child[j].pid=cpid;
- X child[j].portno=inport;
- X if(debug)
- X printf("Child %d pid=%d\n",j,child[j].pid);
- X sleep(1);
- X inport++;
- X }
- X /* if we're the parent, wait for children and restart */
- X if(getpid()==ppid)
- X {
- X while(1)
- X {
- X restart=(-1);
- X cpid=wait(&cstatus);
- X if(debug)
- X printf("Child pid %d died\n",cpid);
- X for(j=0;j<n;j++)
- X if(cpid==child[j].pid)
- X restart=j;
- X if(restart!=(-1))
- X {
- X /* re fork */
- X inport=child[restart].portno;
- X sleep(5);
- X cpid=fork();
- X if(cpid==0)
- X break;
- X child[restart].pid=cpid;
- X if(debug)
- X printf("Restart %d pid=%d\n",restart,child[restart].pid);
- X }
- X }
- X }
- X
- X rsd=openread(inport);
- X if(rsd==(-1))
- X {
- X fprintf(stderr,"%s: Opening port %d failed\n",argv[0],inport);
- X exit(1);
- X }
- X
- X ssd=opensend(server,outport);
- X if(ssd==(-1))
- X {
- X fprintf(stderr,"%s: Connecting to %s/%d failed\n",argv[0],server,outport);
- X exit(1);
- X }
- X for(i=0;i<MAXUSERS;i++)
- X exptime[i]=(-1);
- X
- X /* signon */
- X sdata.type=OUTSWAP(T_SIGNON);
- X sdata.extra.signon.version=OUTSWAP(VERSION);
- X sdata.extra.signon.port=OUTSWAP(inport); /* could be different to server port */
- X gethostname(sdata.extra.signon.hostname,HOSTLEN);
- X sprintf(sdata.extra.signon.username,"ROBOT%04d",inport);
- X
- X signal(SIGALRM,timeout);
- X alarm(3);
- X senddata(ssd,&sdata);
- X
- X if(readdata(rsd,&rdata)!=sizeof(DATA))
- X {
- X fprintf(stderr,"%s: Recieved bad data\n");
- X exit(1);
- X }
- X alarm(0);
- X switch(INSWAP(rdata.type))
- X {
- X case T_ACCEPT:
- X if(debug)
- X printf("accept\nMy id is %d\n",INSWAP(rdata.extra.accept.id));
- X myid=INSWAP(rdata.extra.accept.id);
- X for(i=0;i<MAXUSERS;i++)
- X {
- X strcpy(player[i].user.username,rdata.extra.accept.players[i].username);
- X strcpy(player[i].user.hostname,rdata.extra.accept.players[i].hostname);
- X player[i].kills=INSWAP(rdata.extra.accept.kills[i]);
- X player[i].killed=INSWAP(rdata.extra.accept.killed[i]);
- X }
- X break;
- X case T_REJECT:
- X printf("reject\n");
- X printf("reason: %s\n",rdata.extra.reject.text);
- X exit(1);
- X break;
- X default:
- X if(debug)
- X printf("Unknown datagram type %d (0x%x)\n",INSWAP(rdata.type),INSWAP(rdata.type));
- X }
- X
- X for(i=0;i<OBJECTSIZE;i++)
- X for(j=0;j<OBJECTSIZE;j++)
- X radar[i][j]=0;
- X for(i=0;i<OBJECTSIZE;i++)
- X field[i][0]=UNSET;
- X
- X if(debug)
- X printf("Getting field data\n");
- X sdata.id=OUTSWAP(myid);
- X sdata.type=OUTSWAP(T_DATAREQ);
- X
- X do
- X {
- X fieldok=1;
- X for(i=0;i<OBJECTSIZE;i++)
- X {
- X if(field[i][0]==UNSET)
- X {
- X fflush(stdout);
- X fieldok=0;
- X sdata.extra.datareq.lineno=OUTSWAP(i);
- X senddata(ssd,&sdata);
- X if(readdata(rsd,&rdata)!=sizeof(DATA))
- X {
- X fprintf(stderr,"%s: Recieved bad data\n",argv[0]);
- X exit(1);
- X }
- X if(INSWAP(rdata.type)!=T_FIELDDATA)
- X {
- X if(INSWAP(rdata.type)==T_MESSAGE)
- X {
- X if(debug)
- X printf("Message: %s\n",rdata.extra.message.text);
- X }
- X else
- X if(debug)
- X printf("%s: Expected field data got 0x%x\n",argv[0],INSWAP(rdata.type));
- X }
- X else
- X {
- X if(debug)
- X {
- X if(INSWAP(rdata.extra.field.lineno)!=i)
- X printf("%%%d",INSWAP(rdata.extra.field.lineno));
- X else
- X printf(".%d",i);
- X }
- X memcpy(field[INSWAP(rdata.extra.field.lineno)],rdata.extra.field.object,OBJECTSIZE);
- X }
- X }
- X }
- X }
- X while(!fieldok);
- X if(debug)
- X putchar('\n');
- X
- X signal(SIGHUP,dointr);
- X signal(SIGINT,dointr);
- X signal(SIGTERM,dointr);
- X
- X while(1)
- X {
- X SocketHandle();
- X }
- X}
- END_OF_FILE
- if test 11632 -ne `wc -c <'rtb.c'`; then
- echo shar: \"'rtb.c'\" unpacked with wrong size!
- fi
- # end of 'rtb.c'
- fi
- if test -f 'xtb.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'xtb.c'\"
- else
- echo shar: Extracting \"'xtb.c'\" \(31436 characters\)
- sed "s/^X//" >'xtb.c' <<'END_OF_FILE'
- X/*
- X * X Client
- X *
- X * $Header: /morpork/home/bmh/xtest2/RCS/xtb.c,v 1.41 92/10/19 15:34:32 bmh Exp Locker: bmh $
- X *
- X * Bernard Hatt
- X * Camtec Electronics (Ericsson), Leicester, England, LE1 4SA
- X * bmh@terminus.ericsson.se
- X *
- X */
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/wait.h>
- X#include <sys/ioctl.h>
- X#include <sys/time.h>
- X#include <netinet/in.h>
- X#include <unistd.h>
- X#include <fcntl.h>
- X#include <signal.h>
- X#include <ctype.h>
- X#include <math.h>
- X#include <pwd.h>
- X#include <errno.h>
- X
- X#include <X11/X.h>
- X#include <X11/Xlib.h>
- X#include <X11/Xutil.h>
- X#include <X11/cursorfont.h>
- X
- X#include "defs.h"
- X#include "comms.h"
- X
- X#define xtb_width 64 /* bitmap for iconised window */
- X#define xtb_height 64
- Xstatic char xtb_bits[] = {
- X 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- X 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
- X 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- X 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
- X 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- X 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
- X 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- X 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
- X 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- X 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
- X 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- X 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
- X 0xf0, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xf0, 0xff, 0x3f, 0x00,
- X 0xc0, 0xff, 0xff, 0xff, 0xf0, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0xff,
- X 0xf0, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0xfc, 0x00, 0x00,
- X 0xc0, 0xff, 0xff, 0xff, 0x00, 0xfc, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
- X 0x00, 0xfc, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0xfc, 0x00, 0x00,
- X 0xc0, 0xff, 0xff, 0xff, 0x00, 0xf8, 0xff, 0x0f, 0xc0, 0xff, 0xff, 0xff,
- X 0x00, 0xf0, 0xff, 0x0f, 0xc0, 0xff, 0xff, 0xff, 0x00, 0xf0, 0xff, 0x0f,
- X 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
- X 0x00, 0xfc, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0xfc, 0x00, 0x00,
- X 0x00, 0xf8, 0xff, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x03,
- X 0x00, 0xfc, 0x00, 0x00, 0x80, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0x3f, 0x00,
- X 0xe0, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0x3f, 0x00, 0xf0, 0xff, 0xe0, 0x7f,
- X 0xf0, 0xff, 0x3f, 0x00, 0xf8, 0x0f, 0x00, 0xfe, 0xf0, 0xff, 0x3f, 0x00,
- X 0xfc, 0x07, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xf0,
- X 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
- X 0x7e, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80,
- X 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80,
- X 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x82, 0x0f, 0x00, 0x00, 0x00,
- X 0x50, 0x00, 0x00, 0x81, 0x0f, 0x00, 0x00, 0x00, 0x88, 0x00, 0x80, 0x80,
- X 0x0f, 0x00, 0x00, 0x00, 0x04, 0x01, 0x40, 0xc0, 0x0f, 0x00, 0x00, 0x00,
- X 0x02, 0x02, 0x20, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x01, 0x04, 0x10, 0xc0,
- X 0x07, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xc0, 0x07, 0x00, 0x00, 0x00,
- X 0x00, 0x10, 0x04, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x80,
- X 0x07, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x80, 0x0f, 0x00, 0x00, 0x00,
- X 0x00, 0x80, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x80,
- X 0x0f, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00,
- X 0x00, 0x10, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00,
- X 0x3e, 0x00, 0x00, 0x80, 0x00, 0x04, 0x10, 0x00, 0x3e, 0x00, 0x00, 0x80,
- X 0x01, 0x02, 0x20, 0x00, 0x7c, 0x00, 0x00, 0xc0, 0x02, 0x01, 0x40, 0x00,
- X 0xfc, 0x00, 0x00, 0xe0, 0x84, 0x00, 0x80, 0x00, 0xf8, 0x01, 0x00, 0xf0,
- X 0x48, 0x00, 0x00, 0x01, 0xf0, 0x07, 0x00, 0x7c};
- X
- X
- X#define KeyMask (KeyPressMask|KeyReleaseMask)
- X#define ButtonMask (ButtonPressMask|ButtonReleaseMask)
- X#define MotionMask (PointerMotionMask)
- X
- X#define MainEventMask (KeyMask|ButtonMask|ExposureMask|ButtonPressMask|ButtonReleaseMask)
- X#define FieldEventMask (PointerMotionMask|MainEventMask|ButtonPressMask|ButtonReleaseMask)
- X
- XDisplay *Disp;
- Xint Scr; /* screen no. */
- XWindow Win,Root;
- XWindow RWin,FWin,SWin,QWin,AWin,MWin; /* should have used an */
- XWindow VSb,HSb; /* array/structure for these */
- XWindow RVSb,RHSb;
- X
- XGC GcF,GcB,GcTF,GcTB;
- X
- X
- X#define BOARDER 8 /* boarder between windows */
- X#define TANKPOINTS 20 /* number of points defining a tank */
- X
- Xtypedef struct tank_struct
- X{
- X XPoint coord[TANKPOINTS];
- X} TANK;
- X
- XTANK Tank[TANKROT]=
- X{{
- X {0,0},{T/2,-T},{T,0},{0,-T},{T,0},{0,4*T},{-T,0},{0,-T},{-T,0},{0,3*T},
- X {-T,0},{0,-3*T},{-T,0},{0,T},{-T,0},{0,-4*T},{T,0},{0,T},{T,0},{T/2,T}
- X}};
- X
- XPLAYER player[MAXUSERS]; /* players tanks */
- Xchar field[OBJECTSIZE][OBJECTSIZE];
- Xchar radar[OBJECTSIZE][OBJECTSIZE];
- X
- X/* PIMAPS */
- X#define PIXSIZE 48
- XPixmap TankPix[TANKROT];
- X
- X
- Xint fire=0; /* fire button pressed */
- Xint motion=0; /* tank linear motion */
- Xint mrot=0; /* mouse pointer rotation */
- Xint damage=0; /* damage sustained */
- Xchar message[BUFLEN]=""; /* message for message window */
- Xchar *server=NULL;
- X
- XPOSITION cur={0,300,100,0,0};
- XPOSITION garbage;
- X
- Xint pd[2]; /* pipe for passing current position */
- X
- Xint warpflag=0; /* warp pointer on scrolling main screen */
- Xint invert=1; /* invert motion buttons */
- X
- Xint polyflag=0; /* use polygons to draw tanks */
- Xint pixflag=0; /* use pixmaps to draw tanks */
- X
- X
- Xint myid; /* my id */
- X
- Xint rsd,ssd; /* receive and send socket descripters */
- XDATA rdata,sdata; /* receive and send data */
- X
- XTime movetime=0;
- Xint savedx=(-1),savedy=(-1);
- Xint sfx=(-1),sfy=(-1);
- Xint msx,msy; /* mouse x,y */
- Xint ex[MAXUSERS],ey[MAXUSERS],exptime[MAXUSERS]; /* explosions */
- Xint debug=0;
- X
- Xint ppid,cpid;
- X
- X
- Xchar *progname;
- X
- X
- Xvoid
- Xsignoff(t,reason) /* send signoff to server and exit */
- Xint t,reason;
- X{
- X sdata.id=OUTSWAP(myid);
- X sdata.type=OUTSWAP(T_SIGNOFF);
- X sdata.extra.signoff.reason=OUTSWAP(reason);
- X senddata(ssd,&sdata);
- X if(t!=0)
- X sleep(t);
- X if(getpid()==cpid)
- X kill(ppid,SIGKILL);
- X else
- X kill(cpid,SIGKILL);
- X exit(1);
- X}
- X
- Xvoid
- Xdointr() /* action on interrupt */
- X{
- X signoff(0,DESTROYED);
- X}
- X
- Xvoid
- XdoXio()
- X{
- X signoff(0,QUIT);
- X}
- X
- Xvoid
- Xtimeout() /* timeout on connect */
- X{
- X fprintf(stderr,"%s: No response from server \"%s\" (not running/busy?)\n",progname,server);
- X exit(1);
- X}
- X
- Xvoid
- Xdoexplosions() /* deal with on screen explosions */
- X{
- X int i,j,k,tx,ty,td,rad;
- X for(i=0;i<MAXUSERS;i++)
- X {
- X if(exptime[i]!=(-1))
- X {
- X td=gettime()-exptime[i];
- X if(td>EXPTIME)
- X {
- X exptime[i]=(-1);
- X tx=ex[i]/OBJECTSCALE;
- X ty=ey[i]/OBJECTSCALE;
- X for(k=(-2);k<3;k++)
- X for(j=(-2);j<3;j++)
- X DrawFieldSq(tx+k,ty+j,1);
- X if(damage>=MAXDAMAGE)
- X {
- X signoff(5,KILLED);
- X }
- X XFlush(Disp);
- X }
- X else
- X {
- X if(td<=(EXPTIME/2))
- X {
- X rad=(td*EXPSIZE*2)/EXPTIME;
- X XFillArc(Disp,FWin,GcF,ex[i]-(rad/2),ey[i]-(rad/2),rad,rad,0,360*64);
- X XFlush(Disp);
- X }
- X else
- X {
- X rad=((td-(EXPTIME/2))*2*EXPSIZE)/EXPTIME;
- X if(rad>0)
- X {
- X XFillArc(Disp,FWin,GcB,ex[i]-(rad/2),ey[i]-(rad/2),rad,rad,0,360*64);
- X XFlush(Disp);
- X }
- X }
- X }
- X }
- X }
- X}
- X
- Xvoid
- XInitTables() /* initialise data tables (generate 128 different tank polygons) */
- X{
- X short i,j,x,y;
- X double xc,yc,angle,incr,theta,len;
- X
- X x=0;
- X y=0;
- X incr=(2*PI)/((double)TANKROT);
- X
- X
- X for(i=1;i<TANKPOINTS;i++)
- X {
- X x+=Tank[0].coord[i].x;
- X y+=Tank[0].coord[i].y;
- X Tank[0].coord[i].x=x;
- X Tank[0].coord[i].y=y;
- X }
- X
- X for(j=1;j<TANKROT;j++)
- X for(i=1;i<TANKPOINTS;i++)
- X {
- X angle=((double)j)*incr;
- X xc=(double)Tank[0].coord[i].x;
- X yc=(double)Tank[0].coord[i].y;
- X if(xc==0.0)
- X {
- X if(yc>0)
- X theta=(PI/2.0);
- X else
- X theta=(-PI/2.0);
- X }
- X else
- X {
- X theta=atan2(yc,xc);
- X }
- X
- X len=hypot(xc,yc);
- X theta+=angle;
- X xc=len*cos(theta);
- X yc=len*sin(theta);
- X Tank[j].coord[i].x=(short)(xc+0.5);
- X Tank[j].coord[i].y=(short)(yc+0.5);
- X }
- X for(j=0;j<TANKROT;j++)
- X {
- X for(i=TANKPOINTS;i>0;i--)
- X {
- X x=Tank[j].coord[i-1].x;
- X y=Tank[j].coord[i-1].y;
- X Tank[j].coord[i].x-=x;
- X Tank[j].coord[i].y-=y;
- X }
- X }
- X}
- X
- X
- Xvoid
- Xsendstatus() /* send our status to the server */
- X{
- X sdata.type=OUTSWAP(T_MOVE);
- X sdata.id=OUTSWAP(myid);
- X sdata.extra.move.rot=OUTSWAP(mrot);
- X sdata.extra.move.linear=OUTSWAP(motion);
- X sdata.extra.move.fire=OUTSWAP(fire);
- X/* printf("motion=%d invert=%d\n",motion,invert);*/
- X senddata(ssd,&sdata);
- X}
- X
- Xvoid
- XWipeTank(x,y,rot,id) /* wipe a tank from the screen */
- Xint x,y,rot,id;
- X{
- X int objx,objy;
- X
- X objx=x/OBJECTSCALE;
- X objy=y/OBJECTSCALE;
- X radar[objx][objy]=0;
- X
- X savedx=objx;
- X savedy=objy;
- X
- X x-=(cur.scx*OBJECTSCALE);
- X y-=(cur.scy*OBJECTSCALE);
- X
- X sfx=x/OBJECTSCALE;
- X sfy=y/OBJECTSCALE;
- X
- X if((sfx<(-1))||(sfy<(-1))||(sfx>(OBJX+1))||(sfy>(OBJY+1)))
- X return;
- X if(polyflag)
- X {
- X rot=(rot+TANKROT+(TANKROT/4))%TANKROT;
- X Tank[rot].coord[0].x=x;
- X Tank[rot].coord[0].y=y;
- X XFillPolygon(Disp,FWin,GcB,&Tank[rot],TANKPOINTS,Nonconvex,CoordModePrevious);
- X }
- X else
- X {
- X XCopyPlane(Disp,TankPix[rot],FWin,GcTB,0,0,PIXSIZE,PIXSIZE,x-(PIXSIZE/2),y-(PIXSIZE/2),0x1);
- X }
- X
- X if(id!=myid)
- X XFillRectangle(Disp,FWin,GcB,x-5,y-5,10,10);
- X}
- X
- Xvoid
- XDrawTank(x,y,rot,id) /* draw a tank on the screen */
- Xint x,y,rot,id;
- X{
- X int objx,objy,flag;
- X char str[2];
- X
- X objx=x/OBJECTSCALE;
- X objy=y/OBJECTSCALE;
- X
- X x-=(cur.scx*OBJECTSCALE);
- X y-=(cur.scy*OBJECTSCALE);
- X
- X flag=(!radar[savedx][savedy]);
- X radar[objx][objy]=1;
- X
- X if((savedx!=objx)||(savedy!=objy)||flag)
- X {
- X DrawRadarSq(savedx,savedy,1);
- X DrawRadarSq(objx,objy,1);
- X }
- X
- X objx=x/OBJECTSCALE;
- X objy=y/OBJECTSCALE;
- X if((objx<(-1))||(objy<(-1))||(objx>(OBJX+1))||(objy>(OBJY+1)))
- X return;
- X
- X if((savedx!=objx)||(savedy!=objy))
- X {
- X DrawFieldSq(sfx,sfy,0);
- X }
- X if(polyflag)
- X {
- X rot=(rot+TANKROT+(TANKROT/4))%TANKROT;
- X Tank[rot].coord[0].x=x;
- X Tank[rot].coord[0].y=y;
- X XFillPolygon(Disp,FWin,GcF,&Tank[rot],TANKPOINTS,Nonconvex,CoordModePrevious);
- X }
- X else
- X {
- X XCopyPlane(Disp,TankPix[rot],FWin,GcTF,0,0,PIXSIZE,PIXSIZE,x-(PIXSIZE/2),y-(PIXSIZE/2),0x1);
- X }
- X if(id!=myid)
- X {
- X XFillRectangle(Disp,FWin,GcB,x-5,y-6,10,11);
- X str[1]='\0';
- X str[0]=id+BASECHAR;
- X XDrawString(Disp,FWin,GcF,x-2,y+3,str,1);
- X }
- X}
- X
- XDrawFieldSq(i,j,clear) /* draw a square on the battlefield */
- Xint i,j;
- Xint clear;
- X{
- X int x1,x2,y1,y2,mx,my;
- X switch(field[i+cur.scx][j+cur.scy])
- X {
- X case CLEAR:
- X if(clear)
- X {
- X x1=(i*OBJECTSCALE);
- X y1=(j*OBJECTSCALE);
- X XFillRectangle(Disp,FWin,GcB,x1,y1,OBJECTSCALE,OBJECTSCALE);
- X }
- X break;
- X case ROUGH:
- X x1=(i*OBJECTSCALE);
- X y1=(j*OBJECTSCALE);
- X x2=x1+OBJECTSCALE-1;
- X y2=y1+OBJECTSCALE-1;
- X mx=(x1+x2)/2;
- X my=(y1+y2)/2;
- X if(clear)
- X XFillRectangle(Disp,FWin,GcB,x1,y1,OBJECTSCALE,OBJECTSCALE);
- X XDrawLine(Disp,FWin,GcF,x1,y1,x2,y2);
- X XDrawLine(Disp,FWin,GcF,x1,y2,x2,y1);
- X XDrawLine(Disp,FWin,GcF,mx,y1,x1,my);
- X XDrawLine(Disp,FWin,GcF,mx,y1,x2,my);
- X XDrawLine(Disp,FWin,GcF,mx,y2,x1,my);
- X XDrawLine(Disp,FWin,GcF,mx,y2,x2,my);
- X break;
- X case BLOCKED:
- X x1=(i*OBJECTSCALE);
- X y1=(j*OBJECTSCALE);
- X XFillRectangle(Disp,FWin,GcF,x1,y1,OBJECTSCALE,OBJECTSCALE);
- X break;
- X default:
- X break;
- X }
- X}
- X
- XDrawRadarSq(i,j,clear) /* draw a square on the radar window */
- Xint i,j,clear;
- X{
- X int x1,x2,y1,y2;
- X switch(field[i][j])
- X {
- X case CLEAR:
- X if(clear)
- X {
- X x1=(i*ROSCALE);
- X y1=(j*ROSCALE);
- X XFillRectangle(Disp,RWin,GcB,x1,y1,ROSCALE,ROSCALE);
- X }
- X break;
- X case ROUGH:
- X x1=(i*ROSCALE);
- X y1=(j*ROSCALE);
- X x2=x1+ROSCALE-1;
- X y2=y1+ROSCALE-1;
- X if(clear)
- X XFillRectangle(Disp,RWin,GcB,x1,y1,ROSCALE,ROSCALE);
- X XDrawLine(Disp,RWin,GcF,x1,y1,x2,y2);
- X XDrawLine(Disp,RWin,GcF,x1,y2,x2,y1);
- X break;
- X case BLOCKED:
- X x1=(i*ROSCALE);
- X y1=(j*ROSCALE);
- X XDrawRectangle(Disp,RWin,GcF,x1,y1,ROSCALE-1,ROSCALE-1);
- X break;
- X default:
- X break;
- X }
- X if(radar[i][j])
- X {
- X x1=(i*ROSCALE);
- X y1=(j*ROSCALE);
- X XFillRectangle(Disp,RWin,GcF,x1,y1,ROSCALE,ROSCALE);
- X }
- X}
- X
- Xvoid
- XRefreshVSb(clear) /* Refresh vertical scroll bar */
- Xint clear;
- X{
- X if(clear)
- X XClearWindow(Disp,VSb);
- X XFillRectangle(Disp,VSb,GcF,0,cur.scy*SBY,SCROLLBAR,SBY*OBJY);
- X}
- X
- Xvoid
- XRefreshHSb(clear) /* Refresh horizontal scroll bar */
- Xint clear;
- X{
- X if(clear)
- X XClearWindow(Disp,HSb);
- X XFillRectangle(Disp,HSb,GcF,cur.scx*SBX,0,SBX*OBJX,SCROLLBAR);
- X}
- X
- Xvoid
- XRefreshRVSb(clear) /* Refresh radar vertical scroll bar */
- Xint clear;
- X{
- X if(clear)
- X XClearWindow(Disp,RVSb);
- X XFillRectangle(Disp,RVSb,GcF,0,cur.scy*ROSCALE,BOARDER,OBJY*ROSCALE);
- X}
- X
- Xvoid
- XRefreshRHSb(clear) /* refresh radar horizontal scroll bar */
- Xint clear;
- X{
- X if(clear)
- X XClearWindow(Disp,RHSb);
- X XFillRectangle(Disp,RHSb,GcF,cur.scx*ROSCALE,0,OBJX*ROSCALE,BOARDER);
- X}
- X
- Xvoid
- XRefreshSWin(clear) /* refresh status (list of player names/scores) window */
- Xint clear;
- X{
- X int i;
- X char str[80];
- X
- X if(clear)
- X XFillRectangle(Disp,SWin,GcB,0,0,RADARSIZE,15*(MAXUSERS+1));
- X for(i=0;i<MAXUSERS;i++)
- X {
- X if(*(player[i].user.username)=='\0')
- X continue;
- X sprintf(str,"%c %c [%2d/%2d] %s@%s",i+BASECHAR,(i==myid)?'*':':',player[i].kills,player[i].killed,player[i].user.username,player[i].user.hostname);
- X XDrawString(Disp,SWin,GcF,10,(15*(i+1)),str,strlen(str));
- X }
- X XFlush(Disp);
- X}
- X
- XRefreshFWin(clear) /* refresh battlefield window */
- Xint clear;
- X{
- X int i,j;
- X for(i=0;i<OBJX;i++)
- X for(j=0;j<OBJY;j++)
- X DrawFieldSq(i,j,clear);
- X}
- X
- Xstatic void
- XRefreshRWin(clear) /* refresh radar window */
- Xint clear;
- X{ /* refresh code */
- X
- X int i,j;
- X
- X for(i=0;i<OBJECTSIZE;i++)
- X for(j=0;j<OBJECTSIZE;j++)
- X DrawRadarSq(i,j,clear);
- X XFlush(Disp);
- X}
- X
- Xvoid
- XRefreshQWin(clear) /* refresh QUIT window (button */
- Xint clear;
- X{
- X char *str="QUIT";
- X if(clear)
- X XClearWindow(Disp,QWin);
- X XDrawString(Disp,QWin,GcF,10,15,str,strlen(str));
- X XFlush(Disp);
- X}
- X
- Xvoid
- XRefreshAWin(clear) /* refresh armour (damage) window */
- Xint clear;
- X{
- X char *str;
- X if(damage>=MAXDAMAGE)
- X {
- X XFillRectangle(Disp,AWin,GcB,0,0,RADARSIZE,(DAMAGEBAR/2)-1);
- X str="DESTROYED";
- X }
- X else
- X {
- X str="DAMAGE";
- X }
- X if(clear)
- X XClearWindow(Disp,AWin);
- X XDrawLine(Disp,AWin,GcF,0,DAMAGEBAR/2,RADARSIZE,DAMAGEBAR/2);
- X XDrawString(Disp,AWin,GcF,10,15,str,strlen(str));
- X XFillRectangle(Disp,AWin,GcF,0,DAMAGEBAR/2,damage*DAMAGESCALE,DAMAGEBAR/2);
- X XFlush(Disp);
- X}
- X
- Xvoid
- XRefreshMWin(clear) /* refresh message window */
- Xint clear;
- X{
- X int i;
- X
- X if(clear)
- X XClearWindow(Disp,MWin);
- X for(i=0;i<MAXUSERS;i++)
- X {
- X XDrawString(Disp,MWin,GcF,10,15,message,strlen(message));
- X }
- X XFlush(Disp);
- X}
- X
- Xvoid
- XRefreshWin(clear)
- Xint clear;
- X{
- X}
- X
- Xint
- Xcheckscroll(dx,dy) /* check how far we can scroll */
- Xint *dx,*dy;
- X{
- X int sx,sy,osx,osy;
- X osx=SIZE(*dx);
- X osy=SIZE(*dy);
- X
- X if((cur.scy+(*dy))<0)
- X (*dy)=(-1*cur.scy);
- X if((cur.scy+(*dy))>(OBJECTSIZE-MAINY/OBJECTSCALE))
- X (*dy)=(OBJECTSIZE-MAINY/OBJECTSCALE)-cur.scy;
- X if((cur.scx+(*dx))<0)
- X (*dx)=(-1*cur.scx);
- X if((cur.scx+(*dx))>(OBJECTSIZE-MAINX/OBJECTSCALE))
- X (*dx)=(OBJECTSIZE-MAINX/OBJECTSCALE)-cur.scx;
- X sx=SIZE(*dx);
- X sy=SIZE(*dy);
- X
- X if((osx!=0)&&(sx==0)&&(osy!=0)&&(sy!=0)&&(sy!=osy))
- X return(5);
- X
- X if((osx!=0)&&(sx!=0)&&(osy!=0)&&(sy==0)&&(sx!=osx))
- X return(5);
- X
- X if((osx!=0)&&(sx!=0)&&(osy!=0)&&(sy!=0)&&(sx!=osx)&&(sy!=osy))
- X return(5);
- X
- X if(sx>sy)
- X return(sx);
- X else
- X return(sy);
- X}
- X
- Xvoid
- Xscroll(dx,dy) /* do the scroll */
- Xint dx,dy;
- X{
- X cur.scx+=dx;
- X cur.scy+=dy;
- X
- X if(warpflag)
- X XWarpPointer(Disp,None,None,0,0,MAINX,MAINY,dx*(-1*OBJECTSCALE),dy*(-1*OBJECTSCALE));
- X
- X if(dx!=0)
- X {
- X RefreshHSb(1);
- X RefreshRHSb(1);
- X }
- X if(dy!=0)
- X {
- X RefreshVSb(1);
- X RefreshRVSb(1);
- X }
- X
- X if((dx!=0)||(dy!=0))
- X RefreshFWin(1);
- X}
- X
- X
- Xvoid
- XDoRefresh(refwin) /* send a refresh */
- XWindow refwin;
- X{
- X if(refwin==Win)
- X {
- X RefreshWin(0);
- X return;
- X }
- X if(refwin==FWin)
- X {
- X RefreshFWin(0);
- X return;
- X }
- X if(refwin==RWin)
- X {
- X RefreshRWin(0);
- X return;
- X }
- X if(refwin==SWin)
- X {
- X RefreshSWin(0);
- X return;
- X }
- X if(refwin==QWin)
- X {
- X RefreshQWin(0);
- X return;
- X }
- X if(refwin==VSb)
- X {
- X RefreshVSb(0);
- X return;
- X }
- X if(refwin==HSb)
- X {
- X RefreshHSb(0);
- X return;
- X }
- X if(refwin==RVSb)
- X {
- X RefreshRVSb(0);
- X return;
- X }
- X if(refwin==RHSb)
- X {
- X RefreshRHSb(0);
- X return;
- X }
- X if(refwin==AWin)
- X {
- X RefreshAWin(0);
- X return;
- X }
- X if(refwin==MWin)
- X {
- X RefreshMWin(0);
- X return;
- X }
- X}
- X
- Xint
- XSocketHandle() /* handle data from the server incomming on the socket */
- X{
- X int i,j;
- X int gx,gy,dx,dy;
- X if(readdata(rsd,&rdata)!=sizeof(DATA))
- X {
- X fprintf(stderr,"%s: Recieved bad data\n");
- X exit(1);
- X }
- X switch(INSWAP(rdata.type))
- X {
- X case T_REPLY:
- X gx=(player[myid].pos.x/OBJECTSCALE)-cur.scx;
- X gy=(player[myid].pos.y/OBJECTSCALE)-cur.scy;
- X
- X dy=gy-(MAINX/(2*OBJECTSCALE));
- X dx=gx-(MAINX/(2*OBJECTSCALE));
- X
- X doexplosions();
- X
- X if(checkscroll(&dx,&dy)>1)
- X scroll(dx,dy);
- X
- X for(i=0;i<MAXUSERS;i++)
- X {
- X if(INSWAP(rdata.extra.reply.pos[i].x)==-1)
- X continue;
- X WipeTank(player[i].pos.x,player[i].pos.y,player[i].pos.rot,i);
- X player[i].pos.x=INSWAP(rdata.extra.reply.pos[i].x);
- X player[i].pos.y=INSWAP(rdata.extra.reply.pos[i].y);
- X player[i].pos.rot=INSWAP(rdata.extra.reply.pos[i].rot);
- X DrawTank(player[i].pos.x,player[i].pos.y,player[i].pos.rot,i);
- X XFlush(Disp);
- X }
- X /* update current position */
- X cur.x=player[myid].pos.x;
- X cur.y=player[myid].pos.y;
- X cur.rot=player[myid].pos.rot;
- X
- X /* remove any 'spare' data from the pipe */
- X if(read(pd[0],&garbage,sizeof(POSITION))==-1)
- X {
- X if((errno!=EWOULDBLOCK)&&(errno!=EAGAIN))
- X perror("read pd[0]");
- X }
- X
- X /* tell our 'other half' about our new position */
- X if(write(pd[1],&cur,sizeof(POSITION))==-1)
- X perror("write pd[0]");
- X break;
- X case T_ACCEPT:
- X for(i=0;i<MAXUSERS;i++)
- X {
- X if((*(player[i].user.username)!='\0')&&(*(rdata.extra.accept.players[i].username)=='\0'))
- X {
- X WipeTank(player[i].pos.x,player[i].pos.y,player[i].pos.rot,i);
- X /*DrawRadarSq(player[i].pos.x/OBJECTSCALE,player[i].pos.x/OBJECTSCALE,1);*/
- X }
- X strcpy(player[i].user.username,rdata.extra.accept.players[i].username);
- X strcpy(player[i].user.hostname,rdata.extra.accept.players[i].hostname);
- X player[i].kills=INSWAP(rdata.extra.accept.kills[i]);
- X player[i].killed=INSWAP(rdata.extra.accept.killed[i]);
- X }
- X RefreshRWin(1);
- X RefreshSWin(1);
- X break;
- X case T_EXPLOSION:
- X damage=INSWAP(rdata.extra.explosion.damage[myid]);
- X RefreshAWin(1);
- X for(i=0;i<MAXUSERS;i++)
- X {
- X if(exptime[i]==(-1))
- X {
- X ex[i]=INSWAP(rdata.extra.explosion.x)-(cur.scx*OBJECTSCALE);
- X ey[i]=INSWAP(rdata.extra.explosion.y)-(cur.scy*OBJECTSCALE);
- X
- X if((ex[i]<(-1*EXPSIZE))||(ey[i]<(-1*EXPSIZE))||(ex[i]>(MAINX+EXPSIZE))||(ey[i]>(EXPSIZE+MAINY)))
- X break;
- X exptime[i]=gettime();
- X break;
- X }
- X }
- X break;
- X case T_MESSAGE:
- X strcpy(message,rdata.extra.message.text);
- X RefreshMWin(1);
- X break;
- X case T_ALIVE:
- X sdata.type=OUTSWAP(T_ALIVE);
- X senddata(ssd,&sdata);
- X break;
- X default:
- X printf("Unexpected datagram type %d (0x%x)\n",INSWAP(rdata.type),INSWAP(rdata.type));
- X }
- X}
- X
- X
- Xint
- XEventHandle() /* handle X events */
- X{
- X XEvent Evnt;
- X
- X XNextEvent(Disp,&Evnt);
- X
- X if(read(pd[0],&cur,sizeof(POSITION))==-1)
- X {
- X if((errno!=EWOULDBLOCK)&&(errno!=EAGAIN))
- X perror("read pd[0]");
- X }
- X
- X switch(Evnt.type)
- X {
- X case ButtonPress:
- X {
- X int bno;
- X XButtonEvent *BEvent;
- X BEvent=(XButtonEvent*)(&Evnt);
- X bno=BEvent->button;
- X if(BEvent->window==FWin)
- X {
- X mrot=GetAngle(cur.x,cur.y,msx,msy);
- X switch(bno)
- X {
- X case 1:
- X if(damage<MAXDAMAGE)
- X fire=1;
- X break;
- X case 2:
- X motion=invert;
- X break;
- X case 3:
- X motion=0-invert;
- X break;
- X }
- X sendstatus();
- X }
- X else
- X {
- X if(BEvent->window==QWin)
- X switch(bno)
- X {
- X case 1:
- X signoff(0,QUIT);
- X break;
- X case 2:
- X /* DEBUG */
- X printf("cur.scx,cur.scy=%d,%d msx,msy=%d,%d\n",cur.scx,cur.scy,msx,msy);
- X printf("tankx,tanky=%d,%d\n",cur.x,cur.y);
- X break;
- X }
- X }
- X }
- X break;
- X case ButtonRelease:
- X {
- X int bno;
- X XButtonEvent *BEvent;
- X BEvent=(XButtonEvent*)(&Evnt);
- X bno=BEvent->button;
- X
- X if(BEvent->window==FWin)
- X {
- X mrot=GetAngle(cur.x,cur.y,msx,msy);
- X switch(bno)
- X {
- X case 1:
- X fire=0;
- X sendstatus();
- X break;
- X case 2:
- X if(motion==invert)
- X {
- X motion=0;
- X sendstatus();
- X }
- X break;
- X case 3:
- X if(motion==(0-invert))
- X {
- X motion=0;
- X sendstatus();
- X }
- X break;
- X }
- X }
- X else
- X {
- X printf("Button release outside battlefield\n");
- X }
- X }
- X break;
- X case MotionNotify:
- X {
- X XMotionEvent *MEvent;
- X MEvent=(XMotionEvent*)(&Evnt);
- X msx=(MEvent->x)+(cur.scx*OBJECTSCALE);
- X msy=(MEvent->y)+(cur.scy*OBJECTSCALE);
- X mrot=GetAngle(cur.x,cur.y,msx,msy);
- X if(MEvent->window==FWin)
- X {
- X if((MEvent->time-movetime)>100)
- X {
- X sendstatus();
- X movetime=MEvent->time;
- X }
- X }
- X else
- X {
- X printf("Mouse movement outside battlefield\n");
- X }
- X }
- X break;
- X case GraphicsExpose:
- X case Expose:
- X {
- X XExposeEvent *EEvent;
- X EEvent=(XExposeEvent*)(&Evnt);
- X if(EEvent->count==0)
- X {
- X DoRefresh(EEvent->window);
- X }
- X }
- X break;
- X case DestroyNotify:
- X {
- X XDestroyWindowEvent *XDEvent;
- X XDEvent=(XDestroyWindowEvent*)(&Evnt);
- X signoff(0,DESTROYED);
- X }
- X break;
- X case KeyPress:
- X case KeyRelease:
- X {
- X char buf[2];
- X int oldinvert;
- X XKeyEvent *KEvent;
- X
- X buf[1]='\0';
- X KEvent=(XKeyEvent*)(&Evnt);
- X XLookupString(KEvent,buf,1,NULL,NULL);
- X if(*buf==0x03)
- X signoff(0,QUIT);
- X oldinvert=invert;
- X if(Evnt.type==KeyPress)
- X invert=(-1);
- X else
- X invert=1;
- X if(oldinvert!=invert)
- X {
- X motion=0-motion;
- X sendstatus();
- X }
- X }
- X break;
- X default:
- X/* fprintf(stderr,"Unknown Event\n");*/
- X break;
- X }
- X}
- X
- Xvoid
- XCreatePixmaps()
- X{
- X int i,j;
- X int rot;
- X XGCValues gcv;
- X GC GcPF,GcPB;
- X Pixmap Dummy;
- X
- X if(pixflag)
- X {
- X Dummy=XCreatePixmap(Disp,Win,PIXSIZE,PIXSIZE,1);
- X gcv.function = GXcopy;
- X gcv.plane_mask =AllPlanes;
- X gcv.fill_style = FillSolid;
- X GcPF=XCreateGC(Disp,Dummy,(GCFunction | GCPlaneMask | GCFillStyle),&gcv);
- X XSetForeground(Disp,GcPF,1);
- X XSetBackground(Disp,GcPF,0);
- X
- X GcPB=XCreateGC(Disp,Dummy,(GCFunction | GCPlaneMask | GCFillStyle),&gcv);
- X XSetForeground(Disp,GcPB,0);
- X XSetBackground(Disp,GcPB,1);
- X
- X for(i=0;i<TANKROT;i++)
- X {
- X TankPix[i]=XCreatePixmap(Disp,Win,PIXSIZE,PIXSIZE,1);
- X if(TankPix[i]==BadAlloc)
- X {
- X /* no memory for pixmaps on server */
- X fprintf(stderr,"Failed to allocate pixmaps(%d)(%d*%d*%d), using polygons instead\n",i,PIXSIZE,PIXSIZE,1);
- X /* free currently allocated pixmaps */
- X for(j=0;j<i;j++)
- X XFreePixmap(Disp,TankPix[j]);
- X pixflag=0;
- X polyflag=1;
- X break;
- X }
- X rot=(i+TANKROT+(TANKROT/4))%TANKROT;
- X Tank[rot].coord[0].x=PIXSIZE/2;
- X Tank[rot].coord[0].y=PIXSIZE/2;
- X XFillRectangle(Disp,TankPix[i],GcPB,0,0,PIXSIZE,PIXSIZE);
- X XFillPolygon(Disp,TankPix[i],GcPF,&Tank[rot],TANKPOINTS,Nonconvex,CoordModePrevious);
- X }
- X /* no longer needed */
- X XFreeGC(Disp,GcPF);
- X XFreeGC(Disp,GcPB);
- X XFreePixmap(Disp,Dummy);
- X }
- X}
- X
- X
- XXinit(Name,xs,ys) /* initialise X */
- Xchar *Name;
- Xint xs,ys;
- X{
- X unsigned long bg,fg;
- X Cursor Curs;
- X XGCValues gcv;
- X char *DisplayName;
- X Pixmap iconised;
- X XWMHints hint;
- X int i;
- X
- X DisplayName=getenv("DISPLAY");
- X if(DisplayName==NULL)
- X {
- X fprintf(stderr,"%s: $DISPLAY not set\n",progname);
- X exit(1);
- X }
- X
- X Disp=XOpenDisplay(DisplayName);
- X
- X if(Disp==NULL)
- X {
- X fprintf(stderr,"%s: Unable to open $DISPLAY (%s)\n",progname,DisplayName);
- X exit(1);
- X }
- X
- X Root=XDefaultRootWindow(Disp);
- X Scr=DefaultScreen(Disp);
- X
- X /* if user has specified no defaults */
- X if((!polyflag)&&(!pixflag))
- X {
- X pixflag=1;
- X polyflag=0;
- X }
- X
- X fg=BlackPixel(Disp,Scr);
- X bg=WhitePixel(Disp,Scr);
- X
- X /* Main (parent window */
- X Win=XCreateSimpleWindow(Disp,Root,0,0,xs,ys,2,fg,bg);
- X /* Radar window */
- X RWin=XCreateSimpleWindow(Disp,Win,BOARDER,BOARDER,RADARSIZE,RADARSIZE,1,fg,bg);
- X /* Field window */
- X FWin=XCreateSimpleWindow(Disp,Win,BOARDER*4+RADARSIZE,BOARDER,MAINX,MAINY,1,fg,bg);
- X /* Armour status window */
- X AWin=XCreateSimpleWindow(Disp,Win,BOARDER,BOARDER*4+RADARSIZE,RADARSIZE-2,DAMAGEBAR,2,fg,bg);
- X /* Quit window */
- X QWin=XCreateSimpleWindow(Disp,Win,BOARDER,BOARDER*5+RADARSIZE+DAMAGEBAR,RADARSIZE-2,MESSAGESIZE,2,fg,bg);
- X /* Message window */
- X MWin=XCreateSimpleWindow(Disp,Win,BOARDER,BOARDER*6+MESSAGESIZE+RADARSIZE+DAMAGEBAR,RADARSIZE,MESSAGESIZE,1,fg,bg);
- X /* Status window */
- X SWin=XCreateSimpleWindow(Disp,Win,BOARDER,BOARDER*7+MESSAGESIZE*2+RADARSIZE+DAMAGEBAR,RADARSIZE,15*(MAXUSERS+1),1,fg,bg);
- X
- X /* Main vertical and horizontal scroll bars */
- X VSb=XCreateSimpleWindow(Disp,Win,BOARDER*5+RADARSIZE+MAINX,BOARDER,SCROLLBAR,MAINY-2,2,fg,bg);
- X HSb=XCreateSimpleWindow(Disp,Win,BOARDER*4+RADARSIZE,BOARDER*2+MAINY,MAINX-2,SCROLLBAR,2,fg,bg);
- X /* Radar vertical and horizontal scroll bars */
- X RVSb=XCreateSimpleWindow(Disp,Win,BOARDER*2+RADARSIZE,BOARDER,BOARDER,RADARSIZE,1,fg,bg);
- X RHSb=XCreateSimpleWindow(Disp,Win,BOARDER,BOARDER*2+RADARSIZE,RADARSIZE,BOARDER,1,fg,bg);
- X
- X
- X XStoreName(Disp,Win,Name);
- X
- X gcv.function = GXcopy;
- X gcv.plane_mask = AllPlanes;
- X gcv.fill_style = FillSolid;
- X
- X GcF=XCreateGC(Disp,Win,(GCFunction | GCPlaneMask | GCFillStyle),&gcv);
- X GcB=XCreateGC(Disp,Win,(GCFunction | GCPlaneMask | GCFillStyle),&gcv);
- X
- X XSetForeground(Disp,GcF,fg);
- X XSetBackground(Disp,GcF,bg);
- X XSetForeground(Disp,GcB,bg);
- X XSetBackground(Disp,GcB,fg);
- X
- X gcv.function = GXor;
- X GcTF=XCreateGC(Disp,Win,(GCFunction | GCPlaneMask | GCFillStyle),&gcv);
- X
- X gcv.function = GXandInverted;
- X GcTB=XCreateGC(Disp,Win,(GCFunction | GCPlaneMask | GCFillStyle),&gcv);
- X
- X XSetForeground(Disp,GcTF,fg);
- X XSetBackground(Disp,GcTF,bg);
- X XSetForeground(Disp,GcTB,fg);
- X XSetBackground(Disp,GcTB,bg);
- X
- X Curs=XCreateFontCursor(Disp,XC_crosshair);
- X XDefineCursor(Disp,Win,Curs);
- X iconised=XCreateBitmapFromData(Disp,Win,xtb_bits,xtb_width,xtb_height);
- X hint.flags=(InputHint|IconPixmapHint);
- X hint.input=True;
- X hint.icon_pixmap=iconised;
- X XSetWMHints(Disp,Win,&hint);
- X CreatePixmaps();
- X
- X XSetIOErrorHandler(doXio);
- X}
- X
- Xvoid
- XSelectAllInputs()
- X{
- X XSelectInput(Disp,Win,ExposureMask|StructureNotifyMask);
- X XSelectInput(Disp,RWin,ExposureMask);
- X XSelectInput(Disp,FWin,FieldEventMask);
- X XSelectInput(Disp,QWin,ButtonMask|ExposureMask|StructureNotifyMask);
- X XSelectInput(Disp,SWin,ExposureMask);
- X
- X XSelectInput(Disp,VSb,ExposureMask);
- X XSelectInput(Disp,HSb,ExposureMask);
- X XSelectInput(Disp,RVSb,ExposureMask);
- X XSelectInput(Disp,RHSb,ExposureMask);
- X XSelectInput(Disp,AWin,ExposureMask);
- X XSelectInput(Disp,MWin,ExposureMask);
- X}
- X
- Xvoid
- XMapAllWindows() /* obvious */
- X{
- X XMapWindow(Disp,Win);
- X XMapWindow(Disp,FWin);
- X XMapWindow(Disp,RWin);
- X XMapWindow(Disp,SWin);
- X XMapWindow(Disp,QWin);
- X
- X XMapWindow(Disp,VSb);
- X XMapWindow(Disp,HSb);
- X XMapWindow(Disp,RVSb);
- X XMapWindow(Disp,RHSb);
- X XMapWindow(Disp,AWin);
- X XMapWindow(Disp,MWin);
- X
- X XFlush(Disp);
- X}
- X
- X
- Xmain(argc,argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int i,j;
- X char *p;
- X
- X int inport,outport;
- X int fieldok;
- X progname=argv[0];
- X
- X server=getenv("XTB_SERVER");
- X
- X p=getenv("XTB_INPORT");
- X if(p!=NULL)
- X inport=atoi(p);
- X else
- X inport=DEFCPORT;
- X
- X p=getenv("XTB_OUTPORT");
- X if(p!=NULL)
- X outport=atoi(p);
- X else
- X outport=DEFSPORT;
- X
- X for(i=1;i<argc;i++)
- X {
- X p=argv[i];
- X if(*p++=='-')
- X {
- X switch(*p++)
- X {
- X case 'i': /* input/client port */
- X case 'c':
- X if(*p=='\0')
- X inport=atoi(argv[++i]);
- X else
- X inport=atoi(p);
- X break;
- X case 'o': /* output/server port */
- X case 's':
- X if(*p=='\0')
- X outport=atoi(argv[++i]);
- X else
- X outport=atoi(p);
- X break;
- X case 'h':
- X if(*p=='\0')
- X server=argv[++i];
- X else
- X server=p;
- X break;
- X case 'w':
- X warpflag++;
- X break;
- X case 'd':
- X debug++;
- X break;
- X case 'b': /* use pixmaps for drawing tanks */
- X pixflag++;
- X break;
- X case 'p': /* use polygons for drawing tanks */
- X polyflag++;
- X break;
- X default:
- X fprintf(stderr,"Usage: %s [-h server_host] [-w] [-c client_portno] [-s server_portno] \n",argv[0]);
- X }
- X }
- X }
- X
- X if(server==NULL)
- X {
- X fprintf(stderr,"%s: No server host (-h or $XTB_SERVER) defined\n",argv[0]);
- X exit(1);
- X }
- X
- X rsd=openread(inport);
- X if(rsd==(-1))
- X {
- X fprintf(stderr,"%s: Opening port %d failed\n",argv[0],inport);
- X exit(1);
- X }
- X
- X ssd=opensend(server,outport);
- X if(ssd==(-1))
- X {
- X fprintf(stderr,"%s: Connecting to %s/%d failed\n",argv[0],server,outport);
- X exit(1);
- X }
- X
- X for(i=0;i<MAXUSERS;i++)
- X exptime[i]=(-1);
- X InitTables();
- X Xinit("XTankBattle",MAINX+RADARSIZE+6*BOARDER+SCROLLBAR,MAINY+3*BOARDER+SCROLLBAR);
- X
- X /* signon */
- X sdata.type=OUTSWAP(T_SIGNON);
- X sdata.extra.signon.version=OUTSWAP(VERSION);
- X sdata.extra.signon.port=OUTSWAP(inport); /* could be different to server port */
- X gethostname(sdata.extra.signon.hostname,HOSTLEN);
- X strncpy(sdata.extra.signon.username,((struct passwd*)getpwuid(getuid()))->pw_name,NAMELEN-1);
- X sdata.extra.signon.username[NAMELEN]='\0';
- X
- X signal(SIGALRM,timeout);
- X alarm(3);
- X senddata(ssd,&sdata);
- X
- X if(readdata(rsd,&rdata)!=sizeof(DATA))
- X {
- X fprintf(stderr,"%s: Recieved bad data\n");
- X exit(1);
- X }
- X alarm(0);
- X switch(INSWAP(rdata.type))
- X {
- X case T_ACCEPT:
- X if(debug)
- X {
- X printf("accept\n");
- X printf("My id is %d\n",INSWAP(rdata.extra.accept.id));
- X }
- X myid=INSWAP(rdata.extra.accept.id);
- X for(i=0;i<MAXUSERS;i++)
- X {
- X strcpy(player[i].user.username,rdata.extra.accept.players[i].username);
- X strcpy(player[i].user.hostname,rdata.extra.accept.players[i].hostname);
- X player[i].kills=INSWAP(rdata.extra.accept.kills[i]);
- X player[i].killed=INSWAP(rdata.extra.accept.killed[i]);
- X }
- X break;
- X case T_REJECT:
- X fprintf(stderr,"reject\n");
- X fprintf(stderr,"reason: %s\n",rdata.extra.reject.text);
- X exit(1);
- X break;
- X default:
- X if(debug)
- X printf("Unknown datagram type %d (0x%x)\n",INSWAP(rdata.type),INSWAP(rdata.type));
- X }
- X
- X for(i=0;i<OBJECTSIZE;i++)
- X for(j=0;j<OBJECTSIZE;j++)
- X radar[i][j]=0;
- X for(i=0;i<OBJECTSIZE;i++)
- X field[i][0]=UNSET;
- X
- X MapAllWindows();
- X
- X if(debug)
- X printf("Getting field data\n");
- X sdata.id=OUTSWAP(myid);
- X sdata.type=OUTSWAP(T_DATAREQ);
- X
- X do
- X {
- X fieldok=1;
- X for(i=0;i<OBJECTSIZE;i++)
- X {
- X if(field[i][0]==UNSET)
- X {
- X fflush(stdout);
- X fieldok=0;
- X sdata.extra.datareq.lineno=OUTSWAP(i);
- X senddata(ssd,&sdata);
- X if(readdata(rsd,&rdata)!=sizeof(DATA))
- X {
- X fprintf(stderr,"%s: Recieved bad data\n",argv[0]);
- X exit(1);
- X }
- X if(INSWAP(rdata.type)!=T_FIELDDATA)
- X {
- X if(INSWAP(rdata.type)==T_MESSAGE)
- X strcpy(message,rdata.extra.message.text);
- X else
- X fprintf(stderr,"%s: Expected field data got 0x%x\n",argv[0],INSWAP(rdata.type));
- X }
- X else
- X {
- X if(debug)
- X {
- X if(INSWAP(rdata.extra.field.lineno)!=i)
- X printf("%%%d",INSWAP(rdata.extra.field.lineno));
- X else
- X printf(".%d",i);
- X }
- X memcpy(field[INSWAP(rdata.extra.field.lineno)],rdata.extra.field.object,OBJECTSIZE);
- X }
- X }
- X }
- X }
- X while(!fieldok);
- X putchar('\n');
- X
- X if(pipe(pd)==(-1))
- X {
- X fprintf(stderr,"%s: pipe(pd) failed\n",argv[0]);
- X exit(1);
- X }
- X
- X /* make read pipe descripter non-blocking */
- X i=1;
- X if(ioctl(pd[0],FIONBIO,&i)==-1)
- X {
- X fcntl(pd[0],F_SETFL,O_NDELAY);
- X }
- X
- X ppid=getpid();
- X
- X signal(SIGHUP,dointr);
- X signal(SIGINT,dointr);
- X signal(SIGTERM,dointr);
- X RefreshRWin(0);
- X RefreshSWin(0);
- X RefreshQWin(0);
- X RefreshVSb(0);
- X RefreshHSb(0);
- X RefreshRVSb(0);
- X RefreshRHSb(0);
- X RefreshAWin(0);
- X RefreshMWin(0);
- X
- X switch(cpid=fork())
- X {
- X case 0: /* child */
- X /* server -> socket -> X display */
- X cpid=getpid();
- X Disp=XOpenDisplay(getenv("DISPLAY"));
- X
- X while(1)
- X {
- X SocketHandle();
- X }
- X break;
- X
- X case -1: /* error */
- X fprintf(stderr,"%s: Couldn't fork()\n",argv[0]);
- X exit(1);
- X break;
- X
- X default:/* parent */
- X /* X events -> socket -> server */
- X SelectAllInputs();
- X while(1)
- X EventHandle();
- X break;
- X }
- X}
- END_OF_FILE
- if test 31436 -ne `wc -c <'xtb.c'`; then
- echo shar: \"'xtb.c'\" unpacked with wrong size!
- fi
- # end of 'xtb.c'
- fi
- echo shar: End of archive 1 \(of 2\).
- cp /dev/null ark1isdone
- 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
-