home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume15 / xtb / part02 < prev    next >
Encoding:
Internet Message Format  |  1993-01-26  |  33.6 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: v15i030:  xtb - multi-player X11 tank game and server, Part02/02
  5. Message-ID: <4040@master.CNA.TEK.COM>
  6. Date: 8 Dec 92 17:39:04 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 1399
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1529
  11.  
  12. Submitted-by: bmh@terminus.ericsson.se (Bernard Hatt)
  13. Posting-number: Volume 15, Issue 30
  14. Archive-name: xtb/Part02
  15. Environment: X11, UDP Sockets
  16.  
  17.  
  18. #! /bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 2 (of 2)."
  25. # Contents:  Makefile TODO comms.h defs.h dgram.c xtb.6 xtbd.c
  26. # Wrapped by billr@saab on Tue Dec  8 09:35:46 1992
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'Makefile'\"
  30. else
  31. echo shar: Extracting \"'Makefile'\" \(938 characters\)
  32. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  33. X# Makefile for XTankBattle
  34. X
  35. Xall    : xtb xtbd rtb
  36. X
  37. XCFLAGS = -O2
  38. XCC = cc
  39. X# wherever your X11 include files are 
  40. XXINCS = -I/usr/openwin/include
  41. X
  42. XSOURCES =  xtb.c rtb.c xtbd.c dgram.c common.c
  43. XINCLUDES = defs.h comms.h
  44. XMISC = xtb.6 README TODO
  45. X
  46. Xrtb    : rtb.o dgram.o common.o
  47. X    $(CC) -o rtb rtb.o dgram.o common.o -lm
  48. X
  49. Xxtb    : xtb.o dgram.o common.o
  50. X    $(CC) -o xtb xtb.o dgram.o common.o -lX11 -lm
  51. X
  52. Xxtbd    : xtbd.o dgram.o common.o
  53. X    $(CC) -o xtbd  xtbd.o dgram.o common.o -lm
  54. X
  55. Xxtb.o : xtb.c $(INCLUDES)
  56. X    cc -c xtb.c $(XINCS)
  57. X
  58. Xrtb.o : rtb.c $(INCLUDES)
  59. Xxtbd.o:    xtbd.c  $(INCLUDES)
  60. Xdgram.o : dgram.c $(INCLUDES)
  61. X
  62. Xcommon.o : common.c $(INCLUDES)
  63. X    cc -c common.c -DBSD
  64. X
  65. Xshar: $(SOURCES) $(INCLUDES) Makefile $(MISC)
  66. X    shar $(SOURCES) $(INCLUDES) Makefile $(MISC) >xtb.shar
  67. X
  68. Xtar: $(SOURCES) $(INCLUDES) Makefile $(MISC)
  69. X    tar cvf xtb.tar $(SOURCES) $(INCLUDES) Makefile $(MISC)
  70. X
  71. Xshu:    tar
  72. X    compress xtb.tar
  73. X    uuencode xtb.tar.Z xtb.tar.Z >xtb.shu
  74. X    rm xtb.tar.Z
  75. END_OF_FILE
  76. if test 938 -ne `wc -c <'Makefile'`; then
  77.     echo shar: \"'Makefile'\" unpacked with wrong size!
  78. fi
  79. # end of 'Makefile'
  80. fi
  81. if test -f 'TODO' -a "${1}" != "-c" ; then 
  82.   echo shar: Will not clobber existing file \"'TODO'\"
  83. else
  84. echo shar: Extracting \"'TODO'\" \(848 characters\)
  85. sed "s/^X//" >'TODO' <<'END_OF_FILE'
  86. X
  87. XEnhancement Ideas
  88. X=================
  89. X
  90. XRestart option when killed.
  91. XShootable blocks.
  92. XDifferent tank types (heavy/light armour, high/low speed, short/long range).
  93. XRecognise teams.
  94. XMore than 24 players ?
  95. XBar new entrants to a game, (ie. allow n to start, game ends when n-1 are dead).
  96. XNew players to start with average (or worst) damage of existing players?
  97. XLimited shells/ammo dumps ?
  98. XAutomatic invoicing of players at 10p per game!
  99. XUse UDP broadcast to cut down traffic ?
  100. XTime bar to prevent playing during working hours ?
  101. XClients able to get score list from server ?
  102. X3D view (like Battlezone) ?
  103. XScrolling using copy rather than repaint ?
  104. X
  105. XDone
  106. X====
  107. X
  108. XTwo button mouse support (Any key (without auto-repeat) pressed reverses
  109. X    motion, any key released un-reverses). 
  110. XFixed refresh on startup (failed only occasionly).
  111. XProper restart for robot tanks.
  112. X
  113. END_OF_FILE
  114. if test 848 -ne `wc -c <'TODO'`; then
  115.     echo shar: \"'TODO'\" unpacked with wrong size!
  116. fi
  117. # end of 'TODO'
  118. fi
  119. if test -f 'comms.h' -a "${1}" != "-c" ; then 
  120.   echo shar: Will not clobber existing file \"'comms.h'\"
  121. else
  122. echo shar: Extracting \"'comms.h'\" \(3413 characters\)
  123. sed "s/^X//" >'comms.h' <<'END_OF_FILE'
  124. X/* comms and common data structures */
  125. X
  126. X/*
  127. X * $Header: /morpork/home/bmh/xtest2/RCS/comms.h,v 1.18 92/10/19 15:34:38 bmh Exp Locker: bmh $
  128. X *
  129. X * Bernard Hatt
  130. X * Camtec Electronics (Ericsson), Leicester, England, LE1 4SA
  131. X * bmh@terminus.ericsson.se
  132. X *
  133. X */
  134. X
  135. X    /* types of message */
  136. X#define    T_SIGNON    1    /* signon request to server */
  137. X#define    T_ACCEPT    2    /* accept of signon from server */
  138. X#define T_REJECT    3    /* rejection of signon from server */
  139. X#define T_MOVE        4    /* move made sent to server */
  140. X#define    T_REPLY        5    /* reply from server (once moves have been made) */
  141. X#define    T_SIGNOFF    6    /* signoff to server */
  142. X#define T_FIELDDATA    7    /* battlefield data (from server) */
  143. X#define    T_DATAREQ    8    /* request for battlefield data (to server) */
  144. X#define T_EXPLOSION    9    /* explosion on battlefield */
  145. X#define T_MESSAGE    10    /* message from server */
  146. X#define T_ALIVE        11    /* check if client is alive */
  147. X
  148. X    /* match byte orders of differing machines */
  149. X#define INSWAP(x)    ((int)(htonl((long)(x))))
  150. X#define OUTSWAP(x)    ((int)(ntohl((long)(x))))
  151. X
  152. X
  153. Xtypedef struct struct_userinfo
  154. X{
  155. X    int id;    
  156. X    char username[NAMELEN];
  157. X    char hostname[HOSTLEN];        /* sending hostname */
  158. X} USER;
  159. X
  160. Xtypedef struct struct_position
  161. X{
  162. X    int x;        /* x position on battlefield */
  163. X    int y;        /* y */
  164. X    int rot;    /* rotation */
  165. X    int scx;    /* x distance scrolled */
  166. X    int scy;    /* y */
  167. X} POSITION;
  168. X
  169. Xtypedef struct signon_struct
  170. X{
  171. X    int port;    /* callback port no. */
  172. X    int version;    /* program version */
  173. X    char hostname[HOSTLEN];    /* sending hostname */
  174. X    char username[NAMELEN];
  175. X} SIGNON;
  176. X
  177. Xtypedef struct accept_struct
  178. X{
  179. X    int id;        /* your player id. */
  180. X    USER players[MAXUSERS];
  181. X    int kills[MAXUSERS];    /* no. of kills made */
  182. X    int killed[MAXUSERS];    /* no of times killed */
  183. X} ACCEPT;
  184. X
  185. Xtypedef struct reject_struct
  186. X{
  187. X    int reason;        /* unused */
  188. X    char text[BUFLEN];    /* textual reason for rejection */
  189. X} REJECT;
  190. X
  191. Xtypedef struct move_struct
  192. X{
  193. X    int rot;    /* rotation */
  194. X    int linear;    /* linear movement */
  195. X    int fire;    /* file button */
  196. X} MOVE;
  197. X
  198. Xtypedef struct reply_struct
  199. X{
  200. X    POSITION    pos[MAXUSERS];    /* positions of players */
  201. X} REPLY;
  202. X
  203. Xtypedef struct field_struct
  204. X{
  205. X    int lineno;        /* line no of field */
  206. X    char object[OBJECTSIZE];    /* data */
  207. X} FIELD;
  208. X
  209. Xtypedef struct datareq_struct
  210. X{
  211. X    int lineno;        /* requested reason */
  212. X} DATAREQ;
  213. X
  214. Xtypedef struct signoff_struct
  215. X{
  216. X    int reason;
  217. X} SIGNOFF;
  218. X
  219. Xtypedef struct explosion_struct
  220. X{
  221. X    int x;    /* x and y of explosion */
  222. X    int y;
  223. X    int damage[MAXUSERS];    /* damage sustained by players */
  224. X} EXPLOSION;
  225. X
  226. Xtypedef struct message_struct
  227. X{
  228. X    char text[BUFLEN];
  229. X} MESSAGE;
  230. X
  231. Xtypedef union extra_union
  232. X{
  233. X    SIGNON    signon;
  234. X    ACCEPT    accept;
  235. X    REJECT    reject;
  236. X    MOVE    move;
  237. X    REPLY    reply;
  238. X    FIELD    field;
  239. X    DATAREQ    datareq;
  240. X    EXPLOSION explosion;
  241. X    MESSAGE    message;
  242. X    SIGNOFF    signoff;
  243. X} EXTRA;
  244. X
  245. Xtypedef struct data_struct
  246. X{
  247. X    int type;    /* type of message */
  248. X    int id;        /* id of sending machine */
  249. X    EXTRA extra;
  250. X} DATA;
  251. X
  252. Xtypedef struct player_struct
  253. X{
  254. X    int ssd;    /* socket descripter */
  255. X    int t;        /* last time a move was made */
  256. X    int restime;    /* time of last response */
  257. X    int firetime;    /* last time the player fired */
  258. X    int damage;    /* damage a player has sustained */
  259. X    int kills;    /* kills made by a player */
  260. X    int killed;    /* times killed */
  261. X    USER    user;    /* data about user */
  262. X    POSITION pos;    /* current position */
  263. X    MOVE    move;    /* status */
  264. X} PLAYER;
  265. X
  266. Xtypedef struct score_struct
  267. X{
  268. X    int kills;    /* kills made by a player */
  269. X    int killed;    /* times killed */
  270. X    USER    user;    /* data about user */
  271. X} SCORE;
  272. END_OF_FILE
  273. if test 3413 -ne `wc -c <'comms.h'`; then
  274.     echo shar: \"'comms.h'\" unpacked with wrong size!
  275. fi
  276. # end of 'comms.h'
  277. fi
  278. if test -f 'defs.h' -a "${1}" != "-c" ; then 
  279.   echo shar: Will not clobber existing file \"'defs.h'\"
  280. else
  281. echo shar: Extracting \"'defs.h'\" \(2767 characters\)
  282. sed "s/^X//" >'defs.h' <<'END_OF_FILE'
  283. X/* common defines */
  284. X/*
  285. X * $Header: /morpork/home/bmh/xtest2/RCS/defs.h,v 1.20 92/10/19 15:34:40 bmh Exp Locker: bmh $
  286. X *
  287. X * Bernard Hatt
  288. X * Camtec Electronics (Ericsson), Leicester, England, LE1 4SA
  289. X * bmh@terminus.ericsson.se
  290. X *
  291. X */
  292. X
  293. X    /* increment this version no. if the client/server protocol is */
  294. X    /* changed in any way */
  295. X#define VERSION        7
  296. X
  297. X#define DEFSPORT    1622    /* default server UDP port no. */
  298. X#define DEFCPORT    1623    /* default client UDP port no. */
  299. X#define DEFRPORT    1650    /* default base for robot players */
  300. X
  301. X#define MAXUSERS     10    /* max no of users. */
  302. X
  303. X#if MAXUSERS >10
  304. X#define BASECHAR    'A'    /* use letters if more than 10 users */
  305. X#else
  306. X#define BASECHAR    '0'    /* use digits if less than 10 users */
  307. X#endif
  308. X
  309. X#define MAXROBOTS    (MAXUSERS/2)    /* max no. of robots */
  310. X
  311. X#define SCORES        (MAXUSERS*3)    /* max number of users in score table */
  312. X
  313. X#define MAINX   768      /* X and Y of main battlefield */
  314. X#define MAINY   768   
  315. X
  316. X#define HOSTLEN    16    /* max chars in hostname */
  317. X#define NAMELEN    16    /* max chars in username */
  318. X#define BUFLEN    128    /* general purpose char buffer */
  319. X
  320. X#define MAINSIZE    2048    /* size of field in pixels */
  321. X
  322. X#define OBJECTSIZE    32    /* size of object grid */
  323. X#define OBJECTSCALE    (MAINSIZE/OBJECTSIZE)
  324. X#define OBJX        (MAINX/OBJECTSCALE)
  325. X#define OBJY        (MAINY/OBJECTSCALE)
  326. X
  327. X
  328. X#define RADARSIZE    256    /* size of radar screen (pixels) */
  329. X#define RADARSCALE    (MAINSIZE/RADARSIZE)
  330. X#define ROSCALE        (RADARSIZE/OBJECTSIZE)    /* radar/object scale */
  331. X
  332. X#define SCROLLBAR    8    /* width of scroll bar */
  333. X#define SBX        (MAINX/OBJECTSIZE)
  334. X#define SBY        (MAINY/OBJECTSIZE)
  335. X
  336. X#define MESSAGESIZE    24
  337. X#define DAMAGEBAR    48
  338. X
  339. X#define TANKROT 128     /* number of different tank rotations */
  340. X#define TGRID   6       /* size of grid defining tank */
  341. X#define T       TGRID
  342. X
  343. X
  344. X#define    CLEAR    0    /* types of ground */
  345. X#define ROUGH    1
  346. X#define UNSET    64
  347. X#define    BLOCKED    127
  348. X
  349. X#define QUIT        0    /* user quit */
  350. X#define    KILLED        1    /* killed */
  351. X#define TIMEOUT        2    /* timeout after no responce */
  352. X#define DESTROYED    3    /* DestroyWindow event */
  353. X
  354. X#define MAXDAMAGE    128
  355. X#define DAMAGESCALE    (RADARSIZE/MAXDAMAGE)
  356. X#define EXPSIZE        192    /* size of explosion (pixels dia.) */
  357. X#define EXPTIME        60    /* time for explosion (cs) */
  358. X#define EXPCONST    100    /* power of explosions */
  359. X#define EXPRANGE    (32*32)    /* range for which explosions count as direct hits */
  360. X
  361. X#define STDMOVE    64    /* standard move in pixels/sec */
  362. X#define MSTDMOVE (-1*STDMOVE)    /* minus standard move in pixels/sec */
  363. X#define STDROT    32    /* standard rotation in pixels/sec */
  364. X#define MSTDROT    (-1*STDROT)    /* minus standard rotation in pixels/sec */
  365. X
  366. X
  367. X#define PI    3.14159265358979323846264338327950
  368. X
  369. X/* function type defs. */
  370. X
  371. Xextern char *getenv();
  372. X
  373. X    /* functions in common.c */
  374. Xint gettime(),rnd(),GetAngle();
  375. Xvoid myualarm();
  376. X
  377. X#define SIZE(x) ((x>0)?x:(0-x))
  378. END_OF_FILE
  379. if test 2767 -ne `wc -c <'defs.h'`; then
  380.     echo shar: \"'defs.h'\" unpacked with wrong size!
  381. fi
  382. # end of 'defs.h'
  383. fi
  384. if test -f 'dgram.c' -a "${1}" != "-c" ; then 
  385.   echo shar: Will not clobber existing file \"'dgram.c'\"
  386. else
  387. echo shar: Extracting \"'dgram.c'\" \(1486 characters\)
  388. sed "s/^X//" >'dgram.c' <<'END_OF_FILE'
  389. X/*
  390. X * Comms.
  391. X *
  392. X * $Header: /morpork/home/bmh/xtest2/RCS/dgram.c,v 1.10 92/10/19 15:34:27 bmh Exp Locker: bmh $
  393. X *
  394. X * Bernard Hatt
  395. X * Camtec Electronics (Ericsson), Leicester, England, LE1 4SA
  396. X * bmh@terminus.ericsson.se
  397. X *
  398. X */
  399. X
  400. X#include <sys/types.h>
  401. X#include <sys/socket.h>
  402. X#include <netinet/in.h>
  403. X#include <netdb.h>
  404. X#include <stdio.h>
  405. X
  406. X#include "defs.h"
  407. X#include "comms.h"
  408. X
  409. X#define STREAM_TYPE    SOCK_DGRAM
  410. X
  411. Xstruct hostent *gethostbyname();
  412. X
  413. Xint
  414. Xopenread(port)
  415. Xint port;
  416. X{
  417. X    int sd;
  418. X    struct sockaddr_in name;
  419. X
  420. X    sd=socket(AF_INET,STREAM_TYPE,0);
  421. X    if(sd==-1)
  422. X    {
  423. X        perror("openread()/socket()");
  424. X        return(-1);
  425. X    }
  426. X     name.sin_family=AF_INET;
  427. X    name.sin_addr.s_addr=INADDR_ANY;
  428. X    name.sin_port=htons(port);
  429. X
  430. X    if(bind(sd,&name,sizeof(name)))
  431. X    {
  432. X        perror("openread()/bind()");
  433. X        return(-1);
  434. X    }
  435. X    return(sd);
  436. X}
  437. X
  438. Xint
  439. Xreaddata(sd,data)
  440. Xint sd;
  441. XDATA *data;
  442. X{
  443. X    return(read(sd,data,sizeof(DATA)));
  444. X}
  445. X
  446. Xint
  447. Xopensend(host,port)
  448. Xchar *host;
  449. Xint port;
  450. X{
  451. X    int ret,sd;
  452. X    struct sockaddr_in name;
  453. X    struct hostent *hent;
  454. X
  455. X    sd=socket(AF_INET,STREAM_TYPE,0);
  456. X    if(sd==-1)
  457. X    {
  458. X        perror("opensend()/socket()");
  459. X        return(-1);
  460. X    }
  461. X
  462. X    hent=gethostbyname(host);
  463. X    if(hent==NULL)
  464. X        return(-1);
  465. X
  466. X    bcopy(hent->h_addr,&name.sin_addr,hent->h_length);
  467. X    name.sin_family=AF_INET;
  468. X    name.sin_port=htons(port);
  469. X
  470. X        /* connect port */
  471. X    ret=connect(sd,&name,sizeof(name));
  472. X    if(ret==-1)
  473. X    {
  474. X        perror("opensend()/connect()");
  475. X        return(-1);
  476. X    }
  477. X    return(sd);
  478. X}
  479. X
  480. Xint
  481. Xsenddata(sd,data)
  482. Xint sd;
  483. XDATA *data;
  484. X{
  485. X    return(write(sd,data,sizeof(DATA)));
  486. X}
  487. END_OF_FILE
  488. if test 1486 -ne `wc -c <'dgram.c'`; then
  489.     echo shar: \"'dgram.c'\" unpacked with wrong size!
  490. fi
  491. # end of 'dgram.c'
  492. fi
  493. if test -f 'xtb.6' -a "${1}" != "-c" ; then 
  494.   echo shar: Will not clobber existing file \"'xtb.6'\"
  495. else
  496. echo shar: Extracting \"'xtb.6'\" \(4450 characters\)
  497. sed "s/^X//" >'xtb.6' <<'END_OF_FILE'
  498. X.TH XTB 6 "13 January 1991"
  499. X.SH NAME
  500. Xxtb, xtbd \- X11 Tank battle program and server
  501. X.SH SYNOPSIS
  502. X.B xtb
  503. X[
  504. X.B \-ic
  505. X] [
  506. X.IR portno
  507. X] [
  508. X.B \-os
  509. X] [
  510. X.IR portno
  511. X]
  512. X.B \-h
  513. X.IR hostname
  514. X[
  515. X.B \-w
  516. X]
  517. X[
  518. X.B \-p
  519. X]
  520. X[
  521. X.B \-b
  522. X]
  523. X.LP
  524. X.B xtbd
  525. X.B \-p
  526. X[
  527. X.IR portno
  528. X]
  529. X.LP
  530. X.B rtb
  531. X[
  532. X.B \-ic
  533. X] [
  534. X.IR portno
  535. X] [
  536. X.B \-os
  537. X] [
  538. X.IR portno
  539. X]
  540. X.B \-h
  541. X.IR hostname
  542. X[
  543. X.B \-n
  544. X.IR robots
  545. X]
  546. X.LP
  547. X.SH DESCRIPTION
  548. XMulti player, multi workstation tank battle game.
  549. X.SH OPTIONS
  550. X.B \-h
  551. X    Server hostname to contact.
  552. X.br
  553. X.B \-w
  554. X    Turns on warping of the mouse cursor on scrolling.
  555. XThe default is for the mouse cursor not to be moved when the screen is
  556. Xscrolled (With \fB-w\fR the square under the cursor remains the same.)
  557. X(Use what you find intuitive)
  558. X.br
  559. X.B "\-c\fR or \fB\-i"
  560. X    Client (input) port number for client to use.
  561. X.br
  562. X.B "\-s\fR or \fB\-o"
  563. X    Server (output) port number for client to use.
  564. X.br
  565. X.B "\-p"
  566. X    Server port number for server to use (xtbd).
  567. X.br
  568. X.B "\-p"
  569. X    Use polygons for drawing tanks (xtb).
  570. X.br
  571. X.B "\-b"
  572. X    Use bitmaps for drawing tanks (default) (xtb).
  573. XSome X servers may not have sufficient storage for 128 bitmaps or may find
  574. Xdrawing polygons quicker than copying pixmaps, if so use \fB-b\fR.
  575. X.br
  576. X.B "\-n"
  577. X    Number of robot tanks for rtb to produce.
  578. X.br
  579. X.SH STARTUP
  580. XPick a node (can be any machine with or without X) and run the server (xtbd).
  581. X.ti +1i
  582. X\fIhostname\fR% xtbd
  583. X.LP
  584. XFor each player at a workstation run the client (xtb).
  585. X.ti +1i
  586. Xworkstation% xtb -h \fIhostname\fR
  587. X.br
  588. X(ignore messages about datagrams and fielddata)
  589. X.LP    
  590. XFor second and further players \fBon the same node\fR, each should pick
  591. Xdifferent port numbers to the default (and each other). eg
  592. Xthe second player might type
  593. X.ti +1i
  594. Xworkstation% xtb -h \fIhostname\fR -i 1624
  595. X.LP
  596. XTo run two or more servers on the same node, use a different port number
  597. Xto the default. eg.
  598. X.ti +1i
  599. X\fIhostname\fR% xtbd -p 1627
  600. X.br
  601. Xto contact this server the player would need to type
  602. X.ti +1i
  603. Xworkstation% xtb -h \fIhostname\fR -o 1627
  604. X.LP
  605. XTo start robot tanks, run rtb as you would xtb, adding the -n option for
  606. Xthe number of robots. Robots restart when killed after a 5 second delay.
  607. X.SH PLAYING
  608. XThe display has several areas, the main battlefield, (you appear as a
  609. Xsolid black tank, all others display their id) the radar, a damage
  610. Xdisplay, a message window, a quit button and a list of players and their
  611. Xid's. There are also scroll indicators, for the main and radar windows,
  612. Xshowing the portion of the battlefield that is on display.
  613. X.LP
  614. XThe controls are simple.
  615. X.br
  616. XLeft button    -> Fire (in the direction the tank is facing)
  617. X.br
  618. XMiddle button    -> Reverse
  619. X.br
  620. XRight button    -> Forward
  621. X.LP
  622. XIf you only have a two button mouse, you can use the keyboard to reverse
  623. Xthe tank motion, any key press causes the motion to be reversed, any key
  624. Xrelease returns to normal.  If you have auto-repeat on your keyboard
  625. X(most do), use a key that does not auto repeat (ie. shift,control etc)
  626. XThis will not work for a window manager that does not implement the
  627. Xinput (push-focus) window manager hint (olwm and twm are known to work).
  628. X.LP
  629. XThe tank will rotate towards the mouse cursor when the cursor is in the
  630. Xmain field.
  631. X.LP
  632. XThe solid black squares are obstacles, and cannot be moved through or
  633. Xfired through.
  634. X.LP
  635. XThe hatched areas are rough ground, you can only move at half speed
  636. Xacross these.
  637. X.LP
  638. XThe shells have a range of about four squares, you cannot fire again for
  639. X2.5 sec after firing.
  640. X.LP
  641. XExplosions do damage according to the (inverse square of the) distance
  642. Xfrom the explosion.  Two direct hits is sufficient for a kill, near
  643. Xmisses cause smaller amounts of damage. 
  644. X.LP
  645. XKilling another player clears your own damage (to encourage friendly play!).
  646. X.LP
  647. XQuitting should be done using the quit button (NOT the window manager
  648. Xframe)
  649. X.LP
  650. XIt is possible to shoot through the diagonal of two blocks.
  651. X.LP
  652. XThe battle ground is set for an invocation of the server, each time the
  653. Xserver is started a new battle ground is generated. (Scores are also set
  654. Xto zero when a server is re-started.)
  655. X.LP
  656. X.SH ENVIRONMENT
  657. X.B XTB_SERVER
  658. X- name of server to contact by default
  659. X.br
  660. X.B XTB_INPORT
  661. X- port number for input (client) (-i or -c)
  662. X.br
  663. X.B XTB_OUTPORT
  664. X- port number for output (server) (-o or -s)
  665. X.br
  666. X.SH BUGS
  667. XI don't currently know of any major bugs (that make the game
  668. Xunplayable/stop/core dump), though it is a bit flaky in a few places.
  669. X.SH AUTHOR
  670. XBernard Hatt
  671. X.br
  672. XCamtec Electronics (Ericsson), Leicester, England.
  673. X.br
  674. Xbmh@terminus.ericsson.se
  675. END_OF_FILE
  676. if test 4450 -ne `wc -c <'xtb.6'`; then
  677.     echo shar: \"'xtb.6'\" unpacked with wrong size!
  678. fi
  679. # end of 'xtb.6'
  680. fi
  681. if test -f 'xtbd.c' -a "${1}" != "-c" ; then 
  682.   echo shar: Will not clobber existing file \"'xtbd.c'\"
  683. else
  684. echo shar: Extracting \"'xtbd.c'\" \(15465 characters\)
  685. sed "s/^X//" >'xtbd.c' <<'END_OF_FILE'
  686. X/*
  687. X * Server
  688. X *
  689. X * $Header: /morpork/home/bmh/xtest2/RCS/xtbd.c,v 1.28 92/10/19 15:34:36 bmh Exp Locker: bmh $
  690. X *
  691. X * Bernard Hatt
  692. X * Camtec Electronics (Ericsson), Leicester, England, LE1 4SA
  693. X * bmh@terminus.ericsson.se
  694. X *
  695. X */
  696. X
  697. X#include <stdio.h>
  698. X#include <math.h>
  699. X#include <sys/time.h>
  700. X#include <sys/types.h>
  701. X#include <netinet/in.h>
  702. X#include <signal.h>
  703. X#include <errno.h>
  704. X
  705. X#include "defs.h"
  706. X#include "comms.h"
  707. X
  708. XPLAYER player[MAXUSERS];    /* players tanks */
  709. Xchar    field[OBJECTSIZE][OBJECTSIZE];
  710. XSCORE    score[SCORES];        /* score table */
  711. Xint noscores=0;            /* number of scores in score table */
  712. X
  713. Xint sintable[TANKROT];
  714. Xint costable[TANKROT];
  715. X
  716. X
  717. XDATA pdata;
  718. X
  719. XDATA rdata,sdata;
  720. Xint rsd,ssd;
  721. Xchar mbuf[BUFLEN];
  722. Xint lastsend=0;
  723. X
  724. Xchar *progname;
  725. X
  726. Xint debug=0;
  727. Xint scoreflag=1;
  728. X
  729. Xint
  730. Xisuseron(name,host)
  731. Xchar *name,*host;
  732. X{
  733. X    int i;
  734. X    for(i=0;i<MAXUSERS;i++)
  735. X    {
  736. X        if(strcmp(player[i].user.username,name))
  737. X            continue;
  738. X        if(strcmp(player[i].user.hostname,host))
  739. X            continue;
  740. X        return(i);
  741. X    }
  742. X    return(-1);
  743. X}
  744. X
  745. Xvoid
  746. Xgetscore(id)    /* get score for player[id] */
  747. Xint id;
  748. X{
  749. X    int i;
  750. X    for(i=0;i<noscores;i++)
  751. X    {
  752. X        if(strcmp(player[id].user.username,score[i].user.username))
  753. X            continue;
  754. X        if(strcmp(player[id].user.hostname,score[i].user.hostname))
  755. X            continue;
  756. X        player[id].killed=score[i].killed;
  757. X        player[id].kills=score[i].kills;
  758. X        return;
  759. X    }
  760. X    player[id].killed=0;
  761. X    player[id].kills=0;
  762. X    if(i==SCORES)
  763. X    {
  764. X        fprintf(stderr,"Run out of score table entries\n");
  765. X    }
  766. X    else
  767. X    {
  768. X        strcpy(score[noscores].user.username,player[id].user.username);
  769. X        strcpy(score[noscores].user.hostname,player[id].user.hostname);
  770. X        noscores++;
  771. X    }
  772. X}
  773. X
  774. Xvoid
  775. Xdumpscores()    /* dump all scores */
  776. X{
  777. X    int i;
  778. X    int killed,kills,total;
  779. X    int on;
  780. X    char ch;
  781. X    for(i=0;i<noscores;i++)
  782. X    {
  783. X        ch=' ';
  784. X        kills=score[i].kills;
  785. X        killed=score[i].killed;
  786. X        on=isuseron(score[i].user.username,score[i].user.hostname);
  787. X        if(on!=(-1))
  788. X        {
  789. X            ch='*';
  790. X            kills=player[on].kills;
  791. X            killed=player[on].killed;
  792. X        }
  793. X        total=kills+killed;
  794. X        if(total==0)
  795. X            total=1;
  796. X        printf("%12s@%-12s %c games %-4d, kills %-4d (%3d%%), killed %-4d (%3d%%)\n",score[i].user.username,score[i].user.hostname,ch,total,kills,((100*kills)/total),killed,((100*killed)/total));
  797. X    }
  798. X}
  799. X
  800. Xvoid
  801. Xsetscore(id)    /* set score for player[id] */
  802. Xint id;
  803. X{
  804. X    int i;
  805. X    for(i=0;i<noscores;i++)
  806. X    {
  807. X        if(strcmp(player[id].user.username,score[i].user.username))
  808. X            continue;
  809. X        if(strcmp(player[id].user.hostname,score[i].user.hostname))
  810. X            continue;
  811. X        score[i].killed=player[id].killed;
  812. X        score[i].kills=player[id].kills;
  813. X        printf("Score for %s@%s is %d/%d\n",score[i].user.username,score[i].user.hostname,player[id].kills,player[id].killed);
  814. X        return;
  815. X    }
  816. X    fprintf(stderr,"User not in score table!\n");
  817. X}
  818. X
  819. Xint
  820. Xsqdist(x1,y1,x2,y2)    /* square of distance between (x1,y1) and (x2,y2) */
  821. Xint x1,y1,x2,y2;
  822. X{
  823. X    int dx,dy;
  824. X    dx=(x1-x2);
  825. X    dy=(y1-y2);
  826. X    return(dx*dx+dy*dy);
  827. X}
  828. X
  829. Xvoid
  830. Xsendplayers()    /* send all players their positions */
  831. X{
  832. X    int i;
  833. X    pdata.type=OUTSWAP(T_REPLY);
  834. X
  835. X    for(i=0;i<MAXUSERS;i++)
  836. X    {
  837. X        pdata.extra.reply.pos[i].x=OUTSWAP(player[i].pos.x);
  838. X        pdata.extra.reply.pos[i].y=OUTSWAP(player[i].pos.y);
  839. X        pdata.extra.reply.pos[i].rot=OUTSWAP(player[i].pos.rot);
  840. X    }
  841. X
  842. X    for(i=0;i<MAXUSERS;i++)
  843. X        if(player[i].pos.x!=-1)
  844. X            senddata(player[i].ssd,&pdata);
  845. X}
  846. X
  847. Xvoid
  848. Xsendmessage(str)    /* send a message to all players */
  849. Xchar *str;
  850. X{
  851. X    int i;
  852. X    sdata.type=OUTSWAP(T_MESSAGE);
  853. X    strcpy(sdata.extra.message.text,str);
  854. X    for(i=0;i<MAXUSERS;i++)
  855. X        if(player[i].pos.x!=-1)
  856. X            senddata(player[i].ssd,&sdata);
  857. X}
  858. X
  859. Xvoid
  860. Xfireshell(id)    /* player (id) has fired */
  861. Xint id;
  862. X{
  863. X    int newtime,i,j;
  864. X    int srot,dist;
  865. X    int sx,sy;
  866. X    int dx,dy;
  867. X    int hflag=0,kflag=0,killed;
  868. X
  869. X    newtime=gettime();
  870. X    if((newtime>(250+player[id].firetime))&&(player[id].damage<MAXDAMAGE))
  871. X    {
  872. X        player[id].firetime=newtime;
  873. X        srot=player[id].pos.rot;
  874. X        sx=player[id].pos.x;
  875. X        sy=player[id].pos.y;
  876. X        dx=costable[srot]/4;
  877. X        dy=sintable[srot]/4;
  878. X        for(i=0;i<16;i++)
  879. X        {
  880. X            sx-=dx;
  881. X            sy-=dy;
  882. X            if((sx>MAINSIZE)||(sy>MAINSIZE)||(sx<0)||(sy<0))
  883. X                break;
  884. X            if(field[sx/OBJECTSCALE][sy/OBJECTSCALE]==BLOCKED)
  885. X                break;
  886. X            for(j=0;j<MAXUSERS;j++)
  887. X            {
  888. X                if(id==j)
  889. X                    continue;
  890. X                if(player[j].pos.x==(-1))
  891. X                    continue;
  892. X                if(sqdist(sx,sy,player[j].pos.x,player[j].pos.y)<(TGRID*TGRID*6*6))
  893. X                {
  894. X                    hflag++;
  895. X                    break;
  896. X                }
  897. X            }
  898. X            if(hflag)
  899. X                break;
  900. X        }
  901. X        /* sx,sy is position of shell hit */
  902. X        sdata.type=OUTSWAP(T_EXPLOSION);
  903. X        sdata.extra.explosion.x=OUTSWAP(sx);
  904. X        sdata.extra.explosion.y=OUTSWAP(sy);
  905. X        for(i=0;i<MAXUSERS;i++)
  906. X        {
  907. X            if(player[i].pos.x==(-1))
  908. X                continue;
  909. X            if(player[i].damage>=MAXDAMAGE)
  910. X                continue;
  911. X            dist=sqdist(sx,sy,player[i].pos.x,player[i].pos.y);
  912. X            if(dist<EXPRANGE)
  913. X                player[i].damage+=MAXDAMAGE/2;
  914. X            else
  915. X                player[i].damage+=(EXPCONST*(MAXDAMAGE/2)/((dist-EXPRANGE)+EXPCONST));
  916. X            if(player[i].damage>=MAXDAMAGE)
  917. X            {
  918. X                killed=i;
  919. X                kflag++;
  920. X            }
  921. X            sdata.extra.explosion.damage[i]=OUTSWAP(player[i].damage);
  922. X        }
  923. X
  924. X        if(kflag&&(killed!=id))
  925. X        {
  926. X            player[id].damage=0;
  927. X            player[id].kills++;
  928. X        }
  929. X        
  930. X        for(i=0;i<MAXUSERS;i++)
  931. X        {
  932. X            if(player[i].pos.x==(-1))
  933. X                continue;
  934. X            senddata(player[i].ssd,&sdata);
  935. X        }
  936. X
  937. X        if(kflag)
  938. X        {
  939. X            if(killed==id)
  940. X                sprintf(mbuf,"%s@%s committed suicide",player[killed].user.username,player[killed].user.hostname);
  941. X            else
  942. X                sprintf(mbuf,"%s@%s killed by %s@%s",player[killed].user.username,player[killed].user.hostname,player[id].user.username,player[id].user.hostname);
  943. X            sendmessage(mbuf);
  944. X        }
  945. X
  946. X    }
  947. X}
  948. X
  949. Xvoid
  950. Xdosignon()    /* deal with signon from user */
  951. X{
  952. X    int rndx,rndy;
  953. X    int id,ssd,i,cflag,attempts;
  954. X    /* find free slot */
  955. X    id=(-1);
  956. X    for(i=0;i<MAXUSERS;i++)
  957. X    if(player[i].pos.x==(-1))
  958. X    {
  959. X        id=i;
  960. X        break;
  961. X    }
  962. X    ssd=opensend(rdata.extra.signon.hostname,INSWAP(rdata.extra.signon.port));
  963. X    if(ssd==(-1))
  964. X    {
  965. X        fprintf(stderr,"%s: Connecting to %s/%d failed\n",progname,rdata.extra.signon.hostname,INSWAP(rdata.extra.signon.port));
  966. X    }
  967. X    else
  968. X    {
  969. X        sdata.type=OUTSWAP(T_ACCEPT);
  970. X        if(INSWAP(rdata.extra.signon.version)!=VERSION)
  971. X        {
  972. X            sdata.type=OUTSWAP(T_REJECT);
  973. X            sprintf(sdata.extra.reject.text,"Client/Server version no. mismatch (%d,%d)",INSWAP(rdata.extra.signon.version),VERSION);
  974. X        }
  975. X        if(id==(-1))
  976. X        {
  977. X            sdata.type=OUTSWAP(T_REJECT);
  978. X            strcpy(sdata.extra.reject.text,"Too many users");
  979. X        }
  980. X        if(isuseron(rdata.extra.signon.username,rdata.extra.signon.hostname)!=(-1))
  981. X        {
  982. X            sdata.type=OUTSWAP(T_REJECT);
  983. X            strcpy(sdata.extra.reject.text,"User already signed on");
  984. X        }
  985. X        if(sdata.type==OUTSWAP(T_REJECT))
  986. X        {
  987. X            senddata(ssd,&sdata);
  988. X            printf("Sent reject \"%s\"\n",sdata.extra.reject.text);
  989. X            close(ssd);
  990. X            return;
  991. X        }
  992. X        attempts=0;
  993. X        player[id].ssd=ssd;
  994. X        do
  995. X        {
  996. X            attempts++;
  997. X            cflag=0;
  998. X            rndx=rnd(OBJECTSIZE);
  999. X            rndy=rnd(OBJECTSIZE);
  1000. X            for(i=0;i<MAXUSERS;i++)
  1001. X            {
  1002. X                if(i==id)
  1003. X                    continue;
  1004. X                if(player[i].pos.x==(-1))
  1005. X                    continue;
  1006. X                if(sqdist(rndx*OBJECTSCALE+(OBJECTSCALE/2),rndy*OBJECTSCALE+(OBJECTSCALE/2),player[i].pos.x,player[i].pos.y)<(OBJECTSCALE*OBJECTSCALE*49))
  1007. X                {
  1008. X                    if(attempts<5)
  1009. X                        cflag++;
  1010. X                    break;
  1011. X                }
  1012. X            }
  1013. X        }
  1014. X        while(((field[rndx][rndy]!=CLEAR)||(cflag))&&(attempts<10));
  1015. X
  1016. X        player[id].pos.x=rndx*OBJECTSCALE+(OBJECTSCALE/2);
  1017. X        player[id].pos.y=rndy*OBJECTSCALE+(OBJECTSCALE/2);
  1018. X        player[id].pos.rot=0;
  1019. X        player[id].move.rot=0;
  1020. X        player[id].move.linear=0;
  1021. X        player[id].t=gettime();
  1022. X        player[id].restime=gettime();
  1023. X        player[id].damage=0;
  1024. X        strcpy(player[id].user.username,rdata.extra.signon.username);
  1025. X        strcpy(player[id].user.hostname,rdata.extra.signon.hostname);
  1026. X        getscore(id);
  1027. X        printf("Sent accept (id=%d)\n",id);
  1028. X        sdata.extra.accept.id=OUTSWAP(id);
  1029. X        for(i=0;i<MAXUSERS;i++)
  1030. X        {
  1031. X            strcpy(sdata.extra.accept.players[i].username,player[i].user.username);
  1032. X            strcpy(sdata.extra.accept.players[i].hostname,player[i].user.hostname);
  1033. X            sdata.extra.accept.killed[i]=OUTSWAP(player[i].killed);
  1034. X            sdata.extra.accept.kills[i]=OUTSWAP(player[i].kills);
  1035. X        }
  1036. X        for(i=0;i<MAXUSERS;i++)
  1037. X            if(player[i].pos.x!=-1)
  1038. X                senddata(player[i].ssd,&sdata);
  1039. X        sprintf(mbuf,"Signon from %s@%s",player[id].user.username,player[id].user.hostname);
  1040. X        sendmessage(mbuf);
  1041. X    }
  1042. X}
  1043. X
  1044. Xvoid
  1045. Xdosignoff(thisid,reason)    /* deal with signoff from user */
  1046. Xint thisid,reason;
  1047. X{
  1048. X    int i;
  1049. X
  1050. X    switch(reason)
  1051. X    {
  1052. X    case QUIT:
  1053. X        printf("signoff (QUIT) from %d\n",thisid);
  1054. X        if(player[thisid].damage>(MAXDAMAGE/2))
  1055. X            player[thisid].killed++;
  1056. X        break;
  1057. X    case KILLED:
  1058. X        printf("signoff (KILLED) from %d\n",thisid);
  1059. X        player[thisid].killed++;
  1060. X        break;
  1061. X    case TIMEOUT:
  1062. X        printf("signoff (TIMEOUT) from %d\n",thisid);
  1063. X        break;    
  1064. X    case DESTROYED:
  1065. X        printf("signoff (DESTROYED) from %d\n",thisid);
  1066. X        break;    
  1067. X    }
  1068. X    if((reason!=KILLED)&&(reason!=DESTROYED))
  1069. X    {
  1070. X        sprintf(mbuf,"Signoff from %s@%s",player[thisid].user.username,player[thisid].user.hostname);
  1071. X        sendmessage(mbuf);
  1072. X    }
  1073. X    setscore(thisid);
  1074. X
  1075. X    *(player[thisid].user.username)='\0';
  1076. X    *(player[thisid].user.hostname)='\0';
  1077. X
  1078. X    if(scoreflag)
  1079. X        dumpscores();
  1080. X
  1081. X    sdata.type=OUTSWAP(T_ACCEPT);
  1082. X    for(i=0;i<MAXUSERS;i++)
  1083. X    {
  1084. X        strcpy(sdata.extra.accept.players[i].username,player[i].user.username);
  1085. X        strcpy(sdata.extra.accept.players[i].hostname,player[i].user.hostname);
  1086. X        sdata.extra.accept.killed[i]=OUTSWAP(player[i].killed);
  1087. X        sdata.extra.accept.kills[i]=OUTSWAP(player[i].kills);
  1088. X    }
  1089. X    for(i=0;i<MAXUSERS;i++)
  1090. X        if(player[i].pos.x!=-1)
  1091. X            senddata(player[i].ssd,&sdata);
  1092. X
  1093. X    player[thisid].pos.x=(-1);
  1094. X    close(player[thisid].ssd);
  1095. X}
  1096. X
  1097. Xvoid
  1098. Xmoveplayers()    /* move all players */
  1099. X{
  1100. X    int i,j,newtime,diff,td,max;
  1101. X    int testx,testy,testrot,scale;
  1102. X    int dx,dy,cflag=0;
  1103. X    int stage;
  1104. X
  1105. X    for(i=0;i<MAXUSERS;i++)
  1106. X    {
  1107. X        stage=0;
  1108. X        if(player[i].pos.x==(-1))
  1109. X            continue;
  1110. X        newtime=gettime();
  1111. X        td=newtime-player[i].t;
  1112. X        player[i].t=newtime;
  1113. X        if((gettime()-player[i].restime)>500)
  1114. X        {
  1115. X            sdata.type=OUTSWAP(T_ALIVE);
  1116. X            senddata(player[i].ssd,&sdata);
  1117. X        }
  1118. X
  1119. X        if((gettime()-player[i].restime)>1000)
  1120. X        {
  1121. X            dosignoff(i,TIMEOUT);
  1122. X        }
  1123. X        
  1124. X        scale=100;
  1125. X
  1126. X        diff=player[i].move.rot-player[i].pos.rot;
  1127. X
  1128. X
  1129. X        testx=player[i].pos.x/OBJECTSCALE;
  1130. X        testy=player[i].pos.y/OBJECTSCALE;
  1131. X        if(field[testx][testy]==ROUGH)
  1132. X            scale=200;
  1133. X        if(diff>(TANKROT/2))
  1134. X            diff-=TANKROT;
  1135. X
  1136. X        if(diff<(TANKROT/(-2)))
  1137. X            diff+=TANKROT;
  1138. X
  1139. X        max=((td*STDROT)/scale)+1;
  1140. X
  1141. X        if(diff<0)
  1142. X            diff=((td*diff-99)/100);
  1143. X        else
  1144. X            if(diff>0)
  1145. X                diff=((td*diff+99)/100);
  1146. X
  1147. X        if(diff>max)
  1148. X            diff=max;
  1149. X        if(diff<(max*-1))
  1150. X            diff=(max*-1);
  1151. X
  1152. X        player[i].pos.rot=(player[i].pos.rot+diff+TANKROT)%TANKROT;
  1153. X
  1154. X        testrot=player[i].pos.rot;
  1155. X        dx=((TGRID*6)*costable[testrot])/STDMOVE;
  1156. X        dy=((TGRID*6)*sintable[testrot])/STDMOVE;
  1157. X        testx=(player[i].pos.x+player[i].move.linear*dx);
  1158. X        testy=(player[i].pos.y+player[i].move.linear*dy);
  1159. X
  1160. X        stage=1;
  1161. X        if((testx>MAINSIZE)||(testy>MAINSIZE)||(testx<0)||(testy<0))
  1162. X            goto loopend;
  1163. X        stage=2;
  1164. X        if(field[testx/OBJECTSCALE][testy/OBJECTSCALE]==BLOCKED)
  1165. X            goto loopend;
  1166. X
  1167. X        testrot=(player[i].pos.rot+TANKROT/14)%TANKROT;
  1168. X        dx=((TGRID*6)*costable[testrot])/STDMOVE;
  1169. X        dy=((TGRID*6)*sintable[testrot])/STDMOVE;
  1170. X        testx=(player[i].pos.x+player[i].move.linear*dx);
  1171. X        testy=(player[i].pos.y+player[i].move.linear*dy);
  1172. X
  1173. X        stage=3;
  1174. X        if((testx>MAINSIZE)||(testy>MAINSIZE)||(testx<0)||(testy<0))
  1175. X            goto loopend;
  1176. X        stage=4;
  1177. X        if(field[testx/OBJECTSCALE][testy/OBJECTSCALE]==BLOCKED)
  1178. X            goto loopend;
  1179. X
  1180. X        testrot=(player[i].pos.rot-(TANKROT/14)+TANKROT)%TANKROT;
  1181. X
  1182. X        dx=((TGRID*6)*costable[testrot])/STDMOVE;
  1183. X        dy=((TGRID*6)*sintable[testrot])/STDMOVE;
  1184. X        testx=(player[i].pos.x+player[i].move.linear*dx);
  1185. X        testy=(player[i].pos.y+player[i].move.linear*dy);
  1186. X
  1187. X        stage=5;
  1188. X        if((testx>MAINSIZE)||(testy>MAINSIZE)||(testx<0)||(testy<0))
  1189. X            goto loopend;
  1190. X        stage=6;
  1191. X        if(field[testx/OBJECTSCALE][testy/OBJECTSCALE]==BLOCKED)
  1192. X            goto loopend;
  1193. X
  1194. X        testx=player[i].pos.x+(player[i].move.linear*td*costable[player[i].pos.rot])/scale;
  1195. X        testy=player[i].pos.y+(player[i].move.linear*td*sintable[player[i].pos.rot])/scale;
  1196. X
  1197. X        for(j=0;j<MAXUSERS;j++)
  1198. X        {
  1199. X            if(i==j)
  1200. X                continue;
  1201. X            if(player[j].pos.x==(-1))
  1202. X                continue;
  1203. X            if(sqdist(testx,testy,player[j].pos.x,player[j].pos.y)<(TGRID*TGRID*6*6*2))
  1204. X            {
  1205. X                if(debug)
  1206. X                    printf("Collision %d->%d\n",i,j);
  1207. X                cflag++;
  1208. X                break;
  1209. X            }
  1210. X        }
  1211. X
  1212. X        if(!cflag)
  1213. X        {
  1214. X            player[i].pos.x=testx;
  1215. X            player[i].pos.y=testy;
  1216. X            stage=0;
  1217. X        }
  1218. X
  1219. X
  1220. Xloopend:    if(debug)
  1221. X            if(stage!=0)
  1222. X                printf("Tank %d blocked at stage %d\n",i,stage);
  1223. X    }
  1224. X}
  1225. X
  1226. Xvoid
  1227. Xdoalarm()    /* what to do when alarm expires */
  1228. X{
  1229. X    int i;
  1230. X    for(i=0;i<MAXUSERS;i++)
  1231. X    {
  1232. X        if(player[i].pos.x==(-1))
  1233. X            continue;
  1234. X        if(player[i].move.fire)
  1235. X            fireshell(i);
  1236. X            
  1237. X    }
  1238. X    moveplayers();
  1239. X    sendplayers();
  1240. X    myualarm(100000);    /* reset 1/10th sec alarm */
  1241. X}
  1242. X
  1243. Xmain(argc,argv)
  1244. Xint argc;
  1245. Xchar *argv[];
  1246. X{
  1247. X    int i,j,rn,thisid,reason;
  1248. X    int port=DEFSPORT;
  1249. X    char *p;
  1250. X
  1251. X    srand(time(0));
  1252. X
  1253. X    progname=argv[0];
  1254. X
  1255. X    for(i=1;i<argc;i++)
  1256. X    {
  1257. X        p=argv[i]; 
  1258. X        if(*p++=='-')
  1259. X        {
  1260. X            switch(*p++)
  1261. X            {
  1262. X            case 'p':
  1263. X                if(*p=='\0')
  1264. X                    port=atoi(argv[++i]);
  1265. X                else
  1266. X                    port=atoi(p);
  1267. X                break;
  1268. X            case 'd':
  1269. X                debug=(!debug);
  1270. X                break;
  1271. X            case 's':
  1272. X                scoreflag=(!scoreflag);
  1273. X                break;
  1274. X            default:
  1275. X                fprintf(stderr,"Usage: %s -p portno\n",argv[0]);
  1276. X            }
  1277. X        }
  1278. X    }
  1279. X
  1280. X    fprintf(stderr,"%s: XTankBattle server, datagram size is %d (V%d)\n",progname,sizeof(DATA),VERSION);
  1281. X
  1282. X    srand(time(0));
  1283. X    for(i=0;i<MAXUSERS;i++)
  1284. X    {
  1285. X        player[i].pos.x=(-1);
  1286. X        player[i].user.username[0]='\0';
  1287. X        player[i].user.hostname[0]='\0';
  1288. X    }
  1289. X
  1290. X    for(i=0;i<TANKROT;i++)
  1291. X    {
  1292. X        sintable[i]=(int)(0.5+(double)STDMOVE*sin(((double)i*2.0*PI)/TANKROT));
  1293. X        costable[i]=(int)(0.5+(double)STDMOVE*cos(((double)i*2.0*PI)/TANKROT));
  1294. X    }
  1295. X
  1296. X    for(i=0;i<OBJECTSIZE;i++)
  1297. X        for(j=0;j<OBJECTSIZE;j++)
  1298. X        {
  1299. X            field[i][j]=CLEAR;
  1300. X            rn=rnd(8);
  1301. X            if(rn==1)
  1302. X                field[i][j]=BLOCKED;
  1303. X            if((rn==4)||(rn==6))
  1304. X                field[i][j]=ROUGH;
  1305. X        }
  1306. X
  1307. X    signal(SIGALRM,doalarm);
  1308. X
  1309. X    rsd=openread(port);
  1310. X    if(rsd==-1)
  1311. X    {
  1312. X        fprintf(stderr,"%s: Unable to open port %d for reading\n",argv[0],port);
  1313. X        exit(1);
  1314. X    }
  1315. X    while(1)
  1316. X    {
  1317. X        fflush(stdout);
  1318. X        myualarm(100000);    /* 1/10th sec alarm */
  1319. X        if(readdata(rsd,&rdata)!=sizeof(DATA))
  1320. X        {
  1321. X            if(errno!=EINTR)
  1322. X                printf("Bad data (Config mismatch?)\n");
  1323. X        }
  1324. X        else
  1325. X        {
  1326. X            myualarm(0);    /* turn off alarm */
  1327. X            switch(INSWAP(rdata.type))
  1328. X            {
  1329. X            case T_SIGNON:
  1330. X                printf("signon\n");
  1331. X                printf("host %s/%d\n",rdata.extra.signon.hostname,INSWAP(rdata.extra.signon.port));
  1332. X                printf("user %s\n",rdata.extra.signon.username);
  1333. X
  1334. X                dosignon();
  1335. X                break;
  1336. X            case T_DATAREQ:
  1337. X                i=INSWAP(rdata.extra.datareq.lineno);
  1338. X                ssd=player[INSWAP(rdata.id)].ssd;
  1339. X                sdata.type=OUTSWAP(T_FIELDDATA);
  1340. X                sdata.extra.field.lineno=OUTSWAP(i);
  1341. X                memcpy(sdata.extra.field.object,&field[i][0],OBJECTSIZE);
  1342. X                senddata(ssd,&sdata);
  1343. X                break;
  1344. X            case T_ACCEPT:
  1345. X                printf("accept\n");
  1346. X                break;
  1347. X            case T_REJECT:
  1348. X                printf("reject\n");
  1349. X                break;
  1350. X            case T_MOVE:
  1351. X                thisid=INSWAP(rdata.id);
  1352. X                player[thisid].move.rot=INSWAP(rdata.extra.move.rot);
  1353. X                player[thisid].move.linear=INSWAP(rdata.extra.move.linear);
  1354. X                player[thisid].move.fire=INSWAP(rdata.extra.move.fire);
  1355. X                player[thisid].restime=gettime();
  1356. X
  1357. X                if(player[thisid].move.fire)
  1358. X                    fireshell(thisid);
  1359. X
  1360. X                moveplayers();
  1361. X                if((gettime()-lastsend)>4)
  1362. X                {
  1363. X                    sendplayers();
  1364. X                    lastsend=gettime();
  1365. X                }
  1366. X
  1367. X                break;
  1368. X            case T_REPLY:
  1369. X                printf("reply\n");
  1370. X                break;
  1371. X            case T_SIGNOFF:
  1372. X                thisid=INSWAP(rdata.id);
  1373. X                reason=INSWAP(rdata.extra.signoff.reason);
  1374. X                if(player[thisid].pos.x!=(-1))
  1375. X                    dosignoff(thisid,reason);
  1376. X                break;
  1377. X            case T_ALIVE:
  1378. X                thisid=INSWAP(rdata.id);
  1379. X                player[thisid].restime=gettime();
  1380. X/*                printf("%d is alive\n",thisid);*/
  1381. X                break;
  1382. X            default:
  1383. X                printf("Unknown datagram type %d (0x%x)\n",INSWAP(rdata.type),INSWAP(rdata.type));
  1384. X            }
  1385. X        }
  1386. X    }
  1387. X}
  1388. END_OF_FILE
  1389. if test 15465 -ne `wc -c <'xtbd.c'`; then
  1390.     echo shar: \"'xtbd.c'\" unpacked with wrong size!
  1391. fi
  1392. # end of 'xtbd.c'
  1393. fi
  1394. echo shar: End of archive 2 \(of 2\).
  1395. cp /dev/null ark2isdone
  1396. MISSING=""
  1397. for I in 1 2 ; do
  1398.     if test ! -f ark${I}isdone ; then
  1399.     MISSING="${MISSING} ${I}"
  1400.     fi
  1401. done
  1402. if test "${MISSING}" = "" ; then
  1403.     echo You have unpacked both archives.
  1404.     rm -f ark[1-9]isdone
  1405. else
  1406.     echo You still need to unpack the following archives:
  1407.     echo "        " ${MISSING}
  1408. fi
  1409. ##  End of shell archive.
  1410. exit 0
  1411.