home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume15
/
xtb
/
part01
/
rtb.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-27
|
12KB
|
620 lines
/*
* Robot tank
*
* $Header: /morpork/home/bmh/xtest2/RCS/rtb.c,v 1.7 92/10/19 15:34:30 bmh Exp Locker: bmh $
*
* Bernard Hatt
* Camtec Electronics (Ericsson), Leicester, England, LE1 4SA
* bmh@terminus.ericsson.se
*
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <ctype.h>
#include <math.h>
#include <pwd.h>
#include "defs.h"
#include "comms.h"
int debug=0;
PLAYER player[MAXUSERS]; /* players tanks */
char field[OBJECTSIZE][OBJECTSIZE];
char radar[OBJECTSIZE][OBJECTSIZE];
int distance=0;
int fire=0; /* fire button pressed */
int motion=0; /* tank linear motion */
int mrot=0; /* mouse pointer rotation */
int damage=0; /* damage sustained */
char message[BUFLEN]=""; /* message for message window */
char *server=NULL;
POSITION cur={0,300,100,0,0};
POSITION last;
int myid;
int rsd,ssd;
DATA rdata,sdata;
int savedx=(-1),savedy=(-1);
int sfx=(-1),sfy=(-1);
int lastsend=0;
int robots=0; /* attack other robots */
int humans=1; /* attack humans */
int ex[MAXUSERS],ey[MAXUSERS],exptime[MAXUSERS];
typedef struct child_struct
{
int pid;
int portno;
} CHILD;
CHILD child[MAXROBOTS];
char *progname;
int stuck=0;
void
signoff(t,reason) /* send signoff to server and exit */
int t,reason;
{
sdata.id=OUTSWAP(myid);
sdata.type=OUTSWAP(T_SIGNOFF);
sdata.extra.signoff.reason=OUTSWAP(reason);
senddata(ssd,&sdata);
if(t!=0)
sleep(t);
exit(0);
}
void
dointr() /* action on interrupt */
{
signoff(0,DESTROYED);
}
void
doXio()
{
signoff(0,QUIT);
}
void
timeout() /* timeout on connect */
{
fprintf(stderr,"%s: No response from server \"%s\" (not running/busy?)\n",progname,server);
exit(1);
}
void
sendstatus() /* send our status to the server */
{
sdata.type=OUTSWAP(T_MOVE);
sdata.id=OUTSWAP(myid);
sdata.extra.move.rot=OUTSWAP(mrot);
sdata.extra.move.linear=OUTSWAP(motion);
sdata.extra.move.fire=OUTSWAP(fire);
senddata(ssd,&sdata);
lastsend=gettime();
}
int
isclear(x1,y1,x2,y2) /* is it clear between (x1,y1) and (x2,y2) */
int x1,y1,x2,y2;
{
int i;
int x,y;
int fx,fy;
if((x1<0)||(x1>=MAINSIZE))
return(0);
if((y1<0)||(y1>=MAINSIZE))
return(0);
for(i=0;i<16;i++)
{
x=x1+(((x2-x1)*i)/16);
y=y1+(((y2-y1)*i)/16);
fx=x/OBJECTSCALE;
fy=y/OBJECTSCALE;
if(field[fx][fy]==BLOCKED)
return(0);
}
return(1);
}
void
domymove()
{
int i;
int sqdist,ang;
int dx,dy,cansee,offset;
int cang,cdist=(-1),cid;
int omotion,ofire,omrot,cx,cy;
int sid=(-1),sang,sdist;
ofire=fire;
omotion=motion;
omrot=mrot;
for(i=0;i<MAXUSERS;i++)
{
if(i==myid)
continue;
if(*player[i].user.username=='\0')
continue;
if(*player[i].user.username=='R')
{
if(!robots)
continue;
}
else
{
if(!humans)
continue;
}
dx=player[i].pos.x-cur.x;
dy=player[i].pos.y-cur.y;
sqdist=(dx*dx)+(dy*dy);
ang=GetAngle(0,0,dx,dy);
if(sqdist<(OBJECTSCALE*OBJECTSCALE*16))
{
if(isclear(cur.x,cur.y,player[i].pos.x,player[i].pos.y))
{
sid=i;
sang=ang;
sdist=sqdist;
}
}
if((cdist>sqdist)||(cdist==(-1)))
{
cang=ang;
cdist=sqdist;
cid=i;
}
}
fire=0;
if(cdist!=-1)
{
if(debug)
printf("Closest id %d ang %3d\t",cid,cang);
if(sid!=(-1))
{
mrot=sang;
distance=0;
if(sang==cur.rot)
{
fire=1;
if(sdist<(OBJECTSCALE*OBJECTSCALE*14))
motion=1;
}
if(debug)
{
putchar('F');
}
}
else
{
if(distance!=0)
distance--;
else
mrot=cang;
cx=player[cid].pos.x;
cy=player[cid].pos.y;
if((last.x!=cur.x)||(last.y!=cur.y)||(mrot!=cur.rot))
{
motion=(-1);
if(isclear(cur.x,cur.y,cx,cy))
{
if(debug)
putchar('V');
mrot=cang;
}
else
{
if(distance==0)
{
if(debug)
putchar('M');
mrot=cang;
}
else
{
if(debug)
printf("D%d",distance);
}
}
}
else
{
if(distance==0)
{
if(stuck>32)
stuck=0;
stuck++;
offset=(stuck*OBJECTSCALE/2);
if(isclear(cur.x-offset,cur.y,cx,cy))
{
mrot=0;
motion=(-1);
if(debug)
putchar('W');
distance=stuck*2;
}
else
if(isclear(cur.x+offset,cur.y,cx,cy))
{
mrot=64;
motion=(-1);
if(debug)
putchar('E');
distance=stuck*2;
}
else
if(isclear(cur.x,cur.y-offset,cx,cy))
{
mrot=32;
motion=(-1);
if(debug)
putchar('N');
distance=stuck*2;
}
else
if(isclear(cur.x,cur.y+offset,cx,cy))
{
mrot=96;
motion=(-1);
if(debug)
putchar('S');
distance=stuck*2;
}
}
if((last.x==cur.x)&&(last.y==cur.y)&&(mrot==cur.rot)&&(motion!=0)&&(!fire))
{ /* stuck */
distance=rnd(20)+10;
motion==(-1);
mrot=rnd(TANKROT);
if(debug)
putchar('R');
}
}
}
if(debug)
printf("\tang=%2d motion=%2d %s\n",mrot,motion,fire?"FIRE":"");
}
if((fire!=ofire)||(motion!=omotion)||(mrot!=omrot))
{
sendstatus();
}
last.x=cur.x;
last.y=cur.y;
last.rot=cur.rot;
}
int
SocketHandle() /* handle data from the server incomming on the socket */
{
int i,j;
if(readdata(rsd,&rdata)!=sizeof(DATA))
{
fprintf(stderr,"%s: Recieved bad data\n");
exit(1);
}
switch(INSWAP(rdata.type))
{
case T_REPLY:
for(i=0;i<MAXUSERS;i++)
{
if(INSWAP(rdata.extra.reply.pos[i].x)==-1)
continue;
player[i].pos.x=INSWAP(rdata.extra.reply.pos[i].x);
player[i].pos.y=INSWAP(rdata.extra.reply.pos[i].y);
player[i].pos.rot=INSWAP(rdata.extra.reply.pos[i].rot);
}
/* update current position */
cur.x=player[myid].pos.x;
cur.y=player[myid].pos.y;
cur.rot=player[myid].pos.rot;
break;
case T_ACCEPT:
for(i=0;i<MAXUSERS;i++)
{
strcpy(player[i].user.username,rdata.extra.accept.players[i].username);
strcpy(player[i].user.hostname,rdata.extra.accept.players[i].hostname);
player[i].kills=INSWAP(rdata.extra.accept.kills[i]);
player[i].killed=INSWAP(rdata.extra.accept.killed[i]);
}
break;
case T_EXPLOSION:
damage=INSWAP(rdata.extra.explosion.damage[myid]);
if(debug)
printf("Explosion: damage is %d\n",damage);
if(damage>=MAXDAMAGE)
{
if(debug)
printf("Explosion: killed\n");
signoff(5,KILLED);
}
break;
case T_MESSAGE:
if(debug)
printf("Message: %s\n",rdata.extra.message.text);
break;
case T_ALIVE:
sdata.type=OUTSWAP(T_ALIVE);
senddata(ssd,&sdata);
break;
default:
if(debug)
printf("Unexpected datagram type %d (0x%x)\n",INSWAP(rdata.type),INSWAP(rdata.type));
}
if((gettime()-lastsend)>20)
domymove();
}
main(argc,argv)
int argc;
char *argv[];
{
int i,j;
int n=1,cpid,ppid,cstatus;
int restart;
char *p;
int inport,outport;
int fieldok;
progname=argv[0];
server=getenv("XTB_SERVER");
p=getenv("XTB_INPORT");
if(p!=NULL)
inport=atoi(p);
else
inport=DEFRPORT;
p=getenv("XTB_OUTPORT");
if(p!=NULL)
outport=atoi(p);
else
outport=DEFSPORT;
for(i=1;i<argc;i++)
{
p=argv[i];
if(*p++=='-')
{
switch(*p++)
{
case 'i': /* input/client port */
case 'c':
if(*p=='\0')
inport=atoi(argv[++i]);
else
inport=atoi(p);
break;
case 'o': /* output/server port */
case 's':
if(*p=='\0')
outport=atoi(argv[++i]);
else
outport=atoi(p);
break;
case 'h':
if(*p=='\0')
server=argv[++i];
else
server=p;
break;
case 'n': /* number of robots */
if(*p=='\0')
n=atoi(argv[++i]);
else
n=atoi(p);
if(n<0)
n=1;
if(n>MAXROBOTS)
n=MAXROBOTS;
break;
case 'r': /* restart if killed */
break;
case 'v': /* viciousness */
break;
case 'd': /* debug */
debug++;
break;
case 'R':
robots=!robots;
break;
case 'H':
humans=!humans;
break;
default:
fprintf(stderr,"Usage: %s [-h server_host] [-c client_portno] [-s server_portno] \n",argv[0]);
}
}
}
if(server==NULL)
{
fprintf(stderr,"%s: No server host (-h or $XTB_SERVER) defined\n",argv[0]);
exit(1);
}
ppid=getpid();
/* fork off children, recording port number and pid */
for(j=0;j<n;j++)
{
cpid=fork();
if(cpid==0)
break;
child[j].pid=cpid;
child[j].portno=inport;
if(debug)
printf("Child %d pid=%d\n",j,child[j].pid);
sleep(1);
inport++;
}
/* if we're the parent, wait for children and restart */
if(getpid()==ppid)
{
while(1)
{
restart=(-1);
cpid=wait(&cstatus);
if(debug)
printf("Child pid %d died\n",cpid);
for(j=0;j<n;j++)
if(cpid==child[j].pid)
restart=j;
if(restart!=(-1))
{
/* re fork */
inport=child[restart].portno;
sleep(5);
cpid=fork();
if(cpid==0)
break;
child[restart].pid=cpid;
if(debug)
printf("Restart %d pid=%d\n",restart,child[restart].pid);
}
}
}
rsd=openread(inport);
if(rsd==(-1))
{
fprintf(stderr,"%s: Opening port %d failed\n",argv[0],inport);
exit(1);
}
ssd=opensend(server,outport);
if(ssd==(-1))
{
fprintf(stderr,"%s: Connecting to %s/%d failed\n",argv[0],server,outport);
exit(1);
}
for(i=0;i<MAXUSERS;i++)
exptime[i]=(-1);
/* signon */
sdata.type=OUTSWAP(T_SIGNON);
sdata.extra.signon.version=OUTSWAP(VERSION);
sdata.extra.signon.port=OUTSWAP(inport); /* could be different to server port */
gethostname(sdata.extra.signon.hostname,HOSTLEN);
sprintf(sdata.extra.signon.username,"ROBOT%04d",inport);
signal(SIGALRM,timeout);
alarm(3);
senddata(ssd,&sdata);
if(readdata(rsd,&rdata)!=sizeof(DATA))
{
fprintf(stderr,"%s: Recieved bad data\n");
exit(1);
}
alarm(0);
switch(INSWAP(rdata.type))
{
case T_ACCEPT:
if(debug)
printf("accept\nMy id is %d\n",INSWAP(rdata.extra.accept.id));
myid=INSWAP(rdata.extra.accept.id);
for(i=0;i<MAXUSERS;i++)
{
strcpy(player[i].user.username,rdata.extra.accept.players[i].username);
strcpy(player[i].user.hostname,rdata.extra.accept.players[i].hostname);
player[i].kills=INSWAP(rdata.extra.accept.kills[i]);
player[i].killed=INSWAP(rdata.extra.accept.killed[i]);
}
break;
case T_REJECT:
printf("reject\n");
printf("reason: %s\n",rdata.extra.reject.text);
exit(1);
break;
default:
if(debug)
printf("Unknown datagram type %d (0x%x)\n",INSWAP(rdata.type),INSWAP(rdata.type));
}
for(i=0;i<OBJECTSIZE;i++)
for(j=0;j<OBJECTSIZE;j++)
radar[i][j]=0;
for(i=0;i<OBJECTSIZE;i++)
field[i][0]=UNSET;
if(debug)
printf("Getting field data\n");
sdata.id=OUTSWAP(myid);
sdata.type=OUTSWAP(T_DATAREQ);
do
{
fieldok=1;
for(i=0;i<OBJECTSIZE;i++)
{
if(field[i][0]==UNSET)
{
fflush(stdout);
fieldok=0;
sdata.extra.datareq.lineno=OUTSWAP(i);
senddata(ssd,&sdata);
if(readdata(rsd,&rdata)!=sizeof(DATA))
{
fprintf(stderr,"%s: Recieved bad data\n",argv[0]);
exit(1);
}
if(INSWAP(rdata.type)!=T_FIELDDATA)
{
if(INSWAP(rdata.type)==T_MESSAGE)
{
if(debug)
printf("Message: %s\n",rdata.extra.message.text);
}
else
if(debug)
printf("%s: Expected field data got 0x%x\n",argv[0],INSWAP(rdata.type));
}
else
{
if(debug)
{
if(INSWAP(rdata.extra.field.lineno)!=i)
printf("%%%d",INSWAP(rdata.extra.field.lineno));
else
printf(".%d",i);
}
memcpy(field[INSWAP(rdata.extra.field.lineno)],rdata.extra.field.object,OBJECTSIZE);
}
}
}
}
while(!fieldok);
if(debug)
putchar('\n');
signal(SIGHUP,dointr);
signal(SIGINT,dointr);
signal(SIGTERM,dointr);
while(1)
{
SocketHandle();
}
}