home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume15 / xtb / part01 < prev    next >
Encoding:
Internet Message Format  |  1993-01-26  |  55.2 KB

  1. Path: uunet!news.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v15i029:  xtb - multi-player X11 tank game and server, Part01/02
  5. Message-ID: <4039@master.CNA.TEK.COM>
  6. Date: 8 Dec 92 17:38:36 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2445
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1528
  11.  
  12. Submitted-by: bmh@terminus.ericsson.se (Bernard Hatt)
  13. Posting-number: Volume 15, Issue 29
  14. Archive-name: xtb/Part01
  15. Environment: X11, UDP Sockets
  16.  
  17.     [This is not only multi-player, but the players can be on different
  18.      hosts, as well. It also has robot tanks in case you can't find anyone
  19.      else to play against. Compiled and ran fine on a Sun SS-2.  -br]
  20.  
  21. #! /bin/sh
  22. # This is a shell archive.  Remove anything before this line, then unpack
  23. # it by saving it into a file and typing "sh file".  To overwrite existing
  24. # files, type "sh file -c".  You can also feed this as standard input via
  25. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  26. # will see the following message at the end:
  27. #        "End of archive 1 (of 2)."
  28. # Contents:  README MANIFEST common.c rtb.c xtb.c
  29. # Wrapped by billr@saab on Tue Dec  8 09:35:46 1992
  30. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  31. if test -f 'README' -a "${1}" != "-c" ; then 
  32.   echo shar: Will not clobber existing file \"'README'\"
  33. else
  34. echo shar: Extracting \"'README'\" \(5557 characters\)
  35. sed "s/^X//" >'README' <<'END_OF_FILE'
  36. X
  37. XWHAT YOU NEED TO HAVE
  38. X=====================
  39. X
  40. XAn X11R3 or greater X server.  (It might work on earlier X11 releases,
  41. Xbut I havn't tried)
  42. X
  43. XA display of at least 1024(W)*800(H) pixels.  (1080 pixels wide is better)
  44. X
  45. XA three button mouse (It's playable with a two button mouse). 
  46. X
  47. XA fastish (and unloaded) CPU and reasonable drawing speed.
  48. X
  49. XA fastish network.
  50. X
  51. XNothing better to do.
  52. X
  53. XSoftware that supports the following system/library calls and UDP sockets.
  54. X    Socket/network related
  55. X        socket(), bind(), connect() ,gethostbyname() ,htonl() ,ntohl()
  56. X    Timing related
  57. X        gettimeofday(), setitimer()
  58. X    General
  59. X        gethostname(), getpwuid()
  60. X
  61. XMachines with non 32-bit int's could be a problem (Sorry). 
  62. X
  63. XTwo or more players.  (The more the better). 
  64. X
  65. XThe program works on mono, greyscale and colour displays, and looks
  66. Xexactly the same on each (I havn't got a colour node :-( ). 
  67. X
  68. XCOMPILATION OPTIONS
  69. X===================
  70. X
  71. XIf you have more than 10 people wanting to play, try increasing the
  72. Xvalue if MAXUSERS in "defs.h" up to a maximum of 24.  This should work,
  73. Xbut is untested. 
  74. X
  75. XCOMPILING
  76. X=========
  77. X
  78. XType
  79. X    make
  80. X
  81. XThis should create three programs, xtb, xtbd and rtb.
  82. X
  83. XSTARTING THE GAME
  84. X=================
  85. X
  86. XPick a node (can be any machine with or without X) and run the server (xtbd).
  87. X
  88. X    hostname% xtbd
  89. X
  90. XFor each player at a workstation run the client (xtb).
  91. X
  92. X    workstation% xtb -h hostname
  93. X    (ignore messages about datagrams and fielddata)
  94. X    
  95. XRUNNING TWO (OR MORE) PLAYERS ON THE SAME NODE
  96. X==============================================
  97. X
  98. XThe second and further players, should pick different port numbers to
  99. Xthe default (and each other).  eg the second player might type
  100. X
  101. X    workstation% xtb -h hostname -i 1624
  102. X
  103. XTo run two or more servers on the same node, use a different port number
  104. Xto the default.  eg. 
  105. X
  106. X    hostname% xtbd -p 1627
  107. X
  108. Xto contact this server the player would need to type
  109. X    workstation% xtb -h hostname -o 1627
  110. X
  111. XROBOT TANKS
  112. X===========
  113. X
  114. XIf you are short of people or want to practice, the program rtb adds
  115. Xrobot tanks.  To create 4 robot tanks type
  116. X
  117. X    robothost% rtb -h hostname -n4
  118. X
  119. XRobots re-start when killed after a 5 second delay.  The -i and -o flags
  120. Xfor xtb that change the port numbers used are also valid for rtb.  For
  121. X'n' robots 'n' port numbers are used. 
  122. X
  123. XNote: Robot tanks can use a lot more network bandwidth than human players.
  124. X
  125. XSHELL VARIABLES
  126. X===============
  127. X
  128. XThe shell variables are overridden by the command line options.
  129. X
  130. XXTB_SERVER    The hostname of the server to contact by default.
  131. XXTB_INPORT    The input (client) port number to use.
  132. XXTB_OUTPORT    The output (server) port number to use.
  133. X
  134. XKNOWN TO WORK
  135. X=============
  136. X
  137. XKnown to work as a server
  138. X    Sun 4, DecStation 3100, Microvax 2, Sun 3, HP 9000s827
  139. X
  140. XKnown to work as a client (display)
  141. X    Sun 4, DecStation 3100,  HP9000s710 (With X dev. kit)
  142. X
  143. XWorks as a client with only a small number of players
  144. X    Sun 3
  145. X
  146. XOPTIONS
  147. X=======
  148. X
  149. XThe -w flag turns on warping of the mouse cursor on scrolling.  The
  150. Xdefault is for the mouse cursor not to be moved when the screen is
  151. Xscrolled (ie.  the square under the cursor remains the same.) (Use what
  152. Xyou find intuitive)
  153. X
  154. XFor xtb the -p and -b flags change the method used to draw tanks.
  155. X-p uses polygons (as per previous versions)
  156. X-b (default) uses bitmaps (pixmaps), this takes much more X server memory,
  157. Xbut seems faster on most machines.
  158. X
  159. XPLAYING
  160. X=======
  161. X
  162. XThe display has several areas, the main battlefield, (you appear as a
  163. Xsolid black tank, all others display their id) the radar, a damage
  164. Xdisplay, a message window, a quit button and a list of players and their
  165. Xid's. 
  166. X
  167. XThe controls are simple.
  168. X
  169. XLeft button   -> Fire (in the direction the tank is facing)
  170. XMiddle button -> Reverse
  171. XRight button  -> Forward
  172. X
  173. XIf you only have a two button mouse, you can use the keyboard to reverse
  174. Xthe tank motion, any key press causes the motion to be reversed, any key
  175. Xrelease returns to normal.  If you have auto-repeat on your keyboard
  176. X(most do), use a key that does not auto repeat (ie.  shift,control etc)
  177. XThis will not work for a window manager that does not implement the
  178. Xinput (push-focus) window manager hint. 
  179. X
  180. XThe tank will rotate towards the mouse cursor when the cursor is in the
  181. Xmain field. 
  182. X
  183. XThe solid black squares are obstacles, and cannot be moved through or
  184. Xfired through. 
  185. X
  186. XThe hatched areas are rough ground, you can only move at half speed
  187. Xacross these. 
  188. X
  189. XThe shells have a range of about four squares, you cannot fire again for
  190. X2.5 sec after firing. 
  191. X
  192. XExplosions do damage according to the (inverse square of the) distance
  193. Xfrom the explosion.  Two direct hits is sufficient for a kill, near
  194. Xmisses cause smaller amounts of damage. 
  195. X
  196. XKilling another player clears your own damage (to encourage friendly
  197. Xplay!). 
  198. X
  199. XQuitting should be done using the quit button (NOT the window manager
  200. Xframe)
  201. X
  202. XIt is possible to shoot through the diagonal of two blocks. 
  203. X
  204. XNOTES
  205. X=====
  206. X
  207. XThis was only my third ever X11 program, initially written only with the
  208. Xon-line manuals for reference.  If I were to re-write it, I'd probably
  209. Xdo it differently. 
  210. X
  211. XOne of the design specifications was that the program should be easy to
  212. Xinstall, configure and run, so it does not use any files (other than the
  213. Xexecutables) or require require root permissions to install/run.
  214. X
  215. XThe program is entirely mouse controlled (unless you only have a two
  216. Xbutton mouse)
  217. X
  218. XThe program comes with no warranty.  I would like the conditions that
  219. Xapply to GNU software to apply to this software.
  220. X
  221. XGood Luck!
  222. X
  223. XBernard Hatt
  224. Xbmh@terminus.ericsson.se
  225. XCamtec Electronics (Ericsson), Leicester, England, LE1 4SA.
  226. END_OF_FILE
  227. if test 5557 -ne `wc -c <'README'`; then
  228.     echo shar: \"'README'\" unpacked with wrong size!
  229. fi
  230. # end of 'README'
  231. fi
  232. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  233.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  234. else
  235. echo shar: Extracting \"'MANIFEST'\" \(486 characters\)
  236. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  237. X   File Name        Archive #    Description
  238. X-----------------------------------------------------------
  239. X MANIFEST                   1    This shipping list
  240. X Makefile                   2    
  241. X README                     1    
  242. X TODO                       2    
  243. X common.c                   1    
  244. X comms.h                    2    
  245. X defs.h                     2    
  246. X dgram.c                    2    
  247. X rtb.c                      1    
  248. X xtb.6                      2    
  249. X xtb.c                      1    
  250. X xtbd.c                     2    
  251. END_OF_FILE
  252. if test 486 -ne `wc -c <'MANIFEST'`; then
  253.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  254. fi
  255. # end of 'MANIFEST'
  256. fi
  257. if test -f 'common.c' -a "${1}" != "-c" ; then 
  258.   echo shar: Will not clobber existing file \"'common.c'\"
  259. else
  260. echo shar: Extracting \"'common.c'\" \(1685 characters\)
  261. sed "s/^X//" >'common.c' <<'END_OF_FILE'
  262. X/*
  263. X * Common code.
  264. X *
  265. X * $Header: /morpork/home/bmh/xtest2/RCS/common.c,v 1.2 92/10/19 15:34:25 bmh Exp Locker: bmh $
  266. X *
  267. X * Bernard Hatt
  268. X * Camtec Electronics (Ericsson), Leicester, England, LE1 4SA
  269. X * bmh@terminus.ericsson.se
  270. X *
  271. X */
  272. X         
  273. X#include <stdio.h>
  274. X
  275. X
  276. X#ifdef BSD
  277. X#include <sys/time.h>
  278. X#include <sys/types.h>
  279. X#include <fcntl.h>
  280. X#else
  281. X#include <sys/types.h>
  282. X#include <sys/timeb.h>
  283. X#include <sys/stat.h>
  284. X#include <fcntl.h>
  285. X
  286. X#endif
  287. X
  288. X#include <math.h>
  289. X#include "defs.h"
  290. X#include "comms.h"
  291. X
  292. X#ifdef BSD
  293. X
  294. Xstruct timezone tz={0,0};
  295. Xstruct timeval tv;
  296. Xlong lastsec=0;
  297. X    /* return time in cs ( will fail if test runs for more than */
  298. X    /* 240 days (2^31/(60*60*24*100)) */
  299. X
  300. Xint
  301. Xgettime()
  302. X{
  303. X    gettimeofday(&tv,&tz);
  304. X    if(lastsec==0)
  305. X        lastsec=tv.tv_sec;
  306. X    return((tv.tv_sec-lastsec)*100+(tv.tv_usec/10000));
  307. X}
  308. X
  309. X#else
  310. X
  311. Xstruct timeb tb;
  312. Xlong lastsec=0;
  313. X
  314. Xint
  315. Xgettime()
  316. X{
  317. X        ftime(&tb);
  318. X    if(lastsec==0)
  319. X        lastsec=tb.time;
  320. X    return((tb.time-lastsec)*100+tb.millitm/10);
  321. X}
  322. X
  323. X#endif
  324. X
  325. Xint
  326. Xrnd(n)  /* a random no. between 0 and n-1 */
  327. Xint n;
  328. X{
  329. X    return((rand()/153)%n);   
  330. X}
  331. X
  332. Xvoid    /* because Ultrix doesn't provide the nice SunOS ualarm() */
  333. Xmyualarm(val)
  334. Xint val;
  335. X{
  336. X    struct itimerval itv;
  337. X    itv.it_interval.tv_sec=0; 
  338. X    itv.it_interval.tv_usec=0;
  339. X    itv.it_value.tv_sec=0;
  340. X    itv.it_value.tv_usec=val;
  341. X    setitimer(ITIMER_REAL,&itv,NULL);
  342. X}
  343. X
  344. Xint
  345. XGetAngle(x1,y1,x2,y2)    /* return an angle between two points */
  346. Xint x1,y1,x2,y2;
  347. X{
  348. X    double xc,yc,theta;
  349. X    int ang;
  350. X    xc=(double)(x1-x2);
  351. X    yc=(double)(y1-y2);
  352. X    if(xc==0.0)
  353. X    {
  354. X        if(yc>0)
  355. X            theta=(PI/2.0);
  356. X        else
  357. X            theta=(-PI/2.0);
  358. X    }
  359. X    else
  360. X    {
  361. X        theta=atan2(yc,xc);
  362. X    }
  363. X    theta=(TANKROT*(theta/(2.0*PI)));
  364. X    ang=(int)(theta+0.5+TANKROT)%TANKROT;
  365. X    return(ang);
  366. X}
  367. X
  368. X
  369. END_OF_FILE
  370. if test 1685 -ne `wc -c <'common.c'`; then
  371.     echo shar: \"'common.c'\" unpacked with wrong size!
  372. fi
  373. # end of 'common.c'
  374. fi
  375. if test -f 'rtb.c' -a "${1}" != "-c" ; then 
  376.   echo shar: Will not clobber existing file \"'rtb.c'\"
  377. else
  378. echo shar: Extracting \"'rtb.c'\" \(11632 characters\)
  379. sed "s/^X//" >'rtb.c' <<'END_OF_FILE'
  380. X/*
  381. X * Robot tank
  382. X *
  383. X * $Header: /morpork/home/bmh/xtest2/RCS/rtb.c,v 1.7 92/10/19 15:34:30 bmh Exp Locker: bmh $
  384. X *
  385. X * Bernard Hatt
  386. X * Camtec Electronics (Ericsson), Leicester, England, LE1 4SA
  387. X * bmh@terminus.ericsson.se
  388. X *
  389. X */
  390. X#include <stdio.h>
  391. X#include <sys/types.h>
  392. X#include <sys/wait.h>
  393. X#include <sys/ioctl.h>
  394. X#include <sys/time.h>
  395. X#include <netinet/in.h>
  396. X#include <unistd.h>
  397. X#include <fcntl.h>
  398. X#include <signal.h>
  399. X#include <ctype.h>
  400. X#include <math.h>
  401. X#include <pwd.h>
  402. X
  403. X#include "defs.h"
  404. X#include "comms.h"
  405. X
  406. Xint debug=0;
  407. X
  408. XPLAYER player[MAXUSERS];    /* players tanks */
  409. Xchar    field[OBJECTSIZE][OBJECTSIZE];
  410. Xchar    radar[OBJECTSIZE][OBJECTSIZE];
  411. X
  412. Xint distance=0;
  413. X
  414. Xint fire=0;    /* fire button pressed */
  415. Xint motion=0;    /* tank linear motion */
  416. Xint mrot=0;    /* mouse pointer rotation */
  417. Xint damage=0;    /* damage sustained */
  418. Xchar message[BUFLEN]="";    /* message for message window */
  419. Xchar *server=NULL;
  420. X
  421. XPOSITION cur={0,300,100,0,0};
  422. XPOSITION last;
  423. X
  424. Xint myid;
  425. Xint rsd,ssd;
  426. XDATA rdata,sdata;
  427. Xint savedx=(-1),savedy=(-1);
  428. Xint sfx=(-1),sfy=(-1);
  429. Xint lastsend=0;
  430. X
  431. Xint robots=0;    /* attack other robots */
  432. Xint humans=1;    /* attack humans */
  433. X
  434. X
  435. Xint ex[MAXUSERS],ey[MAXUSERS],exptime[MAXUSERS];
  436. X
  437. Xtypedef struct child_struct
  438. X{
  439. X    int pid;
  440. X    int portno;
  441. X} CHILD;
  442. X
  443. XCHILD child[MAXROBOTS];
  444. X
  445. Xchar *progname;
  446. Xint stuck=0;
  447. X
  448. Xvoid
  449. Xsignoff(t,reason)    /* send signoff to server and exit */
  450. Xint t,reason;
  451. X{
  452. X    sdata.id=OUTSWAP(myid);
  453. X    sdata.type=OUTSWAP(T_SIGNOFF);
  454. X    sdata.extra.signoff.reason=OUTSWAP(reason);
  455. X    senddata(ssd,&sdata);
  456. X    if(t!=0)
  457. X        sleep(t);
  458. X    exit(0);
  459. X}
  460. X
  461. Xvoid
  462. Xdointr()    /* action on interrupt */
  463. X{
  464. X    signoff(0,DESTROYED);
  465. X}
  466. X
  467. Xvoid
  468. XdoXio()
  469. X{
  470. X    signoff(0,QUIT);
  471. X}
  472. X
  473. Xvoid
  474. Xtimeout()    /* timeout on connect */
  475. X{
  476. X    fprintf(stderr,"%s: No response from server \"%s\" (not running/busy?)\n",progname,server);
  477. X    exit(1);
  478. X}
  479. X
  480. X
  481. Xvoid
  482. Xsendstatus()    /* send our status to the server */
  483. X{
  484. X    sdata.type=OUTSWAP(T_MOVE);
  485. X    sdata.id=OUTSWAP(myid);
  486. X    sdata.extra.move.rot=OUTSWAP(mrot);
  487. X    sdata.extra.move.linear=OUTSWAP(motion);
  488. X    sdata.extra.move.fire=OUTSWAP(fire);
  489. X    senddata(ssd,&sdata);
  490. X    lastsend=gettime();
  491. X}
  492. X
  493. X
  494. Xint
  495. Xisclear(x1,y1,x2,y2)    /* is it clear between (x1,y1) and (x2,y2) */
  496. Xint x1,y1,x2,y2;
  497. X{
  498. X    int i;
  499. X    int x,y;
  500. X    int fx,fy;
  501. X    if((x1<0)||(x1>=MAINSIZE))
  502. X        return(0);
  503. X    if((y1<0)||(y1>=MAINSIZE))
  504. X        return(0);
  505. X        
  506. X    for(i=0;i<16;i++)
  507. X    {
  508. X        x=x1+(((x2-x1)*i)/16);
  509. X        y=y1+(((y2-y1)*i)/16);
  510. X        fx=x/OBJECTSCALE;
  511. X        fy=y/OBJECTSCALE;
  512. X        if(field[fx][fy]==BLOCKED)
  513. X            return(0);
  514. X    }
  515. X    return(1);
  516. X}
  517. X
  518. Xvoid
  519. Xdomymove()
  520. X{
  521. X    int i;
  522. X    int sqdist,ang;
  523. X    int dx,dy,cansee,offset;
  524. X    int cang,cdist=(-1),cid;
  525. X    int omotion,ofire,omrot,cx,cy;
  526. X    int sid=(-1),sang,sdist;
  527. X
  528. X    ofire=fire;
  529. X    omotion=motion;
  530. X    omrot=mrot;
  531. X    for(i=0;i<MAXUSERS;i++)
  532. X    {
  533. X        if(i==myid)
  534. X            continue;
  535. X        if(*player[i].user.username=='\0')
  536. X            continue;
  537. X        if(*player[i].user.username=='R')
  538. X        {
  539. X            if(!robots)
  540. X                continue;
  541. X        }
  542. X        else
  543. X        {
  544. X            if(!humans)
  545. X                continue;
  546. X        }
  547. X        dx=player[i].pos.x-cur.x;
  548. X        dy=player[i].pos.y-cur.y;
  549. X        sqdist=(dx*dx)+(dy*dy);
  550. X        ang=GetAngle(0,0,dx,dy);
  551. X        if(sqdist<(OBJECTSCALE*OBJECTSCALE*16))
  552. X        {
  553. X            if(isclear(cur.x,cur.y,player[i].pos.x,player[i].pos.y))
  554. X            {
  555. X                sid=i;
  556. X                sang=ang;
  557. X                sdist=sqdist;
  558. X            }
  559. X        }
  560. X        if((cdist>sqdist)||(cdist==(-1)))
  561. X        {
  562. X            cang=ang;
  563. X            cdist=sqdist;
  564. X            cid=i;
  565. X        }
  566. X    }
  567. X    fire=0;
  568. X    if(cdist!=-1)
  569. X    {
  570. X        if(debug)
  571. X            printf("Closest id %d ang %3d\t",cid,cang);
  572. X        if(sid!=(-1))
  573. X        {
  574. X            mrot=sang;
  575. X            distance=0;
  576. X            if(sang==cur.rot)
  577. X            {
  578. X                fire=1;
  579. X                if(sdist<(OBJECTSCALE*OBJECTSCALE*14))
  580. X                    motion=1;
  581. X            }
  582. X            if(debug)
  583. X            {
  584. X                putchar('F');
  585. X            }
  586. X        }
  587. X        else
  588. X        {
  589. X            if(distance!=0)
  590. X                distance--;
  591. X            else
  592. X                mrot=cang;
  593. X            cx=player[cid].pos.x;
  594. X            cy=player[cid].pos.y;
  595. X            if((last.x!=cur.x)||(last.y!=cur.y)||(mrot!=cur.rot))
  596. X            {
  597. X                motion=(-1);
  598. X                if(isclear(cur.x,cur.y,cx,cy))
  599. X                {
  600. X                    if(debug)
  601. X                        putchar('V');
  602. X                    mrot=cang;
  603. X                }
  604. X                else
  605. X                {
  606. X                    if(distance==0)
  607. X                    {
  608. X                        if(debug)
  609. X                            putchar('M');
  610. X                        mrot=cang;
  611. X                    }
  612. X                    else
  613. X                    {
  614. X                        if(debug)
  615. X                            printf("D%d",distance);
  616. X                    }
  617. X                }
  618. X            }
  619. X            else
  620. X            {
  621. X                if(distance==0)
  622. X                {
  623. X                    if(stuck>32)
  624. X                        stuck=0;
  625. X                    stuck++;
  626. X                    offset=(stuck*OBJECTSCALE/2);
  627. X                    if(isclear(cur.x-offset,cur.y,cx,cy))
  628. X                    {
  629. X                        mrot=0;
  630. X                        motion=(-1);
  631. X                        if(debug)
  632. X                            putchar('W');
  633. X                        distance=stuck*2;
  634. X                    }
  635. X                    else
  636. X                    if(isclear(cur.x+offset,cur.y,cx,cy))
  637. X                    {
  638. X                        mrot=64;
  639. X                        motion=(-1);
  640. X                        if(debug)
  641. X                            putchar('E');
  642. X                        distance=stuck*2;
  643. X                    }
  644. X                    else
  645. X                    if(isclear(cur.x,cur.y-offset,cx,cy))
  646. X                    {
  647. X                        mrot=32;
  648. X                        motion=(-1);
  649. X                        if(debug)
  650. X                            putchar('N');
  651. X                        distance=stuck*2;
  652. X                    }
  653. X                    else
  654. X                    if(isclear(cur.x,cur.y+offset,cx,cy))
  655. X                    {
  656. X                        mrot=96;
  657. X                        motion=(-1);
  658. X                        if(debug)
  659. X                            putchar('S');
  660. X                        distance=stuck*2;
  661. X                    }
  662. X                }
  663. X                if((last.x==cur.x)&&(last.y==cur.y)&&(mrot==cur.rot)&&(motion!=0)&&(!fire))
  664. X                {    /* stuck */
  665. X                    distance=rnd(20)+10;
  666. X                    motion==(-1);
  667. X                    mrot=rnd(TANKROT);
  668. X                    if(debug)
  669. X                        putchar('R');
  670. X                }
  671. X            }
  672. X        }
  673. X        if(debug)
  674. X            printf("\tang=%2d motion=%2d %s\n",mrot,motion,fire?"FIRE":"");
  675. X    }
  676. X    if((fire!=ofire)||(motion!=omotion)||(mrot!=omrot))
  677. X    {
  678. X        sendstatus();
  679. X    }
  680. X    last.x=cur.x;
  681. X    last.y=cur.y;
  682. X    last.rot=cur.rot;
  683. X}
  684. X
  685. Xint
  686. XSocketHandle()    /* handle data from the server incomming on the socket */
  687. X{
  688. X    int i,j;
  689. X
  690. X    if(readdata(rsd,&rdata)!=sizeof(DATA))
  691. X    {
  692. X        fprintf(stderr,"%s: Recieved bad data\n");
  693. X        exit(1);
  694. X    }
  695. X    switch(INSWAP(rdata.type))
  696. X    {
  697. X    case T_REPLY:
  698. X        for(i=0;i<MAXUSERS;i++)
  699. X        {
  700. X            if(INSWAP(rdata.extra.reply.pos[i].x)==-1)
  701. X                continue;
  702. X            player[i].pos.x=INSWAP(rdata.extra.reply.pos[i].x);
  703. X            player[i].pos.y=INSWAP(rdata.extra.reply.pos[i].y);
  704. X            player[i].pos.rot=INSWAP(rdata.extra.reply.pos[i].rot);
  705. X        }
  706. X        /* update current position */
  707. X        cur.x=player[myid].pos.x;
  708. X        cur.y=player[myid].pos.y;
  709. X        cur.rot=player[myid].pos.rot;
  710. X        break;
  711. X    case T_ACCEPT:
  712. X        for(i=0;i<MAXUSERS;i++)
  713. X        {
  714. X            strcpy(player[i].user.username,rdata.extra.accept.players[i].username);
  715. X            strcpy(player[i].user.hostname,rdata.extra.accept.players[i].hostname);
  716. X            player[i].kills=INSWAP(rdata.extra.accept.kills[i]);
  717. X            player[i].killed=INSWAP(rdata.extra.accept.killed[i]);
  718. X        }
  719. X        break;
  720. X    case T_EXPLOSION:
  721. X        damage=INSWAP(rdata.extra.explosion.damage[myid]);
  722. X        if(debug)
  723. X            printf("Explosion: damage is %d\n",damage);
  724. X        if(damage>=MAXDAMAGE)
  725. X        {
  726. X            if(debug)
  727. X                printf("Explosion: killed\n");
  728. X            signoff(5,KILLED);
  729. X        }
  730. X        break;
  731. X    case T_MESSAGE:
  732. X        if(debug)
  733. X            printf("Message: %s\n",rdata.extra.message.text);
  734. X        break;
  735. X    case T_ALIVE:
  736. X        sdata.type=OUTSWAP(T_ALIVE);
  737. X        senddata(ssd,&sdata);
  738. X        break;
  739. X    default:
  740. X        if(debug)
  741. X            printf("Unexpected datagram type %d (0x%x)\n",INSWAP(rdata.type),INSWAP(rdata.type));
  742. X    }
  743. X    if((gettime()-lastsend)>20)
  744. X        domymove();
  745. X}
  746. X
  747. Xmain(argc,argv)
  748. Xint argc;
  749. Xchar *argv[];
  750. X{
  751. X    int i,j;
  752. X    int n=1,cpid,ppid,cstatus;
  753. X    int restart;
  754. X    char *p;
  755. X
  756. X    int inport,outport;
  757. X    int fieldok;
  758. X    progname=argv[0];
  759. X
  760. X    server=getenv("XTB_SERVER");
  761. X
  762. X    p=getenv("XTB_INPORT");
  763. X    if(p!=NULL)
  764. X        inport=atoi(p);
  765. X    else
  766. X        inport=DEFRPORT;
  767. X
  768. X    p=getenv("XTB_OUTPORT");
  769. X    if(p!=NULL)
  770. X        outport=atoi(p);
  771. X    else
  772. X        outport=DEFSPORT;
  773. X
  774. X    for(i=1;i<argc;i++)
  775. X    {
  776. X        p=argv[i];
  777. X        if(*p++=='-')
  778. X        {
  779. X            switch(*p++)
  780. X            {
  781. X            case 'i':    /* input/client port */
  782. X            case 'c':
  783. X                if(*p=='\0')
  784. X                    inport=atoi(argv[++i]);
  785. X                else
  786. X                    inport=atoi(p);
  787. X                break;
  788. X            case 'o':    /* output/server port */
  789. X            case 's':
  790. X                if(*p=='\0')
  791. X                    outport=atoi(argv[++i]);
  792. X                else
  793. X                    outport=atoi(p);
  794. X                break;
  795. X            case 'h':
  796. X                if(*p=='\0')
  797. X                    server=argv[++i];
  798. X                else
  799. X                    server=p;
  800. X                break;
  801. X            case 'n':    /* number of robots */
  802. X                if(*p=='\0')
  803. X                    n=atoi(argv[++i]);
  804. X                else
  805. X                    n=atoi(p);
  806. X                if(n<0)
  807. X                    n=1;
  808. X                if(n>MAXROBOTS)
  809. X                    n=MAXROBOTS;
  810. X                break;
  811. X            case 'r':    /* restart if killed */
  812. X                break;
  813. X            case 'v':    /* viciousness */
  814. X                break;
  815. X            case 'd':    /* debug */
  816. X                debug++;
  817. X                break;
  818. X            case 'R':
  819. X                robots=!robots;
  820. X                break;
  821. X            case 'H':
  822. X                humans=!humans;
  823. X                break;
  824. X            default:
  825. X                fprintf(stderr,"Usage: %s [-h server_host] [-c client_portno] [-s server_portno] \n",argv[0]);
  826. X            }
  827. X        }
  828. X    }
  829. X
  830. X    if(server==NULL)
  831. X    {
  832. X        fprintf(stderr,"%s: No server host (-h or $XTB_SERVER) defined\n",argv[0]);
  833. X        exit(1);
  834. X    }
  835. X
  836. X    ppid=getpid();
  837. X        /* fork off children, recording port number and pid */
  838. X    for(j=0;j<n;j++)
  839. X    {
  840. X        cpid=fork();
  841. X        if(cpid==0)
  842. X            break;
  843. X        child[j].pid=cpid;
  844. X        child[j].portno=inport;
  845. X        if(debug)
  846. X            printf("Child %d pid=%d\n",j,child[j].pid);
  847. X        sleep(1);
  848. X        inport++;
  849. X    }
  850. X        /* if we're the parent, wait for children and restart */
  851. X    if(getpid()==ppid)
  852. X    {
  853. X        while(1)
  854. X        {
  855. X            restart=(-1);
  856. X            cpid=wait(&cstatus);
  857. X            if(debug)
  858. X                printf("Child pid %d died\n",cpid);
  859. X            for(j=0;j<n;j++)
  860. X                if(cpid==child[j].pid)
  861. X                    restart=j;
  862. X            if(restart!=(-1))
  863. X            {
  864. X                /* re fork */
  865. X                inport=child[restart].portno;
  866. X                sleep(5);
  867. X                cpid=fork();
  868. X                if(cpid==0)
  869. X                    break;
  870. X                child[restart].pid=cpid;
  871. X                if(debug)
  872. X                    printf("Restart %d pid=%d\n",restart,child[restart].pid);
  873. X            }
  874. X        }
  875. X    }
  876. X
  877. X    rsd=openread(inport);
  878. X    if(rsd==(-1))
  879. X    {
  880. X        fprintf(stderr,"%s: Opening port %d failed\n",argv[0],inport);
  881. X        exit(1);
  882. X    }
  883. X    
  884. X    ssd=opensend(server,outport);
  885. X    if(ssd==(-1))
  886. X    {
  887. X        fprintf(stderr,"%s: Connecting to %s/%d failed\n",argv[0],server,outport);
  888. X        exit(1);
  889. X    }
  890. X    for(i=0;i<MAXUSERS;i++)
  891. X        exptime[i]=(-1);
  892. X
  893. X        /* signon */
  894. X    sdata.type=OUTSWAP(T_SIGNON);
  895. X    sdata.extra.signon.version=OUTSWAP(VERSION);
  896. X    sdata.extra.signon.port=OUTSWAP(inport);    /* could be different to server port */
  897. X    gethostname(sdata.extra.signon.hostname,HOSTLEN);
  898. X    sprintf(sdata.extra.signon.username,"ROBOT%04d",inport);
  899. X
  900. X    signal(SIGALRM,timeout);
  901. X    alarm(3);
  902. X    senddata(ssd,&sdata);
  903. X
  904. X    if(readdata(rsd,&rdata)!=sizeof(DATA))
  905. X    {
  906. X        fprintf(stderr,"%s: Recieved bad data\n");
  907. X        exit(1);
  908. X    }
  909. X    alarm(0);
  910. X    switch(INSWAP(rdata.type))
  911. X    {
  912. X    case T_ACCEPT:
  913. X        if(debug)
  914. X            printf("accept\nMy id is %d\n",INSWAP(rdata.extra.accept.id));
  915. X        myid=INSWAP(rdata.extra.accept.id);
  916. X        for(i=0;i<MAXUSERS;i++)
  917. X        {
  918. X            strcpy(player[i].user.username,rdata.extra.accept.players[i].username);
  919. X            strcpy(player[i].user.hostname,rdata.extra.accept.players[i].hostname);
  920. X            player[i].kills=INSWAP(rdata.extra.accept.kills[i]);
  921. X            player[i].killed=INSWAP(rdata.extra.accept.killed[i]);
  922. X        }
  923. X        break;
  924. X    case T_REJECT:
  925. X        printf("reject\n");
  926. X        printf("reason: %s\n",rdata.extra.reject.text);
  927. X        exit(1);
  928. X        break;
  929. X    default:
  930. X        if(debug)
  931. X            printf("Unknown datagram type %d (0x%x)\n",INSWAP(rdata.type),INSWAP(rdata.type));
  932. X    }
  933. X
  934. X    for(i=0;i<OBJECTSIZE;i++)
  935. X        for(j=0;j<OBJECTSIZE;j++)
  936. X            radar[i][j]=0;
  937. X    for(i=0;i<OBJECTSIZE;i++)
  938. X        field[i][0]=UNSET;
  939. X
  940. X    if(debug)
  941. X        printf("Getting field data\n");
  942. X    sdata.id=OUTSWAP(myid);
  943. X    sdata.type=OUTSWAP(T_DATAREQ);
  944. X
  945. X    do
  946. X    {
  947. X        fieldok=1;
  948. X        for(i=0;i<OBJECTSIZE;i++)
  949. X        {
  950. X            if(field[i][0]==UNSET)
  951. X            {
  952. X                fflush(stdout);
  953. X                fieldok=0;
  954. X                sdata.extra.datareq.lineno=OUTSWAP(i);
  955. X                senddata(ssd,&sdata);
  956. X                if(readdata(rsd,&rdata)!=sizeof(DATA))
  957. X                {
  958. X                    fprintf(stderr,"%s: Recieved bad data\n",argv[0]);
  959. X                    exit(1);
  960. X                }
  961. X                if(INSWAP(rdata.type)!=T_FIELDDATA)
  962. X                {
  963. X                    if(INSWAP(rdata.type)==T_MESSAGE)
  964. X                    {
  965. X                        if(debug)
  966. X                            printf("Message: %s\n",rdata.extra.message.text);
  967. X                    }
  968. X                    else
  969. X                        if(debug)
  970. X                            printf("%s: Expected field data got 0x%x\n",argv[0],INSWAP(rdata.type));
  971. X                }
  972. X                else
  973. X                {
  974. X                    if(debug)
  975. X                    {
  976. X                        if(INSWAP(rdata.extra.field.lineno)!=i)
  977. X                            printf("%%%d",INSWAP(rdata.extra.field.lineno));
  978. X                        else
  979. X                            printf(".%d",i);
  980. X                    }
  981. X                    memcpy(field[INSWAP(rdata.extra.field.lineno)],rdata.extra.field.object,OBJECTSIZE);
  982. X                }
  983. X            }
  984. X        }
  985. X    }
  986. X    while(!fieldok);
  987. X    if(debug)
  988. X        putchar('\n');
  989. X
  990. X    signal(SIGHUP,dointr);
  991. X    signal(SIGINT,dointr);
  992. X    signal(SIGTERM,dointr);
  993. X
  994. X    while(1)
  995. X    {
  996. X        SocketHandle();
  997. X    }
  998. X}
  999. END_OF_FILE
  1000. if test 11632 -ne `wc -c <'rtb.c'`; then
  1001.     echo shar: \"'rtb.c'\" unpacked with wrong size!
  1002. fi
  1003. # end of 'rtb.c'
  1004. fi
  1005. if test -f 'xtb.c' -a "${1}" != "-c" ; then 
  1006.   echo shar: Will not clobber existing file \"'xtb.c'\"
  1007. else
  1008. echo shar: Extracting \"'xtb.c'\" \(31436 characters\)
  1009. sed "s/^X//" >'xtb.c' <<'END_OF_FILE'
  1010. X/*
  1011. X * X Client 
  1012. X *
  1013. X * $Header: /morpork/home/bmh/xtest2/RCS/xtb.c,v 1.41 92/10/19 15:34:32 bmh Exp Locker: bmh $
  1014. X *
  1015. X * Bernard Hatt
  1016. X * Camtec Electronics (Ericsson), Leicester, England, LE1 4SA
  1017. X * bmh@terminus.ericsson.se
  1018. X *
  1019. X */
  1020. X#include <stdio.h>
  1021. X#include <sys/types.h>
  1022. X#include <sys/wait.h>
  1023. X#include <sys/ioctl.h>
  1024. X#include <sys/time.h>
  1025. X#include <netinet/in.h>
  1026. X#include <unistd.h>
  1027. X#include <fcntl.h>
  1028. X#include <signal.h>
  1029. X#include <ctype.h>
  1030. X#include <math.h>
  1031. X#include <pwd.h>
  1032. X#include <errno.h>
  1033. X
  1034. X#include <X11/X.h>
  1035. X#include <X11/Xlib.h>
  1036. X#include <X11/Xutil.h>
  1037. X#include <X11/cursorfont.h>
  1038. X
  1039. X#include "defs.h"
  1040. X#include "comms.h"
  1041. X
  1042. X#define xtb_width 64    /* bitmap for iconised window */
  1043. X#define xtb_height 64
  1044. Xstatic char xtb_bits[] = {
  1045. X   0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  1046. X   0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
  1047. X   0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  1048. X   0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
  1049. X   0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  1050. X   0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
  1051. X   0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  1052. X   0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
  1053. X   0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  1054. X   0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
  1055. X   0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  1056. X   0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
  1057. X   0xf0, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xf0, 0xff, 0x3f, 0x00,
  1058. X   0xc0, 0xff, 0xff, 0xff, 0xf0, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0xff,
  1059. X   0xf0, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0xfc, 0x00, 0x00,
  1060. X   0xc0, 0xff, 0xff, 0xff, 0x00, 0xfc, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
  1061. X   0x00, 0xfc, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0xfc, 0x00, 0x00,
  1062. X   0xc0, 0xff, 0xff, 0xff, 0x00, 0xf8, 0xff, 0x0f, 0xc0, 0xff, 0xff, 0xff,
  1063. X   0x00, 0xf0, 0xff, 0x0f, 0xc0, 0xff, 0xff, 0xff, 0x00, 0xf0, 0xff, 0x0f,
  1064. X   0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
  1065. X   0x00, 0xfc, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0xfc, 0x00, 0x00,
  1066. X   0x00, 0xf8, 0xff, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x03,
  1067. X   0x00, 0xfc, 0x00, 0x00, 0x80, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0x3f, 0x00,
  1068. X   0xe0, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0x3f, 0x00, 0xf0, 0xff, 0xe0, 0x7f,
  1069. X   0xf0, 0xff, 0x3f, 0x00, 0xf8, 0x0f, 0x00, 0xfe, 0xf0, 0xff, 0x3f, 0x00,
  1070. X   0xfc, 0x07, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xf0,
  1071. X   0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
  1072. X   0x7e, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80,
  1073. X   0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80,
  1074. X   0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x82, 0x0f, 0x00, 0x00, 0x00,
  1075. X   0x50, 0x00, 0x00, 0x81, 0x0f, 0x00, 0x00, 0x00, 0x88, 0x00, 0x80, 0x80,
  1076. X   0x0f, 0x00, 0x00, 0x00, 0x04, 0x01, 0x40, 0xc0, 0x0f, 0x00, 0x00, 0x00,
  1077. X   0x02, 0x02, 0x20, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x01, 0x04, 0x10, 0xc0,
  1078. X   0x07, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xc0, 0x07, 0x00, 0x00, 0x00,
  1079. X   0x00, 0x10, 0x04, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x80,
  1080. X   0x07, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x80, 0x0f, 0x00, 0x00, 0x00,
  1081. X   0x00, 0x80, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x80,
  1082. X   0x0f, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00,
  1083. X   0x00, 0x10, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00,
  1084. X   0x3e, 0x00, 0x00, 0x80, 0x00, 0x04, 0x10, 0x00, 0x3e, 0x00, 0x00, 0x80,
  1085. X   0x01, 0x02, 0x20, 0x00, 0x7c, 0x00, 0x00, 0xc0, 0x02, 0x01, 0x40, 0x00,
  1086. X   0xfc, 0x00, 0x00, 0xe0, 0x84, 0x00, 0x80, 0x00, 0xf8, 0x01, 0x00, 0xf0,
  1087. X   0x48, 0x00, 0x00, 0x01, 0xf0, 0x07, 0x00, 0x7c};
  1088. X
  1089. X
  1090. X#define KeyMask (KeyPressMask|KeyReleaseMask)
  1091. X#define ButtonMask (ButtonPressMask|ButtonReleaseMask)
  1092. X#define MotionMask (PointerMotionMask)
  1093. X
  1094. X#define MainEventMask (KeyMask|ButtonMask|ExposureMask|ButtonPressMask|ButtonReleaseMask)
  1095. X#define FieldEventMask (PointerMotionMask|MainEventMask|ButtonPressMask|ButtonReleaseMask)
  1096. X
  1097. XDisplay *Disp;
  1098. Xint Scr;    /* screen no. */
  1099. XWindow    Win,Root;
  1100. XWindow    RWin,FWin,SWin,QWin,AWin,MWin;    /* should have used an */
  1101. XWindow    VSb,HSb;            /* array/structure for these */
  1102. XWindow    RVSb,RHSb;
  1103. X
  1104. XGC    GcF,GcB,GcTF,GcTB;
  1105. X
  1106. X
  1107. X#define BOARDER    8    /* boarder between windows */
  1108. X#define TANKPOINTS    20    /* number of points defining a tank */
  1109. X
  1110. Xtypedef struct tank_struct
  1111. X{
  1112. X    XPoint    coord[TANKPOINTS];
  1113. X} TANK;
  1114. X
  1115. XTANK Tank[TANKROT]=
  1116. X{{
  1117. X    {0,0},{T/2,-T},{T,0},{0,-T},{T,0},{0,4*T},{-T,0},{0,-T},{-T,0},{0,3*T},
  1118. X    {-T,0},{0,-3*T},{-T,0},{0,T},{-T,0},{0,-4*T},{T,0},{0,T},{T,0},{T/2,T}
  1119. X}};
  1120. X
  1121. XPLAYER player[MAXUSERS];    /* players tanks */
  1122. Xchar    field[OBJECTSIZE][OBJECTSIZE];
  1123. Xchar    radar[OBJECTSIZE][OBJECTSIZE];
  1124. X
  1125. X/* PIMAPS */
  1126. X#define PIXSIZE    48
  1127. XPixmap TankPix[TANKROT];
  1128. X
  1129. X
  1130. Xint fire=0;    /* fire button pressed */
  1131. Xint motion=0;    /* tank linear motion */
  1132. Xint mrot=0;    /* mouse pointer rotation */
  1133. Xint damage=0;    /* damage sustained */
  1134. Xchar message[BUFLEN]="";    /* message for message window */
  1135. Xchar *server=NULL;
  1136. X
  1137. XPOSITION cur={0,300,100,0,0};
  1138. XPOSITION garbage;
  1139. X
  1140. Xint pd[2];    /* pipe for passing current position */
  1141. X
  1142. Xint warpflag=0;    /* warp pointer on scrolling main screen */
  1143. Xint invert=1;    /* invert motion buttons */
  1144. X
  1145. Xint polyflag=0;    /* use polygons to draw tanks */
  1146. Xint pixflag=0;    /* use pixmaps to draw tanks */
  1147. X
  1148. X
  1149. Xint myid;    /* my id */
  1150. X
  1151. Xint rsd,ssd;    /* receive and send socket descripters */
  1152. XDATA rdata,sdata;    /* receive and send data */
  1153. X
  1154. XTime movetime=0;
  1155. Xint savedx=(-1),savedy=(-1);
  1156. Xint sfx=(-1),sfy=(-1);
  1157. Xint msx,msy;    /* mouse x,y */
  1158. Xint ex[MAXUSERS],ey[MAXUSERS],exptime[MAXUSERS];    /* explosions */
  1159. Xint debug=0;
  1160. X
  1161. Xint ppid,cpid;
  1162. X
  1163. X
  1164. Xchar *progname;
  1165. X
  1166. X
  1167. Xvoid
  1168. Xsignoff(t,reason)    /* send signoff to server and exit */
  1169. Xint t,reason;
  1170. X{
  1171. X    sdata.id=OUTSWAP(myid);
  1172. X    sdata.type=OUTSWAP(T_SIGNOFF);
  1173. X    sdata.extra.signoff.reason=OUTSWAP(reason);
  1174. X    senddata(ssd,&sdata);
  1175. X    if(t!=0)
  1176. X        sleep(t);
  1177. X    if(getpid()==cpid)
  1178. X        kill(ppid,SIGKILL);
  1179. X    else
  1180. X        kill(cpid,SIGKILL);
  1181. X    exit(1);
  1182. X}
  1183. X
  1184. Xvoid
  1185. Xdointr()    /* action on interrupt */
  1186. X{
  1187. X    signoff(0,DESTROYED);
  1188. X}
  1189. X
  1190. Xvoid
  1191. XdoXio()
  1192. X{
  1193. X    signoff(0,QUIT);
  1194. X}
  1195. X
  1196. Xvoid
  1197. Xtimeout()    /* timeout on connect */
  1198. X{
  1199. X    fprintf(stderr,"%s: No response from server \"%s\" (not running/busy?)\n",progname,server);
  1200. X    exit(1);
  1201. X}
  1202. X
  1203. Xvoid
  1204. Xdoexplosions()    /* deal with on screen explosions */
  1205. X{
  1206. X    int i,j,k,tx,ty,td,rad;
  1207. X    for(i=0;i<MAXUSERS;i++)
  1208. X    {
  1209. X        if(exptime[i]!=(-1))
  1210. X        {
  1211. X            td=gettime()-exptime[i];
  1212. X            if(td>EXPTIME)
  1213. X            {
  1214. X                exptime[i]=(-1);
  1215. X                tx=ex[i]/OBJECTSCALE;
  1216. X                ty=ey[i]/OBJECTSCALE;
  1217. X                for(k=(-2);k<3;k++)
  1218. X                    for(j=(-2);j<3;j++)
  1219. X                        DrawFieldSq(tx+k,ty+j,1);
  1220. X                if(damage>=MAXDAMAGE)
  1221. X                {
  1222. X                    signoff(5,KILLED);
  1223. X                }
  1224. X                XFlush(Disp);
  1225. X            }
  1226. X            else
  1227. X            {
  1228. X                if(td<=(EXPTIME/2))
  1229. X                {
  1230. X                    rad=(td*EXPSIZE*2)/EXPTIME;
  1231. X                    XFillArc(Disp,FWin,GcF,ex[i]-(rad/2),ey[i]-(rad/2),rad,rad,0,360*64);
  1232. X                    XFlush(Disp);
  1233. X                }
  1234. X                else
  1235. X                {
  1236. X                    rad=((td-(EXPTIME/2))*2*EXPSIZE)/EXPTIME;
  1237. X                    if(rad>0)
  1238. X                    {
  1239. X                        XFillArc(Disp,FWin,GcB,ex[i]-(rad/2),ey[i]-(rad/2),rad,rad,0,360*64);
  1240. X                        XFlush(Disp);
  1241. X                    }
  1242. X                }
  1243. X            }
  1244. X        }
  1245. X    }
  1246. X}
  1247. X
  1248. Xvoid
  1249. XInitTables()    /* initialise data tables (generate 128 different tank polygons) */
  1250. X{
  1251. X    short i,j,x,y;
  1252. X    double xc,yc,angle,incr,theta,len;
  1253. X
  1254. X    x=0;
  1255. X    y=0;
  1256. X    incr=(2*PI)/((double)TANKROT);
  1257. X
  1258. X
  1259. X    for(i=1;i<TANKPOINTS;i++)
  1260. X    {
  1261. X        x+=Tank[0].coord[i].x;
  1262. X        y+=Tank[0].coord[i].y;
  1263. X        Tank[0].coord[i].x=x;
  1264. X        Tank[0].coord[i].y=y;
  1265. X    }
  1266. X
  1267. X    for(j=1;j<TANKROT;j++)
  1268. X        for(i=1;i<TANKPOINTS;i++)
  1269. X        {
  1270. X            angle=((double)j)*incr;
  1271. X            xc=(double)Tank[0].coord[i].x;
  1272. X            yc=(double)Tank[0].coord[i].y;
  1273. X            if(xc==0.0)
  1274. X            {
  1275. X                if(yc>0)
  1276. X                    theta=(PI/2.0);
  1277. X                else
  1278. X                    theta=(-PI/2.0);
  1279. X            }
  1280. X            else
  1281. X            {
  1282. X                theta=atan2(yc,xc);
  1283. X            }
  1284. X
  1285. X            len=hypot(xc,yc);
  1286. X            theta+=angle;
  1287. X            xc=len*cos(theta);
  1288. X            yc=len*sin(theta);
  1289. X            Tank[j].coord[i].x=(short)(xc+0.5);
  1290. X            Tank[j].coord[i].y=(short)(yc+0.5);
  1291. X        }
  1292. X    for(j=0;j<TANKROT;j++)
  1293. X    {
  1294. X        for(i=TANKPOINTS;i>0;i--)
  1295. X        {
  1296. X            x=Tank[j].coord[i-1].x;
  1297. X            y=Tank[j].coord[i-1].y;
  1298. X            Tank[j].coord[i].x-=x;
  1299. X            Tank[j].coord[i].y-=y;
  1300. X        }
  1301. X    }
  1302. X}
  1303. X
  1304. X
  1305. Xvoid
  1306. Xsendstatus()    /* send our status to the server */
  1307. X{
  1308. X    sdata.type=OUTSWAP(T_MOVE);
  1309. X    sdata.id=OUTSWAP(myid);
  1310. X    sdata.extra.move.rot=OUTSWAP(mrot);
  1311. X    sdata.extra.move.linear=OUTSWAP(motion);
  1312. X    sdata.extra.move.fire=OUTSWAP(fire);
  1313. X/*    printf("motion=%d invert=%d\n",motion,invert);*/
  1314. X    senddata(ssd,&sdata);
  1315. X}
  1316. X
  1317. Xvoid
  1318. XWipeTank(x,y,rot,id)    /* wipe a tank from the screen */
  1319. Xint x,y,rot,id;
  1320. X{
  1321. X    int objx,objy;
  1322. X
  1323. X    objx=x/OBJECTSCALE;
  1324. X    objy=y/OBJECTSCALE;
  1325. X    radar[objx][objy]=0;
  1326. X
  1327. X    savedx=objx;
  1328. X    savedy=objy;
  1329. X    
  1330. X    x-=(cur.scx*OBJECTSCALE);
  1331. X    y-=(cur.scy*OBJECTSCALE);
  1332. X
  1333. X    sfx=x/OBJECTSCALE;
  1334. X    sfy=y/OBJECTSCALE;
  1335. X
  1336. X    if((sfx<(-1))||(sfy<(-1))||(sfx>(OBJX+1))||(sfy>(OBJY+1)))
  1337. X        return;
  1338. X    if(polyflag)
  1339. X    {
  1340. X        rot=(rot+TANKROT+(TANKROT/4))%TANKROT;
  1341. X        Tank[rot].coord[0].x=x;
  1342. X        Tank[rot].coord[0].y=y;
  1343. X        XFillPolygon(Disp,FWin,GcB,&Tank[rot],TANKPOINTS,Nonconvex,CoordModePrevious);
  1344. X    }
  1345. X    else
  1346. X    {
  1347. X        XCopyPlane(Disp,TankPix[rot],FWin,GcTB,0,0,PIXSIZE,PIXSIZE,x-(PIXSIZE/2),y-(PIXSIZE/2),0x1);
  1348. X    }
  1349. X
  1350. X    if(id!=myid)
  1351. X        XFillRectangle(Disp,FWin,GcB,x-5,y-5,10,10);
  1352. X}
  1353. X
  1354. Xvoid
  1355. XDrawTank(x,y,rot,id)    /* draw a tank on the screen */
  1356. Xint x,y,rot,id;
  1357. X{
  1358. X    int objx,objy,flag;
  1359. X    char str[2];
  1360. X
  1361. X    objx=x/OBJECTSCALE;
  1362. X    objy=y/OBJECTSCALE;
  1363. X
  1364. X    x-=(cur.scx*OBJECTSCALE);
  1365. X    y-=(cur.scy*OBJECTSCALE);
  1366. X
  1367. X    flag=(!radar[savedx][savedy]);
  1368. X    radar[objx][objy]=1;
  1369. X
  1370. X    if((savedx!=objx)||(savedy!=objy)||flag)
  1371. X    {
  1372. X        DrawRadarSq(savedx,savedy,1);
  1373. X        DrawRadarSq(objx,objy,1);
  1374. X    }
  1375. X
  1376. X    objx=x/OBJECTSCALE;
  1377. X    objy=y/OBJECTSCALE;
  1378. X    if((objx<(-1))||(objy<(-1))||(objx>(OBJX+1))||(objy>(OBJY+1)))
  1379. X        return;
  1380. X
  1381. X    if((savedx!=objx)||(savedy!=objy))
  1382. X    {
  1383. X        DrawFieldSq(sfx,sfy,0);
  1384. X    }
  1385. X    if(polyflag)
  1386. X    {
  1387. X        rot=(rot+TANKROT+(TANKROT/4))%TANKROT;
  1388. X        Tank[rot].coord[0].x=x;
  1389. X        Tank[rot].coord[0].y=y;
  1390. X        XFillPolygon(Disp,FWin,GcF,&Tank[rot],TANKPOINTS,Nonconvex,CoordModePrevious);
  1391. X    }
  1392. X    else
  1393. X    {
  1394. X        XCopyPlane(Disp,TankPix[rot],FWin,GcTF,0,0,PIXSIZE,PIXSIZE,x-(PIXSIZE/2),y-(PIXSIZE/2),0x1);
  1395. X    }
  1396. X    if(id!=myid)
  1397. X    {
  1398. X        XFillRectangle(Disp,FWin,GcB,x-5,y-6,10,11);
  1399. X        str[1]='\0';
  1400. X        str[0]=id+BASECHAR;
  1401. X        XDrawString(Disp,FWin,GcF,x-2,y+3,str,1);
  1402. X    }
  1403. X}
  1404. X
  1405. XDrawFieldSq(i,j,clear)    /* draw a square on the battlefield */
  1406. Xint i,j;
  1407. Xint clear;
  1408. X{
  1409. X    int x1,x2,y1,y2,mx,my;
  1410. X    switch(field[i+cur.scx][j+cur.scy])
  1411. X    {
  1412. X    case CLEAR:
  1413. X        if(clear)
  1414. X        {
  1415. X            x1=(i*OBJECTSCALE);
  1416. X            y1=(j*OBJECTSCALE);
  1417. X            XFillRectangle(Disp,FWin,GcB,x1,y1,OBJECTSCALE,OBJECTSCALE);
  1418. X        }
  1419. X        break;
  1420. X    case ROUGH:
  1421. X        x1=(i*OBJECTSCALE);
  1422. X        y1=(j*OBJECTSCALE);
  1423. X        x2=x1+OBJECTSCALE-1;
  1424. X        y2=y1+OBJECTSCALE-1;
  1425. X        mx=(x1+x2)/2;
  1426. X        my=(y1+y2)/2;
  1427. X        if(clear)
  1428. X            XFillRectangle(Disp,FWin,GcB,x1,y1,OBJECTSCALE,OBJECTSCALE);
  1429. X        XDrawLine(Disp,FWin,GcF,x1,y1,x2,y2);
  1430. X        XDrawLine(Disp,FWin,GcF,x1,y2,x2,y1);
  1431. X        XDrawLine(Disp,FWin,GcF,mx,y1,x1,my);
  1432. X        XDrawLine(Disp,FWin,GcF,mx,y1,x2,my);
  1433. X        XDrawLine(Disp,FWin,GcF,mx,y2,x1,my);
  1434. X        XDrawLine(Disp,FWin,GcF,mx,y2,x2,my);
  1435. X        break;
  1436. X    case BLOCKED:
  1437. X        x1=(i*OBJECTSCALE);
  1438. X        y1=(j*OBJECTSCALE);
  1439. X        XFillRectangle(Disp,FWin,GcF,x1,y1,OBJECTSCALE,OBJECTSCALE);
  1440. X        break;
  1441. X    default:
  1442. X        break;
  1443. X    }
  1444. X}
  1445. X
  1446. XDrawRadarSq(i,j,clear)    /* draw a square on the radar window */
  1447. Xint i,j,clear;
  1448. X{
  1449. X    int x1,x2,y1,y2;
  1450. X    switch(field[i][j])
  1451. X    {
  1452. X    case CLEAR:
  1453. X        if(clear)
  1454. X        {
  1455. X            x1=(i*ROSCALE);
  1456. X            y1=(j*ROSCALE);
  1457. X            XFillRectangle(Disp,RWin,GcB,x1,y1,ROSCALE,ROSCALE);
  1458. X        }
  1459. X        break;
  1460. X    case ROUGH:
  1461. X        x1=(i*ROSCALE);
  1462. X        y1=(j*ROSCALE);
  1463. X        x2=x1+ROSCALE-1;
  1464. X        y2=y1+ROSCALE-1;
  1465. X        if(clear)
  1466. X            XFillRectangle(Disp,RWin,GcB,x1,y1,ROSCALE,ROSCALE);
  1467. X        XDrawLine(Disp,RWin,GcF,x1,y1,x2,y2);
  1468. X        XDrawLine(Disp,RWin,GcF,x1,y2,x2,y1);
  1469. X        break;
  1470. X    case BLOCKED:
  1471. X        x1=(i*ROSCALE);
  1472. X        y1=(j*ROSCALE);
  1473. X        XDrawRectangle(Disp,RWin,GcF,x1,y1,ROSCALE-1,ROSCALE-1);
  1474. X        break;
  1475. X    default:
  1476. X        break;
  1477. X    }
  1478. X    if(radar[i][j])
  1479. X    {
  1480. X        x1=(i*ROSCALE);
  1481. X        y1=(j*ROSCALE);
  1482. X        XFillRectangle(Disp,RWin,GcF,x1,y1,ROSCALE,ROSCALE);
  1483. X    }
  1484. X}
  1485. X
  1486. Xvoid
  1487. XRefreshVSb(clear)    /* Refresh vertical scroll bar */
  1488. Xint clear;
  1489. X{
  1490. X    if(clear)
  1491. X        XClearWindow(Disp,VSb);
  1492. X    XFillRectangle(Disp,VSb,GcF,0,cur.scy*SBY,SCROLLBAR,SBY*OBJY);
  1493. X}
  1494. X
  1495. Xvoid
  1496. XRefreshHSb(clear)    /* Refresh horizontal scroll bar */
  1497. Xint clear;
  1498. X{
  1499. X    if(clear)
  1500. X        XClearWindow(Disp,HSb);
  1501. X    XFillRectangle(Disp,HSb,GcF,cur.scx*SBX,0,SBX*OBJX,SCROLLBAR);
  1502. X}
  1503. X
  1504. Xvoid
  1505. XRefreshRVSb(clear)    /* Refresh radar vertical scroll bar */
  1506. Xint clear;
  1507. X{
  1508. X    if(clear)
  1509. X        XClearWindow(Disp,RVSb);
  1510. X    XFillRectangle(Disp,RVSb,GcF,0,cur.scy*ROSCALE,BOARDER,OBJY*ROSCALE);
  1511. X}
  1512. X
  1513. Xvoid
  1514. XRefreshRHSb(clear)    /* refresh radar horizontal scroll bar */
  1515. Xint clear;
  1516. X{
  1517. X    if(clear)
  1518. X        XClearWindow(Disp,RHSb);
  1519. X    XFillRectangle(Disp,RHSb,GcF,cur.scx*ROSCALE,0,OBJX*ROSCALE,BOARDER);
  1520. X}
  1521. X
  1522. Xvoid
  1523. XRefreshSWin(clear)    /* refresh status (list of player names/scores) window */
  1524. Xint clear;
  1525. X{
  1526. X    int i;
  1527. X    char str[80];
  1528. X
  1529. X    if(clear)
  1530. X        XFillRectangle(Disp,SWin,GcB,0,0,RADARSIZE,15*(MAXUSERS+1));
  1531. X    for(i=0;i<MAXUSERS;i++)
  1532. X    {
  1533. X        if(*(player[i].user.username)=='\0')
  1534. X            continue;
  1535. 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);
  1536. X        XDrawString(Disp,SWin,GcF,10,(15*(i+1)),str,strlen(str));
  1537. X    }
  1538. X    XFlush(Disp);
  1539. X}
  1540. X
  1541. XRefreshFWin(clear)    /* refresh battlefield window */
  1542. Xint clear;
  1543. X{
  1544. X    int i,j;
  1545. X    for(i=0;i<OBJX;i++)
  1546. X        for(j=0;j<OBJY;j++)
  1547. X            DrawFieldSq(i,j,clear);
  1548. X}
  1549. X
  1550. Xstatic void
  1551. XRefreshRWin(clear)    /* refresh radar window */
  1552. Xint clear;
  1553. X{    /* refresh code */
  1554. X
  1555. X    int i,j;
  1556. X
  1557. X    for(i=0;i<OBJECTSIZE;i++)
  1558. X        for(j=0;j<OBJECTSIZE;j++)
  1559. X            DrawRadarSq(i,j,clear);
  1560. X    XFlush(Disp);
  1561. X}
  1562. X
  1563. Xvoid
  1564. XRefreshQWin(clear)    /* refresh QUIT window (button */
  1565. Xint clear;
  1566. X{
  1567. X    char *str="QUIT";
  1568. X    if(clear)
  1569. X        XClearWindow(Disp,QWin);
  1570. X    XDrawString(Disp,QWin,GcF,10,15,str,strlen(str));
  1571. X    XFlush(Disp);
  1572. X}
  1573. X
  1574. Xvoid
  1575. XRefreshAWin(clear)    /* refresh armour (damage) window */
  1576. Xint clear;
  1577. X{
  1578. X    char *str;
  1579. X    if(damage>=MAXDAMAGE)
  1580. X    {
  1581. X        XFillRectangle(Disp,AWin,GcB,0,0,RADARSIZE,(DAMAGEBAR/2)-1);
  1582. X        str="DESTROYED";
  1583. X    }
  1584. X    else
  1585. X    {
  1586. X        str="DAMAGE";
  1587. X    }
  1588. X    if(clear)
  1589. X        XClearWindow(Disp,AWin);
  1590. X    XDrawLine(Disp,AWin,GcF,0,DAMAGEBAR/2,RADARSIZE,DAMAGEBAR/2);
  1591. X    XDrawString(Disp,AWin,GcF,10,15,str,strlen(str));
  1592. X    XFillRectangle(Disp,AWin,GcF,0,DAMAGEBAR/2,damage*DAMAGESCALE,DAMAGEBAR/2);
  1593. X    XFlush(Disp);
  1594. X}
  1595. X
  1596. Xvoid
  1597. XRefreshMWin(clear)    /* refresh message window */
  1598. Xint clear;
  1599. X{
  1600. X    int i;
  1601. X
  1602. X    if(clear)
  1603. X        XClearWindow(Disp,MWin);
  1604. X    for(i=0;i<MAXUSERS;i++)
  1605. X    {
  1606. X        XDrawString(Disp,MWin,GcF,10,15,message,strlen(message));
  1607. X    }
  1608. X    XFlush(Disp);
  1609. X}
  1610. X
  1611. Xvoid
  1612. XRefreshWin(clear)
  1613. Xint clear;
  1614. X{
  1615. X}
  1616. X
  1617. Xint
  1618. Xcheckscroll(dx,dy)    /* check how far we can scroll */
  1619. Xint *dx,*dy;
  1620. X{
  1621. X    int sx,sy,osx,osy;
  1622. X    osx=SIZE(*dx);
  1623. X    osy=SIZE(*dy);
  1624. X
  1625. X    if((cur.scy+(*dy))<0)
  1626. X        (*dy)=(-1*cur.scy);
  1627. X    if((cur.scy+(*dy))>(OBJECTSIZE-MAINY/OBJECTSCALE))
  1628. X        (*dy)=(OBJECTSIZE-MAINY/OBJECTSCALE)-cur.scy;
  1629. X    if((cur.scx+(*dx))<0)
  1630. X        (*dx)=(-1*cur.scx);
  1631. X    if((cur.scx+(*dx))>(OBJECTSIZE-MAINX/OBJECTSCALE))
  1632. X        (*dx)=(OBJECTSIZE-MAINX/OBJECTSCALE)-cur.scx;
  1633. X    sx=SIZE(*dx);
  1634. X    sy=SIZE(*dy);
  1635. X
  1636. X    if((osx!=0)&&(sx==0)&&(osy!=0)&&(sy!=0)&&(sy!=osy))
  1637. X        return(5);
  1638. X
  1639. X    if((osx!=0)&&(sx!=0)&&(osy!=0)&&(sy==0)&&(sx!=osx))
  1640. X        return(5);
  1641. X
  1642. X    if((osx!=0)&&(sx!=0)&&(osy!=0)&&(sy!=0)&&(sx!=osx)&&(sy!=osy))
  1643. X        return(5);
  1644. X
  1645. X    if(sx>sy)
  1646. X        return(sx);
  1647. X    else
  1648. X        return(sy);
  1649. X}
  1650. X
  1651. Xvoid
  1652. Xscroll(dx,dy)    /* do the scroll */
  1653. Xint dx,dy;
  1654. X{
  1655. X    cur.scx+=dx;
  1656. X    cur.scy+=dy;
  1657. X
  1658. X    if(warpflag)
  1659. X        XWarpPointer(Disp,None,None,0,0,MAINX,MAINY,dx*(-1*OBJECTSCALE),dy*(-1*OBJECTSCALE));
  1660. X
  1661. X    if(dx!=0)
  1662. X    {
  1663. X        RefreshHSb(1);
  1664. X        RefreshRHSb(1);
  1665. X    }
  1666. X    if(dy!=0)
  1667. X    {
  1668. X        RefreshVSb(1);
  1669. X        RefreshRVSb(1);
  1670. X    }
  1671. X        
  1672. X    if((dx!=0)||(dy!=0))
  1673. X         RefreshFWin(1);
  1674. X}
  1675. X
  1676. X
  1677. Xvoid
  1678. XDoRefresh(refwin)    /* send a refresh */
  1679. XWindow refwin;
  1680. X{
  1681. X    if(refwin==Win)
  1682. X    {
  1683. X        RefreshWin(0);
  1684. X        return;
  1685. X    }
  1686. X    if(refwin==FWin)
  1687. X    {
  1688. X        RefreshFWin(0);
  1689. X        return;
  1690. X    }
  1691. X    if(refwin==RWin)
  1692. X    {
  1693. X        RefreshRWin(0);
  1694. X        return;
  1695. X    }
  1696. X    if(refwin==SWin)
  1697. X    {
  1698. X        RefreshSWin(0);
  1699. X        return;
  1700. X    }
  1701. X    if(refwin==QWin)
  1702. X    {
  1703. X        RefreshQWin(0);
  1704. X        return;
  1705. X    }
  1706. X    if(refwin==VSb)
  1707. X    {
  1708. X        RefreshVSb(0);
  1709. X        return;
  1710. X    }
  1711. X    if(refwin==HSb)
  1712. X    {
  1713. X        RefreshHSb(0);
  1714. X        return;
  1715. X    }
  1716. X    if(refwin==RVSb)
  1717. X    {
  1718. X        RefreshRVSb(0);
  1719. X        return;
  1720. X    }
  1721. X    if(refwin==RHSb)
  1722. X    {
  1723. X        RefreshRHSb(0);
  1724. X        return;
  1725. X    }
  1726. X    if(refwin==AWin)
  1727. X    {
  1728. X        RefreshAWin(0);
  1729. X        return;
  1730. X    }
  1731. X    if(refwin==MWin)
  1732. X    {
  1733. X        RefreshMWin(0);
  1734. X        return;
  1735. X    }
  1736. X}
  1737. X
  1738. Xint
  1739. XSocketHandle()    /* handle data from the server incomming on the socket */
  1740. X{
  1741. X    int i,j;
  1742. X    int gx,gy,dx,dy;
  1743. X    if(readdata(rsd,&rdata)!=sizeof(DATA))
  1744. X    {
  1745. X        fprintf(stderr,"%s: Recieved bad data\n");
  1746. X        exit(1);
  1747. X    }
  1748. X    switch(INSWAP(rdata.type))
  1749. X    {
  1750. X    case T_REPLY:
  1751. X        gx=(player[myid].pos.x/OBJECTSCALE)-cur.scx;
  1752. X        gy=(player[myid].pos.y/OBJECTSCALE)-cur.scy;
  1753. X
  1754. X        dy=gy-(MAINX/(2*OBJECTSCALE));
  1755. X        dx=gx-(MAINX/(2*OBJECTSCALE));
  1756. X
  1757. X        doexplosions();
  1758. X
  1759. X        if(checkscroll(&dx,&dy)>1)
  1760. X            scroll(dx,dy);
  1761. X
  1762. X        for(i=0;i<MAXUSERS;i++)
  1763. X        {
  1764. X            if(INSWAP(rdata.extra.reply.pos[i].x)==-1)
  1765. X                continue;
  1766. X            WipeTank(player[i].pos.x,player[i].pos.y,player[i].pos.rot,i);
  1767. X            player[i].pos.x=INSWAP(rdata.extra.reply.pos[i].x);
  1768. X            player[i].pos.y=INSWAP(rdata.extra.reply.pos[i].y);
  1769. X            player[i].pos.rot=INSWAP(rdata.extra.reply.pos[i].rot);
  1770. X            DrawTank(player[i].pos.x,player[i].pos.y,player[i].pos.rot,i);
  1771. X            XFlush(Disp);
  1772. X        }
  1773. X        /* update current position */
  1774. X        cur.x=player[myid].pos.x;
  1775. X        cur.y=player[myid].pos.y;
  1776. X        cur.rot=player[myid].pos.rot;
  1777. X
  1778. X            /* remove any 'spare' data from the pipe */
  1779. X        if(read(pd[0],&garbage,sizeof(POSITION))==-1)
  1780. X        {
  1781. X            if((errno!=EWOULDBLOCK)&&(errno!=EAGAIN))
  1782. X                perror("read pd[0]");
  1783. X        }
  1784. X        
  1785. X            /* tell our 'other half' about our new position */
  1786. X        if(write(pd[1],&cur,sizeof(POSITION))==-1)
  1787. X            perror("write pd[0]");
  1788. X        break;
  1789. X    case T_ACCEPT:
  1790. X        for(i=0;i<MAXUSERS;i++)
  1791. X        {
  1792. X            if((*(player[i].user.username)!='\0')&&(*(rdata.extra.accept.players[i].username)=='\0'))
  1793. X            {
  1794. X                WipeTank(player[i].pos.x,player[i].pos.y,player[i].pos.rot,i);
  1795. X                /*DrawRadarSq(player[i].pos.x/OBJECTSCALE,player[i].pos.x/OBJECTSCALE,1);*/
  1796. X            }
  1797. X            strcpy(player[i].user.username,rdata.extra.accept.players[i].username);
  1798. X            strcpy(player[i].user.hostname,rdata.extra.accept.players[i].hostname);
  1799. X            player[i].kills=INSWAP(rdata.extra.accept.kills[i]);
  1800. X            player[i].killed=INSWAP(rdata.extra.accept.killed[i]);
  1801. X        }
  1802. X        RefreshRWin(1);
  1803. X        RefreshSWin(1);
  1804. X        break;
  1805. X    case T_EXPLOSION:
  1806. X        damage=INSWAP(rdata.extra.explosion.damage[myid]);
  1807. X        RefreshAWin(1);
  1808. X        for(i=0;i<MAXUSERS;i++)
  1809. X        {
  1810. X            if(exptime[i]==(-1))
  1811. X            {
  1812. X                ex[i]=INSWAP(rdata.extra.explosion.x)-(cur.scx*OBJECTSCALE);
  1813. X                ey[i]=INSWAP(rdata.extra.explosion.y)-(cur.scy*OBJECTSCALE);
  1814. X
  1815. X                if((ex[i]<(-1*EXPSIZE))||(ey[i]<(-1*EXPSIZE))||(ex[i]>(MAINX+EXPSIZE))||(ey[i]>(EXPSIZE+MAINY)))
  1816. X                    break;
  1817. X                exptime[i]=gettime();
  1818. X                break;
  1819. X            }
  1820. X        }
  1821. X        break;
  1822. X    case T_MESSAGE:
  1823. X        strcpy(message,rdata.extra.message.text);
  1824. X        RefreshMWin(1);
  1825. X        break;
  1826. X    case T_ALIVE:
  1827. X        sdata.type=OUTSWAP(T_ALIVE);
  1828. X        senddata(ssd,&sdata);
  1829. X        break;
  1830. X    default:
  1831. X        printf("Unexpected datagram type %d (0x%x)\n",INSWAP(rdata.type),INSWAP(rdata.type));
  1832. X    }
  1833. X}
  1834. X
  1835. X
  1836. Xint
  1837. XEventHandle()    /* handle X events */
  1838. X{
  1839. X    XEvent Evnt;
  1840. X
  1841. X    XNextEvent(Disp,&Evnt);
  1842. X
  1843. X    if(read(pd[0],&cur,sizeof(POSITION))==-1)
  1844. X    {
  1845. X        if((errno!=EWOULDBLOCK)&&(errno!=EAGAIN))
  1846. X            perror("read pd[0]");
  1847. X    }
  1848. X
  1849. X    switch(Evnt.type)
  1850. X    {
  1851. X    case ButtonPress:
  1852. X        {
  1853. X            int bno;
  1854. X            XButtonEvent *BEvent;
  1855. X            BEvent=(XButtonEvent*)(&Evnt);
  1856. X            bno=BEvent->button;
  1857. X            if(BEvent->window==FWin)
  1858. X            {
  1859. X                mrot=GetAngle(cur.x,cur.y,msx,msy);
  1860. X                switch(bno)
  1861. X                {
  1862. X                case 1:
  1863. X                    if(damage<MAXDAMAGE)
  1864. X                        fire=1;
  1865. X                    break;
  1866. X                case 2:
  1867. X                    motion=invert;
  1868. X                    break;
  1869. X                case 3:
  1870. X                    motion=0-invert;
  1871. X                    break;
  1872. X                }
  1873. X                sendstatus();
  1874. X            }
  1875. X            else
  1876. X            {
  1877. X                if(BEvent->window==QWin)
  1878. X                switch(bno)
  1879. X                {
  1880. X                case 1:
  1881. X                    signoff(0,QUIT);
  1882. X                    break;
  1883. X                case 2:
  1884. X                    /* DEBUG */
  1885. X                    printf("cur.scx,cur.scy=%d,%d msx,msy=%d,%d\n",cur.scx,cur.scy,msx,msy);
  1886. X                    printf("tankx,tanky=%d,%d\n",cur.x,cur.y);
  1887. X                    break;
  1888. X                }
  1889. X            }
  1890. X        }
  1891. X        break;
  1892. X    case ButtonRelease:
  1893. X        {
  1894. X            int bno;
  1895. X            XButtonEvent *BEvent;
  1896. X            BEvent=(XButtonEvent*)(&Evnt);
  1897. X            bno=BEvent->button;
  1898. X
  1899. X            if(BEvent->window==FWin)
  1900. X            {
  1901. X                mrot=GetAngle(cur.x,cur.y,msx,msy);
  1902. X                switch(bno)
  1903. X                {
  1904. X                case 1:
  1905. X                    fire=0;
  1906. X                    sendstatus();
  1907. X                    break;
  1908. X                case 2:
  1909. X                    if(motion==invert)
  1910. X                    {
  1911. X                        motion=0;
  1912. X                        sendstatus();
  1913. X                    }
  1914. X                    break;
  1915. X                case 3:
  1916. X                    if(motion==(0-invert))
  1917. X                    {
  1918. X                        motion=0;
  1919. X                        sendstatus();
  1920. X                    }
  1921. X                    break;
  1922. X                }
  1923. X            }
  1924. X            else
  1925. X            {
  1926. X                printf("Button release outside battlefield\n");
  1927. X            }
  1928. X        }
  1929. X        break;
  1930. X    case MotionNotify:
  1931. X        {
  1932. X            XMotionEvent *MEvent;
  1933. X            MEvent=(XMotionEvent*)(&Evnt);
  1934. X            msx=(MEvent->x)+(cur.scx*OBJECTSCALE);
  1935. X            msy=(MEvent->y)+(cur.scy*OBJECTSCALE);
  1936. X            mrot=GetAngle(cur.x,cur.y,msx,msy);
  1937. X            if(MEvent->window==FWin)
  1938. X            {
  1939. X                if((MEvent->time-movetime)>100)
  1940. X                {
  1941. X                    sendstatus();
  1942. X                    movetime=MEvent->time;
  1943. X                }
  1944. X            }
  1945. X            else
  1946. X            {
  1947. X                printf("Mouse movement outside battlefield\n");
  1948. X            }
  1949. X        }
  1950. X        break;
  1951. X    case GraphicsExpose:
  1952. X    case Expose:
  1953. X        {
  1954. X            XExposeEvent *EEvent;
  1955. X            EEvent=(XExposeEvent*)(&Evnt);
  1956. X            if(EEvent->count==0)
  1957. X            {
  1958. X                DoRefresh(EEvent->window);
  1959. X            }
  1960. X        }
  1961. X        break;
  1962. X    case DestroyNotify:
  1963. X        {
  1964. X            XDestroyWindowEvent *XDEvent;
  1965. X            XDEvent=(XDestroyWindowEvent*)(&Evnt);
  1966. X            signoff(0,DESTROYED);
  1967. X        }
  1968. X        break;
  1969. X    case KeyPress:
  1970. X    case KeyRelease:
  1971. X        {
  1972. X            char buf[2];
  1973. X            int oldinvert;
  1974. X            XKeyEvent *KEvent; 
  1975. X
  1976. X            buf[1]='\0';
  1977. X            KEvent=(XKeyEvent*)(&Evnt);
  1978. X            XLookupString(KEvent,buf,1,NULL,NULL);
  1979. X            if(*buf==0x03)
  1980. X                signoff(0,QUIT);
  1981. X            oldinvert=invert;
  1982. X            if(Evnt.type==KeyPress)
  1983. X                invert=(-1);
  1984. X            else
  1985. X                invert=1;
  1986. X            if(oldinvert!=invert)
  1987. X            {
  1988. X                motion=0-motion;
  1989. X                sendstatus();
  1990. X            }
  1991. X        }
  1992. X        break;
  1993. X    default:
  1994. X/*        fprintf(stderr,"Unknown Event\n");*/
  1995. X        break;
  1996. X    }
  1997. X}
  1998. X
  1999. Xvoid
  2000. XCreatePixmaps()
  2001. X{
  2002. X    int i,j;
  2003. X    int rot;
  2004. X    XGCValues gcv;
  2005. X    GC GcPF,GcPB;
  2006. X    Pixmap Dummy;
  2007. X
  2008. X    if(pixflag)
  2009. X    {
  2010. X        Dummy=XCreatePixmap(Disp,Win,PIXSIZE,PIXSIZE,1);
  2011. X        gcv.function = GXcopy;
  2012. X        gcv.plane_mask =AllPlanes;
  2013. X        gcv.fill_style = FillSolid;
  2014. X        GcPF=XCreateGC(Disp,Dummy,(GCFunction | GCPlaneMask | GCFillStyle),&gcv);
  2015. X        XSetForeground(Disp,GcPF,1);
  2016. X        XSetBackground(Disp,GcPF,0);
  2017. X    
  2018. X        GcPB=XCreateGC(Disp,Dummy,(GCFunction | GCPlaneMask | GCFillStyle),&gcv);
  2019. X        XSetForeground(Disp,GcPB,0);
  2020. X        XSetBackground(Disp,GcPB,1);
  2021. X    
  2022. X        for(i=0;i<TANKROT;i++)
  2023. X        {
  2024. X            TankPix[i]=XCreatePixmap(Disp,Win,PIXSIZE,PIXSIZE,1);
  2025. X            if(TankPix[i]==BadAlloc)
  2026. X            {
  2027. X                /* no memory for pixmaps on server */
  2028. X                fprintf(stderr,"Failed to allocate pixmaps(%d)(%d*%d*%d), using polygons instead\n",i,PIXSIZE,PIXSIZE,1);
  2029. X                /* free currently allocated pixmaps */
  2030. X                for(j=0;j<i;j++)
  2031. X                    XFreePixmap(Disp,TankPix[j]);
  2032. X                pixflag=0;
  2033. X                polyflag=1;
  2034. X                break;
  2035. X            }
  2036. X            rot=(i+TANKROT+(TANKROT/4))%TANKROT;
  2037. X            Tank[rot].coord[0].x=PIXSIZE/2;
  2038. X            Tank[rot].coord[0].y=PIXSIZE/2;
  2039. X            XFillRectangle(Disp,TankPix[i],GcPB,0,0,PIXSIZE,PIXSIZE);
  2040. X            XFillPolygon(Disp,TankPix[i],GcPF,&Tank[rot],TANKPOINTS,Nonconvex,CoordModePrevious);
  2041. X        }
  2042. X            /* no longer needed */
  2043. X        XFreeGC(Disp,GcPF);
  2044. X        XFreeGC(Disp,GcPB);
  2045. X        XFreePixmap(Disp,Dummy);
  2046. X    }
  2047. X}
  2048. X
  2049. X
  2050. XXinit(Name,xs,ys)    /* initialise X */
  2051. Xchar *Name;
  2052. Xint xs,ys;
  2053. X{
  2054. X    unsigned long bg,fg;
  2055. X    Cursor Curs;
  2056. X    XGCValues gcv;
  2057. X    char *DisplayName;
  2058. X    Pixmap iconised;
  2059. X    XWMHints hint;
  2060. X    int i;
  2061. X
  2062. X    DisplayName=getenv("DISPLAY");
  2063. X    if(DisplayName==NULL)
  2064. X    {
  2065. X        fprintf(stderr,"%s: $DISPLAY not set\n",progname);
  2066. X        exit(1);
  2067. X    }
  2068. X
  2069. X    Disp=XOpenDisplay(DisplayName);
  2070. X
  2071. X    if(Disp==NULL)
  2072. X    {
  2073. X        fprintf(stderr,"%s: Unable to open $DISPLAY (%s)\n",progname,DisplayName);
  2074. X        exit(1);
  2075. X    }
  2076. X
  2077. X    Root=XDefaultRootWindow(Disp);
  2078. X    Scr=DefaultScreen(Disp);
  2079. X
  2080. X        /* if user has specified no defaults */
  2081. X    if((!polyflag)&&(!pixflag))
  2082. X    {
  2083. X        pixflag=1;
  2084. X        polyflag=0;
  2085. X    }
  2086. X
  2087. X    fg=BlackPixel(Disp,Scr);
  2088. X    bg=WhitePixel(Disp,Scr);
  2089. X
  2090. X        /* Main (parent window */
  2091. X    Win=XCreateSimpleWindow(Disp,Root,0,0,xs,ys,2,fg,bg);
  2092. X        /* Radar window */
  2093. X    RWin=XCreateSimpleWindow(Disp,Win,BOARDER,BOARDER,RADARSIZE,RADARSIZE,1,fg,bg);
  2094. X        /* Field window */
  2095. X    FWin=XCreateSimpleWindow(Disp,Win,BOARDER*4+RADARSIZE,BOARDER,MAINX,MAINY,1,fg,bg);
  2096. X        /* Armour status window */
  2097. X    AWin=XCreateSimpleWindow(Disp,Win,BOARDER,BOARDER*4+RADARSIZE,RADARSIZE-2,DAMAGEBAR,2,fg,bg);
  2098. X        /* Quit window */
  2099. X    QWin=XCreateSimpleWindow(Disp,Win,BOARDER,BOARDER*5+RADARSIZE+DAMAGEBAR,RADARSIZE-2,MESSAGESIZE,2,fg,bg);
  2100. X        /* Message window */
  2101. X    MWin=XCreateSimpleWindow(Disp,Win,BOARDER,BOARDER*6+MESSAGESIZE+RADARSIZE+DAMAGEBAR,RADARSIZE,MESSAGESIZE,1,fg,bg);
  2102. X        /* Status window */
  2103. X    SWin=XCreateSimpleWindow(Disp,Win,BOARDER,BOARDER*7+MESSAGESIZE*2+RADARSIZE+DAMAGEBAR,RADARSIZE,15*(MAXUSERS+1),1,fg,bg);
  2104. X
  2105. X        /* Main vertical and horizontal scroll bars */
  2106. X    VSb=XCreateSimpleWindow(Disp,Win,BOARDER*5+RADARSIZE+MAINX,BOARDER,SCROLLBAR,MAINY-2,2,fg,bg);
  2107. X    HSb=XCreateSimpleWindow(Disp,Win,BOARDER*4+RADARSIZE,BOARDER*2+MAINY,MAINX-2,SCROLLBAR,2,fg,bg);
  2108. X        /* Radar vertical and horizontal scroll bars */
  2109. X    RVSb=XCreateSimpleWindow(Disp,Win,BOARDER*2+RADARSIZE,BOARDER,BOARDER,RADARSIZE,1,fg,bg);
  2110. X    RHSb=XCreateSimpleWindow(Disp,Win,BOARDER,BOARDER*2+RADARSIZE,RADARSIZE,BOARDER,1,fg,bg);
  2111. X
  2112. X
  2113. X    XStoreName(Disp,Win,Name);
  2114. X
  2115. X    gcv.function = GXcopy;
  2116. X    gcv.plane_mask = AllPlanes;
  2117. X    gcv.fill_style = FillSolid;
  2118. X
  2119. X    GcF=XCreateGC(Disp,Win,(GCFunction | GCPlaneMask | GCFillStyle),&gcv);
  2120. X    GcB=XCreateGC(Disp,Win,(GCFunction | GCPlaneMask | GCFillStyle),&gcv);
  2121. X
  2122. X    XSetForeground(Disp,GcF,fg);
  2123. X    XSetBackground(Disp,GcF,bg);
  2124. X    XSetForeground(Disp,GcB,bg);
  2125. X    XSetBackground(Disp,GcB,fg);
  2126. X
  2127. X    gcv.function = GXor;
  2128. X    GcTF=XCreateGC(Disp,Win,(GCFunction | GCPlaneMask | GCFillStyle),&gcv);
  2129. X
  2130. X    gcv.function = GXandInverted;
  2131. X    GcTB=XCreateGC(Disp,Win,(GCFunction | GCPlaneMask | GCFillStyle),&gcv);
  2132. X
  2133. X    XSetForeground(Disp,GcTF,fg);
  2134. X    XSetBackground(Disp,GcTF,bg);
  2135. X    XSetForeground(Disp,GcTB,fg);
  2136. X    XSetBackground(Disp,GcTB,bg);
  2137. X
  2138. X    Curs=XCreateFontCursor(Disp,XC_crosshair);
  2139. X    XDefineCursor(Disp,Win,Curs);
  2140. X    iconised=XCreateBitmapFromData(Disp,Win,xtb_bits,xtb_width,xtb_height);
  2141. X    hint.flags=(InputHint|IconPixmapHint);
  2142. X    hint.input=True;
  2143. X    hint.icon_pixmap=iconised;
  2144. X    XSetWMHints(Disp,Win,&hint);
  2145. X    CreatePixmaps();
  2146. X
  2147. X    XSetIOErrorHandler(doXio);
  2148. X}
  2149. X
  2150. Xvoid
  2151. XSelectAllInputs()
  2152. X{
  2153. X    XSelectInput(Disp,Win,ExposureMask|StructureNotifyMask);
  2154. X    XSelectInput(Disp,RWin,ExposureMask);
  2155. X    XSelectInput(Disp,FWin,FieldEventMask);
  2156. X    XSelectInput(Disp,QWin,ButtonMask|ExposureMask|StructureNotifyMask);
  2157. X    XSelectInput(Disp,SWin,ExposureMask);
  2158. X
  2159. X    XSelectInput(Disp,VSb,ExposureMask);
  2160. X    XSelectInput(Disp,HSb,ExposureMask);
  2161. X    XSelectInput(Disp,RVSb,ExposureMask);
  2162. X    XSelectInput(Disp,RHSb,ExposureMask);
  2163. X    XSelectInput(Disp,AWin,ExposureMask);
  2164. X    XSelectInput(Disp,MWin,ExposureMask);
  2165. X}
  2166. X
  2167. Xvoid
  2168. XMapAllWindows()        /* obvious */
  2169. X{
  2170. X    XMapWindow(Disp,Win);
  2171. X    XMapWindow(Disp,FWin);
  2172. X    XMapWindow(Disp,RWin);
  2173. X    XMapWindow(Disp,SWin);
  2174. X    XMapWindow(Disp,QWin);
  2175. X
  2176. X    XMapWindow(Disp,VSb);
  2177. X    XMapWindow(Disp,HSb);
  2178. X    XMapWindow(Disp,RVSb);
  2179. X    XMapWindow(Disp,RHSb);
  2180. X    XMapWindow(Disp,AWin);
  2181. X    XMapWindow(Disp,MWin);
  2182. X
  2183. X    XFlush(Disp);
  2184. X}
  2185. X
  2186. X
  2187. Xmain(argc,argv)
  2188. Xint argc;
  2189. Xchar *argv[];
  2190. X{
  2191. X    int i,j;
  2192. X    char *p;
  2193. X
  2194. X    int inport,outport;
  2195. X    int fieldok;
  2196. X    progname=argv[0];
  2197. X
  2198. X    server=getenv("XTB_SERVER");
  2199. X
  2200. X    p=getenv("XTB_INPORT");
  2201. X    if(p!=NULL)
  2202. X        inport=atoi(p);
  2203. X    else
  2204. X        inport=DEFCPORT;
  2205. X
  2206. X    p=getenv("XTB_OUTPORT");
  2207. X    if(p!=NULL)
  2208. X        outport=atoi(p);
  2209. X    else
  2210. X        outport=DEFSPORT;
  2211. X
  2212. X    for(i=1;i<argc;i++)
  2213. X    {
  2214. X        p=argv[i];
  2215. X        if(*p++=='-')
  2216. X        {
  2217. X            switch(*p++)
  2218. X            {
  2219. X            case 'i':    /* input/client port */
  2220. X            case 'c':
  2221. X                if(*p=='\0')
  2222. X                    inport=atoi(argv[++i]);
  2223. X                else
  2224. X                    inport=atoi(p);
  2225. X                break;
  2226. X            case 'o':    /* output/server port */
  2227. X            case 's':
  2228. X                if(*p=='\0')
  2229. X                    outport=atoi(argv[++i]);
  2230. X                else
  2231. X                    outport=atoi(p);
  2232. X                break;
  2233. X            case 'h':
  2234. X                if(*p=='\0')
  2235. X                    server=argv[++i];
  2236. X                else
  2237. X                    server=p;
  2238. X                break;
  2239. X            case 'w':
  2240. X                warpflag++;
  2241. X                break;
  2242. X            case 'd':
  2243. X                debug++;
  2244. X                break;
  2245. X            case 'b':    /* use pixmaps for drawing tanks */
  2246. X                pixflag++;
  2247. X                break;
  2248. X            case 'p':    /* use polygons  for drawing tanks */
  2249. X                polyflag++;
  2250. X                break;
  2251. X            default:
  2252. X                fprintf(stderr,"Usage: %s [-h server_host] [-w] [-c client_portno] [-s server_portno] \n",argv[0]);
  2253. X            }
  2254. X        }
  2255. X    }
  2256. X
  2257. X    if(server==NULL)
  2258. X    {
  2259. X        fprintf(stderr,"%s: No server host (-h or $XTB_SERVER) defined\n",argv[0]);
  2260. X        exit(1);
  2261. X    }
  2262. X
  2263. X    rsd=openread(inport);
  2264. X    if(rsd==(-1))
  2265. X    {
  2266. X        fprintf(stderr,"%s: Opening port %d failed\n",argv[0],inport);
  2267. X        exit(1);
  2268. X    }
  2269. X    
  2270. X    ssd=opensend(server,outport);
  2271. X    if(ssd==(-1))
  2272. X    {
  2273. X        fprintf(stderr,"%s: Connecting to %s/%d failed\n",argv[0],server,outport);
  2274. X        exit(1);
  2275. X    }
  2276. X
  2277. X    for(i=0;i<MAXUSERS;i++)
  2278. X        exptime[i]=(-1);
  2279. X    InitTables();
  2280. X    Xinit("XTankBattle",MAINX+RADARSIZE+6*BOARDER+SCROLLBAR,MAINY+3*BOARDER+SCROLLBAR);
  2281. X
  2282. X        /* signon */
  2283. X    sdata.type=OUTSWAP(T_SIGNON);
  2284. X    sdata.extra.signon.version=OUTSWAP(VERSION);
  2285. X    sdata.extra.signon.port=OUTSWAP(inport);    /* could be different to server port */
  2286. X    gethostname(sdata.extra.signon.hostname,HOSTLEN);
  2287. X    strncpy(sdata.extra.signon.username,((struct passwd*)getpwuid(getuid()))->pw_name,NAMELEN-1);
  2288. X    sdata.extra.signon.username[NAMELEN]='\0';
  2289. X
  2290. X    signal(SIGALRM,timeout);
  2291. X    alarm(3);
  2292. X    senddata(ssd,&sdata);
  2293. X
  2294. X    if(readdata(rsd,&rdata)!=sizeof(DATA))
  2295. X    {
  2296. X        fprintf(stderr,"%s: Recieved bad data\n");
  2297. X        exit(1);
  2298. X    }
  2299. X    alarm(0);
  2300. X    switch(INSWAP(rdata.type))
  2301. X    {
  2302. X    case T_ACCEPT:
  2303. X        if(debug)
  2304. X        {
  2305. X            printf("accept\n");
  2306. X            printf("My id is %d\n",INSWAP(rdata.extra.accept.id));
  2307. X        }
  2308. X        myid=INSWAP(rdata.extra.accept.id);
  2309. X        for(i=0;i<MAXUSERS;i++)
  2310. X        {
  2311. X            strcpy(player[i].user.username,rdata.extra.accept.players[i].username);
  2312. X            strcpy(player[i].user.hostname,rdata.extra.accept.players[i].hostname);
  2313. X            player[i].kills=INSWAP(rdata.extra.accept.kills[i]);
  2314. X            player[i].killed=INSWAP(rdata.extra.accept.killed[i]);
  2315. X        }
  2316. X        break;
  2317. X    case T_REJECT:
  2318. X        fprintf(stderr,"reject\n");
  2319. X        fprintf(stderr,"reason: %s\n",rdata.extra.reject.text);
  2320. X        exit(1);
  2321. X        break;
  2322. X    default:
  2323. X        if(debug)
  2324. X            printf("Unknown datagram type %d (0x%x)\n",INSWAP(rdata.type),INSWAP(rdata.type));
  2325. X    }
  2326. X
  2327. X    for(i=0;i<OBJECTSIZE;i++)
  2328. X        for(j=0;j<OBJECTSIZE;j++)
  2329. X            radar[i][j]=0;
  2330. X    for(i=0;i<OBJECTSIZE;i++)
  2331. X        field[i][0]=UNSET;
  2332. X
  2333. X    MapAllWindows();
  2334. X
  2335. X    if(debug)
  2336. X        printf("Getting field data\n");
  2337. X    sdata.id=OUTSWAP(myid);
  2338. X    sdata.type=OUTSWAP(T_DATAREQ);
  2339. X
  2340. X    do
  2341. X    {
  2342. X        fieldok=1;
  2343. X        for(i=0;i<OBJECTSIZE;i++)
  2344. X        {
  2345. X            if(field[i][0]==UNSET)
  2346. X            {
  2347. X                fflush(stdout);
  2348. X                fieldok=0;
  2349. X                sdata.extra.datareq.lineno=OUTSWAP(i);
  2350. X                senddata(ssd,&sdata);
  2351. X                if(readdata(rsd,&rdata)!=sizeof(DATA))
  2352. X                {
  2353. X                    fprintf(stderr,"%s: Recieved bad data\n",argv[0]);
  2354. X                    exit(1);
  2355. X                }
  2356. X                if(INSWAP(rdata.type)!=T_FIELDDATA)
  2357. X                {
  2358. X                    if(INSWAP(rdata.type)==T_MESSAGE)
  2359. X                        strcpy(message,rdata.extra.message.text);
  2360. X                    else
  2361. X                        fprintf(stderr,"%s: Expected field data got 0x%x\n",argv[0],INSWAP(rdata.type));
  2362. X                }
  2363. X                else
  2364. X                {
  2365. X                    if(debug)
  2366. X                    {
  2367. X                        if(INSWAP(rdata.extra.field.lineno)!=i)
  2368. X                            printf("%%%d",INSWAP(rdata.extra.field.lineno));
  2369. X                        else
  2370. X                            printf(".%d",i);
  2371. X                    }
  2372. X                    memcpy(field[INSWAP(rdata.extra.field.lineno)],rdata.extra.field.object,OBJECTSIZE);
  2373. X                }
  2374. X            }
  2375. X        }
  2376. X    }
  2377. X    while(!fieldok);
  2378. X    putchar('\n');
  2379. X
  2380. X    if(pipe(pd)==(-1))
  2381. X    {
  2382. X        fprintf(stderr,"%s: pipe(pd) failed\n",argv[0]);
  2383. X        exit(1);
  2384. X    }
  2385. X
  2386. X    /* make read pipe descripter non-blocking */
  2387. X    i=1;
  2388. X    if(ioctl(pd[0],FIONBIO,&i)==-1)
  2389. X    {
  2390. X        fcntl(pd[0],F_SETFL,O_NDELAY);
  2391. X    }
  2392. X
  2393. X    ppid=getpid();
  2394. X
  2395. X    signal(SIGHUP,dointr);
  2396. X    signal(SIGINT,dointr);
  2397. X    signal(SIGTERM,dointr);
  2398. X    RefreshRWin(0);
  2399. X    RefreshSWin(0);
  2400. X    RefreshQWin(0);
  2401. X    RefreshVSb(0);
  2402. X    RefreshHSb(0);
  2403. X    RefreshRVSb(0);
  2404. X    RefreshRHSb(0);
  2405. X    RefreshAWin(0);
  2406. X    RefreshMWin(0);
  2407. X
  2408. X    switch(cpid=fork())
  2409. X    {
  2410. X    case 0:    /* child */
  2411. X        /* server -> socket -> X display */
  2412. X        cpid=getpid();
  2413. X        Disp=XOpenDisplay(getenv("DISPLAY"));
  2414. X
  2415. X        while(1)
  2416. X        {
  2417. X            SocketHandle();
  2418. X        }
  2419. X        break;
  2420. X
  2421. X    case -1: /* error */
  2422. X        fprintf(stderr,"%s: Couldn't fork()\n",argv[0]);
  2423. X        exit(1);
  2424. X        break;
  2425. X
  2426. X    default:/* parent */
  2427. X        /* X events -> socket -> server */
  2428. X        SelectAllInputs();
  2429. X        while(1)
  2430. X            EventHandle();
  2431. X        break;
  2432. X    }
  2433. X}
  2434. END_OF_FILE
  2435. if test 31436 -ne `wc -c <'xtb.c'`; then
  2436.     echo shar: \"'xtb.c'\" unpacked with wrong size!
  2437. fi
  2438. # end of 'xtb.c'
  2439. fi
  2440. echo shar: End of archive 1 \(of 2\).
  2441. cp /dev/null ark1isdone
  2442. MISSING=""
  2443. for I in 1 2 ; do
  2444.     if test ! -f ark${I}isdone ; then
  2445.     MISSING="${MISSING} ${I}"
  2446.     fi
  2447. done
  2448. if test "${MISSING}" = "" ; then
  2449.     echo You have unpacked both archives.
  2450.     rm -f ark[1-9]isdone
  2451. else
  2452.     echo You still need to unpack the following archives:
  2453.     echo "        " ${MISSING}
  2454. fi
  2455. ##  End of shell archive.
  2456. exit 0
  2457.