argv@island.uu.net (Dan Heller) (11/22/89)
Submitted-by: Helmut Hoenig <hoenig@informatik.uni-kl.de> Posting-number: Volume 5, Issue 31 Archive-name: tron/part01 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: read_me.txt makefile tron_server.c # Wrapped by hoenig@incas on Thu Nov 16 14:22:40 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'read_me.txt' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'read_me.txt'\" else echo shar: Extracting \"'read_me.txt'\" \(4246 characters\) sed "s/^X//" >'read_me.txt' <<'END_OF_FILE' X X ++++++++++++ X +++ TRON +++ - an XWindows game X ++++++++++++ (colored or black&white) X Xby Helmut Hoenig (MAY-1988) X X X This is an X-version of the well known light-race of Xthe TRON-film. I actually wrote that program to get a bit Xmore familiar with X and with communication between programs Xthrough sockets. (That should be an excuse for writing pro- Xgrams with such a bad structure.) But at least it runs and Xbesides the programming-experience I got, we already had a Xlot of fun with it. X X After we tested the program for more than a year, I Xfinally decided to post it. To play that game you need: XUNIX, XWindows X11R3, a C-compiler, a lot of include-files. X X The makefile will help you to compile the 4 source- Xfiles into the 2 binary-files "tron_server" and "tron_run". XThese files have to be available in the same directory on Xevery host, where the program should be used (e.g. X/usr/games), since the programs are getting started via a Xremote shell using a system()-call. (see "tron_server.c", Xline 284ff) X X X+++ HOW IT WORKS +++ (you might skip this if it works) X X The "tron_server"-program is used to start the system Xup. I also call it the master. In the startup-sequence, a X"tron_run"-program is started for each player (usually on Xdifferent hosts). Each program connects itself to the mas- Xter. Through that stream-connection, the master is able to Xsend commands to the players (e.g. start game) and the Xplayers can answer with the number of rounds they played Xuntil they were busted. X X After the startup-sequence, we have a star- Xconfiguration of the players and the master. Each player Xsends the port-number of an additional datagram-socket to Xthe master, which is used during the game. The master opens Xa window to select the players and start the game. When the Xgame gets started, every player-program receives the port- Xnumber and host of the next player. In that way a datagram- Xpaket, produced by the first player, can be send around in a Xring. X X No effort (except a timeout, which ends the game) has Xbeen made to recover from missing datagrams, since it seems Xthat they don't get lost on our system. They just come a bit Xlate sometimes and then there's no sense in playing anyway. X X X+++ WHAT TO KNOW +++ X X The game is made for up to 8 players. At least one of Xthem has to be human. X X The players control their racers by mouse or keyboard. XThe keys to use are available from the program. X X Even if you play with the keyboard, you've got to place Xyour racer with the mouse (and middle button) in the field. XIt starts running in the direction of your mouse. If you Xwait a few seconds, the racers are automatically placed Xunder your mouse and the game starts. X X For each player you can enter the display- and the Xhost-name (separated by a '^', e.g. 'display:0.0^host'). If Xthere is no display-name given the host is used for an Xauto-player only (e.g. '^host'). As you usually play on the Xhost of the display, a single name is enough to select host Xand display. (So the usual command-line looks like X'tron_server host1 host2 ^auto_player1 ...) You might get Xproblems in the starting up sequence, if there are too many Xauto-players on the same host. X X X+++ PROBLEMS +++ X X On our system, we sometimes have problems in the Xstartup-sequence as there seem to be a lot processes Xenvolved when starting the remote-shells. It happen, that Xthe startup fails, when there are too many players (auto- Xplayers) on the same host. To avoid that it is possible to Xlet the server sleep some seconds between the starting of Xplayers by the option '-s<seconds>'. X X When controlling with the mouse, you might get problems Xwith your window-manager, if it grabs combinations of Xshift/control and mouse-buttons. Play with keyboards or kill Xthe window-manager in that case. X X X+++ HAVE FUN +++ X X Helmut Hoenig X XPS.: X XTRON runs on our system with suns and MicroVaxes. It is Xtested on 3 kinds of monochrom-displays and a colored one. X XPlease let me know if TRON runs on your system ! XMy address: X hoenig@informatik.uni-kl.de END_OF_FILE if test 4246 -ne `wc -c <'read_me.txt'`; then echo shar: \"'read_me.txt'\" unpacked with wrong size! fi # end of 'read_me.txt' fi if test -f 'makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'makefile'\" else echo shar: Extracting \"'makefile'\" \(889 characters\) sed "s/^X//" >'makefile' <<'END_OF_FILE' X# Tron consists of 2 program files. The 'tron_server' is used to start up X# the system. It starts a 'tron_run'-program for each player. For that it X# gets the file-name of it through the TRON_RUN_FILE-Macro. That name has X# to be the same on every host (e.g. /usr/games). X# The SOCKET_NAME-Macro is used, but not really nescessary. X XCFLAGS = -g XOBJ1 = tron_run.o texter.o helps.o XOBJ2 = tron_server.o texter.o helps.o X Xmain: tron_run tron_server X Xtron_run: $(OBJ1) X $(CC) $(CFLAGS) $(OBJ1) -lX11 -o tron_run X Xtron_server: $(OBJ2) X $(CC) $(CFLAGS) $(OBJ2) -lX11 -o tron_server X Xtron_run.o: grey_maps.h messages.h header.h X Xtron_server.o: messages.h header.h X $(CC) $(CFLAGS) \ X -DSOCKET_NAME=\"tron\" \ X -DTRON_RUN_FILE=\"~hoenig/sockets/tron_run\" \ X -c tron_server.c X Xtexter.o: header.h X $(CC) $(CFLAGS) \ X -DFONT_NAME=\"-*-courier-bold-r-normal--24-*-*-*-*-*-*-*\" \ X -c texter.c END_OF_FILE if test 889 -ne `wc -c <'makefile'`; then echo shar: \"'makefile'\" unpacked with wrong size! fi # end of 'makefile' fi if test -f 'tron_server.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tron_server.c'\" else echo shar: Extracting \"'tron_server.c'\" \(19352 characters\) sed "s/^X//" >'tron_server.c' <<'END_OF_FILE' X/* This program was written by Helmut Hoenig */ X/* in May of 1988 at the Unitversity of */ X/* Kaiserslautern, Germany. It may be copied freely. */ X X#define moremessages 0 X X#include <X11/Xlib.h> X#include <stdio.h> X#include <strings.h> X#include <sys/types.h> X#include <sys/socket.h> X#include <sys/uio.h> X#include <sys/time.h> X#include <netinet/in.h> X#include <netdb.h> X X#include "header.h" X#include "messages.h" X Xshort readshort(); X X#define HMAX 8 Xint max; /* when starting the system, this is the actual number of players */ X Xint messflag; X#define MAXPLAYERS 10 X X/* fields for result-messages */ Xstatic int points[MAXPLAYERS]; Xstatic int place[MAXPLAYERS]; Xstatic int count[MAXPLAYERS]; Xstatic int sorted[MAXPLAYERS]; Xstatic char tscreen[20][80]; Xstatic int lines; Xstatic int players; X Xstruct hostent *hostaddr[HMAX]; Xint active[HMAX]={ 0,0,0,0,0,0,0,0 }; Xint auto_only[HMAX]={ 0,0,0,0,0,0,0,0 }; X Xchar host_name[HMAX][20]; Xchar disp_name[HMAX][20]; X Xint sockets[HMAX],ports[HMAX]; Xlong play_time[HMAX]; Xstruct sockaddr_in rsin[HMAX]; Xint rsinlen[HMAX]; Xint socks[HMAX]; X X Xchar *my_host; /* eigener hostname */ X Xstruct servent *sp; X Xstruct sockaddr_in sin; Xint mastersocket; X Xchar *getenv(); X Xlong packet_count = 0; Xint data_error=0; Xint g_count=0; Xint match; X XDisplay *display; XScreen *screen; Xchar dispname[20]; Xextern XFontStruct *(finfo[]); Xextern Window aw; Xint waiting; XXEvent event; X#define FID 0 X Xusage() X{ X printf("\n\nusage:\ttron_server [ option ] <player_list>\n"); X printf("\n\t-v - prints some additional messages in starting sequence.\n"); X printf("\t-h - prints this.\n"); X printf("\t-s<sec> - to sleep <sec> seconds after the start of each players.\n"); X printf("\n<player_list>: List with the display_names and/or host_names of the players.\n"); X printf(" If only one name per player is given, the display is the display of the host.\n"); X printf(" Otherwise you can write <display_name>'^'<host_name> to get a special display.\n"); X printf(" An empty display-name stands for an automatic player. (e.g. ^host)\n"); X printf("\n"); X} X Xmain(argc,argv) X int argc; X char *argv[]; X{ int i,j; X char command[200]; X int test; X int waitflag=0; X char *ptr; X char *disp_arg=NULL; XXSetWindowAttributes attrib; X X/********************************************************************* X * At first, the host-names of the command-line are tested. * X * If there is a display for the player (no auto-player), the server * X * tests the possibility of opening XWindows on the display. If that * X * fails or a display is used twice, the player is ignored. * X * ==> In the end, there should be at least 2 correct names. * X *********************************************************************/ X X max=0; X messflag=0; X printf("\nTRON - programmed by Helmut Hoenig. (MAY-1988)\n"); X printf("startup-sequence at the following displays:\n"); X X if (argc==1) X { usage(); X exit(); X }; X X for (i=1;i<argc;i++) X { if (strcmp("-v",argv[i])==0) messflag=1; X else if (strncmp("-s",argv[i],2)==0) waitflag=atoi(&argv[i][2]); X else if ((strcmp("-",argv[i])==0)||(strcmp("-h",argv[i])==0)) X { usage(); X exit(); X } X else if (strcmp("-display",argv[i])==0) disp_arg = argv[++i]; X else if (max<HMAX) X { ptr = index(argv[i],'^'); X if (ptr==NULL) X { if ((ptr=index(argv[i],':'))==NULL) X { X /* a single host-name is extended by ":0.0" to the display-name */ X strcpy(host_name[max],argv[i]); X strcpy(disp_name[max],argv[i]); X strcat(disp_name[max],":0.0"); X } X else X { X /* in display-names the host-names are the string up to the ':' */ X strncpy(host_name[max],argv[i],ptr-argv[i]); X host_name[max][ptr-argv[i]+1]='\0'; X strcpy(disp_name[max],argv[i]); X if ((ptr=index(argv[i],'.'))==NULL) X { strcat(disp_name[max],".0"); X } X } X } X else X { X /* if host- and display is given the display-name, the display-name X might be extended to a '*:*.0'-form. */ X strcpy(host_name[max],ptr+1); X if (ptr==argv[i]) X { X /* A missing display-name indicates an auto-player. */ X strcpy(disp_name[max],host_name[max]); X strcat(disp_name[max],"-0"); X } X else X { *ptr ='\0'; X strcpy(disp_name[max],argv[i]); X if ((ptr=index(argv[i],':'))==NULL) X { strcat(disp_name[max],":0.0"); X } X else X { if ((ptr=index(argv[i],'.'))==NULL) X { strcat(disp_name[max],".0"); X } X } X } X } X X /* after extending names: check, if the argument is a host-name. */ X hostaddr[max]=gethostbyname(host_name[max]); X if (hostaddr[max]==NULL) X { printf("*** %s is not a host.\n",host_name[max]); X } X else X { X /* check the display-name */ X do X { for (j=0;j<max;j++) X { if (strcmp(disp_name[j],disp_name[max])==NULL) break; X } X X if (j==max) X { if (index(disp_name[max],'-')!=NULL) X { X /* Name of Auto-Player is O.K. */ X printf("%2d: auto-player %s\n",max+1,disp_name[max]); X auto_only[max++]=1; X } X else X { X if ((display=XOpenDisplay(disp_name[max]))==NULL) X { printf("XWindows ??? "); X } X else X /* Display is O.K. */ X { XCloseDisplay(display); X } X if (strncmp(disp_name[max],host_name[max],strlen(host_name[max]))==NULL) X printf("%2d: %s\n",max+1,disp_name[max]); X else X printf("%2d: %s (%s)\n",max+1,disp_name[max],host_name[max]); X auto_only[max++]=0; X } X break; X } X else X { X /* disp_name[max] already used. is it for an auto-player ? */ X if (index(disp_name[max],'-')!=NULL) X { disp_name[max][strlen(disp_name[max])-1]++; X } X else X { printf("display %s used twice.\n",disp_name[max]); X break; X } X } X } X while(j<max); X }; X } X } X X if (max<2) X { fprintf(stderr,"*** But there should be at least 2 players. ***\n"); X usage(); X exit(0); X }; X X/*************************************************************** X * After name-checking is done, a streamsocket is created * X * where the player-programs can connect to. A socket_name is * X * *NOT* nescessary as the server tells the clients his * X * socket-number as a parameter. * X ***************************************************************/ X X my_host=getenv("HOST"); X X/* Erzeugung eines Streamsockets in der Domain AF_INET */ X mastersocket=streamsocket(); X X/* Information ueber den Service mit Namen "service" */ X if ((sp=getservbyname(SOCKET_NAME,0))==0) X { fprintf(stderr,"#%s: socket not found by name.\n",my_host); X init_addr(&sin,my_host,htons((short)22222)); X } X else X/* Initialisieren der Struktur sockaddr_in */ X { bzero(&sin,sizeof sin); X sin.sin_family=AF_INET; X sin.sin_port= sp->s_port; X sin.sin_addr.s_addr= INADDR_ANY; X }; X X/* Namensbindung an den Socket */ X if (bind ( mastersocket,&sin,sizeof sin)<0) X { fprintf(stderr,"### #%s: error in bind.\n",my_host); X do X { sin.sin_port++; X } X while (bind (mastersocket,&sin,sizeof sin)<0); X fprintf(stderr,"### #%s: port %d selected as an alternative.\n",my_host,ntohs(sin.sin_port)); X }; X if (messflag) printf("*** master-socket is %s@%d. ***\n",my_host,(int)ntohs(sin.sin_port)); X X/* Einrichten einer Warteschlange */ X listen(mastersocket,max); X X/****************************************************************** X * The 'tron_run'-Program will now be started on each player-host.* X * A Bell-Signal is given on each display. * X ******************************************************************/ X X for (i=0;i<max;i++) X { play_time[i]=0; X if (!auto_only[i]) X { if ((display=XOpenDisplay(disp_name[i]))!=NULL) X { XBell(display,60); X XCloseDisplay(display); X } X } X X/*********************************************************************************** X the following command is now prepared to be executed by system(): X'<foreign_host> <file_name> <my_host> <mastersocket> <count> <message_flag> &' Xwith <foreign_host> - host for a player X <file_name> - name of the 'tron_run'-binary-file on that host X the macro TRON_RUN_FILE from the top off that source-file is used. X <my_host> - my host (for the stream-connection) X <mastersocket> - my socket (for the stream-connection) X <display> - the display, usually <foreign_host>:0.0 X <count> - to get the players in an order X <messageflag> - to produce additional messages by the players X***********************************************************************************/ X sprintf(command,"%s '%s %s %d %s %d %d' &", X host_name[i], X TRON_RUN_FILE, X my_host, X (int)ntohs(sin.sin_port), X disp_name[i], X i, X messflag); X X if (messflag) printf("#%s: starting up %s on %s.\n",my_host,disp_name[i],host_name[i]); X#if (moremessages) X printf("%s\n",command); X#endif X system(command); X if (waitflag) X { printf("sleeping %d seconds.\n",waitflag); X fflush(stdout); X sleep(waitflag); X } X } X X printf("#%s: %d clients started.\n",my_host,max); X X/******************************************************************************** X * The server waits, until all players are started and connected to the server. * X * Each Player-Program returns a port-number, which it uses in the game. * X ********************************************************************************/ X X for (i=0;i<max;i++) X { int j,count,auto_player; X X rsinlen[i]=sizeof rsin[i]; X socks[i]=accept(mastersocket,&rsin[i],&rsinlen[i]); X count=readint(socks[i]); /*** that's the <count>-argument X of the player's command-line. ***/ X sockets[count]=socks[i]; X ports[count]=(int)readshort(sockets[count]); X auto_player = readint(sockets[count]); X if (auto_player!=auto_only[count]) X { fprintf(stderr,"*** no XWindows on %s -> auto-player-mode only\n",disp_name[count]); X auto_only[count]=auto_player; X }; X if (messflag) printf("#%s: connection %s@%d established.\n",my_host,disp_name[count],ports[count]); X }; X printf("#%s: all clients connected.\n",my_host); X X close(mastersocket); X X/********************************************************** X * After all players are running, a window can be openend * X * to select who is really playing. * X **********************************************************/ X X if ((display=XOpenDisplay(disp_arg))==NULL) X { fprintf(stderr,"*** %s: Can't open display.\n",my_host); X exit(0); X }; X screen=XScreenOfDisplay(display,DefaultScreen(display)); X init_texter(); X X aw=XCreateSimpleWindow(display,RootWindowOfScreen(screen), X 20,50,26 * CharWidth(FID),(max+3+7) * CharHeight(FID), X 4,XBlackPixelOfScreen(screen),XWhitePixelOfScreen(screen)); X attrib.override_redirect = 1; X XChangeWindowAttributes(display,aw,CWOverrideRedirect,&attrib); X XSelectInput(display,aw,ExposureMask | ButtonPressMask); X X/************************************************************************* X * The next loop is executed, until QUIT is selected in the main menu. * X * You have to wait until a match is ended to get back to the main menu. * X *************************************************************************/ X for(;;) X { long tp1,tp2; X X if (data_error) X prepare_message(); X else X prepare_scores(); X send_scores(); X X if (match) X { int root_x,root_y,x,y; X Window root,child; X int mask; X X sleep(2); X /*********************************************************** X * you CAN STOP a match by holding down the left AND right * X * button on your mouse, befor the next game starts. * X ***********************************************************/ X X XQueryPointer(display,ROOT,&root,&child,&root_x,&root_y,&x,&y,&mask); X if ((mask & Button3Mask) && (mask & Button1Mask)) X { match=0; X sprintf(tscreen[0],"Match ended."); X send_scores(); X }; X }; X X if (!match) X { X XMapRaised(display,aw); X waiting=1; X do X { X XWindowEvent(display,aw,ExposureMask | ButtonPressMask,&event); X aw_event(event.type); X } X while(waiting); X XUnmapWindow(display,aw); X }; X tp1=time((long)0); X send_game_start(); X wait_players_ready(); X wait_game_over(); X tp2=time((long)0); X X for(i=0;i<max;i++) X if (active[i]==1) play_time[i]+=(tp2 - tp1); X }; X} X Xint check_points(a,b) X int *a,*b; X{ X if (points[*a]<points[*b]) return(1); X if (points[*a]>points[*b]) return(-1); X return(0); X} X X/************************************************ X * preparation of a text-field with the * X * sorted list of players with their scores. * X ************************************************/ Xprepare_scores() X{ int i; X X/* Spieler nach Punkten sortieren */ X players=0; X for (i=0;i<max;i++) X if (active[i]) sorted[players++]=i; X X qsort(sorted,players,sizeof(int),check_points); X X/* pruefen, ob Spielende erreicht */ X if (match) X { int mp=5*players; X X if ((points[sorted[0]]>=mp) && (points[sorted[0]]>points[sorted[1]]+1)) X { match=0; X sprintf(tscreen[0],"-- Final Result --"); X } X else X sprintf(tscreen[0],"Points: (%d)",mp); X } X else X { X sprintf(tscreen[0],"Points:"); X }; X X sprintf(tscreen[1],""); X X lines=2; X for (i=0;i<players;i++) X sprintf(tscreen[lines++],"%-13s%2d%3d",disp_name[sorted[i]],place[sorted[i]],points[sorted[i]]); X} X Xshow_keys() X{ X sprintf(tscreen[0],"**** TRON - by Helmut Hoenig ****"); X sprintf(tscreen[1],""); X sprintf(tscreen[2]," Keyboard Mouse"); X sprintf(tscreen[3],""); X sprintf(tscreen[4],"left turn: 'z' 'x' 'm' ',' left"); X sprintf(tscreen[5],"right turn: 'c' 'v' '.' '/' right"); X sprintf(tscreen[6],"jump: SPACE middle"); X sprintf(tscreen[7],"speed: SHIFT"); X sprintf(tscreen[8],"booster: SHIFT & CTRL"); X sprintf(tscreen[9],""); X sprintf(tscreen[10]," >> no turns while booster's on. <<"); X lines=11; X send_scores(); X}; X Xprepare_message() X{ X sprintf(tscreen[0],"- Timeout -"); X lines=1; X} X X/********************************************* X * sends the textfield to all active players * X *********************************************/ Xsend_scores() X{ int i,l; X X for (i=0;i<max;i++) X if (active[i] & 1) X { writeint(sockets[i],SCORE); X writeint(sockets[i],lines); X for (l=0;l<lines;l++) X { writestring(sockets[i],tscreen[l]); X }; X }; X} X X/************************************************************** X * sends the game_start-message to all players. * X * containing the port-number and host of the next player and * X * a flag, if the player should create the first datagram. * X **************************************************************/ Xsend_game_start() X{ int i,ind=0,starter=0; X X int perm[MAXPLAYERS]; X X g_count++; X X for (i=0;i<max;i++) X if (active[i]) perm[ind++]=i; X X for (i=0;i<ind;i++) X { writeint(sockets[perm[i]],GAMESTART); X writeint(sockets[perm[i]],players); X writeint(sockets[perm[i]],active[perm[i]]); X writeint(sockets[perm[i]],g_count); X if (i == 0) X writeint(sockets[perm[i]],1); X else X writeint(sockets[perm[i]],0); X X writestring(sockets[perm[i]],host_name[perm[((i+1) % ind)]]); X writeshort(sockets[perm[i]],ports[perm[((i+1) % ind)]]); X }; X} X Xsend_exit() X{ int i; X X for (i=0;i<max;i++) X writeint(sockets[i],EXIT); X} X X/*********************************************** X * waits, until all players are ready to start * X ***********************************************/ Xwait_players_ready() X{ Xint readfds,writefds,execptfds; Xstruct timeval timeout; X Xint ready_count=0,i,nfound; X X do X { readfds=0; X writefds=0; X execptfds=0; X/* timeout.tv_sec=0; X timeout.tv_usec=0; X*/ X for (i=0;i<max;i++) X if (active[i]) readfds |= (1<<sockets[i]); X X nfound=select(32,&readfds,&writefds,&execptfds,0); X if (nfound<0) X { fprintf(stderr,"#%s: error occured in select.\n",my_host); X exit(0); X }; X for (i=0;i<max;i++) X if (readfds & (1<<sockets[i])) X { int v; X if ((v=readint(sockets[i]))!=PLAYER_READY) X { fprintf(stderr,"#%s: illegal message (%d) received from %s.\n",my_host,v,disp_name[i]); X send_exit(); X exit(0); X }; X ready_count++; X }; X } X while(ready_count<players); X} X Xint check_count(a,b) X int *a,*b; X{ X if (count[*a]<count[*b]) return(1); X if (count[*a]>count[*b]) return(-1); X return(0); X} X X/*************************************************** X * waits, until the game is over. * X * the server receives a counter from each player, * X * which says, when it was destroyed. * X ***************************************************/ Xwait_game_over() X{ Xint readfds,writefds,execptfds; Xstruct timeval timeout; X Xint ready_count=0,i,nfound; X X data_error=0; X while(ready_count<players) X { readfds=0; X writefds=0; X execptfds=0; X/* timeout.tv_sec=0; X timeout.tv_usec=0; X*/ X for (i=0;i<max;i++) X if (active[i]) readfds |= (1<<sockets[i]); X X nfound=select(32,&readfds,&writefds,&execptfds,0); X if (nfound<0) X { fprintf(stderr,"#%s: error occured in select.\n",my_host); X exit(0); X }; X for (i=0;i<max;i++) X if (readfds & (1<<sockets[i])) X { int v; X if ((v=readint(sockets[i]))!=DESTROYED) X { data_error=1; X printf("#%s: error-message by %s.\n",my_host,disp_name[i]); X fflush(stdout); X } X else X { X/* printf("#%s: %s destroyed.\n",my_host,disp_name[i]); */ X count[i]=readint(sockets[i]); X }; X ready_count++; X }; X }; X X/* printf("#%s: all players destroyed.\n",my_host); */ X X/* Punkte verteilen */ Xif (!data_error) X{ players=0; X for (i=0;i<max;i++) X if (active[i]) sorted[players++]=i; X X qsort(sorted,players,sizeof(int),check_count); X X for (i=0;i<players;i++) X { points[sorted[i]] +=(place[sorted[i]] = players-i-1); X X }; X packet_count += (long)count[sorted[0]]; X}; X} X X X/******************************************************* X * XWindow-Functions for redrawing and event-executing * X *******************************************************/ Xredraw_disps() X{ int i; X X XRaiseWindow(display,aw); X printat(1,1,"TRON",FID); X for (i=0;i<max;i++) X { printat(1,i+3,disp_name[i],FID); X if (active[i]==2) X printcleared(20,i+3,"AUTO",FID); X else if (active[i]==1) X printcleared(20,i+3," YES",FID); X else X printcleared(20,i+3," NO",FID); X }; X printat(1,3+max+1,"Start Match",FID); X printat(1,3+max+2,"Start Game",FID); X printat(1,3+max+3,"Show Keys",FID); X printat(1,3+max+4,"Clear Scores",FID); X printat(1,3+max+5,"Quit",FID); X XFlush(display); X} X Xaw_event(type) X unsigned type; X{ int i,y; X X switch(type) X { X case Expose: X redraw_disps(); X break; X case ButtonPress: X y=((event.xbutton.y)/CharHeight(FID))-3; X if (y<0) break; X X if (y<max) X { X active[y]=(active[y]+1)%3; /* switching: NO->YES->AUTO->NO */ X if (auto_only[y]) X { if (active[y]==1) active[y]++; X } X if (active[y] & 2) writeint(sockets[y],UNMAP); X } X else X { y-=max+1; X if (y<2) /* START GAME OR MATCH */ X { int i1,i2,j; X X i1=i2=0; X for (j=0;j<max;j++) X { if (active[j]) X { i1++; X if (active[j]==1) i2++; X } X } X if ((i1>1)&&(i2>0)) X { waiting=0; X match=(y==0); X } X else X { XBell(display,50); X XFlush(display); X } X }; X if (y==2) /* SHOW KEYS */ X { int t; X for (t=0;t<max;t++) X if (active[t]==1) break; X if (t==max) X XBell(display,10); X else X show_keys(); X return; X }; X X if ((y==3) || (match)) /* CLEAR SCORES */ X for (i=0;i<max;i++) X { sorted[i]=i; X points[i]=0; X place[i]=0; X }; X if (y==4) /* QUIT */ X { send_exit(); X X printf("#%s: program ends.\n",my_host); X printf("#total number of datagrams: %ld\n",packet_count); X fflush(stdout); X exit(0); X }; X }; X if (waiting) X { redraw_disps(); X prepare_scores(); X send_scores(); X }; X }; X} END_OF_FILE if test 19352 -ne `wc -c <'tron_server.c'`; then echo shar: \"'tron_server.c'\" unpacked with wrong size! fi # end of 'tron_server.c' fi echo shar: End of shell archive. echo '*** Think of changing the TRON_RUN_FILE-Macro in the makefile ! ***' exit 0