home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume15 / xtb / part01 / rtb.c < prev    next >
C/C++ Source or Header  |  1993-01-27  |  12KB  |  620 lines

  1. /*
  2.  * Robot tank
  3.  *
  4.  * $Header: /morpork/home/bmh/xtest2/RCS/rtb.c,v 1.7 92/10/19 15:34:30 bmh Exp Locker: bmh $
  5.  *
  6.  * Bernard Hatt
  7.  * Camtec Electronics (Ericsson), Leicester, England, LE1 4SA
  8.  * bmh@terminus.ericsson.se
  9.  *
  10.  */
  11. #include <stdio.h>
  12. #include <sys/types.h>
  13. #include <sys/wait.h>
  14. #include <sys/ioctl.h>
  15. #include <sys/time.h>
  16. #include <netinet/in.h>
  17. #include <unistd.h>
  18. #include <fcntl.h>
  19. #include <signal.h>
  20. #include <ctype.h>
  21. #include <math.h>
  22. #include <pwd.h>
  23.  
  24. #include "defs.h"
  25. #include "comms.h"
  26.  
  27. int debug=0;
  28.  
  29. PLAYER player[MAXUSERS];    /* players tanks */
  30. char    field[OBJECTSIZE][OBJECTSIZE];
  31. char    radar[OBJECTSIZE][OBJECTSIZE];
  32.  
  33. int distance=0;
  34.  
  35. int fire=0;    /* fire button pressed */
  36. int motion=0;    /* tank linear motion */
  37. int mrot=0;    /* mouse pointer rotation */
  38. int damage=0;    /* damage sustained */
  39. char message[BUFLEN]="";    /* message for message window */
  40. char *server=NULL;
  41.  
  42. POSITION cur={0,300,100,0,0};
  43. POSITION last;
  44.  
  45. int myid;
  46. int rsd,ssd;
  47. DATA rdata,sdata;
  48. int savedx=(-1),savedy=(-1);
  49. int sfx=(-1),sfy=(-1);
  50. int lastsend=0;
  51.  
  52. int robots=0;    /* attack other robots */
  53. int humans=1;    /* attack humans */
  54.  
  55.  
  56. int ex[MAXUSERS],ey[MAXUSERS],exptime[MAXUSERS];
  57.  
  58. typedef struct child_struct
  59. {
  60.     int pid;
  61.     int portno;
  62. } CHILD;
  63.  
  64. CHILD child[MAXROBOTS];
  65.  
  66. char *progname;
  67. int stuck=0;
  68.  
  69. void
  70. signoff(t,reason)    /* send signoff to server and exit */
  71. int t,reason;
  72. {
  73.     sdata.id=OUTSWAP(myid);
  74.     sdata.type=OUTSWAP(T_SIGNOFF);
  75.     sdata.extra.signoff.reason=OUTSWAP(reason);
  76.     senddata(ssd,&sdata);
  77.     if(t!=0)
  78.         sleep(t);
  79.     exit(0);
  80. }
  81.  
  82. void
  83. dointr()    /* action on interrupt */
  84. {
  85.     signoff(0,DESTROYED);
  86. }
  87.  
  88. void
  89. doXio()
  90. {
  91.     signoff(0,QUIT);
  92. }
  93.  
  94. void
  95. timeout()    /* timeout on connect */
  96. {
  97.     fprintf(stderr,"%s: No response from server \"%s\" (not running/busy?)\n",progname,server);
  98.     exit(1);
  99. }
  100.  
  101.  
  102. void
  103. sendstatus()    /* send our status to the server */
  104. {
  105.     sdata.type=OUTSWAP(T_MOVE);
  106.     sdata.id=OUTSWAP(myid);
  107.     sdata.extra.move.rot=OUTSWAP(mrot);
  108.     sdata.extra.move.linear=OUTSWAP(motion);
  109.     sdata.extra.move.fire=OUTSWAP(fire);
  110.     senddata(ssd,&sdata);
  111.     lastsend=gettime();
  112. }
  113.  
  114.  
  115. int
  116. isclear(x1,y1,x2,y2)    /* is it clear between (x1,y1) and (x2,y2) */
  117. int x1,y1,x2,y2;
  118. {
  119.     int i;
  120.     int x,y;
  121.     int fx,fy;
  122.     if((x1<0)||(x1>=MAINSIZE))
  123.         return(0);
  124.     if((y1<0)||(y1>=MAINSIZE))
  125.         return(0);
  126.         
  127.     for(i=0;i<16;i++)
  128.     {
  129.         x=x1+(((x2-x1)*i)/16);
  130.         y=y1+(((y2-y1)*i)/16);
  131.         fx=x/OBJECTSCALE;
  132.         fy=y/OBJECTSCALE;
  133.         if(field[fx][fy]==BLOCKED)
  134.             return(0);
  135.     }
  136.     return(1);
  137. }
  138.  
  139. void
  140. domymove()
  141. {
  142.     int i;
  143.     int sqdist,ang;
  144.     int dx,dy,cansee,offset;
  145.     int cang,cdist=(-1),cid;
  146.     int omotion,ofire,omrot,cx,cy;
  147.     int sid=(-1),sang,sdist;
  148.  
  149.     ofire=fire;
  150.     omotion=motion;
  151.     omrot=mrot;
  152.     for(i=0;i<MAXUSERS;i++)
  153.     {
  154.         if(i==myid)
  155.             continue;
  156.         if(*player[i].user.username=='\0')
  157.             continue;
  158.         if(*player[i].user.username=='R')
  159.         {
  160.             if(!robots)
  161.                 continue;
  162.         }
  163.         else
  164.         {
  165.             if(!humans)
  166.                 continue;
  167.         }
  168.         dx=player[i].pos.x-cur.x;
  169.         dy=player[i].pos.y-cur.y;
  170.         sqdist=(dx*dx)+(dy*dy);
  171.         ang=GetAngle(0,0,dx,dy);
  172.         if(sqdist<(OBJECTSCALE*OBJECTSCALE*16))
  173.         {
  174.             if(isclear(cur.x,cur.y,player[i].pos.x,player[i].pos.y))
  175.             {
  176.                 sid=i;
  177.                 sang=ang;
  178.                 sdist=sqdist;
  179.             }
  180.         }
  181.         if((cdist>sqdist)||(cdist==(-1)))
  182.         {
  183.             cang=ang;
  184.             cdist=sqdist;
  185.             cid=i;
  186.         }
  187.     }
  188.     fire=0;
  189.     if(cdist!=-1)
  190.     {
  191.         if(debug)
  192.             printf("Closest id %d ang %3d\t",cid,cang);
  193.         if(sid!=(-1))
  194.         {
  195.             mrot=sang;
  196.             distance=0;
  197.             if(sang==cur.rot)
  198.             {
  199.                 fire=1;
  200.                 if(sdist<(OBJECTSCALE*OBJECTSCALE*14))
  201.                     motion=1;
  202.             }
  203.             if(debug)
  204.             {
  205.                 putchar('F');
  206.             }
  207.         }
  208.         else
  209.         {
  210.             if(distance!=0)
  211.                 distance--;
  212.             else
  213.                 mrot=cang;
  214.             cx=player[cid].pos.x;
  215.             cy=player[cid].pos.y;
  216.             if((last.x!=cur.x)||(last.y!=cur.y)||(mrot!=cur.rot))
  217.             {
  218.                 motion=(-1);
  219.                 if(isclear(cur.x,cur.y,cx,cy))
  220.                 {
  221.                     if(debug)
  222.                         putchar('V');
  223.                     mrot=cang;
  224.                 }
  225.                 else
  226.                 {
  227.                     if(distance==0)
  228.                     {
  229.                         if(debug)
  230.                             putchar('M');
  231.                         mrot=cang;
  232.                     }
  233.                     else
  234.                     {
  235.                         if(debug)
  236.                             printf("D%d",distance);
  237.                     }
  238.                 }
  239.             }
  240.             else
  241.             {
  242.                 if(distance==0)
  243.                 {
  244.                     if(stuck>32)
  245.                         stuck=0;
  246.                     stuck++;
  247.                     offset=(stuck*OBJECTSCALE/2);
  248.                     if(isclear(cur.x-offset,cur.y,cx,cy))
  249.                     {
  250.                         mrot=0;
  251.                         motion=(-1);
  252.                         if(debug)
  253.                             putchar('W');
  254.                         distance=stuck*2;
  255.                     }
  256.                     else
  257.                     if(isclear(cur.x+offset,cur.y,cx,cy))
  258.                     {
  259.                         mrot=64;
  260.                         motion=(-1);
  261.                         if(debug)
  262.                             putchar('E');
  263.                         distance=stuck*2;
  264.                     }
  265.                     else
  266.                     if(isclear(cur.x,cur.y-offset,cx,cy))
  267.                     {
  268.                         mrot=32;
  269.                         motion=(-1);
  270.                         if(debug)
  271.                             putchar('N');
  272.                         distance=stuck*2;
  273.                     }
  274.                     else
  275.                     if(isclear(cur.x,cur.y+offset,cx,cy))
  276.                     {
  277.                         mrot=96;
  278.                         motion=(-1);
  279.                         if(debug)
  280.                             putchar('S');
  281.                         distance=stuck*2;
  282.                     }
  283.                 }
  284.                 if((last.x==cur.x)&&(last.y==cur.y)&&(mrot==cur.rot)&&(motion!=0)&&(!fire))
  285.                 {    /* stuck */
  286.                     distance=rnd(20)+10;
  287.                     motion==(-1);
  288.                     mrot=rnd(TANKROT);
  289.                     if(debug)
  290.                         putchar('R');
  291.                 }
  292.             }
  293.         }
  294.         if(debug)
  295.             printf("\tang=%2d motion=%2d %s\n",mrot,motion,fire?"FIRE":"");
  296.     }
  297.     if((fire!=ofire)||(motion!=omotion)||(mrot!=omrot))
  298.     {
  299.         sendstatus();
  300.     }
  301.     last.x=cur.x;
  302.     last.y=cur.y;
  303.     last.rot=cur.rot;
  304. }
  305.  
  306. int
  307. SocketHandle()    /* handle data from the server incomming on the socket */
  308. {
  309.     int i,j;
  310.  
  311.     if(readdata(rsd,&rdata)!=sizeof(DATA))
  312.     {
  313.         fprintf(stderr,"%s: Recieved bad data\n");
  314.         exit(1);
  315.     }
  316.     switch(INSWAP(rdata.type))
  317.     {
  318.     case T_REPLY:
  319.         for(i=0;i<MAXUSERS;i++)
  320.         {
  321.             if(INSWAP(rdata.extra.reply.pos[i].x)==-1)
  322.                 continue;
  323.             player[i].pos.x=INSWAP(rdata.extra.reply.pos[i].x);
  324.             player[i].pos.y=INSWAP(rdata.extra.reply.pos[i].y);
  325.             player[i].pos.rot=INSWAP(rdata.extra.reply.pos[i].rot);
  326.         }
  327.         /* update current position */
  328.         cur.x=player[myid].pos.x;
  329.         cur.y=player[myid].pos.y;
  330.         cur.rot=player[myid].pos.rot;
  331.         break;
  332.     case T_ACCEPT:
  333.         for(i=0;i<MAXUSERS;i++)
  334.         {
  335.             strcpy(player[i].user.username,rdata.extra.accept.players[i].username);
  336.             strcpy(player[i].user.hostname,rdata.extra.accept.players[i].hostname);
  337.             player[i].kills=INSWAP(rdata.extra.accept.kills[i]);
  338.             player[i].killed=INSWAP(rdata.extra.accept.killed[i]);
  339.         }
  340.         break;
  341.     case T_EXPLOSION:
  342.         damage=INSWAP(rdata.extra.explosion.damage[myid]);
  343.         if(debug)
  344.             printf("Explosion: damage is %d\n",damage);
  345.         if(damage>=MAXDAMAGE)
  346.         {
  347.             if(debug)
  348.                 printf("Explosion: killed\n");
  349.             signoff(5,KILLED);
  350.         }
  351.         break;
  352.     case T_MESSAGE:
  353.         if(debug)
  354.             printf("Message: %s\n",rdata.extra.message.text);
  355.         break;
  356.     case T_ALIVE:
  357.         sdata.type=OUTSWAP(T_ALIVE);
  358.         senddata(ssd,&sdata);
  359.         break;
  360.     default:
  361.         if(debug)
  362.             printf("Unexpected datagram type %d (0x%x)\n",INSWAP(rdata.type),INSWAP(rdata.type));
  363.     }
  364.     if((gettime()-lastsend)>20)
  365.         domymove();
  366. }
  367.  
  368. main(argc,argv)
  369. int argc;
  370. char *argv[];
  371. {
  372.     int i,j;
  373.     int n=1,cpid,ppid,cstatus;
  374.     int restart;
  375.     char *p;
  376.  
  377.     int inport,outport;
  378.     int fieldok;
  379.     progname=argv[0];
  380.  
  381.     server=getenv("XTB_SERVER");
  382.  
  383.     p=getenv("XTB_INPORT");
  384.     if(p!=NULL)
  385.         inport=atoi(p);
  386.     else
  387.         inport=DEFRPORT;
  388.  
  389.     p=getenv("XTB_OUTPORT");
  390.     if(p!=NULL)
  391.         outport=atoi(p);
  392.     else
  393.         outport=DEFSPORT;
  394.  
  395.     for(i=1;i<argc;i++)
  396.     {
  397.         p=argv[i];
  398.         if(*p++=='-')
  399.         {
  400.             switch(*p++)
  401.             {
  402.             case 'i':    /* input/client port */
  403.             case 'c':
  404.                 if(*p=='\0')
  405.                     inport=atoi(argv[++i]);
  406.                 else
  407.                     inport=atoi(p);
  408.                 break;
  409.             case 'o':    /* output/server port */
  410.             case 's':
  411.                 if(*p=='\0')
  412.                     outport=atoi(argv[++i]);
  413.                 else
  414.                     outport=atoi(p);
  415.                 break;
  416.             case 'h':
  417.                 if(*p=='\0')
  418.                     server=argv[++i];
  419.                 else
  420.                     server=p;
  421.                 break;
  422.             case 'n':    /* number of robots */
  423.                 if(*p=='\0')
  424.                     n=atoi(argv[++i]);
  425.                 else
  426.                     n=atoi(p);
  427.                 if(n<0)
  428.                     n=1;
  429.                 if(n>MAXROBOTS)
  430.                     n=MAXROBOTS;
  431.                 break;
  432.             case 'r':    /* restart if killed */
  433.                 break;
  434.             case 'v':    /* viciousness */
  435.                 break;
  436.             case 'd':    /* debug */
  437.                 debug++;
  438.                 break;
  439.             case 'R':
  440.                 robots=!robots;
  441.                 break;
  442.             case 'H':
  443.                 humans=!humans;
  444.                 break;
  445.             default:
  446.                 fprintf(stderr,"Usage: %s [-h server_host] [-c client_portno] [-s server_portno] \n",argv[0]);
  447.             }
  448.         }
  449.     }
  450.  
  451.     if(server==NULL)
  452.     {
  453.         fprintf(stderr,"%s: No server host (-h or $XTB_SERVER) defined\n",argv[0]);
  454.         exit(1);
  455.     }
  456.  
  457.     ppid=getpid();
  458.         /* fork off children, recording port number and pid */
  459.     for(j=0;j<n;j++)
  460.     {
  461.         cpid=fork();
  462.         if(cpid==0)
  463.             break;
  464.         child[j].pid=cpid;
  465.         child[j].portno=inport;
  466.         if(debug)
  467.             printf("Child %d pid=%d\n",j,child[j].pid);
  468.         sleep(1);
  469.         inport++;
  470.     }
  471.         /* if we're the parent, wait for children and restart */
  472.     if(getpid()==ppid)
  473.     {
  474.         while(1)
  475.         {
  476.             restart=(-1);
  477.             cpid=wait(&cstatus);
  478.             if(debug)
  479.                 printf("Child pid %d died\n",cpid);
  480.             for(j=0;j<n;j++)
  481.                 if(cpid==child[j].pid)
  482.                     restart=j;
  483.             if(restart!=(-1))
  484.             {
  485.                 /* re fork */
  486.                 inport=child[restart].portno;
  487.                 sleep(5);
  488.                 cpid=fork();
  489.                 if(cpid==0)
  490.                     break;
  491.                 child[restart].pid=cpid;
  492.                 if(debug)
  493.                     printf("Restart %d pid=%d\n",restart,child[restart].pid);
  494.             }
  495.         }
  496.     }
  497.  
  498.     rsd=openread(inport);
  499.     if(rsd==(-1))
  500.     {
  501.         fprintf(stderr,"%s: Opening port %d failed\n",argv[0],inport);
  502.         exit(1);
  503.     }
  504.     
  505.     ssd=opensend(server,outport);
  506.     if(ssd==(-1))
  507.     {
  508.         fprintf(stderr,"%s: Connecting to %s/%d failed\n",argv[0],server,outport);
  509.         exit(1);
  510.     }
  511.     for(i=0;i<MAXUSERS;i++)
  512.         exptime[i]=(-1);
  513.  
  514.         /* signon */
  515.     sdata.type=OUTSWAP(T_SIGNON);
  516.     sdata.extra.signon.version=OUTSWAP(VERSION);
  517.     sdata.extra.signon.port=OUTSWAP(inport);    /* could be different to server port */
  518.     gethostname(sdata.extra.signon.hostname,HOSTLEN);
  519.     sprintf(sdata.extra.signon.username,"ROBOT%04d",inport);
  520.  
  521.     signal(SIGALRM,timeout);
  522.     alarm(3);
  523.     senddata(ssd,&sdata);
  524.  
  525.     if(readdata(rsd,&rdata)!=sizeof(DATA))
  526.     {
  527.         fprintf(stderr,"%s: Recieved bad data\n");
  528.         exit(1);
  529.     }
  530.     alarm(0);
  531.     switch(INSWAP(rdata.type))
  532.     {
  533.     case T_ACCEPT:
  534.         if(debug)
  535.             printf("accept\nMy id is %d\n",INSWAP(rdata.extra.accept.id));
  536.         myid=INSWAP(rdata.extra.accept.id);
  537.         for(i=0;i<MAXUSERS;i++)
  538.         {
  539.             strcpy(player[i].user.username,rdata.extra.accept.players[i].username);
  540.             strcpy(player[i].user.hostname,rdata.extra.accept.players[i].hostname);
  541.             player[i].kills=INSWAP(rdata.extra.accept.kills[i]);
  542.             player[i].killed=INSWAP(rdata.extra.accept.killed[i]);
  543.         }
  544.         break;
  545.     case T_REJECT:
  546.         printf("reject\n");
  547.         printf("reason: %s\n",rdata.extra.reject.text);
  548.         exit(1);
  549.         break;
  550.     default:
  551.         if(debug)
  552.             printf("Unknown datagram type %d (0x%x)\n",INSWAP(rdata.type),INSWAP(rdata.type));
  553.     }
  554.  
  555.     for(i=0;i<OBJECTSIZE;i++)
  556.         for(j=0;j<OBJECTSIZE;j++)
  557.             radar[i][j]=0;
  558.     for(i=0;i<OBJECTSIZE;i++)
  559.         field[i][0]=UNSET;
  560.  
  561.     if(debug)
  562.         printf("Getting field data\n");
  563.     sdata.id=OUTSWAP(myid);
  564.     sdata.type=OUTSWAP(T_DATAREQ);
  565.  
  566.     do
  567.     {
  568.         fieldok=1;
  569.         for(i=0;i<OBJECTSIZE;i++)
  570.         {
  571.             if(field[i][0]==UNSET)
  572.             {
  573.                 fflush(stdout);
  574.                 fieldok=0;
  575.                 sdata.extra.datareq.lineno=OUTSWAP(i);
  576.                 senddata(ssd,&sdata);
  577.                 if(readdata(rsd,&rdata)!=sizeof(DATA))
  578.                 {
  579.                     fprintf(stderr,"%s: Recieved bad data\n",argv[0]);
  580.                     exit(1);
  581.                 }
  582.                 if(INSWAP(rdata.type)!=T_FIELDDATA)
  583.                 {
  584.                     if(INSWAP(rdata.type)==T_MESSAGE)
  585.                     {
  586.                         if(debug)
  587.                             printf("Message: %s\n",rdata.extra.message.text);
  588.                     }
  589.                     else
  590.                         if(debug)
  591.                             printf("%s: Expected field data got 0x%x\n",argv[0],INSWAP(rdata.type));
  592.                 }
  593.                 else
  594.                 {
  595.                     if(debug)
  596.                     {
  597.                         if(INSWAP(rdata.extra.field.lineno)!=i)
  598.                             printf("%%%d",INSWAP(rdata.extra.field.lineno));
  599.                         else
  600.                             printf(".%d",i);
  601.                     }
  602.                     memcpy(field[INSWAP(rdata.extra.field.lineno)],rdata.extra.field.object,OBJECTSIZE);
  603.                 }
  604.             }
  605.         }
  606.     }
  607.     while(!fieldok);
  608.     if(debug)
  609.         putchar('\n');
  610.  
  611.     signal(SIGHUP,dointr);
  612.     signal(SIGINT,dointr);
  613.     signal(SIGTERM,dointr);
  614.  
  615.     while(1)
  616.     {
  617.         SocketHandle();
  618.     }
  619. }
  620.